[
  {
    "path": ".editorconfig",
    "content": "# EditorConfig is awesome: http://EditorConfig.org\n\n# top-most EditorConfig file\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = tab\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.md]\nindent_size = 2\nindent_style = space\n"
  },
  {
    "path": ".github/workflows/tests.yml",
    "content": "# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node\n# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions\n\nname: build and test\n\non: [push]\n\njobs:\n  build-and-test:\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [lts/*]\n\n    steps:\n      - uses: actions/checkout@v2\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n      - run: npm clean-install\n      - run: npm test\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.idea\n.vscode\n.tmp\nbuild/npm*\nnode_modules\nnpm-debug.log\n"
  },
  {
    "path": ".npmignore",
    "content": "assets/\nbower.json\ndocs/\nexamples/\nCONTRIBUTING.md\ntest/\n"
  },
  {
    "path": ".prettierignore",
    "content": "dist/\n.tmp/\n.vscode/\nexamples/js/stats.min.js\nexamples/example-projects/plain-typescript-modules/**/*.js\n"
  },
  {
    "path": ".prettierrc.cjs",
    "content": "module.exports = {\n\tarrowParens: 'avoid',\n\tbracketSpacing: false,\n\tprintWidth: 120,\n\tsemi: false,\n\tsingleQuote: true,\n\ttrailingComma: 'all',\n\tuseTabs: true,\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n- Using welcoming and inclusive language\n- Being respectful of differing viewpoints and experiences\n- Gracefully accepting constructive criticism\n- Focusing on what is best for the community\n- Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n- The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n- Trolling, insulting/derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n- Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at coc@soledadpenades.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n## Code of conduct\n\nPlease note that this project is released with a [Contributor Code of Conduct](./CODE_OF_CONDUCT.md). **By participating in this project you agree to abide by its terms**.\n\n## Before reporting a bug\n\nIf you find something that you believe to be a bug, please\n\n1. search the [issue tracker](https://github.com/tweenjs/tween.js/issues) for similar issues\n2. check out the [master](https://github.com/tweenjs/tween.js/tree/master) branch and see if the bug still exists there.\n\n## How to report a bug\n\n1. Specify the revision number of the tween.js library where the bug occurred\n2. Specify your browser version and operating system (i.e. Chrome 23.0.1271.95, Windows 7)\n3. Describe the problem in detail. What happened? What did you expect to happen?\n4. Provide a small test case (e.g. using http://jsfiddle.net). Or if not possible, provide a link to a live version of your application.\n\n## Contributing\n\n1. Get a GitHub account (if you don't have one yet).\n2. Fork the project in GitHub.\n3. Check the [contribution guidelines](https://github.com/tweenjs/tween.js/wiki/Contributing-to-tween.js).\n4. Make changes to your clone of the repository\n5. Submit a pull request.\n\n_If you tried all of the above and still can't fix the bug, or you're not sure you're doing things right, [let us know](https://github.com/tween.js/tween.js/issues)._\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License\n\nCopyright (c) 2010-2012 Tween.js authors.\n\nEasing equations Copyright (c) 2001 Robert Penner http://robertpenner.com/easing/\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# tween.js\n\nJavaScript (TypeScript) tweening engine for easy animations, incorporating optimised Robert Penner's equations.\n\n[![NPM Version][npm-image]][npm-url]\n[![CDNJS][cdnjs-image]][cdnjs-url]\n[![NPM Downloads][downloads-image]][downloads-url]\n[![Build and Tests][ci-image]][ci-url]\n\nMore languages: [English](./README.md), [简体中文](./README_zh-CN.md)\n\n---\n\n```html\n<div id=\"box\"></div>\n\n<style>\n\t#box {\n\t\tbackground-color: deeppink;\n\t\twidth: 100px;\n\t\theight: 100px;\n\t}\n</style>\n\n<script type=\"module\">\n\timport {Tween, Easing} from 'https://unpkg.com/@tweenjs/tween.js@23.1.3/dist/tween.esm.js'\n\n\tconst box = document.getElementById('box') // Get the element we want to animate.\n\n\tconst coords = {x: 0, y: 0} // Start at (0, 0)\n\n\tconst tween = new Tween(coords, false) // Create a new tween that modifies 'coords'.\n\t\t.to({x: 300, y: 200}, 1000) // Move to (300, 200) in 1 second.\n\t\t.easing(Easing.Quadratic.InOut) // Use an easing function to make the animation smooth.\n\t\t.onUpdate(() => {\n\t\t\t// Called after tween.js updates 'coords'.\n\t\t\t// Move 'box' to the position described by 'coords' with a CSS translation.\n\t\t\tbox.style.setProperty('transform', 'translate(' + coords.x + 'px, ' + coords.y + 'px)')\n\t\t})\n\t\t.start() // Start the tween immediately.\n\n\t// Setup the animation loop.\n\tfunction animate(time) {\n\t\ttween.update(time)\n\t\trequestAnimationFrame(animate)\n\t}\n\trequestAnimationFrame(animate)\n</script>\n```\n\n[Try this example on CodePen](https://codepen.io/trusktr/pen/KKGaBVz?editors=1000)\n\n# Features\n\n- Does one thing only and does it well: tweens properties of an object\n- Doesn't take care of CSS units (e.g. appending `px`)\n- Doesn't interpolate colors\n- Easing functions are reusable outside of Tween\n- Can also use custom easing functions\n- Doesn't make its own animation loop, making it flexible for integration into\n  any animation loop.\n\n# Examples\n\n<table>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/00_hello_world.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/00_hello_world.png\" alt=\"hello world\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\thello world<br />\n\t\t\t(<a href=\"examples/00_hello_world.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/01_bars.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/01_bars.png\" alt=\"Bars\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tBars<br />\n\t\t\t(<a href=\"examples/01_bars.html\">source</a>)\n\t\t</td>\n\t<tr>\n\t</tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/02_black_and_red.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/02_black_and_red.png\" alt=\"Black and red\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tBlack and red<br />\n\t\t\t(<a href=\"examples/02_black_and_red.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/03_graphs.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/03_graphs.png\" alt=\"Graphs\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tGraphs<br />\n\t\t\t(<a href=\"examples/03_graphs.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/04_simplest.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/04_simplest.png\" alt=\"Simplest possible example\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tSimplest possible example<br />\n\t\t\t(<a href=\"examples/04_simplest.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/05_video_and_time.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/06_video_and_time.png\" alt=\"Video and time\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tVideo and time<br />\n\t\t\t(<a href=\"examples/05_video_and_time.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/06_array_interpolation.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/03_graphs.png\" alt=\"Array interpolation\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tArray interpolation<br />\n\t\t\t(<a href=\"examples/06_array_interpolation.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/07_dynamic_to.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/07_dynamic_to.png\" alt=\"Dynamic to, object\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tDynamic to, object<br />\n\t\t\t(<a href=\"examples/07_dynamic_to.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/07a_dynamic_to_two_array_values.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/07a_dynamic_to.png\" alt=\"Dynamic to, interpolation array\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tDynamic to, interpolation array<br />\n\t\t\t(<a href=\"examples/07a_dynamic_to_two_array_values.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/07b_dynamic_to_an_array_of_values.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/07b_dynamic_to.png\" alt=\"Dynamic to, large interpolation array\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tDynamic to, large interpolation array<br />\n\t\t\t(<a href=\"examples/07b_dynamic_to_an_array_of_values.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/08_repeat.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/08_repeat.png\" alt=\"Repeat\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tRepeat<br />\n\t\t\t(<a href=\"examples/08_repeat.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/09_relative_values.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/09_relative.png\" alt=\"Relative values\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tRelative values<br />\n\t\t\t(<a href=\"examples/09_relative_values.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/10_yoyo.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/10_yoyo.png\" alt=\"Yoyo\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tYoyo<br />\n\t\t\t(<a href=\"examples/10_yoyo.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/11_stop_all_chained_tweens.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/11_stop_all_chained_tweens.png\" alt=\"Stop all chained tweens\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tStop all chained tweens<br />\n\t\t\t(<a href=\"examples/11_stop_all_chained_tweens.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/12_graphs_custom_functions.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/03_graphs.png\" alt=\"Custom functions\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tCustom functions<br />\n\t\t\t(<a href=\"examples/12_graphs_custom_functions.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/13_relative_start_time.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/13_relative_start_time.png\" alt=\"Relative start time\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tRelative start time<br />\n\t\t\t(<a href=\"examples/13_relative_start_time.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/14_pause_tween.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/14_pause_tween.png\" alt=\"Pause tween\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tPause tween<br />\n\t\t\t(<a href=\"examples/14_pause_tween.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/15_complex_properties.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/15_complex_properties.png\" alt=\"Complex properties\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tComplex properties<br />\n\t\t\t(<a href=\"examples/15_complex_properties.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/16_animate_an_array_of_values.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/16_animate_an_array_of_values.png\" alt=\"Animate an array of values\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tAnimate an array of values<br />\n\t\t\t(<a href=\"examples/16_animate_an_array_of_values.html\">source</a>)\n\t\t</td>\n\t</tr>\n</table>\n\n# Installation\n\nThe recommended method is to use `import` syntax. Here we've listed various\ninstall methods starting roughly with the most recommended first and least\ndesirable last. Evaluate all of the following methods to pick what is most\nsuitable for your project.\n\n## With `npm install` and `import` from `node_modules`\n\nYou can add tween.js as an npm dependency:\n\n```bash\nnpm install @tweenjs/tween.js\n```\n\n### Without a build tool\n\n#### Installed locally\n\nYou can import from `node_modules` if you serve `node_modules` as part of your\nwebsite, using a standard `importmap` script tag. First, assuming `node_modules`\nis at the root of your website, you can write an import map like so in your HTML\nfile:\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"@tweenjs/tween.js\": \"/node_modules/@tweenjs/tween.js/dist/tween.esm.js\"\n\t\t}\n\t}\n</script>\n```\n\nNow in any of your module scripts you can import Tween.js by its package name:\n\n```html\n<script type=\"module\">\n\timport {Tween} from '@tweenjs/tween.js'\n</script>\n```\n\n#### Import from CDN\n\nNote that, without the `importmap`, you can import directly from a CDN as with the first example above, like so:\n\n```html\n<script type=\"module\">\n\timport {Tween} from 'https://unpkg.com/browse/@tweenjs/tween.js@23.1.3/dist/tween.esm.js'\n</script>\n```\n\nYou can also link your `importmap` to the CDN instead of a local `node_modules` folder, if you prefer that:\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"@tweenjs/tween.js\": \"https://unpkg.com/browse/@tweenjs/tween.js@23.1.3/dist/tween.esm.js\"\n\t\t}\n\t}\n</script>\n\n<script type=\"module\">\n\timport {Tween} from '@tweenjs/tween.js'\n</script>\n```\n\n### With a build tool\n\nIf you are using [Node.js](https://nodejs.org/),\n[Parcel](https://parceljs.org/), [Webpack](https://webpack.js.org/),\n[Rollup](https://rollupjs.org/), [Vite](https://vitejs.dev/), or another build\ntool, then you can install `@tweenjs/tween.js` with `npm install\n@tweenjs/tween.js`, and `import` the library into your JavaScript (or\nTypeScript) file, and the build tool will know how to find the source code from\n`node_modules` without needing to create an `importmap` script:\n\n```javascript\nimport * as TWEEN from '@tweenjs/tween.js'\n```\n\nHowever, note that this approach requires always running a build tool for your\napp to work, while the `importmap` approach will simply work without any build\ntools as a simple static HTML site.\n\n## Manual build\n\nAnother approach is to download the source code with git, manually build the\nlibrary, then place the output in your project. Node.js is required for this.\n\n```bash\ngit clone https://github.com/tweenjs/tween.js\ncd tween.js\nnpm install\nnpm run build\n```\n\nThis will create some builds in the `dist` directory. There are currently two different builds of the library:\n\n- ES6 Module in `/dist/tween.esm.js` (recommended)\n- UMD in `/dist/tween.umd.js` (deprecated, will be removed in a future major version)\n\nYou are now able to copy one of those two files into your project, and use like this (recommended):\n\n```html\n<script type=\"module\">\n\timport {Tween} from 'path/to/tween.esm.js'\n</script>\n```\n\nor (deprecated, to be removed in future major):\n\n```html\n<script src=\"path/to/tween.umd.js\"></script>\n<script>\n\tconst {Tween} = TWEEN\n</script>\n```\n\nwhere `path/to` is replaced with the location where you placed the file.\n\n> [!Note]\n> You can also download these files from unpkg, for example here:\n> https://unpkg.com/browse/@tweenjs/tween.js@23.1.3/dist/\n\n## Global variable from CDN (deprecated)\n\n> [!Note]\n> This method is deprecated and will be removed in a future major version!\n\nInstall a global `TWEEN` variable from a content-delivery network (CDN) using the UMD file.\n\nFrom cdnjs:\n\n```html\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/tween.js/23.1.3/tween.umd.js\"></script>\n```\n\nOr from unpkg.com:\n\n```html\n<script src=\"https://unpkg.com/@tweenjs/tween.js@^23.1.3/dist/tween.umd.js\"></script>\n```\n\nThen use the `TWEEN` variable in any script:\n\n```html\n<script>\n\tconst {Tween, Easing, Group /*, ...*/} = TWEEN\n\n\tconst tween = new Tween(someObject)\n\t// ...\n</script>\n```\n\n> [!Note]\n> unpkg.com supports a semver version in the URL, where the `^` in the\n> URL tells unpkg to give you the latest version 20.x.x.\n\n## CommonJS (deprecated)\n\nSkip this section if you don't know what CommonJS is!\n\n> [!Note]\n> This method is deprecated and will be removed in a future major version!\n\nAny of the above methods work in older systems that still use CommonJS. Repeat\nany of the above methods but using `dist/tween.cjs` instead of\n`dist/tween.esm.js` or `dist/tween.umd.js`.\n\n# Documentation\n\n- [User guide](./docs/user_guide.md)\n- [Contributor guide](./docs/contributor_guide.md)\n- [Tutorial](https://web.archive.org/web/20220601192930/http://learningthreejs.com/blog/2011/08/17/tweenjs-for-smooth-animation/) using tween.js with three.js\n- Also: [libtween](https://github.com/jsm174/libtween), a port of tween.js to C by [jsm174](https://github.com/jsm174)\n\n# Tests\n\nYou need to install `npm` first--this comes with node.js, so install that one first. Then, cd to `tween.js`'s (or wherever you cloned the repo) directory and run:\n\n```bash\nnpm install\n```\n\nTo run the tests run:\n\n```bash\nnpm test\n```\n\nIf you want to add any feature or change existing features, you _must_ run the\ntests to make sure you didn't break anything else. Any pull request (PR) needs\nto have updated passing tests for feature changes (or new passing tests for new\nfeatures or fixes) in `src/tests.ts` to be accepted. See\n[contributing](CONTRIBUTING.md) for more information.\n\n# People\n\nMaintainers: [Joe Pea (@trusktr)](https://github.com/trusktr).\n\n[All contributors](http://github.com/tweenjs/tween.js/contributors).\n\n# Projects using tween.js\n\n[<img src=\"./assets/projects/11_lume.jpg\" width=\"100\" alt=\"Lume\" />](https://lume.io)\n[![A-Frame VR](https://tweenjs.github.io/tween.js/assets/projects/10_aframe.png)](https://aframe.io)\n[![MOMA Inventing Abstraction 1910-1925](https://tweenjs.github.io/tween.js/assets/projects/09_moma.png)](http://www.moma.org/interactives/exhibitions/2012/inventingabstraction/)\n[![Web Lab](https://tweenjs.github.io/tween.js/assets/projects/08_web_lab.png)](http://www.chromeweblab.com/)\n[![MACCHINA I](https://tweenjs.github.io/tween.js/assets/projects/07_macchina.png)](http://5013.es/toys/macchina)\n[![Minesweeper 3D](https://tweenjs.github.io/tween.js/assets/projects/06_minesweeper3d.png)](http://egraether.com/mine3d/)\n[![ROME](https://tweenjs.github.io/tween.js/assets/projects/05_rome.png)](http://ro.me)\n[![WebGL Globe](https://tweenjs.github.io/tween.js/assets/projects/04_webgl_globe.png)](http://data-arts.appspot.com/globe)\n[![Androidify](https://tweenjs.github.io/tween.js/assets/projects/03_androidify.png)](http://www.androidify.com/)\n[![The Wilderness Downtown](https://tweenjs.github.io/tween.js/assets/projects/01_wilderness.png)](http://thewildernessdowntown.com/)\n[![Linechart](https://tweenjs.github.io/tween.js/assets/projects/00_linechart.png)](http://dejavis.org/linechart)\n\n[npm-image]: https://img.shields.io/npm/v/@tweenjs/tween.js.svg\n[npm-url]: https://npmjs.org/package/@tweenjs/tween.js\n[downloads-image]: https://img.shields.io/npm/dm/@tweenjs/tween.js.svg\n[downloads-url]: https://npmjs.org/package/@tweenjs/tween.js\n[ci-image]: https://github.com/tweenjs/tween.js/workflows/build%20and%20tests/badge.svg?branch=master\n[ci-url]: https://github.com/tweenjs/tween.js/actions\n[cdnjs-image]: https://img.shields.io/cdnjs/v/tween.js.svg\n[cdnjs-url]: https://cdnjs.com/libraries/tween.js\n"
  },
  {
    "path": "README_zh-CN.md",
    "content": "# tween.js\n\n用于简单动画的 JavaScript (TypeScript) 补间引擎，结合优化的 Robert Penner 方程式。\n\n[![NPM Version][npm-image]][npm-url]\n[![CDNJS][cdnjs-image]][cdnjs-url]\n[![NPM Downloads][downloads-image]][downloads-url]\n[![Build and Tests][ci-image]][ci-url]\n\n更多语言: [English](./README.md), [简体中文](./README_zh-CN.md)\n\n---\n\n```html\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/tween.js/23.1.3/tween.umd.js\"></script>\n\n<div id=\"box\"></div>\n\n<style>\n\t#box {\n\t\tbackground-color: deeppink;\n\t\twidth: 100px;\n\t\theight: 100px;\n\t}\n</style>\n\n<script>\n\tconst box = document.getElementById('box') // 获取我们想要设置动画的元素。\n\n\tconst coords = {x: 0, y: 0} // 从 (0, 0) 开始\n\n\tconst tween = new TWEEN.Tween(coords, false) // 创建一个修改“坐标”的新 tween。\n\t\t.to({x: 300, y: 200}, 1000) // 在 1 秒内移动到 (300, 200)。\n\t\t.easing(TWEEN.Easing.Quadratic.InOut) // 使用缓动函数使动画流畅。\n\t\t.onUpdate(() => {\n\t\t\t// 在 tween.js 更新“坐标”后调用。\n\t\t\t// 使用 CSS transform 将 'box' 移动到 'coords' 描述的位置。\n\t\t\tbox.style.setProperty('transform', 'translate(' + coords.x + 'px, ' + coords.y + 'px)')\n\t\t})\n\t\t.start() // 立即开始 tween。\n\n\t// 设置动画循环。\n\tfunction animate(time) {\n\t\ttween.update(time)\n\t\trequestAnimationFrame(animate)\n\t}\n\trequestAnimationFrame(animate)\n</script>\n```\n\n[在 CodePen 上试试这个例子](https://codepen.io/trusktr/pen/KKGaBVz?editors=1000)\n\n## 安装\n\n## 从 CDN 安装\n\n从上例中的内容分发网络 (CDN) 安装。\n\ncdnjs:\n\n```html\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/tween.js/23.1.3/tween.umd.js\"></script>\n```\n\n或者 unpkg.com:\n\n```html\n<script src=\"https://unpkg.com/@tweenjs/tween.js@^23.1.3/dist/tween.umd.js\"></script>\n```\n\n请注意，unpkg.com 支持 URL 中的 semver 版本，其中 URL 中的 `^` 告诉 unpkg 为你提供最新版本 20.x.x。\n\n## 使用 script 标签构建并包含在你的项目中\n\n目前需要 npm 来构建项目。\n\n```bash\ngit clone https://github.com/tweenjs/tween.js\ncd tween.js\nnpm install\nnpm run build\n```\n\n这将在 `dist` 目录中创建一些构建。 目前有两种不同的库版本：\n\n- UMD : `tween.umd.js`\n- ES6 Module : `tween.esm.js`\n\n你现在可以将 tween.umd.js 复制到你的项目中，然后将其包含在一个 script 标签，它将 TWEEN 添加到全局范围，\n\n```html\n<script src=\"path/to/tween.umd.js\"></script>\n```\n\n或将 TWEEN 作为 JavaScript 模块导入，\n\n```html\n<script type=\"module\">\n\timport * as TWEEN from 'path/to/tween.esm.js'\n</script>\n```\n\n其中 `path/to` 替换为你放置文件的位置。\n\n## 使用 `npm install` 和 `import` 从 `node_modules` 中添加\n\n你可以将 tween.js 添加为 npm 依赖项：\n\n```bash\nnpm install @tweenjs/tween.js\n```\n\n### 使用构建工具\n\n如果你使用 [Node.js](https://nodejs.org/)、[Parcel](https://parceljs.org/)、[Webpack](https://webpack.js.org/), [Rollup](https://rollupjs.org/)、[Vite](https://vitejs.dev/) 或者其他的构建工具，那么你现在可以使用以下方式来导入 tween.js：\n\n```javascript\nimport * as TWEEN from '@tweenjs/tween.js'\n```\n\n### 没有构建工具\n\n如果你将 `node_modules` 作为网站的一部分提供服务，则可以使用 `importmap` script 标签从 `node_modules` 导入。 首先，假设 `node_modules` 位于你网站的根目录，你可以编写一个导入映射：\n\n```html\n<script type=\"importmap\">\n\t{\n\t\t\"imports\": {\n\t\t\t\"@tweenjs/tween.js\": \"/node_modules/@tweenjs/tween.js/dist/tween.esm.js\"\n\t\t}\n\t}\n</script>\n```\n\n现在，在任何 module script 中，你都可以通过包名导入它：\n\n```javascript\nimport * as TWEEN from '@tweenjs/tween.js'\n```\n\n# 特性\n\n- 做一件事并且只做一件事：补间属性\n- 不处理 CSS 单位（例如附加 `px`）\n- 不插值颜色\n- 缓动函数可在 Tween 之外重复使用\n- 也可以使用自定义缓动函数\n\n# 文档\n\n<table>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/00_hello_world.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/00_hello_world.png\" alt=\"hello world\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\thello world<br />\n\t\t\t(<a href=\"examples/00_hello_world.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/01_bars.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/01_bars.png\" alt=\"Bars\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tBars<br />\n\t\t\t(<a href=\"examples/01_bars.html\">source</a>)\n\t\t</td>\n\t<tr>\n\t</tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/02_black_and_red.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/02_black_and_red.png\" alt=\"Black and red\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tBlack and red<br />\n\t\t\t(<a href=\"examples/02_black_and_red.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/03_graphs.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/03_graphs.png\" alt=\"Graphs\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tGraphs<br />\n\t\t\t(<a href=\"examples/03_graphs.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/04_simplest.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/04_simplest.png\" alt=\"Simplest possible example\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tSimplest possible example<br />\n\t\t\t(<a href=\"examples/04_simplest.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/05_video_and_time.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/06_video_and_time.png\" alt=\"Video and time\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tVideo and time<br />\n\t\t\t(<a href=\"examples/05_video_and_time.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/06_array_interpolation.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/03_graphs.png\" alt=\"Array interpolation\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tArray interpolation<br />\n\t\t\t(<a href=\"examples/06_array_interpolation.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/07_dynamic_to.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/07_dynamic_to.png\" alt=\"Dynamic to, object\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tDynamic to, object<br />\n\t\t\t(<a href=\"examples/07_dynamic_to.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/07a_dynamic_to_two_array_values.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/07a_dynamic_to.png\" alt=\"Dynamic to, interpolation array\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tDynamic to, interpolation array<br />\n\t\t\t(<a href=\"examples/07a_dynamic_to_two_array_values.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/07b_dynamic_to_an_array_of_values.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/07b_dynamic_to.png\" alt=\"Dynamic to, large interpolation array\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tDynamic to, large interpolation array<br />\n\t\t\t(<a href=\"examples/07b_dynamic_to_an_array_of_values.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/08_repeat.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/08_repeat.png\" alt=\"Repeat\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tRepeat<br />\n\t\t\t(<a href=\"examples/08_repeat.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/09_relative_values.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/09_relative.png\" alt=\"Relative values\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tRelative values<br />\n\t\t\t(<a href=\"examples/09_relative_values.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/10_yoyo.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/10_yoyo.png\" alt=\"Yoyo\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tYoyo<br />\n\t\t\t(<a href=\"examples/10_yoyo.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/11_stop_all_chained_tweens.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/11_stop_all_chained_tweens.png\" alt=\"Stop all chained tweens\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tStop all chained tweens<br />\n\t\t\t(<a href=\"examples/11_stop_all_chained_tweens.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/12_graphs_custom_functions.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/03_graphs.png\" alt=\"Custom functions\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tCustom functions<br />\n\t\t\t(<a href=\"examples/12_graphs_custom_functions.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/13_relative_start_time.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/13_relative_start_time.png\" alt=\"Relative start time\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tRelative start time<br />\n\t\t\t(<a href=\"examples/13_relative_start_time.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/14_pause_tween.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/14_pause_tween.png\" alt=\"Pause tween\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tPause tween<br />\n\t\t\t(<a href=\"examples/14_pause_tween.html\">source</a>)\n\t\t</td>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/15_complex_properties.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/15_complex_properties.png\" alt=\"Complex properties\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tComplex properties<br />\n\t\t\t(<a href=\"examples/15_complex_properties.html\">source</a>)\n\t\t</td>\n\t</tr>\n\t<tr>\n\t\t<td>\n\t\t\t<a href=\"http://tweenjs.github.io/tween.js/examples/16_animate_an_array_of_values.html\">\n\t\t\t\t<img width=\"100\" height=\"50\" src=\"https://tweenjs.github.io/tween.js/assets/examples/16_animate_an_array_of_values.png\" alt=\"Animate an array of values\" />\n\t\t\t</a>\n\t\t</td>\n\t\t<td>\n\t\t\tAnimate an array of values<br />\n\t\t\t(<a href=\"examples/16_animate_an_array_of_values.html\">source</a>)\n\t\t</td>\n\t</tr>\n</table>\n\n# 测试\n\n你需要先安装 `npm`——它随 node.js 一起提供，因此请先安装它。 然后，cd 到 `tween.js` 的（或你克隆 repo 的任何地方）目录并运行：\n\n```bash\nnpm install\n```\n\n运行测试：\n\n```bash\nnpm test\n```\n\n如果你想添加任何功能或更改现有功能，你 _必须_ 运行测试以确保你没有破坏任何其他功能。任何拉取请求 (PR) 都需要在 `src/tests.ts` 中更新通过功能更改测试（或通过新功能或修复的新测试）才能接受 PR。 有关更多信息，请参阅 [贡献](CONTRIBUTING.md)。\n\n# 使用 tween.js 的项目\n\n[<img src=\"./assets/projects/11_lume.jpg\" width=\"100\" alt=\"Lume\" />](https://lume.io)\n[![A-Frame VR](https://tweenjs.github.io/tween.js/assets/projects/10_aframe.png)](https://aframe.io)\n[![MOMA Inventing Abstraction 1910-1925](https://tweenjs.github.io/tween.js/assets/projects/09_moma.png)](http://www.moma.org/interactives/exhibitions/2012/inventingabstraction/)\n[![Web Lab](https://tweenjs.github.io/tween.js/assets/projects/08_web_lab.png)](http://www.chromeweblab.com/)\n[![MACCHINA I](https://tweenjs.github.io/tween.js/assets/projects/07_macchina.png)](http://5013.es/toys/macchina)\n[![Minesweeper 3D](https://tweenjs.github.io/tween.js/assets/projects/06_minesweeper3d.png)](http://egraether.com/mine3d/)\n[![ROME](https://tweenjs.github.io/tween.js/assets/projects/05_rome.png)](http://ro.me)\n[![WebGL Globe](https://tweenjs.github.io/tween.js/assets/projects/04_webgl_globe.png)](http://data-arts.appspot.com/globe)\n[![Androidify](https://tweenjs.github.io/tween.js/assets/projects/03_androidify.png)](http://www.androidify.com/)\n[![The Wilderness Downtown](https://tweenjs.github.io/tween.js/assets/projects/01_wilderness.png)](http://thewildernessdowntown.com/)\n[![Linechart](https://tweenjs.github.io/tween.js/assets/projects/00_linechart.png)](http://dejavis.org/linechart)\n\n[npm-image]: https://img.shields.io/npm/v/@tweenjs/tween.js.svg\n[npm-url]: https://npmjs.org/package/@tweenjs/tween.js\n[downloads-image]: https://img.shields.io/npm/dm/@tweenjs/tween.js.svg\n[downloads-url]: https://npmjs.org/package/@tweenjs/tween.js\n[ci-image]: https://github.com/tweenjs/tween.js/workflows/build%20and%20tests/badge.svg?branch=master\n[ci-url]: https://github.com/tweenjs/tween.js/actions\n[cdnjs-image]: https://img.shields.io/cdnjs/v/tween.js.svg\n[cdnjs-url]: https://cdnjs.com/libraries/tween.js\n"
  },
  {
    "path": "assets/style.css",
    "content": "body {\n\tbackground: #fff;\n\tfont-family: Helvetica, Arial, sans;\n}\n\na {\n\tcolor: #333;\n}\n\nh2 {\n\tfont-weight: normal;\n}\n\n#info {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpadding: 1.5em 2em;\n}\n\n#info h1 {\n\tfont-size: 3em;\n\tcolor: #333;\n\tmargin-top: 0;\n\tletter-spacing: -0.05em;\n}\n\n#info h2 {\n\tfont-size: 2.5em;\n\ttext-transform: uppercase;\n\tcolor: #666;\n\tmargin-top: 0;\n}\n\n#info p {\n\tfont-size: 2em;\n\tline-height: 1em;\n\tcolor: #aaa;\n\tmax-width: 10em;\n}\n"
  },
  {
    "path": "dist/tween.amd.js",
    "content": "define(['exports'], (function (exports) { 'use strict';\n\n    /**\n     * The Ease class provides a collection of easing functions for use with tween.js.\n     */\n    var Easing = Object.freeze({\n        Linear: Object.freeze({\n            None: function (amount) {\n                return amount;\n            },\n            In: function (amount) {\n                return amount;\n            },\n            Out: function (amount) {\n                return amount;\n            },\n            InOut: function (amount) {\n                return amount;\n            },\n        }),\n        Quadratic: Object.freeze({\n            In: function (amount) {\n                return amount * amount;\n            },\n            Out: function (amount) {\n                return amount * (2 - amount);\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return 0.5 * amount * amount;\n                }\n                return -0.5 * (--amount * (amount - 2) - 1);\n            },\n        }),\n        Cubic: Object.freeze({\n            In: function (amount) {\n                return amount * amount * amount;\n            },\n            Out: function (amount) {\n                return --amount * amount * amount + 1;\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return 0.5 * amount * amount * amount;\n                }\n                return 0.5 * ((amount -= 2) * amount * amount + 2);\n            },\n        }),\n        Quartic: Object.freeze({\n            In: function (amount) {\n                return amount * amount * amount * amount;\n            },\n            Out: function (amount) {\n                return 1 - --amount * amount * amount * amount;\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return 0.5 * amount * amount * amount * amount;\n                }\n                return -0.5 * ((amount -= 2) * amount * amount * amount - 2);\n            },\n        }),\n        Quintic: Object.freeze({\n            In: function (amount) {\n                return amount * amount * amount * amount * amount;\n            },\n            Out: function (amount) {\n                return --amount * amount * amount * amount * amount + 1;\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return 0.5 * amount * amount * amount * amount * amount;\n                }\n                return 0.5 * ((amount -= 2) * amount * amount * amount * amount + 2);\n            },\n        }),\n        Sinusoidal: Object.freeze({\n            In: function (amount) {\n                return 1 - Math.sin(((1.0 - amount) * Math.PI) / 2);\n            },\n            Out: function (amount) {\n                return Math.sin((amount * Math.PI) / 2);\n            },\n            InOut: function (amount) {\n                return 0.5 * (1 - Math.sin(Math.PI * (0.5 - amount)));\n            },\n        }),\n        Exponential: Object.freeze({\n            In: function (amount) {\n                return amount === 0 ? 0 : Math.pow(1024, amount - 1);\n            },\n            Out: function (amount) {\n                return amount === 1 ? 1 : 1 - Math.pow(2, -10 * amount);\n            },\n            InOut: function (amount) {\n                if (amount === 0) {\n                    return 0;\n                }\n                if (amount === 1) {\n                    return 1;\n                }\n                if ((amount *= 2) < 1) {\n                    return 0.5 * Math.pow(1024, amount - 1);\n                }\n                return 0.5 * (-Math.pow(2, -10 * (amount - 1)) + 2);\n            },\n        }),\n        Circular: Object.freeze({\n            In: function (amount) {\n                return 1 - Math.sqrt(1 - amount * amount);\n            },\n            Out: function (amount) {\n                return Math.sqrt(1 - --amount * amount);\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return -0.5 * (Math.sqrt(1 - amount * amount) - 1);\n                }\n                return 0.5 * (Math.sqrt(1 - (amount -= 2) * amount) + 1);\n            },\n        }),\n        Elastic: Object.freeze({\n            In: function (amount) {\n                if (amount === 0) {\n                    return 0;\n                }\n                if (amount === 1) {\n                    return 1;\n                }\n                return -Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);\n            },\n            Out: function (amount) {\n                if (amount === 0) {\n                    return 0;\n                }\n                if (amount === 1) {\n                    return 1;\n                }\n                return Math.pow(2, -10 * amount) * Math.sin((amount - 0.1) * 5 * Math.PI) + 1;\n            },\n            InOut: function (amount) {\n                if (amount === 0) {\n                    return 0;\n                }\n                if (amount === 1) {\n                    return 1;\n                }\n                amount *= 2;\n                if (amount < 1) {\n                    return -0.5 * Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);\n                }\n                return 0.5 * Math.pow(2, -10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI) + 1;\n            },\n        }),\n        Back: Object.freeze({\n            In: function (amount) {\n                var s = 1.70158;\n                return amount === 1 ? 1 : amount * amount * ((s + 1) * amount - s);\n            },\n            Out: function (amount) {\n                var s = 1.70158;\n                return amount === 0 ? 0 : --amount * amount * ((s + 1) * amount + s) + 1;\n            },\n            InOut: function (amount) {\n                var s = 1.70158 * 1.525;\n                if ((amount *= 2) < 1) {\n                    return 0.5 * (amount * amount * ((s + 1) * amount - s));\n                }\n                return 0.5 * ((amount -= 2) * amount * ((s + 1) * amount + s) + 2);\n            },\n        }),\n        Bounce: Object.freeze({\n            In: function (amount) {\n                return 1 - Easing.Bounce.Out(1 - amount);\n            },\n            Out: function (amount) {\n                if (amount < 1 / 2.75) {\n                    return 7.5625 * amount * amount;\n                }\n                else if (amount < 2 / 2.75) {\n                    return 7.5625 * (amount -= 1.5 / 2.75) * amount + 0.75;\n                }\n                else if (amount < 2.5 / 2.75) {\n                    return 7.5625 * (amount -= 2.25 / 2.75) * amount + 0.9375;\n                }\n                else {\n                    return 7.5625 * (amount -= 2.625 / 2.75) * amount + 0.984375;\n                }\n            },\n            InOut: function (amount) {\n                if (amount < 0.5) {\n                    return Easing.Bounce.In(amount * 2) * 0.5;\n                }\n                return Easing.Bounce.Out(amount * 2 - 1) * 0.5 + 0.5;\n            },\n        }),\n        generatePow: function (power) {\n            if (power === void 0) { power = 4; }\n            power = power < Number.EPSILON ? Number.EPSILON : power;\n            power = power > 10000 ? 10000 : power;\n            return {\n                In: function (amount) {\n                    return Math.pow(amount, power);\n                },\n                Out: function (amount) {\n                    return 1 - Math.pow((1 - amount), power);\n                },\n                InOut: function (amount) {\n                    if (amount < 0.5) {\n                        return Math.pow((amount * 2), power) / 2;\n                    }\n                    return (1 - Math.pow((2 - amount * 2), power)) / 2 + 0.5;\n                },\n            };\n        },\n    });\n\n    var _nowFunc = function () { return performance.now(); };\n    var now = function () {\n        return _nowFunc();\n    };\n    function setNow(nowFunction) {\n        _nowFunc = nowFunction;\n    }\n\n    /**\n     * Controlling groups of tweens\n     *\n     * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n     * In these cases, you may want to create your own smaller groups of tween\n     */\n    var Group = /** @class */ (function () {\n        function Group() {\n            var tweens = [];\n            for (var _i = 0; _i < arguments.length; _i++) {\n                tweens[_i] = arguments[_i];\n            }\n            this._tweens = {};\n            this._tweensAddedDuringUpdate = {};\n            this.add.apply(this, tweens);\n        }\n        Group.prototype.getAll = function () {\n            var _this = this;\n            return Object.keys(this._tweens).map(function (tweenId) { return _this._tweens[tweenId]; });\n        };\n        Group.prototype.removeAll = function () {\n            this._tweens = {};\n        };\n        Group.prototype.add = function () {\n            var _a;\n            var tweens = [];\n            for (var _i = 0; _i < arguments.length; _i++) {\n                tweens[_i] = arguments[_i];\n            }\n            for (var _b = 0, tweens_1 = tweens; _b < tweens_1.length; _b++) {\n                var tween = tweens_1[_b];\n                // Remove from any other group first, a tween can only be in one group at a time.\n                // @ts-expect-error library internal access\n                (_a = tween._group) === null || _a === void 0 ? void 0 : _a.remove(tween);\n                // @ts-expect-error library internal access\n                tween._group = this;\n                this._tweens[tween.getId()] = tween;\n                this._tweensAddedDuringUpdate[tween.getId()] = tween;\n            }\n        };\n        Group.prototype.remove = function () {\n            var tweens = [];\n            for (var _i = 0; _i < arguments.length; _i++) {\n                tweens[_i] = arguments[_i];\n            }\n            for (var _a = 0, tweens_2 = tweens; _a < tweens_2.length; _a++) {\n                var tween = tweens_2[_a];\n                // @ts-expect-error library internal access\n                tween._group = undefined;\n                delete this._tweens[tween.getId()];\n                delete this._tweensAddedDuringUpdate[tween.getId()];\n            }\n        };\n        /** Return true if all tweens in the group are not paused or playing. */\n        Group.prototype.allStopped = function () {\n            return this.getAll().every(function (tween) { return !tween.isPlaying(); });\n        };\n        Group.prototype.update = function (time, preserve) {\n            if (time === void 0) { time = now(); }\n            if (preserve === void 0) { preserve = true; }\n            var tweenIds = Object.keys(this._tweens);\n            if (tweenIds.length === 0)\n                return;\n            // Tweens are updated in \"batches\". If you add a new tween during an\n            // update, then the new tween will be updated in the next batch.\n            // If you remove a tween during an update, it may or may not be updated.\n            // However, if the removed tween was added during the current batch,\n            // then it will not be updated.\n            while (tweenIds.length > 0) {\n                this._tweensAddedDuringUpdate = {};\n                for (var i = 0; i < tweenIds.length; i++) {\n                    var tween = this._tweens[tweenIds[i]];\n                    var autoStart = !preserve;\n                    if (tween && tween.update(time, autoStart) === false && !preserve)\n                        this.remove(tween);\n                }\n                tweenIds = Object.keys(this._tweensAddedDuringUpdate);\n            }\n        };\n        Group.prototype.onComplete = function (callback) {\n            var group = this.getAll();\n            group.forEach(function (tween) {\n                var prevCallback = tween.getCompleteCallback();\n                tween.onComplete(function () {\n                    prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);\n                    // After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.\n                    var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });\n                    if (completedGroup.length === group.length - 1)\n                        callback(group);\n                });\n            });\n        };\n        return Group;\n    }());\n\n    /**\n     *\n     */\n    var Interpolation = {\n        Linear: function (v, k) {\n            var m = v.length - 1;\n            var f = m * k;\n            var i = Math.floor(f);\n            var fn = Interpolation.Utils.Linear;\n            if (k < 0) {\n                return fn(v[0], v[1], f);\n            }\n            if (k > 1) {\n                return fn(v[m], v[m - 1], m - f);\n            }\n            return fn(v[i], v[i + 1 > m ? m : i + 1], f - i);\n        },\n        Bezier: function (v, k) {\n            var b = 0;\n            var n = v.length - 1;\n            var pw = Math.pow;\n            var bn = Interpolation.Utils.Bernstein;\n            for (var i = 0; i <= n; i++) {\n                b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);\n            }\n            return b;\n        },\n        CatmullRom: function (v, k) {\n            var m = v.length - 1;\n            var f = m * k;\n            var i = Math.floor(f);\n            var fn = Interpolation.Utils.CatmullRom;\n            if (v[0] === v[m]) {\n                if (k < 0) {\n                    i = Math.floor((f = m * (1 + k)));\n                }\n                return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);\n            }\n            else {\n                if (k < 0) {\n                    return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]);\n                }\n                if (k > 1) {\n                    return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);\n                }\n                return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);\n            }\n        },\n        Utils: {\n            Linear: function (p0, p1, t) {\n                return (p1 - p0) * t + p0;\n            },\n            Bernstein: function (n, i) {\n                var fc = Interpolation.Utils.Factorial;\n                return fc(n) / fc(i) / fc(n - i);\n            },\n            Factorial: (function () {\n                var a = [1];\n                return function (n) {\n                    var s = 1;\n                    if (a[n]) {\n                        return a[n];\n                    }\n                    for (var i = n; i > 1; i--) {\n                        s *= i;\n                    }\n                    a[n] = s;\n                    return s;\n                };\n            })(),\n            CatmullRom: function (p0, p1, p2, p3, t) {\n                var v0 = (p2 - p0) * 0.5;\n                var v1 = (p3 - p1) * 0.5;\n                var t2 = t * t;\n                var t3 = t * t2;\n                return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;\n            },\n        },\n    };\n\n    /**\n     * Utils\n     */\n    var Sequence = /** @class */ (function () {\n        function Sequence() {\n        }\n        Sequence.nextId = function () {\n            return Sequence._nextId++;\n        };\n        Sequence._nextId = 0;\n        return Sequence;\n    }());\n\n    var mainGroup = new Group();\n\n    /**\n     * Tween.js - Licensed under the MIT license\n     * https://github.com/tweenjs/tween.js\n     * ----------------------------------------------\n     *\n     * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n     * Thank you all, you're awesome!\n     */\n    var Tween = /** @class */ (function () {\n        function Tween(object, group) {\n            this._isPaused = false;\n            this._pauseStart = 0;\n            this._valuesStart = {};\n            this._valuesEnd = {};\n            this._valuesStartRepeat = {};\n            this._duration = 1000;\n            this._isDynamic = false;\n            this._initialRepeat = 0;\n            this._repeat = 0;\n            this._yoyo = false;\n            this._isPlaying = false;\n            this._reversed = false;\n            this._delayTime = 0;\n            this._startTime = 0;\n            this._easingFunction = Easing.Linear.None;\n            this._interpolationFunction = Interpolation.Linear;\n            // eslint-disable-next-line\n            this._chainedTweens = [];\n            this._onStartCallbackFired = false;\n            this._onEveryStartCallbackFired = false;\n            this._id = Sequence.nextId();\n            this._isChainStopped = false;\n            this._propertiesAreSetUp = false;\n            this._goToEnd = false;\n            this._object = object;\n            if (typeof group === 'object') {\n                this._group = group;\n                group.add(this);\n            }\n            // Use \"true\" to restore old behavior (will be removed in future release).\n            else if (group === true) {\n                this._group = mainGroup;\n                mainGroup.add(this);\n            }\n        }\n        Tween.prototype.getId = function () {\n            return this._id;\n        };\n        Tween.prototype.getCompleteCallback = function () {\n            return this._onCompleteCallback;\n        };\n        Tween.prototype.isPlaying = function () {\n            return this._isPlaying;\n        };\n        Tween.prototype.isPaused = function () {\n            return this._isPaused;\n        };\n        Tween.prototype.getDuration = function () {\n            return this._duration;\n        };\n        Tween.prototype.to = function (target, duration) {\n            if (duration === void 0) { duration = 1000; }\n            if (this._isPlaying)\n                throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.');\n            this._valuesEnd = target;\n            this._propertiesAreSetUp = false;\n            this._duration = duration < 0 ? 0 : duration;\n            return this;\n        };\n        Tween.prototype.duration = function (duration) {\n            if (duration === void 0) { duration = 1000; }\n            this._duration = duration < 0 ? 0 : duration;\n            return this;\n        };\n        Tween.prototype.dynamic = function (dynamic) {\n            if (dynamic === void 0) { dynamic = false; }\n            this._isDynamic = dynamic;\n            return this;\n        };\n        Tween.prototype.start = function (time, overrideStartingValues) {\n            if (time === void 0) { time = now(); }\n            if (overrideStartingValues === void 0) { overrideStartingValues = false; }\n            if (this._isPlaying) {\n                return this;\n            }\n            this._repeat = this._initialRepeat;\n            if (this._reversed) {\n                // If we were reversed (f.e. using the yoyo feature) then we need to\n                // flip the tween direction back to forward.\n                this._reversed = false;\n                for (var property in this._valuesStartRepeat) {\n                    this._swapEndStartRepeatValues(property);\n                    this._valuesStart[property] = this._valuesStartRepeat[property];\n                }\n            }\n            this._isPlaying = true;\n            this._isPaused = false;\n            this._onStartCallbackFired = false;\n            this._onEveryStartCallbackFired = false;\n            this._isChainStopped = false;\n            this._startTime = time;\n            this._startTime += this._delayTime;\n            if (!this._propertiesAreSetUp || overrideStartingValues) {\n                this._propertiesAreSetUp = true;\n                // If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n                if (!this._isDynamic) {\n                    var tmp = {};\n                    for (var prop in this._valuesEnd)\n                        tmp[prop] = this._valuesEnd[prop];\n                    this._valuesEnd = tmp;\n                }\n                this._setupProperties(this._object, this._valuesStart, this._valuesEnd, this._valuesStartRepeat, overrideStartingValues);\n            }\n            return this;\n        };\n        Tween.prototype.startFromCurrentValues = function (time) {\n            return this.start(time, true);\n        };\n        Tween.prototype._setupProperties = function (_object, _valuesStart, _valuesEnd, _valuesStartRepeat, overrideStartingValues) {\n            for (var property in _valuesEnd) {\n                var startValue = _object[property];\n                var startValueIsArray = Array.isArray(startValue);\n                var propType = startValueIsArray ? 'array' : typeof startValue;\n                var isInterpolationList = !startValueIsArray && Array.isArray(_valuesEnd[property]);\n                // If `to()` specifies a property that doesn't exist in the source object,\n                // we should not set that property in the object\n                if (propType === 'undefined' || propType === 'function') {\n                    continue;\n                }\n                // Check if an Array was provided as property value\n                if (isInterpolationList) {\n                    var endValues = _valuesEnd[property];\n                    if (endValues.length === 0) {\n                        continue;\n                    }\n                    // Handle an array of relative values.\n                    // Creates a local copy of the Array with the start value at the front\n                    var temp = [startValue];\n                    for (var i = 0, l = endValues.length; i < l; i += 1) {\n                        var value = this._handleRelativeValue(startValue, endValues[i]);\n                        if (isNaN(value)) {\n                            isInterpolationList = false;\n                            console.warn('Found invalid interpolation list. Skipping.');\n                            break;\n                        }\n                        temp.push(value);\n                    }\n                    if (isInterpolationList) {\n                        // if (_valuesStart[property] === undefined) { // handle end values only the first time. NOT NEEDED? setupProperties is now guarded by _propertiesAreSetUp.\n                        _valuesEnd[property] = temp;\n                        // }\n                    }\n                }\n                // handle the deepness of the values\n                if ((propType === 'object' || startValueIsArray) && startValue && !isInterpolationList) {\n                    _valuesStart[property] = startValueIsArray ? [] : {};\n                    var nestedObject = startValue;\n                    for (var prop in nestedObject) {\n                        _valuesStart[property][prop] = nestedObject[prop];\n                    }\n                    // TODO? repeat nested values? And yoyo? And array values?\n                    _valuesStartRepeat[property] = startValueIsArray ? [] : {};\n                    var endValues = _valuesEnd[property];\n                    // If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n                    if (!this._isDynamic) {\n                        var tmp = {};\n                        for (var prop in endValues)\n                            tmp[prop] = endValues[prop];\n                        _valuesEnd[property] = endValues = tmp;\n                    }\n                    this._setupProperties(nestedObject, _valuesStart[property], endValues, _valuesStartRepeat[property], overrideStartingValues);\n                }\n                else {\n                    // Save the starting value, but only once unless override is requested.\n                    if (typeof _valuesStart[property] === 'undefined' || overrideStartingValues) {\n                        _valuesStart[property] = startValue;\n                    }\n                    if (!startValueIsArray) {\n                        // eslint-disable-next-line\n                        // @ts-ignore FIXME?\n                        _valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings\n                    }\n                    if (isInterpolationList) {\n                        // eslint-disable-next-line\n                        // @ts-ignore FIXME?\n                        _valuesStartRepeat[property] = _valuesEnd[property].slice().reverse();\n                    }\n                    else {\n                        _valuesStartRepeat[property] = _valuesStart[property] || 0;\n                    }\n                }\n            }\n        };\n        Tween.prototype.stop = function () {\n            if (!this._isChainStopped) {\n                this._isChainStopped = true;\n                this.stopChainedTweens();\n            }\n            if (!this._isPlaying) {\n                return this;\n            }\n            this._isPlaying = false;\n            this._isPaused = false;\n            if (this._onStopCallback) {\n                this._onStopCallback(this._object);\n            }\n            return this;\n        };\n        Tween.prototype.end = function () {\n            this._goToEnd = true;\n            this.update(this._startTime + this._duration);\n            return this;\n        };\n        Tween.prototype.pause = function (time) {\n            if (time === void 0) { time = now(); }\n            if (this._isPaused || !this._isPlaying) {\n                return this;\n            }\n            this._isPaused = true;\n            this._pauseStart = time;\n            return this;\n        };\n        Tween.prototype.resume = function (time) {\n            if (time === void 0) { time = now(); }\n            if (!this._isPaused || !this._isPlaying) {\n                return this;\n            }\n            this._isPaused = false;\n            this._startTime += time - this._pauseStart;\n            this._pauseStart = 0;\n            return this;\n        };\n        Tween.prototype.stopChainedTweens = function () {\n            for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n                this._chainedTweens[i].stop();\n            }\n            return this;\n        };\n        Tween.prototype.group = function (group) {\n            if (!group) {\n                console.warn('tween.group() without args has been removed, use group.add(tween) instead.');\n                return this;\n            }\n            group.add(this);\n            return this;\n        };\n        /**\n         * Removes the tween from whichever group it is in.\n         */\n        Tween.prototype.remove = function () {\n            var _a;\n            (_a = this._group) === null || _a === void 0 ? void 0 : _a.remove(this);\n            return this;\n        };\n        Tween.prototype.delay = function (amount) {\n            if (amount === void 0) { amount = 0; }\n            this._delayTime = amount;\n            return this;\n        };\n        Tween.prototype.repeat = function (times) {\n            if (times === void 0) { times = 0; }\n            this._initialRepeat = times;\n            this._repeat = times;\n            return this;\n        };\n        Tween.prototype.repeatDelay = function (amount) {\n            this._repeatDelayTime = amount;\n            return this;\n        };\n        Tween.prototype.yoyo = function (yoyo) {\n            if (yoyo === void 0) { yoyo = false; }\n            this._yoyo = yoyo;\n            return this;\n        };\n        Tween.prototype.easing = function (easingFunction) {\n            if (easingFunction === void 0) { easingFunction = Easing.Linear.None; }\n            this._easingFunction = easingFunction;\n            return this;\n        };\n        Tween.prototype.interpolation = function (interpolationFunction) {\n            if (interpolationFunction === void 0) { interpolationFunction = Interpolation.Linear; }\n            this._interpolationFunction = interpolationFunction;\n            return this;\n        };\n        // eslint-disable-next-line\n        Tween.prototype.chain = function () {\n            var tweens = [];\n            for (var _i = 0; _i < arguments.length; _i++) {\n                tweens[_i] = arguments[_i];\n            }\n            this._chainedTweens = tweens;\n            return this;\n        };\n        Tween.prototype.onStart = function (callback) {\n            this._onStartCallback = callback;\n            return this;\n        };\n        Tween.prototype.onEveryStart = function (callback) {\n            this._onEveryStartCallback = callback;\n            return this;\n        };\n        Tween.prototype.onUpdate = function (callback) {\n            this._onUpdateCallback = callback;\n            return this;\n        };\n        Tween.prototype.onRepeat = function (callback) {\n            this._onRepeatCallback = callback;\n            return this;\n        };\n        Tween.prototype.onComplete = function (callback) {\n            this._onCompleteCallback = callback;\n            return this;\n        };\n        Tween.prototype.onStop = function (callback) {\n            this._onStopCallback = callback;\n            return this;\n        };\n        /**\n         * @returns true if the tween is still playing after the update, false\n         * otherwise (calling update on a paused tween still returns true because\n         * it is still playing, just paused).\n         *\n         * @param autoStart - When true, calling update will implicitly call start()\n         * as well. Note, if you stop() or end() the tween, but are still calling\n         * update(), it will start again!\n         */\n        Tween.prototype.update = function (time, autoStart) {\n            var _this = this;\n            var _a;\n            if (time === void 0) { time = now(); }\n            if (autoStart === void 0) { autoStart = Tween.autoStartOnUpdate; }\n            if (this._isPaused)\n                return true;\n            var property;\n            if (!this._goToEnd && !this._isPlaying) {\n                if (autoStart)\n                    this.start(time, true);\n                else\n                    return false;\n            }\n            this._goToEnd = false;\n            if (time < this._startTime) {\n                return true;\n            }\n            if (this._onStartCallbackFired === false) {\n                if (this._onStartCallback) {\n                    this._onStartCallback(this._object);\n                }\n                this._onStartCallbackFired = true;\n            }\n            if (this._onEveryStartCallbackFired === false) {\n                if (this._onEveryStartCallback) {\n                    this._onEveryStartCallback(this._object);\n                }\n                this._onEveryStartCallbackFired = true;\n            }\n            var elapsedTime = time - this._startTime;\n            var durationAndDelay = this._duration + ((_a = this._repeatDelayTime) !== null && _a !== void 0 ? _a : this._delayTime);\n            var totalTime = this._duration + this._repeat * durationAndDelay;\n            var calculateElapsedPortion = function () {\n                if (_this._duration === 0)\n                    return 1;\n                if (elapsedTime > totalTime) {\n                    return 1;\n                }\n                var timesRepeated = Math.trunc(elapsedTime / durationAndDelay);\n                var timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay;\n                // TODO use %?\n                // const timeIntoCurrentRepeat = elapsedTime % durationAndDelay\n                var portion = Math.min(timeIntoCurrentRepeat / _this._duration, 1);\n                if (portion === 0 && elapsedTime === _this._duration) {\n                    return 1;\n                }\n                return portion;\n            };\n            var elapsed = calculateElapsedPortion();\n            var value = this._easingFunction(elapsed);\n            // properties transformations\n            this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value);\n            if (this._onUpdateCallback) {\n                this._onUpdateCallback(this._object, elapsed);\n            }\n            if (this._duration === 0 || elapsedTime >= this._duration) {\n                if (this._repeat > 0) {\n                    var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);\n                    if (isFinite(this._repeat)) {\n                        this._repeat -= completeCount;\n                    }\n                    // Reassign starting values, restart by making startTime = now\n                    for (property in this._valuesStartRepeat) {\n                        if (!this._yoyo && typeof this._valuesEnd[property] === 'string') {\n                            this._valuesStartRepeat[property] =\n                                // eslint-disable-next-line\n                                // @ts-ignore FIXME?\n                                this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);\n                        }\n                        if (this._yoyo) {\n                            this._swapEndStartRepeatValues(property);\n                        }\n                        this._valuesStart[property] = this._valuesStartRepeat[property];\n                    }\n                    if (this._yoyo) {\n                        this._reversed = !this._reversed;\n                    }\n                    this._startTime += durationAndDelay * completeCount;\n                    if (this._onRepeatCallback) {\n                        this._onRepeatCallback(this._object);\n                    }\n                    this._onEveryStartCallbackFired = false;\n                    return true;\n                }\n                else {\n                    if (this._onCompleteCallback) {\n                        this._onCompleteCallback(this._object);\n                    }\n                    for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n                        // Make the chained tweens start exactly at the time they should,\n                        // even if the `update()` method was called way past the duration of the tween\n                        this._chainedTweens[i].start(this._startTime + this._duration, false);\n                    }\n                    this._isPlaying = false;\n                    return false;\n                }\n            }\n            return true;\n        };\n        Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) {\n            for (var property in _valuesEnd) {\n                // Don't update properties that do not exist in the source object\n                if (_valuesStart[property] === undefined) {\n                    continue;\n                }\n                var start = _valuesStart[property] || 0;\n                var end = _valuesEnd[property];\n                var startIsArray = Array.isArray(_object[property]);\n                var endIsArray = Array.isArray(end);\n                var isInterpolationList = !startIsArray && endIsArray;\n                if (isInterpolationList) {\n                    _object[property] = this._interpolationFunction(end, value);\n                }\n                else if (typeof end === 'object' && end) {\n                    // eslint-disable-next-line\n                    // @ts-ignore FIXME?\n                    this._updateProperties(_object[property], start, end, value);\n                }\n                else {\n                    // Parses relative end values with start as base (e.g.: +10, -3)\n                    end = this._handleRelativeValue(start, end);\n                    // Protect against non numeric properties.\n                    if (typeof end === 'number') {\n                        // eslint-disable-next-line\n                        // @ts-ignore FIXME?\n                        _object[property] = start + (end - start) * value;\n                    }\n                }\n            }\n        };\n        Tween.prototype._handleRelativeValue = function (start, end) {\n            if (typeof end !== 'string') {\n                return end;\n            }\n            if (end.charAt(0) === '+' || end.charAt(0) === '-') {\n                return start + parseFloat(end);\n            }\n            return parseFloat(end);\n        };\n        Tween.prototype._swapEndStartRepeatValues = function (property) {\n            var tmp = this._valuesStartRepeat[property];\n            var endValue = this._valuesEnd[property];\n            if (typeof endValue === 'string') {\n                this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(endValue);\n            }\n            else {\n                this._valuesStartRepeat[property] = this._valuesEnd[property];\n            }\n            this._valuesEnd[property] = tmp;\n        };\n        Tween.autoStartOnUpdate = false;\n        return Tween;\n    }());\n\n    var VERSION = '25.0.0';\n\n    /**\n     * Tween.js - Licensed under the MIT license\n     * https://github.com/tweenjs/tween.js\n     * ----------------------------------------------\n     *\n     * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n     * Thank you all, you're awesome!\n     */\n    var nextId = Sequence.nextId;\n    /**\n     * Controlling groups of tweens\n     *\n     * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n     * In these cases, you may want to create your own smaller groups of tweens.\n     */\n    var TWEEN = mainGroup;\n    // This is the best way to export things in a way that's compatible with both ES\n    // Modules and CommonJS, without build hacks, and so as not to break the\n    // existing API.\n    // https://github.com/rollup/rollup/issues/1961#issuecomment-423037881\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var getAll = TWEEN.getAll.bind(TWEEN);\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var removeAll = TWEEN.removeAll.bind(TWEEN);\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var add = TWEEN.add.bind(TWEEN);\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var remove = TWEEN.remove.bind(TWEEN);\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var update = TWEEN.update.bind(TWEEN);\n    var exports$1 = {\n        Easing: Easing,\n        Group: Group,\n        Interpolation: Interpolation,\n        now: now,\n        setNow: setNow,\n        Sequence: Sequence,\n        nextId: nextId,\n        Tween: Tween,\n        VERSION: VERSION,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        getAll: getAll,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        removeAll: removeAll,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        add: add,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        remove: remove,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        update: update,\n    };\n\n    exports.Easing = Easing;\n    exports.Group = Group;\n    exports.Interpolation = Interpolation;\n    exports.Sequence = Sequence;\n    exports.Tween = Tween;\n    exports.VERSION = VERSION;\n    exports.add = add;\n    exports.default = exports$1;\n    exports.getAll = getAll;\n    exports.nextId = nextId;\n    exports.now = now;\n    exports.remove = remove;\n    exports.removeAll = removeAll;\n    exports.setNow = setNow;\n    exports.update = update;\n\n    Object.defineProperty(exports, '__esModule', { value: true });\n\n}));\n"
  },
  {
    "path": "dist/tween.cjs",
    "content": "'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\n/**\n * The Ease class provides a collection of easing functions for use with tween.js.\n */\nvar Easing = Object.freeze({\n    Linear: Object.freeze({\n        None: function (amount) {\n            return amount;\n        },\n        In: function (amount) {\n            return amount;\n        },\n        Out: function (amount) {\n            return amount;\n        },\n        InOut: function (amount) {\n            return amount;\n        },\n    }),\n    Quadratic: Object.freeze({\n        In: function (amount) {\n            return amount * amount;\n        },\n        Out: function (amount) {\n            return amount * (2 - amount);\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return 0.5 * amount * amount;\n            }\n            return -0.5 * (--amount * (amount - 2) - 1);\n        },\n    }),\n    Cubic: Object.freeze({\n        In: function (amount) {\n            return amount * amount * amount;\n        },\n        Out: function (amount) {\n            return --amount * amount * amount + 1;\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return 0.5 * amount * amount * amount;\n            }\n            return 0.5 * ((amount -= 2) * amount * amount + 2);\n        },\n    }),\n    Quartic: Object.freeze({\n        In: function (amount) {\n            return amount * amount * amount * amount;\n        },\n        Out: function (amount) {\n            return 1 - --amount * amount * amount * amount;\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return 0.5 * amount * amount * amount * amount;\n            }\n            return -0.5 * ((amount -= 2) * amount * amount * amount - 2);\n        },\n    }),\n    Quintic: Object.freeze({\n        In: function (amount) {\n            return amount * amount * amount * amount * amount;\n        },\n        Out: function (amount) {\n            return --amount * amount * amount * amount * amount + 1;\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return 0.5 * amount * amount * amount * amount * amount;\n            }\n            return 0.5 * ((amount -= 2) * amount * amount * amount * amount + 2);\n        },\n    }),\n    Sinusoidal: Object.freeze({\n        In: function (amount) {\n            return 1 - Math.sin(((1.0 - amount) * Math.PI) / 2);\n        },\n        Out: function (amount) {\n            return Math.sin((amount * Math.PI) / 2);\n        },\n        InOut: function (amount) {\n            return 0.5 * (1 - Math.sin(Math.PI * (0.5 - amount)));\n        },\n    }),\n    Exponential: Object.freeze({\n        In: function (amount) {\n            return amount === 0 ? 0 : Math.pow(1024, amount - 1);\n        },\n        Out: function (amount) {\n            return amount === 1 ? 1 : 1 - Math.pow(2, -10 * amount);\n        },\n        InOut: function (amount) {\n            if (amount === 0) {\n                return 0;\n            }\n            if (amount === 1) {\n                return 1;\n            }\n            if ((amount *= 2) < 1) {\n                return 0.5 * Math.pow(1024, amount - 1);\n            }\n            return 0.5 * (-Math.pow(2, -10 * (amount - 1)) + 2);\n        },\n    }),\n    Circular: Object.freeze({\n        In: function (amount) {\n            return 1 - Math.sqrt(1 - amount * amount);\n        },\n        Out: function (amount) {\n            return Math.sqrt(1 - --amount * amount);\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return -0.5 * (Math.sqrt(1 - amount * amount) - 1);\n            }\n            return 0.5 * (Math.sqrt(1 - (amount -= 2) * amount) + 1);\n        },\n    }),\n    Elastic: Object.freeze({\n        In: function (amount) {\n            if (amount === 0) {\n                return 0;\n            }\n            if (amount === 1) {\n                return 1;\n            }\n            return -Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);\n        },\n        Out: function (amount) {\n            if (amount === 0) {\n                return 0;\n            }\n            if (amount === 1) {\n                return 1;\n            }\n            return Math.pow(2, -10 * amount) * Math.sin((amount - 0.1) * 5 * Math.PI) + 1;\n        },\n        InOut: function (amount) {\n            if (amount === 0) {\n                return 0;\n            }\n            if (amount === 1) {\n                return 1;\n            }\n            amount *= 2;\n            if (amount < 1) {\n                return -0.5 * Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);\n            }\n            return 0.5 * Math.pow(2, -10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI) + 1;\n        },\n    }),\n    Back: Object.freeze({\n        In: function (amount) {\n            var s = 1.70158;\n            return amount === 1 ? 1 : amount * amount * ((s + 1) * amount - s);\n        },\n        Out: function (amount) {\n            var s = 1.70158;\n            return amount === 0 ? 0 : --amount * amount * ((s + 1) * amount + s) + 1;\n        },\n        InOut: function (amount) {\n            var s = 1.70158 * 1.525;\n            if ((amount *= 2) < 1) {\n                return 0.5 * (amount * amount * ((s + 1) * amount - s));\n            }\n            return 0.5 * ((amount -= 2) * amount * ((s + 1) * amount + s) + 2);\n        },\n    }),\n    Bounce: Object.freeze({\n        In: function (amount) {\n            return 1 - Easing.Bounce.Out(1 - amount);\n        },\n        Out: function (amount) {\n            if (amount < 1 / 2.75) {\n                return 7.5625 * amount * amount;\n            }\n            else if (amount < 2 / 2.75) {\n                return 7.5625 * (amount -= 1.5 / 2.75) * amount + 0.75;\n            }\n            else if (amount < 2.5 / 2.75) {\n                return 7.5625 * (amount -= 2.25 / 2.75) * amount + 0.9375;\n            }\n            else {\n                return 7.5625 * (amount -= 2.625 / 2.75) * amount + 0.984375;\n            }\n        },\n        InOut: function (amount) {\n            if (amount < 0.5) {\n                return Easing.Bounce.In(amount * 2) * 0.5;\n            }\n            return Easing.Bounce.Out(amount * 2 - 1) * 0.5 + 0.5;\n        },\n    }),\n    generatePow: function (power) {\n        if (power === void 0) { power = 4; }\n        power = power < Number.EPSILON ? Number.EPSILON : power;\n        power = power > 10000 ? 10000 : power;\n        return {\n            In: function (amount) {\n                return Math.pow(amount, power);\n            },\n            Out: function (amount) {\n                return 1 - Math.pow((1 - amount), power);\n            },\n            InOut: function (amount) {\n                if (amount < 0.5) {\n                    return Math.pow((amount * 2), power) / 2;\n                }\n                return (1 - Math.pow((2 - amount * 2), power)) / 2 + 0.5;\n            },\n        };\n    },\n});\n\nvar _nowFunc = function () { return performance.now(); };\nvar now = function () {\n    return _nowFunc();\n};\nfunction setNow(nowFunction) {\n    _nowFunc = nowFunction;\n}\n\n/**\n * Controlling groups of tweens\n *\n * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n * In these cases, you may want to create your own smaller groups of tween\n */\nvar Group = /** @class */ (function () {\n    function Group() {\n        var tweens = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            tweens[_i] = arguments[_i];\n        }\n        this._tweens = {};\n        this._tweensAddedDuringUpdate = {};\n        this.add.apply(this, tweens);\n    }\n    Group.prototype.getAll = function () {\n        var _this = this;\n        return Object.keys(this._tweens).map(function (tweenId) { return _this._tweens[tweenId]; });\n    };\n    Group.prototype.removeAll = function () {\n        this._tweens = {};\n    };\n    Group.prototype.add = function () {\n        var _a;\n        var tweens = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            tweens[_i] = arguments[_i];\n        }\n        for (var _b = 0, tweens_1 = tweens; _b < tweens_1.length; _b++) {\n            var tween = tweens_1[_b];\n            // Remove from any other group first, a tween can only be in one group at a time.\n            // @ts-expect-error library internal access\n            (_a = tween._group) === null || _a === void 0 ? void 0 : _a.remove(tween);\n            // @ts-expect-error library internal access\n            tween._group = this;\n            this._tweens[tween.getId()] = tween;\n            this._tweensAddedDuringUpdate[tween.getId()] = tween;\n        }\n    };\n    Group.prototype.remove = function () {\n        var tweens = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            tweens[_i] = arguments[_i];\n        }\n        for (var _a = 0, tweens_2 = tweens; _a < tweens_2.length; _a++) {\n            var tween = tweens_2[_a];\n            // @ts-expect-error library internal access\n            tween._group = undefined;\n            delete this._tweens[tween.getId()];\n            delete this._tweensAddedDuringUpdate[tween.getId()];\n        }\n    };\n    /** Return true if all tweens in the group are not paused or playing. */\n    Group.prototype.allStopped = function () {\n        return this.getAll().every(function (tween) { return !tween.isPlaying(); });\n    };\n    Group.prototype.update = function (time, preserve) {\n        if (time === void 0) { time = now(); }\n        if (preserve === void 0) { preserve = true; }\n        var tweenIds = Object.keys(this._tweens);\n        if (tweenIds.length === 0)\n            return;\n        // Tweens are updated in \"batches\". If you add a new tween during an\n        // update, then the new tween will be updated in the next batch.\n        // If you remove a tween during an update, it may or may not be updated.\n        // However, if the removed tween was added during the current batch,\n        // then it will not be updated.\n        while (tweenIds.length > 0) {\n            this._tweensAddedDuringUpdate = {};\n            for (var i = 0; i < tweenIds.length; i++) {\n                var tween = this._tweens[tweenIds[i]];\n                var autoStart = !preserve;\n                if (tween && tween.update(time, autoStart) === false && !preserve)\n                    this.remove(tween);\n            }\n            tweenIds = Object.keys(this._tweensAddedDuringUpdate);\n        }\n    };\n    Group.prototype.onComplete = function (callback) {\n        var group = this.getAll();\n        group.forEach(function (tween) {\n            var prevCallback = tween.getCompleteCallback();\n            tween.onComplete(function () {\n                prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);\n                // After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.\n                var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });\n                if (completedGroup.length === group.length - 1)\n                    callback(group);\n            });\n        });\n    };\n    return Group;\n}());\n\n/**\n *\n */\nvar Interpolation = {\n    Linear: function (v, k) {\n        var m = v.length - 1;\n        var f = m * k;\n        var i = Math.floor(f);\n        var fn = Interpolation.Utils.Linear;\n        if (k < 0) {\n            return fn(v[0], v[1], f);\n        }\n        if (k > 1) {\n            return fn(v[m], v[m - 1], m - f);\n        }\n        return fn(v[i], v[i + 1 > m ? m : i + 1], f - i);\n    },\n    Bezier: function (v, k) {\n        var b = 0;\n        var n = v.length - 1;\n        var pw = Math.pow;\n        var bn = Interpolation.Utils.Bernstein;\n        for (var i = 0; i <= n; i++) {\n            b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);\n        }\n        return b;\n    },\n    CatmullRom: function (v, k) {\n        var m = v.length - 1;\n        var f = m * k;\n        var i = Math.floor(f);\n        var fn = Interpolation.Utils.CatmullRom;\n        if (v[0] === v[m]) {\n            if (k < 0) {\n                i = Math.floor((f = m * (1 + k)));\n            }\n            return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);\n        }\n        else {\n            if (k < 0) {\n                return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]);\n            }\n            if (k > 1) {\n                return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);\n            }\n            return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);\n        }\n    },\n    Utils: {\n        Linear: function (p0, p1, t) {\n            return (p1 - p0) * t + p0;\n        },\n        Bernstein: function (n, i) {\n            var fc = Interpolation.Utils.Factorial;\n            return fc(n) / fc(i) / fc(n - i);\n        },\n        Factorial: (function () {\n            var a = [1];\n            return function (n) {\n                var s = 1;\n                if (a[n]) {\n                    return a[n];\n                }\n                for (var i = n; i > 1; i--) {\n                    s *= i;\n                }\n                a[n] = s;\n                return s;\n            };\n        })(),\n        CatmullRom: function (p0, p1, p2, p3, t) {\n            var v0 = (p2 - p0) * 0.5;\n            var v1 = (p3 - p1) * 0.5;\n            var t2 = t * t;\n            var t3 = t * t2;\n            return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;\n        },\n    },\n};\n\n/**\n * Utils\n */\nvar Sequence = /** @class */ (function () {\n    function Sequence() {\n    }\n    Sequence.nextId = function () {\n        return Sequence._nextId++;\n    };\n    Sequence._nextId = 0;\n    return Sequence;\n}());\n\nvar mainGroup = new Group();\n\n/**\n * Tween.js - Licensed under the MIT license\n * https://github.com/tweenjs/tween.js\n * ----------------------------------------------\n *\n * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n * Thank you all, you're awesome!\n */\nvar Tween = /** @class */ (function () {\n    function Tween(object, group) {\n        this._isPaused = false;\n        this._pauseStart = 0;\n        this._valuesStart = {};\n        this._valuesEnd = {};\n        this._valuesStartRepeat = {};\n        this._duration = 1000;\n        this._isDynamic = false;\n        this._initialRepeat = 0;\n        this._repeat = 0;\n        this._yoyo = false;\n        this._isPlaying = false;\n        this._reversed = false;\n        this._delayTime = 0;\n        this._startTime = 0;\n        this._easingFunction = Easing.Linear.None;\n        this._interpolationFunction = Interpolation.Linear;\n        // eslint-disable-next-line\n        this._chainedTweens = [];\n        this._onStartCallbackFired = false;\n        this._onEveryStartCallbackFired = false;\n        this._id = Sequence.nextId();\n        this._isChainStopped = false;\n        this._propertiesAreSetUp = false;\n        this._goToEnd = false;\n        this._object = object;\n        if (typeof group === 'object') {\n            this._group = group;\n            group.add(this);\n        }\n        // Use \"true\" to restore old behavior (will be removed in future release).\n        else if (group === true) {\n            this._group = mainGroup;\n            mainGroup.add(this);\n        }\n    }\n    Tween.prototype.getId = function () {\n        return this._id;\n    };\n    Tween.prototype.getCompleteCallback = function () {\n        return this._onCompleteCallback;\n    };\n    Tween.prototype.isPlaying = function () {\n        return this._isPlaying;\n    };\n    Tween.prototype.isPaused = function () {\n        return this._isPaused;\n    };\n    Tween.prototype.getDuration = function () {\n        return this._duration;\n    };\n    Tween.prototype.to = function (target, duration) {\n        if (duration === void 0) { duration = 1000; }\n        if (this._isPlaying)\n            throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.');\n        this._valuesEnd = target;\n        this._propertiesAreSetUp = false;\n        this._duration = duration < 0 ? 0 : duration;\n        return this;\n    };\n    Tween.prototype.duration = function (duration) {\n        if (duration === void 0) { duration = 1000; }\n        this._duration = duration < 0 ? 0 : duration;\n        return this;\n    };\n    Tween.prototype.dynamic = function (dynamic) {\n        if (dynamic === void 0) { dynamic = false; }\n        this._isDynamic = dynamic;\n        return this;\n    };\n    Tween.prototype.start = function (time, overrideStartingValues) {\n        if (time === void 0) { time = now(); }\n        if (overrideStartingValues === void 0) { overrideStartingValues = false; }\n        if (this._isPlaying) {\n            return this;\n        }\n        this._repeat = this._initialRepeat;\n        if (this._reversed) {\n            // If we were reversed (f.e. using the yoyo feature) then we need to\n            // flip the tween direction back to forward.\n            this._reversed = false;\n            for (var property in this._valuesStartRepeat) {\n                this._swapEndStartRepeatValues(property);\n                this._valuesStart[property] = this._valuesStartRepeat[property];\n            }\n        }\n        this._isPlaying = true;\n        this._isPaused = false;\n        this._onStartCallbackFired = false;\n        this._onEveryStartCallbackFired = false;\n        this._isChainStopped = false;\n        this._startTime = time;\n        this._startTime += this._delayTime;\n        if (!this._propertiesAreSetUp || overrideStartingValues) {\n            this._propertiesAreSetUp = true;\n            // If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n            if (!this._isDynamic) {\n                var tmp = {};\n                for (var prop in this._valuesEnd)\n                    tmp[prop] = this._valuesEnd[prop];\n                this._valuesEnd = tmp;\n            }\n            this._setupProperties(this._object, this._valuesStart, this._valuesEnd, this._valuesStartRepeat, overrideStartingValues);\n        }\n        return this;\n    };\n    Tween.prototype.startFromCurrentValues = function (time) {\n        return this.start(time, true);\n    };\n    Tween.prototype._setupProperties = function (_object, _valuesStart, _valuesEnd, _valuesStartRepeat, overrideStartingValues) {\n        for (var property in _valuesEnd) {\n            var startValue = _object[property];\n            var startValueIsArray = Array.isArray(startValue);\n            var propType = startValueIsArray ? 'array' : typeof startValue;\n            var isInterpolationList = !startValueIsArray && Array.isArray(_valuesEnd[property]);\n            // If `to()` specifies a property that doesn't exist in the source object,\n            // we should not set that property in the object\n            if (propType === 'undefined' || propType === 'function') {\n                continue;\n            }\n            // Check if an Array was provided as property value\n            if (isInterpolationList) {\n                var endValues = _valuesEnd[property];\n                if (endValues.length === 0) {\n                    continue;\n                }\n                // Handle an array of relative values.\n                // Creates a local copy of the Array with the start value at the front\n                var temp = [startValue];\n                for (var i = 0, l = endValues.length; i < l; i += 1) {\n                    var value = this._handleRelativeValue(startValue, endValues[i]);\n                    if (isNaN(value)) {\n                        isInterpolationList = false;\n                        console.warn('Found invalid interpolation list. Skipping.');\n                        break;\n                    }\n                    temp.push(value);\n                }\n                if (isInterpolationList) {\n                    // if (_valuesStart[property] === undefined) { // handle end values only the first time. NOT NEEDED? setupProperties is now guarded by _propertiesAreSetUp.\n                    _valuesEnd[property] = temp;\n                    // }\n                }\n            }\n            // handle the deepness of the values\n            if ((propType === 'object' || startValueIsArray) && startValue && !isInterpolationList) {\n                _valuesStart[property] = startValueIsArray ? [] : {};\n                var nestedObject = startValue;\n                for (var prop in nestedObject) {\n                    _valuesStart[property][prop] = nestedObject[prop];\n                }\n                // TODO? repeat nested values? And yoyo? And array values?\n                _valuesStartRepeat[property] = startValueIsArray ? [] : {};\n                var endValues = _valuesEnd[property];\n                // If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n                if (!this._isDynamic) {\n                    var tmp = {};\n                    for (var prop in endValues)\n                        tmp[prop] = endValues[prop];\n                    _valuesEnd[property] = endValues = tmp;\n                }\n                this._setupProperties(nestedObject, _valuesStart[property], endValues, _valuesStartRepeat[property], overrideStartingValues);\n            }\n            else {\n                // Save the starting value, but only once unless override is requested.\n                if (typeof _valuesStart[property] === 'undefined' || overrideStartingValues) {\n                    _valuesStart[property] = startValue;\n                }\n                if (!startValueIsArray) {\n                    // eslint-disable-next-line\n                    // @ts-ignore FIXME?\n                    _valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings\n                }\n                if (isInterpolationList) {\n                    // eslint-disable-next-line\n                    // @ts-ignore FIXME?\n                    _valuesStartRepeat[property] = _valuesEnd[property].slice().reverse();\n                }\n                else {\n                    _valuesStartRepeat[property] = _valuesStart[property] || 0;\n                }\n            }\n        }\n    };\n    Tween.prototype.stop = function () {\n        if (!this._isChainStopped) {\n            this._isChainStopped = true;\n            this.stopChainedTweens();\n        }\n        if (!this._isPlaying) {\n            return this;\n        }\n        this._isPlaying = false;\n        this._isPaused = false;\n        if (this._onStopCallback) {\n            this._onStopCallback(this._object);\n        }\n        return this;\n    };\n    Tween.prototype.end = function () {\n        this._goToEnd = true;\n        this.update(this._startTime + this._duration);\n        return this;\n    };\n    Tween.prototype.pause = function (time) {\n        if (time === void 0) { time = now(); }\n        if (this._isPaused || !this._isPlaying) {\n            return this;\n        }\n        this._isPaused = true;\n        this._pauseStart = time;\n        return this;\n    };\n    Tween.prototype.resume = function (time) {\n        if (time === void 0) { time = now(); }\n        if (!this._isPaused || !this._isPlaying) {\n            return this;\n        }\n        this._isPaused = false;\n        this._startTime += time - this._pauseStart;\n        this._pauseStart = 0;\n        return this;\n    };\n    Tween.prototype.stopChainedTweens = function () {\n        for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n            this._chainedTweens[i].stop();\n        }\n        return this;\n    };\n    Tween.prototype.group = function (group) {\n        if (!group) {\n            console.warn('tween.group() without args has been removed, use group.add(tween) instead.');\n            return this;\n        }\n        group.add(this);\n        return this;\n    };\n    /**\n     * Removes the tween from whichever group it is in.\n     */\n    Tween.prototype.remove = function () {\n        var _a;\n        (_a = this._group) === null || _a === void 0 ? void 0 : _a.remove(this);\n        return this;\n    };\n    Tween.prototype.delay = function (amount) {\n        if (amount === void 0) { amount = 0; }\n        this._delayTime = amount;\n        return this;\n    };\n    Tween.prototype.repeat = function (times) {\n        if (times === void 0) { times = 0; }\n        this._initialRepeat = times;\n        this._repeat = times;\n        return this;\n    };\n    Tween.prototype.repeatDelay = function (amount) {\n        this._repeatDelayTime = amount;\n        return this;\n    };\n    Tween.prototype.yoyo = function (yoyo) {\n        if (yoyo === void 0) { yoyo = false; }\n        this._yoyo = yoyo;\n        return this;\n    };\n    Tween.prototype.easing = function (easingFunction) {\n        if (easingFunction === void 0) { easingFunction = Easing.Linear.None; }\n        this._easingFunction = easingFunction;\n        return this;\n    };\n    Tween.prototype.interpolation = function (interpolationFunction) {\n        if (interpolationFunction === void 0) { interpolationFunction = Interpolation.Linear; }\n        this._interpolationFunction = interpolationFunction;\n        return this;\n    };\n    // eslint-disable-next-line\n    Tween.prototype.chain = function () {\n        var tweens = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            tweens[_i] = arguments[_i];\n        }\n        this._chainedTweens = tweens;\n        return this;\n    };\n    Tween.prototype.onStart = function (callback) {\n        this._onStartCallback = callback;\n        return this;\n    };\n    Tween.prototype.onEveryStart = function (callback) {\n        this._onEveryStartCallback = callback;\n        return this;\n    };\n    Tween.prototype.onUpdate = function (callback) {\n        this._onUpdateCallback = callback;\n        return this;\n    };\n    Tween.prototype.onRepeat = function (callback) {\n        this._onRepeatCallback = callback;\n        return this;\n    };\n    Tween.prototype.onComplete = function (callback) {\n        this._onCompleteCallback = callback;\n        return this;\n    };\n    Tween.prototype.onStop = function (callback) {\n        this._onStopCallback = callback;\n        return this;\n    };\n    /**\n     * @returns true if the tween is still playing after the update, false\n     * otherwise (calling update on a paused tween still returns true because\n     * it is still playing, just paused).\n     *\n     * @param autoStart - When true, calling update will implicitly call start()\n     * as well. Note, if you stop() or end() the tween, but are still calling\n     * update(), it will start again!\n     */\n    Tween.prototype.update = function (time, autoStart) {\n        var _this = this;\n        var _a;\n        if (time === void 0) { time = now(); }\n        if (autoStart === void 0) { autoStart = Tween.autoStartOnUpdate; }\n        if (this._isPaused)\n            return true;\n        var property;\n        if (!this._goToEnd && !this._isPlaying) {\n            if (autoStart)\n                this.start(time, true);\n            else\n                return false;\n        }\n        this._goToEnd = false;\n        if (time < this._startTime) {\n            return true;\n        }\n        if (this._onStartCallbackFired === false) {\n            if (this._onStartCallback) {\n                this._onStartCallback(this._object);\n            }\n            this._onStartCallbackFired = true;\n        }\n        if (this._onEveryStartCallbackFired === false) {\n            if (this._onEveryStartCallback) {\n                this._onEveryStartCallback(this._object);\n            }\n            this._onEveryStartCallbackFired = true;\n        }\n        var elapsedTime = time - this._startTime;\n        var durationAndDelay = this._duration + ((_a = this._repeatDelayTime) !== null && _a !== void 0 ? _a : this._delayTime);\n        var totalTime = this._duration + this._repeat * durationAndDelay;\n        var calculateElapsedPortion = function () {\n            if (_this._duration === 0)\n                return 1;\n            if (elapsedTime > totalTime) {\n                return 1;\n            }\n            var timesRepeated = Math.trunc(elapsedTime / durationAndDelay);\n            var timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay;\n            // TODO use %?\n            // const timeIntoCurrentRepeat = elapsedTime % durationAndDelay\n            var portion = Math.min(timeIntoCurrentRepeat / _this._duration, 1);\n            if (portion === 0 && elapsedTime === _this._duration) {\n                return 1;\n            }\n            return portion;\n        };\n        var elapsed = calculateElapsedPortion();\n        var value = this._easingFunction(elapsed);\n        // properties transformations\n        this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value);\n        if (this._onUpdateCallback) {\n            this._onUpdateCallback(this._object, elapsed);\n        }\n        if (this._duration === 0 || elapsedTime >= this._duration) {\n            if (this._repeat > 0) {\n                var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);\n                if (isFinite(this._repeat)) {\n                    this._repeat -= completeCount;\n                }\n                // Reassign starting values, restart by making startTime = now\n                for (property in this._valuesStartRepeat) {\n                    if (!this._yoyo && typeof this._valuesEnd[property] === 'string') {\n                        this._valuesStartRepeat[property] =\n                            // eslint-disable-next-line\n                            // @ts-ignore FIXME?\n                            this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);\n                    }\n                    if (this._yoyo) {\n                        this._swapEndStartRepeatValues(property);\n                    }\n                    this._valuesStart[property] = this._valuesStartRepeat[property];\n                }\n                if (this._yoyo) {\n                    this._reversed = !this._reversed;\n                }\n                this._startTime += durationAndDelay * completeCount;\n                if (this._onRepeatCallback) {\n                    this._onRepeatCallback(this._object);\n                }\n                this._onEveryStartCallbackFired = false;\n                return true;\n            }\n            else {\n                if (this._onCompleteCallback) {\n                    this._onCompleteCallback(this._object);\n                }\n                for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n                    // Make the chained tweens start exactly at the time they should,\n                    // even if the `update()` method was called way past the duration of the tween\n                    this._chainedTweens[i].start(this._startTime + this._duration, false);\n                }\n                this._isPlaying = false;\n                return false;\n            }\n        }\n        return true;\n    };\n    Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) {\n        for (var property in _valuesEnd) {\n            // Don't update properties that do not exist in the source object\n            if (_valuesStart[property] === undefined) {\n                continue;\n            }\n            var start = _valuesStart[property] || 0;\n            var end = _valuesEnd[property];\n            var startIsArray = Array.isArray(_object[property]);\n            var endIsArray = Array.isArray(end);\n            var isInterpolationList = !startIsArray && endIsArray;\n            if (isInterpolationList) {\n                _object[property] = this._interpolationFunction(end, value);\n            }\n            else if (typeof end === 'object' && end) {\n                // eslint-disable-next-line\n                // @ts-ignore FIXME?\n                this._updateProperties(_object[property], start, end, value);\n            }\n            else {\n                // Parses relative end values with start as base (e.g.: +10, -3)\n                end = this._handleRelativeValue(start, end);\n                // Protect against non numeric properties.\n                if (typeof end === 'number') {\n                    // eslint-disable-next-line\n                    // @ts-ignore FIXME?\n                    _object[property] = start + (end - start) * value;\n                }\n            }\n        }\n    };\n    Tween.prototype._handleRelativeValue = function (start, end) {\n        if (typeof end !== 'string') {\n            return end;\n        }\n        if (end.charAt(0) === '+' || end.charAt(0) === '-') {\n            return start + parseFloat(end);\n        }\n        return parseFloat(end);\n    };\n    Tween.prototype._swapEndStartRepeatValues = function (property) {\n        var tmp = this._valuesStartRepeat[property];\n        var endValue = this._valuesEnd[property];\n        if (typeof endValue === 'string') {\n            this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(endValue);\n        }\n        else {\n            this._valuesStartRepeat[property] = this._valuesEnd[property];\n        }\n        this._valuesEnd[property] = tmp;\n    };\n    Tween.autoStartOnUpdate = false;\n    return Tween;\n}());\n\nvar VERSION = '25.0.0';\n\n/**\n * Tween.js - Licensed under the MIT license\n * https://github.com/tweenjs/tween.js\n * ----------------------------------------------\n *\n * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n * Thank you all, you're awesome!\n */\nvar nextId = Sequence.nextId;\n/**\n * Controlling groups of tweens\n *\n * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n * In these cases, you may want to create your own smaller groups of tweens.\n */\nvar TWEEN = mainGroup;\n// This is the best way to export things in a way that's compatible with both ES\n// Modules and CommonJS, without build hacks, and so as not to break the\n// existing API.\n// https://github.com/rollup/rollup/issues/1961#issuecomment-423037881\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar getAll = TWEEN.getAll.bind(TWEEN);\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar removeAll = TWEEN.removeAll.bind(TWEEN);\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar add = TWEEN.add.bind(TWEEN);\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar remove = TWEEN.remove.bind(TWEEN);\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar update = TWEEN.update.bind(TWEEN);\nvar exports$1 = {\n    Easing: Easing,\n    Group: Group,\n    Interpolation: Interpolation,\n    now: now,\n    setNow: setNow,\n    Sequence: Sequence,\n    nextId: nextId,\n    Tween: Tween,\n    VERSION: VERSION,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    getAll: getAll,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    removeAll: removeAll,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    add: add,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    remove: remove,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    update: update,\n};\n\nexports.Easing = Easing;\nexports.Group = Group;\nexports.Interpolation = Interpolation;\nexports.Sequence = Sequence;\nexports.Tween = Tween;\nexports.VERSION = VERSION;\nexports.add = add;\nexports.default = exports$1;\nexports.getAll = getAll;\nexports.nextId = nextId;\nexports.now = now;\nexports.remove = remove;\nexports.removeAll = removeAll;\nexports.setNow = setNow;\nexports.update = update;\n"
  },
  {
    "path": "dist/tween.d.ts",
    "content": "type EasingFunction = (amount: number) => number;\ntype EasingFunctionGroup = {\n    In: EasingFunction;\n    Out: EasingFunction;\n    InOut: EasingFunction;\n};\n/**\n * The Ease class provides a collection of easing functions for use with tween.js.\n */\ndeclare const Easing: Readonly<{\n    Linear: Readonly<EasingFunctionGroup & {\n        None: EasingFunction;\n    }>;\n    Quadratic: Readonly<EasingFunctionGroup>;\n    Cubic: Readonly<EasingFunctionGroup>;\n    Quartic: Readonly<EasingFunctionGroup>;\n    Quintic: Readonly<EasingFunctionGroup>;\n    Sinusoidal: Readonly<EasingFunctionGroup>;\n    Exponential: Readonly<EasingFunctionGroup>;\n    Circular: Readonly<EasingFunctionGroup>;\n    Elastic: Readonly<EasingFunctionGroup>;\n    Back: Readonly<EasingFunctionGroup>;\n    Bounce: Readonly<EasingFunctionGroup>;\n    generatePow(power?: number): EasingFunctionGroup;\n}>;\n\n/**\n *\n */\ntype InterpolationFunction = (v: number[], k: number) => number;\n/**\n *\n */\ndeclare const Interpolation: {\n    Linear: (v: number[], k: number) => number;\n    Bezier: (v: number[], k: number) => number;\n    CatmullRom: (v: number[], k: number) => number;\n    Utils: {\n        Linear: (p0: number, p1: number, t: number) => number;\n        Bernstein: (n: number, i: number) => number;\n        Factorial: (n: number) => number;\n        CatmullRom: (p0: number, p1: number, p2: number, p3: number, t: number) => number;\n    };\n};\n\n/**\n * Tween.js - Licensed under the MIT license\n * https://github.com/tweenjs/tween.js\n * ----------------------------------------------\n *\n * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n * Thank you all, you're awesome!\n */\n\ndeclare class Tween<T extends UnknownProps = any> {\n    static autoStartOnUpdate: boolean;\n    private _isPaused;\n    private _pauseStart;\n    private _valuesStart;\n    private _valuesEnd;\n    private _valuesStartRepeat;\n    private _duration;\n    private _isDynamic;\n    private _initialRepeat;\n    private _repeat;\n    private _repeatDelayTime?;\n    private _yoyo;\n    private _isPlaying;\n    private _reversed;\n    private _delayTime;\n    private _startTime;\n    private _easingFunction;\n    private _interpolationFunction;\n    private _chainedTweens;\n    private _onStartCallback?;\n    private _onStartCallbackFired;\n    private _onEveryStartCallback?;\n    private _onEveryStartCallbackFired;\n    private _onUpdateCallback?;\n    private _onRepeatCallback?;\n    private _onCompleteCallback?;\n    private _onStopCallback?;\n    private _id;\n    private _isChainStopped;\n    private _propertiesAreSetUp;\n    private _object;\n    private _group?;\n    /**\n     * @param object - The object whose properties this Tween will animate.\n     * @param group - The object whose properties this Tween will animate.\n     */\n    constructor(object: T, group?: Group);\n    /**\n     * @deprecated The group parameter is now deprecated, instead use `new\n     * Tween(object)` then `group.add(tween)` to add a tween to a group. Use\n     * `new Tween(object, true)` to restore the old behavior for now, but this\n     * will be removed in the future.\n     */\n    constructor(object: T, group: true);\n    getId(): number;\n    getCompleteCallback(): ((object: T) => void) | undefined;\n    isPlaying(): boolean;\n    isPaused(): boolean;\n    getDuration(): number;\n    to(target: UnknownProps, duration?: number): this;\n    duration(duration?: number): this;\n    dynamic(dynamic?: boolean): this;\n    start(time?: number, overrideStartingValues?: boolean): this;\n    startFromCurrentValues(time?: number): this;\n    private _setupProperties;\n    stop(): this;\n    end(): this;\n    pause(time?: number): this;\n    resume(time?: number): this;\n    stopChainedTweens(): this;\n    /**\n     * Removes the tween from the current group it is in, if any, then adds the\n     * tween to the specified `group`.\n     */\n    group(group: Group): this;\n    /**\n     * @deprecated The argless call signature has been removed. Use\n     * `tween.group(group)` or `group.add(tween)`, instead.\n     */\n    group(): this;\n    /**\n     * Removes the tween from whichever group it is in.\n     */\n    remove(): this;\n    delay(amount?: number): this;\n    repeat(times?: number): this;\n    repeatDelay(amount?: number): this;\n    yoyo(yoyo?: boolean): this;\n    easing(easingFunction?: EasingFunction): this;\n    interpolation(interpolationFunction?: InterpolationFunction): this;\n    chain(...tweens: Array<Tween<any>>): this;\n    onStart(callback?: (object: T) => void): this;\n    onEveryStart(callback?: (object: T) => void): this;\n    onUpdate(callback?: (object: T, elapsed: number) => void): this;\n    onRepeat(callback?: (object: T) => void): this;\n    onComplete(callback?: (object: T) => void): this;\n    onStop(callback?: (object: T) => void): this;\n    private _goToEnd;\n    /**\n     * @returns true if the tween is still playing after the update, false\n     * otherwise (calling update on a paused tween still returns true because\n     * it is still playing, just paused).\n     *\n     * @param autoStart - When true, calling update will implicitly call start()\n     * as well. Note, if you stop() or end() the tween, but are still calling\n     * update(), it will start again!\n     */\n    update(time?: number, autoStart?: boolean): boolean;\n    private _updateProperties;\n    private _handleRelativeValue;\n    private _swapEndStartRepeatValues;\n}\ntype UnknownProps = Record<string, any>;\n\n/**\n * Controlling groups of tweens\n *\n * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n * In these cases, you may want to create your own smaller groups of tween\n */\ndeclare class Group {\n    private _tweens;\n    private _tweensAddedDuringUpdate;\n    constructor(...tweens: Tween[]);\n    getAll(): Array<Tween>;\n    removeAll(): void;\n    add(...tweens: Tween[]): void;\n    remove(...tweens: Tween[]): void;\n    /** Return true if all tweens in the group are not paused or playing. */\n    allStopped(): boolean;\n    update(time?: number): void;\n    /**\n     * @deprecated The `preserve` parameter is now defaulted to `true` and will\n     * be removed in a future major release, at which point all tweens of a\n     * group will always be preserved when calling update. To migrate, always\n     * use `group.add(tween)` or `group.remove(tween)` to manually add or remove\n     * tweens, and do not rely on tweens being automatically added or removed.\n     */\n    update(time?: number, preserve?: boolean): void;\n    onComplete(callback: (object: Tween[]) => void): void;\n}\n\ndeclare const now: () => number;\ndeclare function setNow(nowFunction: Function): void;\n\n/**\n * Utils\n */\ndeclare class Sequence {\n    private static _nextId;\n    static nextId(): number;\n}\n\ndeclare const VERSION = \"25.0.0\";\n\ndeclare const nextId: typeof Sequence.nextId;\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\ndeclare const getAll: () => Tween<any>[];\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\ndeclare const removeAll: () => void;\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\ndeclare const add: (...tweens: Tween<any>[]) => void;\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\ndeclare const remove: (...tweens: Tween<any>[]) => void;\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\ndeclare const update: {\n    (time?: number | undefined): void;\n    (time?: number | undefined, preserve?: boolean | undefined): void;\n};\n\ndeclare const exports: {\n    Easing: Readonly<{\n        Linear: Readonly<EasingFunctionGroup & {\n            None: EasingFunction;\n        }>;\n        Quadratic: Readonly<EasingFunctionGroup>;\n        Cubic: Readonly<EasingFunctionGroup>;\n        Quartic: Readonly<EasingFunctionGroup>;\n        Quintic: Readonly<EasingFunctionGroup>;\n        Sinusoidal: Readonly<EasingFunctionGroup>;\n        Exponential: Readonly<EasingFunctionGroup>;\n        Circular: Readonly<EasingFunctionGroup>;\n        Elastic: Readonly<EasingFunctionGroup>;\n        Back: Readonly<EasingFunctionGroup>;\n        Bounce: Readonly<EasingFunctionGroup>;\n        generatePow(power?: number): EasingFunctionGroup;\n    }>;\n    Group: typeof Group;\n    Interpolation: {\n        Linear: (v: number[], k: number) => number;\n        Bezier: (v: number[], k: number) => number;\n        CatmullRom: (v: number[], k: number) => number;\n        Utils: {\n            Linear: (p0: number, p1: number, t: number) => number;\n            Bernstein: (n: number, i: number) => number;\n            Factorial: (n: number) => number;\n            CatmullRom: (p0: number, p1: number, p2: number, p3: number, t: number) => number;\n        };\n    };\n    now: () => number;\n    setNow: typeof setNow;\n    Sequence: typeof Sequence;\n    nextId: typeof Sequence.nextId;\n    Tween: typeof Tween;\n    VERSION: string;\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    getAll: () => Tween<any>[];\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    removeAll: () => void;\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    add: (...tweens: Tween<any>[]) => void;\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    remove: (...tweens: Tween<any>[]) => void;\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    update: {\n        (time?: number | undefined): void;\n        (time?: number | undefined, preserve?: boolean | undefined): void;\n    };\n};\n\nexport { Easing, Group, Interpolation, Sequence, Tween, VERSION, add, exports as default, getAll, nextId, now, remove, removeAll, setNow, update };\n"
  },
  {
    "path": "dist/tween.esm.js",
    "content": "/**\n * The Ease class provides a collection of easing functions for use with tween.js.\n */\nvar Easing = Object.freeze({\n    Linear: Object.freeze({\n        None: function (amount) {\n            return amount;\n        },\n        In: function (amount) {\n            return amount;\n        },\n        Out: function (amount) {\n            return amount;\n        },\n        InOut: function (amount) {\n            return amount;\n        },\n    }),\n    Quadratic: Object.freeze({\n        In: function (amount) {\n            return amount * amount;\n        },\n        Out: function (amount) {\n            return amount * (2 - amount);\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return 0.5 * amount * amount;\n            }\n            return -0.5 * (--amount * (amount - 2) - 1);\n        },\n    }),\n    Cubic: Object.freeze({\n        In: function (amount) {\n            return amount * amount * amount;\n        },\n        Out: function (amount) {\n            return --amount * amount * amount + 1;\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return 0.5 * amount * amount * amount;\n            }\n            return 0.5 * ((amount -= 2) * amount * amount + 2);\n        },\n    }),\n    Quartic: Object.freeze({\n        In: function (amount) {\n            return amount * amount * amount * amount;\n        },\n        Out: function (amount) {\n            return 1 - --amount * amount * amount * amount;\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return 0.5 * amount * amount * amount * amount;\n            }\n            return -0.5 * ((amount -= 2) * amount * amount * amount - 2);\n        },\n    }),\n    Quintic: Object.freeze({\n        In: function (amount) {\n            return amount * amount * amount * amount * amount;\n        },\n        Out: function (amount) {\n            return --amount * amount * amount * amount * amount + 1;\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return 0.5 * amount * amount * amount * amount * amount;\n            }\n            return 0.5 * ((amount -= 2) * amount * amount * amount * amount + 2);\n        },\n    }),\n    Sinusoidal: Object.freeze({\n        In: function (amount) {\n            return 1 - Math.sin(((1.0 - amount) * Math.PI) / 2);\n        },\n        Out: function (amount) {\n            return Math.sin((amount * Math.PI) / 2);\n        },\n        InOut: function (amount) {\n            return 0.5 * (1 - Math.sin(Math.PI * (0.5 - amount)));\n        },\n    }),\n    Exponential: Object.freeze({\n        In: function (amount) {\n            return amount === 0 ? 0 : Math.pow(1024, amount - 1);\n        },\n        Out: function (amount) {\n            return amount === 1 ? 1 : 1 - Math.pow(2, -10 * amount);\n        },\n        InOut: function (amount) {\n            if (amount === 0) {\n                return 0;\n            }\n            if (amount === 1) {\n                return 1;\n            }\n            if ((amount *= 2) < 1) {\n                return 0.5 * Math.pow(1024, amount - 1);\n            }\n            return 0.5 * (-Math.pow(2, -10 * (amount - 1)) + 2);\n        },\n    }),\n    Circular: Object.freeze({\n        In: function (amount) {\n            return 1 - Math.sqrt(1 - amount * amount);\n        },\n        Out: function (amount) {\n            return Math.sqrt(1 - --amount * amount);\n        },\n        InOut: function (amount) {\n            if ((amount *= 2) < 1) {\n                return -0.5 * (Math.sqrt(1 - amount * amount) - 1);\n            }\n            return 0.5 * (Math.sqrt(1 - (amount -= 2) * amount) + 1);\n        },\n    }),\n    Elastic: Object.freeze({\n        In: function (amount) {\n            if (amount === 0) {\n                return 0;\n            }\n            if (amount === 1) {\n                return 1;\n            }\n            return -Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);\n        },\n        Out: function (amount) {\n            if (amount === 0) {\n                return 0;\n            }\n            if (amount === 1) {\n                return 1;\n            }\n            return Math.pow(2, -10 * amount) * Math.sin((amount - 0.1) * 5 * Math.PI) + 1;\n        },\n        InOut: function (amount) {\n            if (amount === 0) {\n                return 0;\n            }\n            if (amount === 1) {\n                return 1;\n            }\n            amount *= 2;\n            if (amount < 1) {\n                return -0.5 * Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);\n            }\n            return 0.5 * Math.pow(2, -10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI) + 1;\n        },\n    }),\n    Back: Object.freeze({\n        In: function (amount) {\n            var s = 1.70158;\n            return amount === 1 ? 1 : amount * amount * ((s + 1) * amount - s);\n        },\n        Out: function (amount) {\n            var s = 1.70158;\n            return amount === 0 ? 0 : --amount * amount * ((s + 1) * amount + s) + 1;\n        },\n        InOut: function (amount) {\n            var s = 1.70158 * 1.525;\n            if ((amount *= 2) < 1) {\n                return 0.5 * (amount * amount * ((s + 1) * amount - s));\n            }\n            return 0.5 * ((amount -= 2) * amount * ((s + 1) * amount + s) + 2);\n        },\n    }),\n    Bounce: Object.freeze({\n        In: function (amount) {\n            return 1 - Easing.Bounce.Out(1 - amount);\n        },\n        Out: function (amount) {\n            if (amount < 1 / 2.75) {\n                return 7.5625 * amount * amount;\n            }\n            else if (amount < 2 / 2.75) {\n                return 7.5625 * (amount -= 1.5 / 2.75) * amount + 0.75;\n            }\n            else if (amount < 2.5 / 2.75) {\n                return 7.5625 * (amount -= 2.25 / 2.75) * amount + 0.9375;\n            }\n            else {\n                return 7.5625 * (amount -= 2.625 / 2.75) * amount + 0.984375;\n            }\n        },\n        InOut: function (amount) {\n            if (amount < 0.5) {\n                return Easing.Bounce.In(amount * 2) * 0.5;\n            }\n            return Easing.Bounce.Out(amount * 2 - 1) * 0.5 + 0.5;\n        },\n    }),\n    generatePow: function (power) {\n        if (power === void 0) { power = 4; }\n        power = power < Number.EPSILON ? Number.EPSILON : power;\n        power = power > 10000 ? 10000 : power;\n        return {\n            In: function (amount) {\n                return Math.pow(amount, power);\n            },\n            Out: function (amount) {\n                return 1 - Math.pow((1 - amount), power);\n            },\n            InOut: function (amount) {\n                if (amount < 0.5) {\n                    return Math.pow((amount * 2), power) / 2;\n                }\n                return (1 - Math.pow((2 - amount * 2), power)) / 2 + 0.5;\n            },\n        };\n    },\n});\n\nvar _nowFunc = function () { return performance.now(); };\nvar now = function () {\n    return _nowFunc();\n};\nfunction setNow(nowFunction) {\n    _nowFunc = nowFunction;\n}\n\n/**\n * Controlling groups of tweens\n *\n * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n * In these cases, you may want to create your own smaller groups of tween\n */\nvar Group = /** @class */ (function () {\n    function Group() {\n        var tweens = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            tweens[_i] = arguments[_i];\n        }\n        this._tweens = {};\n        this._tweensAddedDuringUpdate = {};\n        this.add.apply(this, tweens);\n    }\n    Group.prototype.getAll = function () {\n        var _this = this;\n        return Object.keys(this._tweens).map(function (tweenId) { return _this._tweens[tweenId]; });\n    };\n    Group.prototype.removeAll = function () {\n        this._tweens = {};\n    };\n    Group.prototype.add = function () {\n        var _a;\n        var tweens = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            tweens[_i] = arguments[_i];\n        }\n        for (var _b = 0, tweens_1 = tweens; _b < tweens_1.length; _b++) {\n            var tween = tweens_1[_b];\n            // Remove from any other group first, a tween can only be in one group at a time.\n            // @ts-expect-error library internal access\n            (_a = tween._group) === null || _a === void 0 ? void 0 : _a.remove(tween);\n            // @ts-expect-error library internal access\n            tween._group = this;\n            this._tweens[tween.getId()] = tween;\n            this._tweensAddedDuringUpdate[tween.getId()] = tween;\n        }\n    };\n    Group.prototype.remove = function () {\n        var tweens = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            tweens[_i] = arguments[_i];\n        }\n        for (var _a = 0, tweens_2 = tweens; _a < tweens_2.length; _a++) {\n            var tween = tweens_2[_a];\n            // @ts-expect-error library internal access\n            tween._group = undefined;\n            delete this._tweens[tween.getId()];\n            delete this._tweensAddedDuringUpdate[tween.getId()];\n        }\n    };\n    /** Return true if all tweens in the group are not paused or playing. */\n    Group.prototype.allStopped = function () {\n        return this.getAll().every(function (tween) { return !tween.isPlaying(); });\n    };\n    Group.prototype.update = function (time, preserve) {\n        if (time === void 0) { time = now(); }\n        if (preserve === void 0) { preserve = true; }\n        var tweenIds = Object.keys(this._tweens);\n        if (tweenIds.length === 0)\n            return;\n        // Tweens are updated in \"batches\". If you add a new tween during an\n        // update, then the new tween will be updated in the next batch.\n        // If you remove a tween during an update, it may or may not be updated.\n        // However, if the removed tween was added during the current batch,\n        // then it will not be updated.\n        while (tweenIds.length > 0) {\n            this._tweensAddedDuringUpdate = {};\n            for (var i = 0; i < tweenIds.length; i++) {\n                var tween = this._tweens[tweenIds[i]];\n                var autoStart = !preserve;\n                if (tween && tween.update(time, autoStart) === false && !preserve)\n                    this.remove(tween);\n            }\n            tweenIds = Object.keys(this._tweensAddedDuringUpdate);\n        }\n    };\n    Group.prototype.onComplete = function (callback) {\n        var group = this.getAll();\n        group.forEach(function (tween) {\n            var prevCallback = tween.getCompleteCallback();\n            tween.onComplete(function () {\n                prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);\n                // After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.\n                var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });\n                if (completedGroup.length === group.length - 1)\n                    callback(group);\n            });\n        });\n    };\n    return Group;\n}());\n\n/**\n *\n */\nvar Interpolation = {\n    Linear: function (v, k) {\n        var m = v.length - 1;\n        var f = m * k;\n        var i = Math.floor(f);\n        var fn = Interpolation.Utils.Linear;\n        if (k < 0) {\n            return fn(v[0], v[1], f);\n        }\n        if (k > 1) {\n            return fn(v[m], v[m - 1], m - f);\n        }\n        return fn(v[i], v[i + 1 > m ? m : i + 1], f - i);\n    },\n    Bezier: function (v, k) {\n        var b = 0;\n        var n = v.length - 1;\n        var pw = Math.pow;\n        var bn = Interpolation.Utils.Bernstein;\n        for (var i = 0; i <= n; i++) {\n            b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);\n        }\n        return b;\n    },\n    CatmullRom: function (v, k) {\n        var m = v.length - 1;\n        var f = m * k;\n        var i = Math.floor(f);\n        var fn = Interpolation.Utils.CatmullRom;\n        if (v[0] === v[m]) {\n            if (k < 0) {\n                i = Math.floor((f = m * (1 + k)));\n            }\n            return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);\n        }\n        else {\n            if (k < 0) {\n                return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]);\n            }\n            if (k > 1) {\n                return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);\n            }\n            return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);\n        }\n    },\n    Utils: {\n        Linear: function (p0, p1, t) {\n            return (p1 - p0) * t + p0;\n        },\n        Bernstein: function (n, i) {\n            var fc = Interpolation.Utils.Factorial;\n            return fc(n) / fc(i) / fc(n - i);\n        },\n        Factorial: (function () {\n            var a = [1];\n            return function (n) {\n                var s = 1;\n                if (a[n]) {\n                    return a[n];\n                }\n                for (var i = n; i > 1; i--) {\n                    s *= i;\n                }\n                a[n] = s;\n                return s;\n            };\n        })(),\n        CatmullRom: function (p0, p1, p2, p3, t) {\n            var v0 = (p2 - p0) * 0.5;\n            var v1 = (p3 - p1) * 0.5;\n            var t2 = t * t;\n            var t3 = t * t2;\n            return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;\n        },\n    },\n};\n\n/**\n * Utils\n */\nvar Sequence = /** @class */ (function () {\n    function Sequence() {\n    }\n    Sequence.nextId = function () {\n        return Sequence._nextId++;\n    };\n    Sequence._nextId = 0;\n    return Sequence;\n}());\n\nvar mainGroup = new Group();\n\n/**\n * Tween.js - Licensed under the MIT license\n * https://github.com/tweenjs/tween.js\n * ----------------------------------------------\n *\n * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n * Thank you all, you're awesome!\n */\nvar Tween = /** @class */ (function () {\n    function Tween(object, group) {\n        this._isPaused = false;\n        this._pauseStart = 0;\n        this._valuesStart = {};\n        this._valuesEnd = {};\n        this._valuesStartRepeat = {};\n        this._duration = 1000;\n        this._isDynamic = false;\n        this._initialRepeat = 0;\n        this._repeat = 0;\n        this._yoyo = false;\n        this._isPlaying = false;\n        this._reversed = false;\n        this._delayTime = 0;\n        this._startTime = 0;\n        this._easingFunction = Easing.Linear.None;\n        this._interpolationFunction = Interpolation.Linear;\n        // eslint-disable-next-line\n        this._chainedTweens = [];\n        this._onStartCallbackFired = false;\n        this._onEveryStartCallbackFired = false;\n        this._id = Sequence.nextId();\n        this._isChainStopped = false;\n        this._propertiesAreSetUp = false;\n        this._goToEnd = false;\n        this._object = object;\n        if (typeof group === 'object') {\n            this._group = group;\n            group.add(this);\n        }\n        // Use \"true\" to restore old behavior (will be removed in future release).\n        else if (group === true) {\n            this._group = mainGroup;\n            mainGroup.add(this);\n        }\n    }\n    Tween.prototype.getId = function () {\n        return this._id;\n    };\n    Tween.prototype.getCompleteCallback = function () {\n        return this._onCompleteCallback;\n    };\n    Tween.prototype.isPlaying = function () {\n        return this._isPlaying;\n    };\n    Tween.prototype.isPaused = function () {\n        return this._isPaused;\n    };\n    Tween.prototype.getDuration = function () {\n        return this._duration;\n    };\n    Tween.prototype.to = function (target, duration) {\n        if (duration === void 0) { duration = 1000; }\n        if (this._isPlaying)\n            throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.');\n        this._valuesEnd = target;\n        this._propertiesAreSetUp = false;\n        this._duration = duration < 0 ? 0 : duration;\n        return this;\n    };\n    Tween.prototype.duration = function (duration) {\n        if (duration === void 0) { duration = 1000; }\n        this._duration = duration < 0 ? 0 : duration;\n        return this;\n    };\n    Tween.prototype.dynamic = function (dynamic) {\n        if (dynamic === void 0) { dynamic = false; }\n        this._isDynamic = dynamic;\n        return this;\n    };\n    Tween.prototype.start = function (time, overrideStartingValues) {\n        if (time === void 0) { time = now(); }\n        if (overrideStartingValues === void 0) { overrideStartingValues = false; }\n        if (this._isPlaying) {\n            return this;\n        }\n        this._repeat = this._initialRepeat;\n        if (this._reversed) {\n            // If we were reversed (f.e. using the yoyo feature) then we need to\n            // flip the tween direction back to forward.\n            this._reversed = false;\n            for (var property in this._valuesStartRepeat) {\n                this._swapEndStartRepeatValues(property);\n                this._valuesStart[property] = this._valuesStartRepeat[property];\n            }\n        }\n        this._isPlaying = true;\n        this._isPaused = false;\n        this._onStartCallbackFired = false;\n        this._onEveryStartCallbackFired = false;\n        this._isChainStopped = false;\n        this._startTime = time;\n        this._startTime += this._delayTime;\n        if (!this._propertiesAreSetUp || overrideStartingValues) {\n            this._propertiesAreSetUp = true;\n            // If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n            if (!this._isDynamic) {\n                var tmp = {};\n                for (var prop in this._valuesEnd)\n                    tmp[prop] = this._valuesEnd[prop];\n                this._valuesEnd = tmp;\n            }\n            this._setupProperties(this._object, this._valuesStart, this._valuesEnd, this._valuesStartRepeat, overrideStartingValues);\n        }\n        return this;\n    };\n    Tween.prototype.startFromCurrentValues = function (time) {\n        return this.start(time, true);\n    };\n    Tween.prototype._setupProperties = function (_object, _valuesStart, _valuesEnd, _valuesStartRepeat, overrideStartingValues) {\n        for (var property in _valuesEnd) {\n            var startValue = _object[property];\n            var startValueIsArray = Array.isArray(startValue);\n            var propType = startValueIsArray ? 'array' : typeof startValue;\n            var isInterpolationList = !startValueIsArray && Array.isArray(_valuesEnd[property]);\n            // If `to()` specifies a property that doesn't exist in the source object,\n            // we should not set that property in the object\n            if (propType === 'undefined' || propType === 'function') {\n                continue;\n            }\n            // Check if an Array was provided as property value\n            if (isInterpolationList) {\n                var endValues = _valuesEnd[property];\n                if (endValues.length === 0) {\n                    continue;\n                }\n                // Handle an array of relative values.\n                // Creates a local copy of the Array with the start value at the front\n                var temp = [startValue];\n                for (var i = 0, l = endValues.length; i < l; i += 1) {\n                    var value = this._handleRelativeValue(startValue, endValues[i]);\n                    if (isNaN(value)) {\n                        isInterpolationList = false;\n                        console.warn('Found invalid interpolation list. Skipping.');\n                        break;\n                    }\n                    temp.push(value);\n                }\n                if (isInterpolationList) {\n                    // if (_valuesStart[property] === undefined) { // handle end values only the first time. NOT NEEDED? setupProperties is now guarded by _propertiesAreSetUp.\n                    _valuesEnd[property] = temp;\n                    // }\n                }\n            }\n            // handle the deepness of the values\n            if ((propType === 'object' || startValueIsArray) && startValue && !isInterpolationList) {\n                _valuesStart[property] = startValueIsArray ? [] : {};\n                var nestedObject = startValue;\n                for (var prop in nestedObject) {\n                    _valuesStart[property][prop] = nestedObject[prop];\n                }\n                // TODO? repeat nested values? And yoyo? And array values?\n                _valuesStartRepeat[property] = startValueIsArray ? [] : {};\n                var endValues = _valuesEnd[property];\n                // If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n                if (!this._isDynamic) {\n                    var tmp = {};\n                    for (var prop in endValues)\n                        tmp[prop] = endValues[prop];\n                    _valuesEnd[property] = endValues = tmp;\n                }\n                this._setupProperties(nestedObject, _valuesStart[property], endValues, _valuesStartRepeat[property], overrideStartingValues);\n            }\n            else {\n                // Save the starting value, but only once unless override is requested.\n                if (typeof _valuesStart[property] === 'undefined' || overrideStartingValues) {\n                    _valuesStart[property] = startValue;\n                }\n                if (!startValueIsArray) {\n                    // eslint-disable-next-line\n                    // @ts-ignore FIXME?\n                    _valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings\n                }\n                if (isInterpolationList) {\n                    // eslint-disable-next-line\n                    // @ts-ignore FIXME?\n                    _valuesStartRepeat[property] = _valuesEnd[property].slice().reverse();\n                }\n                else {\n                    _valuesStartRepeat[property] = _valuesStart[property] || 0;\n                }\n            }\n        }\n    };\n    Tween.prototype.stop = function () {\n        if (!this._isChainStopped) {\n            this._isChainStopped = true;\n            this.stopChainedTweens();\n        }\n        if (!this._isPlaying) {\n            return this;\n        }\n        this._isPlaying = false;\n        this._isPaused = false;\n        if (this._onStopCallback) {\n            this._onStopCallback(this._object);\n        }\n        return this;\n    };\n    Tween.prototype.end = function () {\n        this._goToEnd = true;\n        this.update(this._startTime + this._duration);\n        return this;\n    };\n    Tween.prototype.pause = function (time) {\n        if (time === void 0) { time = now(); }\n        if (this._isPaused || !this._isPlaying) {\n            return this;\n        }\n        this._isPaused = true;\n        this._pauseStart = time;\n        return this;\n    };\n    Tween.prototype.resume = function (time) {\n        if (time === void 0) { time = now(); }\n        if (!this._isPaused || !this._isPlaying) {\n            return this;\n        }\n        this._isPaused = false;\n        this._startTime += time - this._pauseStart;\n        this._pauseStart = 0;\n        return this;\n    };\n    Tween.prototype.stopChainedTweens = function () {\n        for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n            this._chainedTweens[i].stop();\n        }\n        return this;\n    };\n    Tween.prototype.group = function (group) {\n        if (!group) {\n            console.warn('tween.group() without args has been removed, use group.add(tween) instead.');\n            return this;\n        }\n        group.add(this);\n        return this;\n    };\n    /**\n     * Removes the tween from whichever group it is in.\n     */\n    Tween.prototype.remove = function () {\n        var _a;\n        (_a = this._group) === null || _a === void 0 ? void 0 : _a.remove(this);\n        return this;\n    };\n    Tween.prototype.delay = function (amount) {\n        if (amount === void 0) { amount = 0; }\n        this._delayTime = amount;\n        return this;\n    };\n    Tween.prototype.repeat = function (times) {\n        if (times === void 0) { times = 0; }\n        this._initialRepeat = times;\n        this._repeat = times;\n        return this;\n    };\n    Tween.prototype.repeatDelay = function (amount) {\n        this._repeatDelayTime = amount;\n        return this;\n    };\n    Tween.prototype.yoyo = function (yoyo) {\n        if (yoyo === void 0) { yoyo = false; }\n        this._yoyo = yoyo;\n        return this;\n    };\n    Tween.prototype.easing = function (easingFunction) {\n        if (easingFunction === void 0) { easingFunction = Easing.Linear.None; }\n        this._easingFunction = easingFunction;\n        return this;\n    };\n    Tween.prototype.interpolation = function (interpolationFunction) {\n        if (interpolationFunction === void 0) { interpolationFunction = Interpolation.Linear; }\n        this._interpolationFunction = interpolationFunction;\n        return this;\n    };\n    // eslint-disable-next-line\n    Tween.prototype.chain = function () {\n        var tweens = [];\n        for (var _i = 0; _i < arguments.length; _i++) {\n            tweens[_i] = arguments[_i];\n        }\n        this._chainedTweens = tweens;\n        return this;\n    };\n    Tween.prototype.onStart = function (callback) {\n        this._onStartCallback = callback;\n        return this;\n    };\n    Tween.prototype.onEveryStart = function (callback) {\n        this._onEveryStartCallback = callback;\n        return this;\n    };\n    Tween.prototype.onUpdate = function (callback) {\n        this._onUpdateCallback = callback;\n        return this;\n    };\n    Tween.prototype.onRepeat = function (callback) {\n        this._onRepeatCallback = callback;\n        return this;\n    };\n    Tween.prototype.onComplete = function (callback) {\n        this._onCompleteCallback = callback;\n        return this;\n    };\n    Tween.prototype.onStop = function (callback) {\n        this._onStopCallback = callback;\n        return this;\n    };\n    /**\n     * @returns true if the tween is still playing after the update, false\n     * otherwise (calling update on a paused tween still returns true because\n     * it is still playing, just paused).\n     *\n     * @param autoStart - When true, calling update will implicitly call start()\n     * as well. Note, if you stop() or end() the tween, but are still calling\n     * update(), it will start again!\n     */\n    Tween.prototype.update = function (time, autoStart) {\n        var _this = this;\n        var _a;\n        if (time === void 0) { time = now(); }\n        if (autoStart === void 0) { autoStart = Tween.autoStartOnUpdate; }\n        if (this._isPaused)\n            return true;\n        var property;\n        if (!this._goToEnd && !this._isPlaying) {\n            if (autoStart)\n                this.start(time, true);\n            else\n                return false;\n        }\n        this._goToEnd = false;\n        if (time < this._startTime) {\n            return true;\n        }\n        if (this._onStartCallbackFired === false) {\n            if (this._onStartCallback) {\n                this._onStartCallback(this._object);\n            }\n            this._onStartCallbackFired = true;\n        }\n        if (this._onEveryStartCallbackFired === false) {\n            if (this._onEveryStartCallback) {\n                this._onEveryStartCallback(this._object);\n            }\n            this._onEveryStartCallbackFired = true;\n        }\n        var elapsedTime = time - this._startTime;\n        var durationAndDelay = this._duration + ((_a = this._repeatDelayTime) !== null && _a !== void 0 ? _a : this._delayTime);\n        var totalTime = this._duration + this._repeat * durationAndDelay;\n        var calculateElapsedPortion = function () {\n            if (_this._duration === 0)\n                return 1;\n            if (elapsedTime > totalTime) {\n                return 1;\n            }\n            var timesRepeated = Math.trunc(elapsedTime / durationAndDelay);\n            var timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay;\n            // TODO use %?\n            // const timeIntoCurrentRepeat = elapsedTime % durationAndDelay\n            var portion = Math.min(timeIntoCurrentRepeat / _this._duration, 1);\n            if (portion === 0 && elapsedTime === _this._duration) {\n                return 1;\n            }\n            return portion;\n        };\n        var elapsed = calculateElapsedPortion();\n        var value = this._easingFunction(elapsed);\n        // properties transformations\n        this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value);\n        if (this._onUpdateCallback) {\n            this._onUpdateCallback(this._object, elapsed);\n        }\n        if (this._duration === 0 || elapsedTime >= this._duration) {\n            if (this._repeat > 0) {\n                var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);\n                if (isFinite(this._repeat)) {\n                    this._repeat -= completeCount;\n                }\n                // Reassign starting values, restart by making startTime = now\n                for (property in this._valuesStartRepeat) {\n                    if (!this._yoyo && typeof this._valuesEnd[property] === 'string') {\n                        this._valuesStartRepeat[property] =\n                            // eslint-disable-next-line\n                            // @ts-ignore FIXME?\n                            this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);\n                    }\n                    if (this._yoyo) {\n                        this._swapEndStartRepeatValues(property);\n                    }\n                    this._valuesStart[property] = this._valuesStartRepeat[property];\n                }\n                if (this._yoyo) {\n                    this._reversed = !this._reversed;\n                }\n                this._startTime += durationAndDelay * completeCount;\n                if (this._onRepeatCallback) {\n                    this._onRepeatCallback(this._object);\n                }\n                this._onEveryStartCallbackFired = false;\n                return true;\n            }\n            else {\n                if (this._onCompleteCallback) {\n                    this._onCompleteCallback(this._object);\n                }\n                for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n                    // Make the chained tweens start exactly at the time they should,\n                    // even if the `update()` method was called way past the duration of the tween\n                    this._chainedTweens[i].start(this._startTime + this._duration, false);\n                }\n                this._isPlaying = false;\n                return false;\n            }\n        }\n        return true;\n    };\n    Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) {\n        for (var property in _valuesEnd) {\n            // Don't update properties that do not exist in the source object\n            if (_valuesStart[property] === undefined) {\n                continue;\n            }\n            var start = _valuesStart[property] || 0;\n            var end = _valuesEnd[property];\n            var startIsArray = Array.isArray(_object[property]);\n            var endIsArray = Array.isArray(end);\n            var isInterpolationList = !startIsArray && endIsArray;\n            if (isInterpolationList) {\n                _object[property] = this._interpolationFunction(end, value);\n            }\n            else if (typeof end === 'object' && end) {\n                // eslint-disable-next-line\n                // @ts-ignore FIXME?\n                this._updateProperties(_object[property], start, end, value);\n            }\n            else {\n                // Parses relative end values with start as base (e.g.: +10, -3)\n                end = this._handleRelativeValue(start, end);\n                // Protect against non numeric properties.\n                if (typeof end === 'number') {\n                    // eslint-disable-next-line\n                    // @ts-ignore FIXME?\n                    _object[property] = start + (end - start) * value;\n                }\n            }\n        }\n    };\n    Tween.prototype._handleRelativeValue = function (start, end) {\n        if (typeof end !== 'string') {\n            return end;\n        }\n        if (end.charAt(0) === '+' || end.charAt(0) === '-') {\n            return start + parseFloat(end);\n        }\n        return parseFloat(end);\n    };\n    Tween.prototype._swapEndStartRepeatValues = function (property) {\n        var tmp = this._valuesStartRepeat[property];\n        var endValue = this._valuesEnd[property];\n        if (typeof endValue === 'string') {\n            this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(endValue);\n        }\n        else {\n            this._valuesStartRepeat[property] = this._valuesEnd[property];\n        }\n        this._valuesEnd[property] = tmp;\n    };\n    Tween.autoStartOnUpdate = false;\n    return Tween;\n}());\n\nvar VERSION = '25.0.0';\n\n/**\n * Tween.js - Licensed under the MIT license\n * https://github.com/tweenjs/tween.js\n * ----------------------------------------------\n *\n * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n * Thank you all, you're awesome!\n */\nvar nextId = Sequence.nextId;\n/**\n * Controlling groups of tweens\n *\n * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n * In these cases, you may want to create your own smaller groups of tweens.\n */\nvar TWEEN = mainGroup;\n// This is the best way to export things in a way that's compatible with both ES\n// Modules and CommonJS, without build hacks, and so as not to break the\n// existing API.\n// https://github.com/rollup/rollup/issues/1961#issuecomment-423037881\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar getAll = TWEEN.getAll.bind(TWEEN);\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar removeAll = TWEEN.removeAll.bind(TWEEN);\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar add = TWEEN.add.bind(TWEEN);\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar remove = TWEEN.remove.bind(TWEEN);\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nvar update = TWEEN.update.bind(TWEEN);\nvar exports = {\n    Easing: Easing,\n    Group: Group,\n    Interpolation: Interpolation,\n    now: now,\n    setNow: setNow,\n    Sequence: Sequence,\n    nextId: nextId,\n    Tween: Tween,\n    VERSION: VERSION,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    getAll: getAll,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    removeAll: removeAll,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    add: add,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    remove: remove,\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    update: update,\n};\n\nexport { Easing, Group, Interpolation, Sequence, Tween, VERSION, add, exports as default, getAll, nextId, now, remove, removeAll, setNow, update };\n"
  },
  {
    "path": "dist/tween.umd.js",
    "content": "(function (global, factory) {\n    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n    typeof define === 'function' && define.amd ? define(['exports'], factory) :\n    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.TWEEN = {}));\n})(this, (function (exports) { 'use strict';\n\n    /**\n     * The Ease class provides a collection of easing functions for use with tween.js.\n     */\n    var Easing = Object.freeze({\n        Linear: Object.freeze({\n            None: function (amount) {\n                return amount;\n            },\n            In: function (amount) {\n                return amount;\n            },\n            Out: function (amount) {\n                return amount;\n            },\n            InOut: function (amount) {\n                return amount;\n            },\n        }),\n        Quadratic: Object.freeze({\n            In: function (amount) {\n                return amount * amount;\n            },\n            Out: function (amount) {\n                return amount * (2 - amount);\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return 0.5 * amount * amount;\n                }\n                return -0.5 * (--amount * (amount - 2) - 1);\n            },\n        }),\n        Cubic: Object.freeze({\n            In: function (amount) {\n                return amount * amount * amount;\n            },\n            Out: function (amount) {\n                return --amount * amount * amount + 1;\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return 0.5 * amount * amount * amount;\n                }\n                return 0.5 * ((amount -= 2) * amount * amount + 2);\n            },\n        }),\n        Quartic: Object.freeze({\n            In: function (amount) {\n                return amount * amount * amount * amount;\n            },\n            Out: function (amount) {\n                return 1 - --amount * amount * amount * amount;\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return 0.5 * amount * amount * amount * amount;\n                }\n                return -0.5 * ((amount -= 2) * amount * amount * amount - 2);\n            },\n        }),\n        Quintic: Object.freeze({\n            In: function (amount) {\n                return amount * amount * amount * amount * amount;\n            },\n            Out: function (amount) {\n                return --amount * amount * amount * amount * amount + 1;\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return 0.5 * amount * amount * amount * amount * amount;\n                }\n                return 0.5 * ((amount -= 2) * amount * amount * amount * amount + 2);\n            },\n        }),\n        Sinusoidal: Object.freeze({\n            In: function (amount) {\n                return 1 - Math.sin(((1.0 - amount) * Math.PI) / 2);\n            },\n            Out: function (amount) {\n                return Math.sin((amount * Math.PI) / 2);\n            },\n            InOut: function (amount) {\n                return 0.5 * (1 - Math.sin(Math.PI * (0.5 - amount)));\n            },\n        }),\n        Exponential: Object.freeze({\n            In: function (amount) {\n                return amount === 0 ? 0 : Math.pow(1024, amount - 1);\n            },\n            Out: function (amount) {\n                return amount === 1 ? 1 : 1 - Math.pow(2, -10 * amount);\n            },\n            InOut: function (amount) {\n                if (amount === 0) {\n                    return 0;\n                }\n                if (amount === 1) {\n                    return 1;\n                }\n                if ((amount *= 2) < 1) {\n                    return 0.5 * Math.pow(1024, amount - 1);\n                }\n                return 0.5 * (-Math.pow(2, -10 * (amount - 1)) + 2);\n            },\n        }),\n        Circular: Object.freeze({\n            In: function (amount) {\n                return 1 - Math.sqrt(1 - amount * amount);\n            },\n            Out: function (amount) {\n                return Math.sqrt(1 - --amount * amount);\n            },\n            InOut: function (amount) {\n                if ((amount *= 2) < 1) {\n                    return -0.5 * (Math.sqrt(1 - amount * amount) - 1);\n                }\n                return 0.5 * (Math.sqrt(1 - (amount -= 2) * amount) + 1);\n            },\n        }),\n        Elastic: Object.freeze({\n            In: function (amount) {\n                if (amount === 0) {\n                    return 0;\n                }\n                if (amount === 1) {\n                    return 1;\n                }\n                return -Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);\n            },\n            Out: function (amount) {\n                if (amount === 0) {\n                    return 0;\n                }\n                if (amount === 1) {\n                    return 1;\n                }\n                return Math.pow(2, -10 * amount) * Math.sin((amount - 0.1) * 5 * Math.PI) + 1;\n            },\n            InOut: function (amount) {\n                if (amount === 0) {\n                    return 0;\n                }\n                if (amount === 1) {\n                    return 1;\n                }\n                amount *= 2;\n                if (amount < 1) {\n                    return -0.5 * Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI);\n                }\n                return 0.5 * Math.pow(2, -10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI) + 1;\n            },\n        }),\n        Back: Object.freeze({\n            In: function (amount) {\n                var s = 1.70158;\n                return amount === 1 ? 1 : amount * amount * ((s + 1) * amount - s);\n            },\n            Out: function (amount) {\n                var s = 1.70158;\n                return amount === 0 ? 0 : --amount * amount * ((s + 1) * amount + s) + 1;\n            },\n            InOut: function (amount) {\n                var s = 1.70158 * 1.525;\n                if ((amount *= 2) < 1) {\n                    return 0.5 * (amount * amount * ((s + 1) * amount - s));\n                }\n                return 0.5 * ((amount -= 2) * amount * ((s + 1) * amount + s) + 2);\n            },\n        }),\n        Bounce: Object.freeze({\n            In: function (amount) {\n                return 1 - Easing.Bounce.Out(1 - amount);\n            },\n            Out: function (amount) {\n                if (amount < 1 / 2.75) {\n                    return 7.5625 * amount * amount;\n                }\n                else if (amount < 2 / 2.75) {\n                    return 7.5625 * (amount -= 1.5 / 2.75) * amount + 0.75;\n                }\n                else if (amount < 2.5 / 2.75) {\n                    return 7.5625 * (amount -= 2.25 / 2.75) * amount + 0.9375;\n                }\n                else {\n                    return 7.5625 * (amount -= 2.625 / 2.75) * amount + 0.984375;\n                }\n            },\n            InOut: function (amount) {\n                if (amount < 0.5) {\n                    return Easing.Bounce.In(amount * 2) * 0.5;\n                }\n                return Easing.Bounce.Out(amount * 2 - 1) * 0.5 + 0.5;\n            },\n        }),\n        generatePow: function (power) {\n            if (power === void 0) { power = 4; }\n            power = power < Number.EPSILON ? Number.EPSILON : power;\n            power = power > 10000 ? 10000 : power;\n            return {\n                In: function (amount) {\n                    return Math.pow(amount, power);\n                },\n                Out: function (amount) {\n                    return 1 - Math.pow((1 - amount), power);\n                },\n                InOut: function (amount) {\n                    if (amount < 0.5) {\n                        return Math.pow((amount * 2), power) / 2;\n                    }\n                    return (1 - Math.pow((2 - amount * 2), power)) / 2 + 0.5;\n                },\n            };\n        },\n    });\n\n    var _nowFunc = function () { return performance.now(); };\n    var now = function () {\n        return _nowFunc();\n    };\n    function setNow(nowFunction) {\n        _nowFunc = nowFunction;\n    }\n\n    /**\n     * Controlling groups of tweens\n     *\n     * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n     * In these cases, you may want to create your own smaller groups of tween\n     */\n    var Group = /** @class */ (function () {\n        function Group() {\n            var tweens = [];\n            for (var _i = 0; _i < arguments.length; _i++) {\n                tweens[_i] = arguments[_i];\n            }\n            this._tweens = {};\n            this._tweensAddedDuringUpdate = {};\n            this.add.apply(this, tweens);\n        }\n        Group.prototype.getAll = function () {\n            var _this = this;\n            return Object.keys(this._tweens).map(function (tweenId) { return _this._tweens[tweenId]; });\n        };\n        Group.prototype.removeAll = function () {\n            this._tweens = {};\n        };\n        Group.prototype.add = function () {\n            var _a;\n            var tweens = [];\n            for (var _i = 0; _i < arguments.length; _i++) {\n                tweens[_i] = arguments[_i];\n            }\n            for (var _b = 0, tweens_1 = tweens; _b < tweens_1.length; _b++) {\n                var tween = tweens_1[_b];\n                // Remove from any other group first, a tween can only be in one group at a time.\n                // @ts-expect-error library internal access\n                (_a = tween._group) === null || _a === void 0 ? void 0 : _a.remove(tween);\n                // @ts-expect-error library internal access\n                tween._group = this;\n                this._tweens[tween.getId()] = tween;\n                this._tweensAddedDuringUpdate[tween.getId()] = tween;\n            }\n        };\n        Group.prototype.remove = function () {\n            var tweens = [];\n            for (var _i = 0; _i < arguments.length; _i++) {\n                tweens[_i] = arguments[_i];\n            }\n            for (var _a = 0, tweens_2 = tweens; _a < tweens_2.length; _a++) {\n                var tween = tweens_2[_a];\n                // @ts-expect-error library internal access\n                tween._group = undefined;\n                delete this._tweens[tween.getId()];\n                delete this._tweensAddedDuringUpdate[tween.getId()];\n            }\n        };\n        /** Return true if all tweens in the group are not paused or playing. */\n        Group.prototype.allStopped = function () {\n            return this.getAll().every(function (tween) { return !tween.isPlaying(); });\n        };\n        Group.prototype.update = function (time, preserve) {\n            if (time === void 0) { time = now(); }\n            if (preserve === void 0) { preserve = true; }\n            var tweenIds = Object.keys(this._tweens);\n            if (tweenIds.length === 0)\n                return;\n            // Tweens are updated in \"batches\". If you add a new tween during an\n            // update, then the new tween will be updated in the next batch.\n            // If you remove a tween during an update, it may or may not be updated.\n            // However, if the removed tween was added during the current batch,\n            // then it will not be updated.\n            while (tweenIds.length > 0) {\n                this._tweensAddedDuringUpdate = {};\n                for (var i = 0; i < tweenIds.length; i++) {\n                    var tween = this._tweens[tweenIds[i]];\n                    var autoStart = !preserve;\n                    if (tween && tween.update(time, autoStart) === false && !preserve)\n                        this.remove(tween);\n                }\n                tweenIds = Object.keys(this._tweensAddedDuringUpdate);\n            }\n        };\n        Group.prototype.onComplete = function (callback) {\n            var group = this.getAll();\n            group.forEach(function (tween) {\n                var prevCallback = tween.getCompleteCallback();\n                tween.onComplete(function () {\n                    prevCallback === null || prevCallback === void 0 ? void 0 : prevCallback(tween);\n                    // After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.\n                    var completedGroup = group.filter(function (tween) { return !tween.isPlaying(); });\n                    if (completedGroup.length === group.length - 1)\n                        callback(group);\n                });\n            });\n        };\n        return Group;\n    }());\n\n    /**\n     *\n     */\n    var Interpolation = {\n        Linear: function (v, k) {\n            var m = v.length - 1;\n            var f = m * k;\n            var i = Math.floor(f);\n            var fn = Interpolation.Utils.Linear;\n            if (k < 0) {\n                return fn(v[0], v[1], f);\n            }\n            if (k > 1) {\n                return fn(v[m], v[m - 1], m - f);\n            }\n            return fn(v[i], v[i + 1 > m ? m : i + 1], f - i);\n        },\n        Bezier: function (v, k) {\n            var b = 0;\n            var n = v.length - 1;\n            var pw = Math.pow;\n            var bn = Interpolation.Utils.Bernstein;\n            for (var i = 0; i <= n; i++) {\n                b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i);\n            }\n            return b;\n        },\n        CatmullRom: function (v, k) {\n            var m = v.length - 1;\n            var f = m * k;\n            var i = Math.floor(f);\n            var fn = Interpolation.Utils.CatmullRom;\n            if (v[0] === v[m]) {\n                if (k < 0) {\n                    i = Math.floor((f = m * (1 + k)));\n                }\n                return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i);\n            }\n            else {\n                if (k < 0) {\n                    return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0]);\n                }\n                if (k > 1) {\n                    return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m]);\n                }\n                return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i);\n            }\n        },\n        Utils: {\n            Linear: function (p0, p1, t) {\n                return (p1 - p0) * t + p0;\n            },\n            Bernstein: function (n, i) {\n                var fc = Interpolation.Utils.Factorial;\n                return fc(n) / fc(i) / fc(n - i);\n            },\n            Factorial: (function () {\n                var a = [1];\n                return function (n) {\n                    var s = 1;\n                    if (a[n]) {\n                        return a[n];\n                    }\n                    for (var i = n; i > 1; i--) {\n                        s *= i;\n                    }\n                    a[n] = s;\n                    return s;\n                };\n            })(),\n            CatmullRom: function (p0, p1, p2, p3, t) {\n                var v0 = (p2 - p0) * 0.5;\n                var v1 = (p3 - p1) * 0.5;\n                var t2 = t * t;\n                var t3 = t * t2;\n                return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;\n            },\n        },\n    };\n\n    /**\n     * Utils\n     */\n    var Sequence = /** @class */ (function () {\n        function Sequence() {\n        }\n        Sequence.nextId = function () {\n            return Sequence._nextId++;\n        };\n        Sequence._nextId = 0;\n        return Sequence;\n    }());\n\n    var mainGroup = new Group();\n\n    /**\n     * Tween.js - Licensed under the MIT license\n     * https://github.com/tweenjs/tween.js\n     * ----------------------------------------------\n     *\n     * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n     * Thank you all, you're awesome!\n     */\n    var Tween = /** @class */ (function () {\n        function Tween(object, group) {\n            this._isPaused = false;\n            this._pauseStart = 0;\n            this._valuesStart = {};\n            this._valuesEnd = {};\n            this._valuesStartRepeat = {};\n            this._duration = 1000;\n            this._isDynamic = false;\n            this._initialRepeat = 0;\n            this._repeat = 0;\n            this._yoyo = false;\n            this._isPlaying = false;\n            this._reversed = false;\n            this._delayTime = 0;\n            this._startTime = 0;\n            this._easingFunction = Easing.Linear.None;\n            this._interpolationFunction = Interpolation.Linear;\n            // eslint-disable-next-line\n            this._chainedTweens = [];\n            this._onStartCallbackFired = false;\n            this._onEveryStartCallbackFired = false;\n            this._id = Sequence.nextId();\n            this._isChainStopped = false;\n            this._propertiesAreSetUp = false;\n            this._goToEnd = false;\n            this._object = object;\n            if (typeof group === 'object') {\n                this._group = group;\n                group.add(this);\n            }\n            // Use \"true\" to restore old behavior (will be removed in future release).\n            else if (group === true) {\n                this._group = mainGroup;\n                mainGroup.add(this);\n            }\n        }\n        Tween.prototype.getId = function () {\n            return this._id;\n        };\n        Tween.prototype.getCompleteCallback = function () {\n            return this._onCompleteCallback;\n        };\n        Tween.prototype.isPlaying = function () {\n            return this._isPlaying;\n        };\n        Tween.prototype.isPaused = function () {\n            return this._isPaused;\n        };\n        Tween.prototype.getDuration = function () {\n            return this._duration;\n        };\n        Tween.prototype.to = function (target, duration) {\n            if (duration === void 0) { duration = 1000; }\n            if (this._isPlaying)\n                throw new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.');\n            this._valuesEnd = target;\n            this._propertiesAreSetUp = false;\n            this._duration = duration < 0 ? 0 : duration;\n            return this;\n        };\n        Tween.prototype.duration = function (duration) {\n            if (duration === void 0) { duration = 1000; }\n            this._duration = duration < 0 ? 0 : duration;\n            return this;\n        };\n        Tween.prototype.dynamic = function (dynamic) {\n            if (dynamic === void 0) { dynamic = false; }\n            this._isDynamic = dynamic;\n            return this;\n        };\n        Tween.prototype.start = function (time, overrideStartingValues) {\n            if (time === void 0) { time = now(); }\n            if (overrideStartingValues === void 0) { overrideStartingValues = false; }\n            if (this._isPlaying) {\n                return this;\n            }\n            this._repeat = this._initialRepeat;\n            if (this._reversed) {\n                // If we were reversed (f.e. using the yoyo feature) then we need to\n                // flip the tween direction back to forward.\n                this._reversed = false;\n                for (var property in this._valuesStartRepeat) {\n                    this._swapEndStartRepeatValues(property);\n                    this._valuesStart[property] = this._valuesStartRepeat[property];\n                }\n            }\n            this._isPlaying = true;\n            this._isPaused = false;\n            this._onStartCallbackFired = false;\n            this._onEveryStartCallbackFired = false;\n            this._isChainStopped = false;\n            this._startTime = time;\n            this._startTime += this._delayTime;\n            if (!this._propertiesAreSetUp || overrideStartingValues) {\n                this._propertiesAreSetUp = true;\n                // If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n                if (!this._isDynamic) {\n                    var tmp = {};\n                    for (var prop in this._valuesEnd)\n                        tmp[prop] = this._valuesEnd[prop];\n                    this._valuesEnd = tmp;\n                }\n                this._setupProperties(this._object, this._valuesStart, this._valuesEnd, this._valuesStartRepeat, overrideStartingValues);\n            }\n            return this;\n        };\n        Tween.prototype.startFromCurrentValues = function (time) {\n            return this.start(time, true);\n        };\n        Tween.prototype._setupProperties = function (_object, _valuesStart, _valuesEnd, _valuesStartRepeat, overrideStartingValues) {\n            for (var property in _valuesEnd) {\n                var startValue = _object[property];\n                var startValueIsArray = Array.isArray(startValue);\n                var propType = startValueIsArray ? 'array' : typeof startValue;\n                var isInterpolationList = !startValueIsArray && Array.isArray(_valuesEnd[property]);\n                // If `to()` specifies a property that doesn't exist in the source object,\n                // we should not set that property in the object\n                if (propType === 'undefined' || propType === 'function') {\n                    continue;\n                }\n                // Check if an Array was provided as property value\n                if (isInterpolationList) {\n                    var endValues = _valuesEnd[property];\n                    if (endValues.length === 0) {\n                        continue;\n                    }\n                    // Handle an array of relative values.\n                    // Creates a local copy of the Array with the start value at the front\n                    var temp = [startValue];\n                    for (var i = 0, l = endValues.length; i < l; i += 1) {\n                        var value = this._handleRelativeValue(startValue, endValues[i]);\n                        if (isNaN(value)) {\n                            isInterpolationList = false;\n                            console.warn('Found invalid interpolation list. Skipping.');\n                            break;\n                        }\n                        temp.push(value);\n                    }\n                    if (isInterpolationList) {\n                        // if (_valuesStart[property] === undefined) { // handle end values only the first time. NOT NEEDED? setupProperties is now guarded by _propertiesAreSetUp.\n                        _valuesEnd[property] = temp;\n                        // }\n                    }\n                }\n                // handle the deepness of the values\n                if ((propType === 'object' || startValueIsArray) && startValue && !isInterpolationList) {\n                    _valuesStart[property] = startValueIsArray ? [] : {};\n                    var nestedObject = startValue;\n                    for (var prop in nestedObject) {\n                        _valuesStart[property][prop] = nestedObject[prop];\n                    }\n                    // TODO? repeat nested values? And yoyo? And array values?\n                    _valuesStartRepeat[property] = startValueIsArray ? [] : {};\n                    var endValues = _valuesEnd[property];\n                    // If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n                    if (!this._isDynamic) {\n                        var tmp = {};\n                        for (var prop in endValues)\n                            tmp[prop] = endValues[prop];\n                        _valuesEnd[property] = endValues = tmp;\n                    }\n                    this._setupProperties(nestedObject, _valuesStart[property], endValues, _valuesStartRepeat[property], overrideStartingValues);\n                }\n                else {\n                    // Save the starting value, but only once unless override is requested.\n                    if (typeof _valuesStart[property] === 'undefined' || overrideStartingValues) {\n                        _valuesStart[property] = startValue;\n                    }\n                    if (!startValueIsArray) {\n                        // eslint-disable-next-line\n                        // @ts-ignore FIXME?\n                        _valuesStart[property] *= 1.0; // Ensures we're using numbers, not strings\n                    }\n                    if (isInterpolationList) {\n                        // eslint-disable-next-line\n                        // @ts-ignore FIXME?\n                        _valuesStartRepeat[property] = _valuesEnd[property].slice().reverse();\n                    }\n                    else {\n                        _valuesStartRepeat[property] = _valuesStart[property] || 0;\n                    }\n                }\n            }\n        };\n        Tween.prototype.stop = function () {\n            if (!this._isChainStopped) {\n                this._isChainStopped = true;\n                this.stopChainedTweens();\n            }\n            if (!this._isPlaying) {\n                return this;\n            }\n            this._isPlaying = false;\n            this._isPaused = false;\n            if (this._onStopCallback) {\n                this._onStopCallback(this._object);\n            }\n            return this;\n        };\n        Tween.prototype.end = function () {\n            this._goToEnd = true;\n            this.update(this._startTime + this._duration);\n            return this;\n        };\n        Tween.prototype.pause = function (time) {\n            if (time === void 0) { time = now(); }\n            if (this._isPaused || !this._isPlaying) {\n                return this;\n            }\n            this._isPaused = true;\n            this._pauseStart = time;\n            return this;\n        };\n        Tween.prototype.resume = function (time) {\n            if (time === void 0) { time = now(); }\n            if (!this._isPaused || !this._isPlaying) {\n                return this;\n            }\n            this._isPaused = false;\n            this._startTime += time - this._pauseStart;\n            this._pauseStart = 0;\n            return this;\n        };\n        Tween.prototype.stopChainedTweens = function () {\n            for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n                this._chainedTweens[i].stop();\n            }\n            return this;\n        };\n        Tween.prototype.group = function (group) {\n            if (!group) {\n                console.warn('tween.group() without args has been removed, use group.add(tween) instead.');\n                return this;\n            }\n            group.add(this);\n            return this;\n        };\n        /**\n         * Removes the tween from whichever group it is in.\n         */\n        Tween.prototype.remove = function () {\n            var _a;\n            (_a = this._group) === null || _a === void 0 ? void 0 : _a.remove(this);\n            return this;\n        };\n        Tween.prototype.delay = function (amount) {\n            if (amount === void 0) { amount = 0; }\n            this._delayTime = amount;\n            return this;\n        };\n        Tween.prototype.repeat = function (times) {\n            if (times === void 0) { times = 0; }\n            this._initialRepeat = times;\n            this._repeat = times;\n            return this;\n        };\n        Tween.prototype.repeatDelay = function (amount) {\n            this._repeatDelayTime = amount;\n            return this;\n        };\n        Tween.prototype.yoyo = function (yoyo) {\n            if (yoyo === void 0) { yoyo = false; }\n            this._yoyo = yoyo;\n            return this;\n        };\n        Tween.prototype.easing = function (easingFunction) {\n            if (easingFunction === void 0) { easingFunction = Easing.Linear.None; }\n            this._easingFunction = easingFunction;\n            return this;\n        };\n        Tween.prototype.interpolation = function (interpolationFunction) {\n            if (interpolationFunction === void 0) { interpolationFunction = Interpolation.Linear; }\n            this._interpolationFunction = interpolationFunction;\n            return this;\n        };\n        // eslint-disable-next-line\n        Tween.prototype.chain = function () {\n            var tweens = [];\n            for (var _i = 0; _i < arguments.length; _i++) {\n                tweens[_i] = arguments[_i];\n            }\n            this._chainedTweens = tweens;\n            return this;\n        };\n        Tween.prototype.onStart = function (callback) {\n            this._onStartCallback = callback;\n            return this;\n        };\n        Tween.prototype.onEveryStart = function (callback) {\n            this._onEveryStartCallback = callback;\n            return this;\n        };\n        Tween.prototype.onUpdate = function (callback) {\n            this._onUpdateCallback = callback;\n            return this;\n        };\n        Tween.prototype.onRepeat = function (callback) {\n            this._onRepeatCallback = callback;\n            return this;\n        };\n        Tween.prototype.onComplete = function (callback) {\n            this._onCompleteCallback = callback;\n            return this;\n        };\n        Tween.prototype.onStop = function (callback) {\n            this._onStopCallback = callback;\n            return this;\n        };\n        /**\n         * @returns true if the tween is still playing after the update, false\n         * otherwise (calling update on a paused tween still returns true because\n         * it is still playing, just paused).\n         *\n         * @param autoStart - When true, calling update will implicitly call start()\n         * as well. Note, if you stop() or end() the tween, but are still calling\n         * update(), it will start again!\n         */\n        Tween.prototype.update = function (time, autoStart) {\n            var _this = this;\n            var _a;\n            if (time === void 0) { time = now(); }\n            if (autoStart === void 0) { autoStart = Tween.autoStartOnUpdate; }\n            if (this._isPaused)\n                return true;\n            var property;\n            if (!this._goToEnd && !this._isPlaying) {\n                if (autoStart)\n                    this.start(time, true);\n                else\n                    return false;\n            }\n            this._goToEnd = false;\n            if (time < this._startTime) {\n                return true;\n            }\n            if (this._onStartCallbackFired === false) {\n                if (this._onStartCallback) {\n                    this._onStartCallback(this._object);\n                }\n                this._onStartCallbackFired = true;\n            }\n            if (this._onEveryStartCallbackFired === false) {\n                if (this._onEveryStartCallback) {\n                    this._onEveryStartCallback(this._object);\n                }\n                this._onEveryStartCallbackFired = true;\n            }\n            var elapsedTime = time - this._startTime;\n            var durationAndDelay = this._duration + ((_a = this._repeatDelayTime) !== null && _a !== void 0 ? _a : this._delayTime);\n            var totalTime = this._duration + this._repeat * durationAndDelay;\n            var calculateElapsedPortion = function () {\n                if (_this._duration === 0)\n                    return 1;\n                if (elapsedTime > totalTime) {\n                    return 1;\n                }\n                var timesRepeated = Math.trunc(elapsedTime / durationAndDelay);\n                var timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay;\n                // TODO use %?\n                // const timeIntoCurrentRepeat = elapsedTime % durationAndDelay\n                var portion = Math.min(timeIntoCurrentRepeat / _this._duration, 1);\n                if (portion === 0 && elapsedTime === _this._duration) {\n                    return 1;\n                }\n                return portion;\n            };\n            var elapsed = calculateElapsedPortion();\n            var value = this._easingFunction(elapsed);\n            // properties transformations\n            this._updateProperties(this._object, this._valuesStart, this._valuesEnd, value);\n            if (this._onUpdateCallback) {\n                this._onUpdateCallback(this._object, elapsed);\n            }\n            if (this._duration === 0 || elapsedTime >= this._duration) {\n                if (this._repeat > 0) {\n                    var completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat);\n                    if (isFinite(this._repeat)) {\n                        this._repeat -= completeCount;\n                    }\n                    // Reassign starting values, restart by making startTime = now\n                    for (property in this._valuesStartRepeat) {\n                        if (!this._yoyo && typeof this._valuesEnd[property] === 'string') {\n                            this._valuesStartRepeat[property] =\n                                // eslint-disable-next-line\n                                // @ts-ignore FIXME?\n                                this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]);\n                        }\n                        if (this._yoyo) {\n                            this._swapEndStartRepeatValues(property);\n                        }\n                        this._valuesStart[property] = this._valuesStartRepeat[property];\n                    }\n                    if (this._yoyo) {\n                        this._reversed = !this._reversed;\n                    }\n                    this._startTime += durationAndDelay * completeCount;\n                    if (this._onRepeatCallback) {\n                        this._onRepeatCallback(this._object);\n                    }\n                    this._onEveryStartCallbackFired = false;\n                    return true;\n                }\n                else {\n                    if (this._onCompleteCallback) {\n                        this._onCompleteCallback(this._object);\n                    }\n                    for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n                        // Make the chained tweens start exactly at the time they should,\n                        // even if the `update()` method was called way past the duration of the tween\n                        this._chainedTweens[i].start(this._startTime + this._duration, false);\n                    }\n                    this._isPlaying = false;\n                    return false;\n                }\n            }\n            return true;\n        };\n        Tween.prototype._updateProperties = function (_object, _valuesStart, _valuesEnd, value) {\n            for (var property in _valuesEnd) {\n                // Don't update properties that do not exist in the source object\n                if (_valuesStart[property] === undefined) {\n                    continue;\n                }\n                var start = _valuesStart[property] || 0;\n                var end = _valuesEnd[property];\n                var startIsArray = Array.isArray(_object[property]);\n                var endIsArray = Array.isArray(end);\n                var isInterpolationList = !startIsArray && endIsArray;\n                if (isInterpolationList) {\n                    _object[property] = this._interpolationFunction(end, value);\n                }\n                else if (typeof end === 'object' && end) {\n                    // eslint-disable-next-line\n                    // @ts-ignore FIXME?\n                    this._updateProperties(_object[property], start, end, value);\n                }\n                else {\n                    // Parses relative end values with start as base (e.g.: +10, -3)\n                    end = this._handleRelativeValue(start, end);\n                    // Protect against non numeric properties.\n                    if (typeof end === 'number') {\n                        // eslint-disable-next-line\n                        // @ts-ignore FIXME?\n                        _object[property] = start + (end - start) * value;\n                    }\n                }\n            }\n        };\n        Tween.prototype._handleRelativeValue = function (start, end) {\n            if (typeof end !== 'string') {\n                return end;\n            }\n            if (end.charAt(0) === '+' || end.charAt(0) === '-') {\n                return start + parseFloat(end);\n            }\n            return parseFloat(end);\n        };\n        Tween.prototype._swapEndStartRepeatValues = function (property) {\n            var tmp = this._valuesStartRepeat[property];\n            var endValue = this._valuesEnd[property];\n            if (typeof endValue === 'string') {\n                this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(endValue);\n            }\n            else {\n                this._valuesStartRepeat[property] = this._valuesEnd[property];\n            }\n            this._valuesEnd[property] = tmp;\n        };\n        Tween.autoStartOnUpdate = false;\n        return Tween;\n    }());\n\n    var VERSION = '25.0.0';\n\n    /**\n     * Tween.js - Licensed under the MIT license\n     * https://github.com/tweenjs/tween.js\n     * ----------------------------------------------\n     *\n     * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n     * Thank you all, you're awesome!\n     */\n    var nextId = Sequence.nextId;\n    /**\n     * Controlling groups of tweens\n     *\n     * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n     * In these cases, you may want to create your own smaller groups of tweens.\n     */\n    var TWEEN = mainGroup;\n    // This is the best way to export things in a way that's compatible with both ES\n    // Modules and CommonJS, without build hacks, and so as not to break the\n    // existing API.\n    // https://github.com/rollup/rollup/issues/1961#issuecomment-423037881\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var getAll = TWEEN.getAll.bind(TWEEN);\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var removeAll = TWEEN.removeAll.bind(TWEEN);\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var add = TWEEN.add.bind(TWEEN);\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var remove = TWEEN.remove.bind(TWEEN);\n    /**\n     * @deprecated The global TWEEN Group will be removed in a following major\n     * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n     * group.\n     *\n     * Old code:\n     *\n     * ```js\n     * import * as TWEEN from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new TWEEN.Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   TWEEN.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     *\n     * New code:\n     *\n     * ```js\n     * import {Tween, Group} from '@tweenjs/tween.js'\n     *\n     * //...\n     *\n     * const tween = new Tween(obj)\n     * const tween2 = new TWEEN.Tween(obj2)\n     *\n     * //...\n     *\n     * const group = new Group()\n     * group.add(tween)\n     * group.add(tween2)\n     *\n     * //...\n     *\n     * requestAnimationFrame(function loop(time) {\n     *   group.update(time)\n     *   requestAnimationFrame(loop)\n     * })\n     * ```\n     */\n    var update = TWEEN.update.bind(TWEEN);\n    var exports$1 = {\n        Easing: Easing,\n        Group: Group,\n        Interpolation: Interpolation,\n        now: now,\n        setNow: setNow,\n        Sequence: Sequence,\n        nextId: nextId,\n        Tween: Tween,\n        VERSION: VERSION,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        getAll: getAll,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        removeAll: removeAll,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        add: add,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        remove: remove,\n        /**\n         * @deprecated The global TWEEN Group will be removed in a following major\n         * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n         * group.\n         *\n         * Old code:\n         *\n         * ```js\n         * import * as TWEEN from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new TWEEN.Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   TWEEN.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         *\n         * New code:\n         *\n         * ```js\n         * import {Tween, Group} from '@tweenjs/tween.js'\n         *\n         * //...\n         *\n         * const tween = new Tween(obj)\n         * const tween2 = new TWEEN.Tween(obj2)\n         *\n         * //...\n         *\n         * const group = new Group()\n         * group.add(tween)\n         * group.add(tween2)\n         *\n         * //...\n         *\n         * requestAnimationFrame(function loop(time) {\n         *   group.update(time)\n         *   requestAnimationFrame(loop)\n         * })\n         * ```\n         */\n        update: update,\n    };\n\n    exports.Easing = Easing;\n    exports.Group = Group;\n    exports.Interpolation = Interpolation;\n    exports.Sequence = Sequence;\n    exports.Tween = Tween;\n    exports.VERSION = VERSION;\n    exports.add = add;\n    exports.default = exports$1;\n    exports.getAll = getAll;\n    exports.nextId = nextId;\n    exports.now = now;\n    exports.remove = remove;\n    exports.removeAll = removeAll;\n    exports.setNow = setNow;\n    exports.update = update;\n\n    Object.defineProperty(exports, '__esModule', { value: true });\n\n}));\n"
  },
  {
    "path": "docs/contributor_guide.md",
    "content": "# tween.js contributor guide\n\nMore languages: [English](./contributor_guide.md), [简体中文](./contributor_guide_zh-CN.md)\n\nThis guide is for people who want to _contribute_ to the library or are curious to learn what's behind the scenes: how is it tested? what do we automate? how do we do releases? etc.\n\nIf you are looking for documentation on _how to use_ the library, the [user guide](./user_guide.md) is for you.\n\n**NOTE: this document is a work in progress. More content will be added in stages. If you have questions you'd like to see answered, please add them [as comments on this issue](https://github.com/tweenjs/tween.js/issues/323). THANKS!**\n\nIn this guide:\n\n- [tween.js contributor guide](#tweenjs-contributor-guide)\n  - [Developer requirements](#developer-requirements)\n  - [Testing](#testing)\n    - [Unit tests](#unit-tests)\n    - [Code style and lint tests](#code-style-and-lint-tests)\n    - [Other types of tests](#other-types-of-tests)\n  - [Continuous integration](#continuous-integration)\n  - [Release process](#release-process)\n\n## Developer requirements\n\nAlthough tween.js does _not_ need node.js to work, we use it for development. So you will need to [install node.js](https://nodejs.org/en/download/) before you can work on the library.\n\nNode.js includes the `npm` tool that we use to run scripts such as the one for packaging, running tests, etc. Please make sure it is working in your system before you attempt to run any of the steps detailed below.\n\nOnce node.js is installed, clone the tween.js repository:\n\n```bash\ngit clone https://github.com/tweenjs/tween.js.git\n```\n\nChange to the folder:\n\n```bash\ncd tween.js\n```\n\nAnd run the script to install development dependencies:\n\n```bash\nnpm install\n```\n\nOr in three lines:\n\n```bash\ngit clone https://github.com/tweenjs/tween.js.git\ncd tween.js\nnpm install\n```\n\nOnce `npm install` completes successfully, try having a go at running the tests:\n\n```bash\nnpm test\n```\n\nIf you get issues running any of the above, try to search for the text of the error using your search engine of choice. This is normally the fastest route, as many people might have encountered the same issue already.\n\n## Testing\n\nThere's a suite of automated tests in the `test` directory.\n\nThese can quickly spot regressions on the code--useful when new features are added or when code is changed to fix a bug; we don't want to introduce new bugs! They also spot style issues, which helps us keep the library cohesive.\n\nTo run the tests, type:\n\n```bash\nnpm test\n```\n\nYou should run the tests after you change code in the library. If you change the behaviour the tests describe, the tests won't pass and you'll get an error pointing to the test(s) that failed. This might be either because...\n\n- you overlooked something or there's an error in your code, or...\n- the library or the tests themselves are wrong\n\nThe one that happens more frequently is the first one, but the second one has happened, with edge cases.\n\n**Another thing you should do once the automated tests pass is to run the examples in the `examples` folder**. It is rare, but it might happen that your changes introduced cosmetic differences that the automated tests are not checking for, and the only way to notice this is by running the examples and have a human spot the difference in output. If you don't want to checkout two copies of the library, you can look at [the online examples](https://github.com/tweenjs/tween.js#examples).\n\n### Unit tests\n\nTests are in the `src/tests.ts` file.\n\nThe tests are executed using [nodeunit](https://www.npmjs.com/package/nodeunit).\n\n**TODO:** the tests should also work if opening `test/unit/nodeunit.html` in a browser, but they are broken right now. There is [an open issue](https://github.com/tweenjs/tween.js/issues/307) to make them work again.\n\n### Code style and lint tests\n\nWe use [Prettier](https://prettier.io) and [ESLint](https://eslint.org) to ensure the code style is uniform.\n\nTo automatically format code and report any errors for pieces of code that aren't automatically formattable, run:\n\n```bash\nnpm run test-lint\n```\n\nThe Prettier rules are in `.prettierrc.js` and ESLint rules are in `.eslintrc.js`.\n\n### Other types of tests\n\nWe would like to test for performance regressions i.e. if a change made things go slower, or simply, for performance, so we can compare the performance of the same code between different browsers.\n\nThere's an [open issue](https://github.com/tweenjs/discuss/issues/3) to track work on this, but we have not made progress on it yet. Help! :-)\n\n## Continuous integration\n\nWe use GitHub Actions for continuous integration so that a build and tests will run for every pull request. The `.github/workflows/tests.yml` file tells GitHub what to run; in our case we run `npm install` followed by `npm test` in the OSes and versions of Node.js specified in that file.\n\n**TODO:** Add macOS and Windows to OSes that the tests run on. Help! :)\n\n## Release process\n\nCurrently the release process is manual.\n\nWhen ready to make a release on the `master` branch, ensure there are no un-committed changes, then run `npm run release:patch` to release a new version with its patch number bumped, `npm run release:minor` to release a new version with its minor number bumped, or `npm run release:major` to release a new version with its major number bumped.\n\nTip: see [semver.org](https://semver.org) and the [npm-semver](https://docs.npmjs.com/misc/semver) docs to learn about semantic versioning.\n"
  },
  {
    "path": "docs/contributor_guide_zh-CN.md",
    "content": "# tween.js 贡献者指南\n\n更多语言: [English](./contributor_guide.md), [简体中文](./contributor_guide_zh-CN.md)\n\n本指南适用于想要向库贡献的人，或者想了解背后的内容：如何进行测试？我们自动化什么？我们如何做发布？等等。\n\n如果你正在查找*如何使用*库的文档，[用户指南](./user_guide_zh-CN.md) 是适合你的。\n\n**NOTE: 这个文档是一个正在进行的工作。更多内容将分阶段添加。如果你有问题，你想看到回答，请在 [as comments on this issue](https://github.com/tweenjs/tween.js/issues/323) 中提出，谢谢！**\n\n目录:\n\n- [tween.js 贡献者指南](#tween.js-贡献者指南)\n- [开发者要求](#开发者要求)\n- [测试](#测试)\n  - [单元测试](#单元测试)\n  - [代码风格和 lint 测试](#代码风格和-lint-测试)\n  - [其他类型的测试](#其他类型的测试)\n- [持续集成](#持续集成)\n- [发布流程](#发布流程)\n\n## 开发者要求\n\n虽然 tween.js *不*需要依赖 node.js 运行，但我们使用 node.js 来进行开发。所以我们需要先 [安装 node.js](https://nodejs.org/en/download/)，然后才能在库中工作。\n\nNode.js 包括我们用来运行脚本的 npm 工具，例如打包、运行测试等的脚本。在你尝试运行下面详述的任何步骤之前，请确保它在你的系统中正常工作。\n\n安装 node.js 后，克隆 tween.js 存储库：\n\n```bash\ngit clone https://github.com/tweenjs/tween.js.git\n```\n\n进入该文件夹：\n\n```bash\ncd tween.js\n```\n\n并运行脚本来安装开发依赖项：\n\n```bash\nnpm install\n```\n\n或者分三行：\n\n```bash\ngit clone https://github.com/tweenjs/tween.js.git\ncd tween.js\nnpm install\n```\n\n`npm install` 成功完成后，尝试运行测试：\n\n```bash\nnpm test\n```\n\n如果你在运行上述任何步骤时遇到问题，请尝试使用你选择的搜索引擎搜索错误文本。这通常是最快的解决方法，因为很多人可能已经遇到过同样的问题。\n\n## 测试\n\n`test` 目录中有一套自动化测试。\n\n这些可以快速发现代码上的回归，在添加新功能或更改代码以修复 Bug 时很有用；我们不想引入新的 Bugs！自动化测试还会发现风格问题，这有助于我们保持库的凝聚力。\n\n要运行测试，请输入：\n\n```bash\nnpm test\n```\n\n你应该在更改库中的代码后运行测试。如果你更改测试描述的行为，测试将不会通过，你将得到指向失败测试的错误。 这可能是因为...\n\n- 你忽略了一些东西，或者你的代码有错误，或者...\n- 库或测试本身是错误的\n\n以上两种情况，发生频率更高的是第一个，但第如果二个发生了，可能是边缘情况。\n\n**自动化测试通过之后，你应该做的另一件事是运行 `examples` 文件夹中的示例**。有种情况很少见，但可能会发生：你的更改引入了自动测试未检查的外观差异，注意到这一点的唯一方法是运行示例并让人工发现输出中的差异。如果你不想签出库的两个副本，可以查看[在线例子](https://github.com/tweenjs/tween.js#examples)。\n\n### 单元测试\n\n测试用例在 `src/tests.ts` 文件中。\n\n测试使用 [nodeunit](https://www.npmjs.com/package/nodeunit) 执行。\n\n**TODO:** 如果在浏览器中打开 `test/unit/nodeunit.html`，测试也应该能够正常运行，但是现在已经被损坏。有一个 [打开的问题](https://github.com/tweenjs/tween.js/issues/307) 可以使他们再次工作。\n\n### 代码风格和 lint 测试\n\n我们使用 [JSCS](http://jscs.info/) 和 [JSHint](http://jshint.com/) 来保证代码风格的统一。\n\n要自动格式化代码并报告不可被格式化的代码片段的任何错误，请运行：\n\n```base\nnpm run test-lint\n```\n\nPrettier 规则在 `.prettierrc.js` 中，ESLint 规则在 `.eslintrc.js` 中。\n\n### 其他类型的测试\n\n我们想回归测试性能，即如果更改使运行变得更慢，或者简单地测试性能，那么我们可以比较不同浏览器之间相同代码的性能。\n\n有一个[open issue](https://github.com/tweenjs/discuss/issues/3)来跟踪这方面的工作，但我们还没有取得进展。请求帮助！ :-)\n\n## 持续集成\n\n我们使用 GitHub Actions 进行持续集成，以便为每个 pull request 运行构建和测试。 `.github/workflows/tests.yml` 文件告诉 GitHub 要运行什么；在我们的例子中，我们在该文件中指定的操作系统和 Node.js 版本中运行 `npm install`，然后运行 `npm test`。\n\n**TODO**：将 macOS 和 Windows 添加到运行测试的操作系统。 请求帮助！ :)\n\n## 发布流程\n\n目前发布过程是手动的。\n\n当准备好在 `master` 分支上发布时，确保没有未提交的更改，然后运行 `npm run release:patch` 发布一个新版本，其补丁号已被修改，`npm run release:minor` ，修改 minor 版本号并发布一个新版本，或者 `npm run release:major` 修改 major 版本号并发布一个新版本。\n\nTip: 请参阅 [semver.org](https://semver.org/) 和 [npm-semver](https://docs.npmjs.com/misc/semver) 文档以了解语义版本控制。\n"
  },
  {
    "path": "docs/user_guide.md",
    "content": "# tween.js user guide\n\nMore languages: [English](./user_guide.md), [简体中文](./user_guide_zh-CN.md)\n\n_**NOTE** This is a work in progress. If you find that something is unclear or missing details, please [file an issue](https://github.com/tweenjs/tween.js/issues/new) and help make this guide better. Or feel free to submit clarifications or improvements of your own if you feel you can help too!_\n\n## What is a tween? How do they work? Why do you want to use them?\n\nA tween (from [_in-between_](http://en.wikipedia.org/wiki/Inbetweening)) is a concept that allows you to change the values of the properties of an object in a smooth way. You just tell it which properties you want to change, which final values should they have when the tween finishes running, and how long should this take, and the tweening engine will take care of finding the intermediate values from the starting to the ending point.\n\nFor example, suppose you have a `position` object with `x` and `y` coordinates:\n\n```javascript\nconst position = {x: 100, y: 0}\n```\n\nIf you wanted to change the `x` value from `100` to `200`, you'd do this:\n\n```javascript\nimport {Tween} from '@tweenjs/tween.js'\n\n// Create a tween for position first\nconst tween = new Tween(position)\n\n// Then tell the tween we want to animate the x property over 1000 milliseconds\ntween.to({x: 200}, 1000)\n```\n\nActually this won't do anything yet. The tween has been created but it's not active. You need to start it:\n\n```javascript\n// And set it to start\ntween.start()\n```\n\nFinally in order to run as smoothly as possible you should call the `tween.update()` function in the same main loop you're using for animating. This generally looks like this:\n\n```javascript\nanimate()\n\nfunction animate() {\n\trequestAnimationFrame(animate)\n\t// [...]\n\ttween.update()\n\t// [...]\n}\n```\n\nAfter 1 second (i.e. 1000 milliseconds) `position.x` will be `200`.\n\nBut unless you print the value of `x` to the console, you can't see its value changing. You might want to use the `onUpdate` callback:\n\n```javascript\ntween.onUpdate(function (object) {\n\tconsole.log(object.x)\n})\n```\n\nThis function will be called each time the tween is updated; how often this happens depends on many factors--how fast (and how busy!) your computer or device is, for example.\n\nSo far we've only used tweens to print values to the console, but you could use it for things such as animating positions of three.js objects:\n\n```javascript\nconst tween = new Tween(cube.position).to({x: 100, y: 100, z: 100}, 10000).start()\n\nanimate()\n\nfunction animate() {\n\trequestAnimationFrame(animate)\n\ttween.update()\n\n\tthreeRenderer.render(scene, camera)\n}\n```\n\nIn this case, because the three.js renderer will look at the object's position before rendering, you don't need to use an explicit `onUpdate` callback.\n\nYou might have noticed something different here too: we're chaining the tween function calls! Each tween function returns the tween instance, so you can rewrite the following code:\n\n```javascript\nconst tween = new Tween(position)\ntween.to({x: 200}, 1000)\ntween.start()\n```\n\ninto this\n\n```javascript\nconst tween = new Tween(position).to({x: 200}, 1000).start()\n```\n\nYou'll see this a lot in the examples, so it's good to be familiar with it! Check [04-simplest](../examples/04_simplest.html) for a working example.\n\n## Animating with tween.js\n\nTween.js doesn't run by itself. You need to tell it when to run, by explicitly calling the `update` method of each tween, or the `update` method of a `Group` that has multiple tweens (more on Groups below). The recommended method is to do this inside your main animation loop, which should be called with `requestAnimationFrame` for getting the best graphics performance:\n\nWe've seen this example before:\n\n```javascript\nanimate()\n\nfunction animate() {\n\trequestAnimationFrame(animate)\n\t// [...]\n\ttween.update()\n\t// [...]\n}\n```\n\nIf called without parameters, `update` will determine the current time in order to find out how long has it been since the last time it ran.\n\nHowever you can also pass an explicit time parameter to `update`. Thus,\n\n```javascript\ntween.update(100)\n```\n\nmeans \"update with time = 100 milliseconds\". You can use this to make sure that all the time-dependent functions in your code are using the very same time value. For example, suppose you've got a player and want to run tweens in sync. Your `animate` code could look like this:\n\n```javascript\nlet currentTime = player.currentTime\ntween.update(currentTime)\n```\n\nWe use explicit time values for the unit tests. You can have a look at [tests.ts](../src/tests.ts) to see how we call `tween.update()` with different values in order to simulate time passing.\n\n## Controlling a tween\n\n### `start` and `stop`\n\nSo far we've learnt about the `Tween.start` method, but there are more methods that control individual tweens. Probably the most important one is the `start` counterpart: `stop`. If you want to cancel a tween, just call this method over an individual tween:\n\n```js\ntween.stop()\n```\n\nStopping a tween that was never started or that has already been stopped has no effect. No errors are thrown either.\n\nThe `start` method also accepts a `time` argument. If you use it, the tween won't start until that particular moment in time; otherwise it will start as soon as possible (i.e. on the next call to `tween.update()`).\n\nThe `start` method accepts a second boolean argument: when `true`, a tween that we previously used will start from the values in the target object, instead of starting from the beginning. Useful for stopping a tween, then starting another one that will continue from the current location.\n\n### `startFromCurrentValues`\n\nThis is an alias for `tween.start(undefined, true)`, to make a previously-used\ntween start from the last values of the target object, instead of from the\nbeginning.\n\n### `update`\n\nIndividual tweens have an `update` method to so that they can be updated over time in an animation loop, and on each update they will apply updated values to their target object.\n\n```js\nconst tween = new Tween(someObject).to(/*...*/).start()\n\nfunction animate(time) {\n\ttween.update(time)\n\trequestAnimationFrame(animate)\n}\n```\n\n### `pause`\n\nWhile an tween is running (i.e. it has already been `start`ed and may have\nalready been `update`d numerous times) it can be paused. Even if `update()` is\ncalled while the tween is paused, its time will not move forward. `isPlaying`\nwill still be true while a tween is `paused` and its `update()` method continues\nto track time progression (you can continue to call `update()` while a tween is\npaused).\n\n```js\ntween.start()\n\nfunction animate() {\n\ttween.update()\n\trequestAnimationFrame(animate)\n}\nanimate()\n\n// at any time while the tween is running\ntween.pause()\n```\n\n### `chain`\n\nThings get more interesting when you sequence different tweens in order, i.e. setup one tween to start once a previous one has finished. We call this _chaining tweens_, and it's done with the `chain` method. Thus, to make `tweenB` start after `tweenA` finishes:\n\n```javascript\ntweenA.chain(tweenB)\n```\n\nOr, for an infinite chain, set `tweenA` to start once `tweenB` finishes:\n\n```javascript\ntweenA.chain(tweenB)\ntweenB.chain(tweenA)\n```\n\nCheck [Hello world](../examples/00_hello_world.html) to see an example of these infinite chains.\n\nIn other cases, you may want to chain multiple tweens to another tween in a way that they (the chained tweens) all start animating at the same time:\n\n```javascript\ntweenA.chain(tweenB, tweenC)\n```\n\n> **Warning** Calling `tweenA.chain(tweenB)` actually modifies tweenA so that tweenB is always started when tweenA finishes. The return value of `chain` is just tweenA, not a new tween.\n\n### `repeat`\n\nIf you wanted a tween to repeat forever you could chain it to itself, but a better way is to use the `repeat` method. It accepts a parameter that describes how many repetitions you want after the first tween is completed:\n\n```javascript\ntween.repeat(10) // repeats 10 times after the first tween and stops\ntween.repeat(Infinity) // repeats forever\n```\n\nThe total number of tweens will be the repeat parameter plus one for the initial tween.\nCheck the [Repeat](../examples/08_repeat.html) example.\n\n### `yoyo`\n\nThis function only has effect if used along with `repeat`. When active, the behaviour of the tween will be _like a yoyo_, i.e. it will bounce to and from the start and end values, instead of just repeating the same sequence from the beginning:\n\n```js\ntween.yoyo(false) // default value, animation will only go from start to end value\ntween.yoyo(true) // tween will 'yoyo' between start and end values\n```\n\n### `delay`\n\nMore complex arrangements might require delaying a tween before it actually starts running. You can do that using the `delay` method:\n\n```javascript\ntween.delay(1000)\ntween.start()\n```\n\nwill start executing 1 second after the `start` method has been called.\n\n### `repeatDelay`\n\nNormally the `delay` time is applied between repetitions of a tween, but if a value is provided to the `repeatDelay` function then that value will determine the total time elapsed between repetitions of a tween.\n\nConsider this example:\n\n```javascript\ntween.delay(1000)\ntween.repeatDelay(500)\ntween.start()\n```\n\nThe first iteration of the tween will happen after one second, the second iteration will happen a half second after the first iteration ends, the third iteration will happen a half second after the second iteration ends, etc. If you want to delay the initial iteration but you don't want any delay between iterations, then make sure to call `tween.repeatDelay(0)`.\n\n### `dynamic`\n\nIf `dynamic` is set to `true` (it defaults to `false`) objects passed to `tween.to()` can be modified on the outside of a tween while the tween is animating. This can be used to dynamically modify the outcome of a tween while it is running.\n\nSee the [Dynamic to](http://tweenjs.github.io/tween.js/examples/07_dynamic_to.html) example. In that example, in both scenes, the position of the rabbit is updated during the animation. The rabbit position happens to be the object passed into the fox's `tween.to()` method. As the rabbit position is updated, in the first scene with `.dynamic(false)` the fox moves towards the initial position of the rabbit and does not chase the rabbit, and in the second scene with `.dynamic(true)` the final destination of the fox is hence also updated which makes the fox chase the rabbit.\n\nSee the other `dynamic to` examples for more ideas.\n\n> **Warning** When `dynamic` is set to `false`, Tween makes a copy of the object passed into `tween.to()` and will never modify it (hence updating the original object from the outside is not dynamic). When `dynamic` is `true`, Tween uses the original object as the source of values during animation (every update reads the values, hence they can be modified dynamically) but note that **in dynamic mode, Tween will modify any interpolation arrays of the object passed into `tween.to()` which may cause side-effects on any external code that may also rely on the same object**.\n\n## Controlling groups of tweens\n\nSometimes you want to update multiple tweens at once, which can be useful when\ngrouping a set of tweens into a logical component in your application. You can\ndo this with a `Group`.\n\nFirst add multiple tweens to a group:\n\n```js\nimport {Group, Tween} from '@tweenjs/tween.js'\n\nconst tween1 = new Tween(obj1).to(...).start()\nconst tween2 = new Tween(obj2).to(...).start()\n\nconst group = new Group()\ngroup.add(tween1)\ngroup.add(tween2)\n```\n\nThen call `group.update()` in your animation loop instead of on individual\ntweens:\n\n```js\nanimate()\n\nfunction animate() {\n\trequestAnimationFrame(animate)\n\t// [...]\n\tgroup.update()\n\t// [...]\n}\n```\n\nNote that a tween can only belong to a single group. Adding a tween to a group\nautomatically removes it from any previous group.\n\n### `group.getAll()`\n\nReturns an array of all tweens added to a group.\n\n### `group.add(tween)`\n\nAdd a tween to a group.\n\n### `group.remove(tween)`\n\nRemove a tween from a group.\n\n### `group.removeAll()`\n\nRemove all tween from a group.\n\n### `group.update(time?)`\n\nUpdate all tweens in a group, with an optional time value. If time value is not\nsupplied, it default to the current time.\n\n## Changing the easing function (AKA make it bouncy)\n\nTween.js will perform the interpolation between values (i.e. the easing) in a linear manner, so the change will be directly proportional to the elapsed time. This is predictable but also quite uninteresting visually wise. Worry not--this behaviour can be easily changed using the `easing` method. For example:\n\n```javascript\nimport {Tween, Easing} from '@tweenjs/tween.js'\n// ...\ntween.easing(Easing.Quadratic.In)\n```\n\nThis will result in the tween slowly starting to change towards the final value, accelerating towards the middle, and then quickly reaching its final value. In contrast, `Easing.Quadratic.Out` would start changing quickly towards the value, but then slow down as it approaches the final value.\n\n### Available `Easing` functions\n\nThere are a few existing easing functions provided with tween.js. They are grouped by the type of equation they represent: Linear, Quadratic, Cubic, Quartic, Quintic, Sinusoidal, Exponential, Circular, Elastic, Back and Bounce, and then by the easing type: In, Out and InOut.\n\nProbably the names won't be saying anything to you unless you're familiar with these concepts already, so it is probably the time to check the [Graphs](../examples/03_graphs.html) example, which graphs all the curves in one page so you can compare how they look at a glance.\n\n`Easing` also has a function called `generatePow()`. This function generates easing functions for different curves depending on arguments. You can check the relevance of the arguments to curves in the [example of pow easing](../examples/17_generate_pow.html) page.\n\n_Credit where credit is due:_ these functions are derived from the original set of equations that Robert Penner graciously made available as free software a few years ago, but have been optimised to play nicely with JavaScript.\n\n### Using a custom easing function\n\nNot only can you use any of the existing functions, but you can also provide your own, as long as it follows a couple of conventions:\n\n- it must accept one parameter:\n  - `k`: the easing progress, or how far along the duration of the tween we are. Allowed values are in the range [0, 1].\n- it must return a value based on the input parameters.\n\nThe easing function is only called _once per tween_ on each update, no matter how many properties are to be changed. The result is then used with the initial value and the difference (the _deltas_) between this and the final values, as in this pseudocode:\n\n```\neasedElapsed = easing(k);\nfor each property:\n    newPropertyValue = initialPropertyValue + propertyDelta * easedElapsed;\n```\n\nFor the performance-obsessed people out there: the deltas are calculated only when `start()` is called on a tween.\n\nSo let's suppose you wanted to use a custom easing function that eased the values but applied a Math.floor to the output, so only the integer part would be returned, resulting in a sort of step-ladder output:\n\n```javascript\nfunction tenStepEasing(k) {\n\treturn Math.floor(k * 10) / 10\n}\n```\n\nAnd you could use it in a tween by simply calling its easing method, as we've seen before:\n\n```javascript\ntween.easing(tenStepEasing)\n```\n\nCheck the [graphs for custom easing functions](../examples/12_graphs_custom_functions.html) example to see this in action (and also some _metaprogramming_ for generating step functions).\n\n## Callbacks\n\nAnother powerful feature is to be able to run your own functions at specific times in each tween's life cycle. This is usually required when changing properties is not enough.\n\nFor example, suppose you're trying to animate some object whose properties can't be accessed directly but require you to call a setter instead. You can use an `update` callback to read the new updated values and then manually call the setters. All callbacks are passed the tweened object as the only parameter.\n\n```javascript\nconst trickyObjTween = new Tween({\n\tpropertyA: trickyObj.getPropertyA(),\n\tpropertyB: trickyObj.getPropertyB(),\n})\n\t.to({propertyA: 100, propertyB: 200})\n\t.onUpdate(function (object) {\n\t\tobject.setA(object.propertyA)\n\t\tobject.setB(object.propertyB)\n\t})\n```\n\nOr imagine you want to play a sound when a tween is started. You can use a `start` callback:\n\n```javascript\nconst tween = new Tween(obj).to({x: 100}).onStart(function () {\n\tsound.play()\n})\n```\n\nThe scope for each callback is the tweened object--in this case, `obj`.\n\n### onStart\n\nExecuted right before the tween starts animating, after any delay time specified by the `delay` method. This will be executed only once per tween, i.e. it will _not_ be run when the tween is repeated via `repeat()`.\n\nIt is great for synchronising to other events or triggering actions you want to happen when a tween starts.\n\nThe tweened object is passed in as the first parameter.\n\n### onEveryStart\n\nAs per `onStart`, except that it _will_ be run on every repeat of the tween.\n\nThe tweened object is passed in as the first parameter.\n\n### onStop\n\nExecuted when a tween is explicitly stopped via `stop()`, but not when it is completed normally, and before stopping any possible chained tween.\n\nThe tweened object is passed in as the first parameter.\n\n### onUpdate\n\nExecuted each time the tween is updated, after the values have been actually updated.\n\nThe tweened object is passed in as the first parameter.\n\n### onComplete\n\nExecuted when a tween is finished normally (i.e. not stopped).\n\nThe tweened object is passed in as the first parameter.\n\n### onRepeat\n\nExecuted whenever a tween has just finished one repetition and will begin another.\n\nThe tweened object is passed in as the first parameter.\n\nTo clarify when `onStart`, `onEveryStart` and `onRepeat` are called, consider:\n\n```javascript\nconst obj = {x: 0}\n\nconst t = new Tween(obj)\n\t.to({x: 5}, 5)\n\t.repeat(Infinity)\n\t.onStart(() => {\n\t\tconsole.log('onStart')\n\t})\n\t.onRepeat(() => {\n\t\tconsole.log('onRepeat')\n\t})\n\t.onEveryStart(() => {\n\t\tconsole.log('onEveryStart')\n\t})\n\t.start(0)\n\nfor (let ticks = 0; ticks < 22; ticks += 1) {\n\tconsole.log('Tick', ticks)\n\tt.update(ticks)\n\n\tconsole.log(obj)\n\tconsole.log()\n}\n```\n\nThe output would look like this, on the left as above, and on the right with `.delay(5)`:\n\n```\nTick 0           Tick 0\nonStart          { x: 0 }\nonEveryStart\n{ x: 0 }\n\nTick 1           Tick 1\n{ x: 1 }         { x: 0 }\n\nTick 2           Tick 2\n{ x: 2 }         { x: 0 }\n\nTick 3           Tick 3\n{ x: 3 }         { x: 0 }\n\nTick 4           Tick 4\n{ x: 4 }         { x: 0 }\n\nTick 5           Tick 5\nonRepeat         onStart\n{ x: 5 }         onEveryStart\n                 { x: 0 }\n\nTick 6           Tick 6\nonEveryStart     { x: 1 }\n{ x: 1 }\n\nTick 7           Tick 7\n{ x: 2 }         { x: 2 }\n\nTick 8           Tick 8\n{ x: 3 }         { x: 3 }\n\nTick 9           Tick 9\n{ x: 4 }         { x: 4 }\n\nTick 10          Tick 10\nonRepeat         onRepeat\n{ x: 5 }         { x: 5 }\n\nTick 11          Tick 11\nonEveryStart     { x: 5 }\n{ x: 1 }\n\nTick 12          Tick 12\n{ x: 2 }         { x: 5 }\n\nTick 13          Tick 13\n{ x: 3 }         { x: 5 }\n\nTick 14          Tick 14\n{ x: 4 }         { x: 5 }\n\nTick 15          Tick 15\nonRepeat         onEveryStart\n{ x: 5 }         { x: 0 }\n\nTick 16          Tick 16\nonEveryStart     { x: 1 }\n{ x: 1 }\n\nTick 17          Tick 17\n{ x: 2 }         { x: 2 }\n\nTick 18          Tick 18\n{ x: 3 }         { x: 3 }\n\nTick 19          Tick 19\n{ x: 4 }         { x: 4 }\n\nTick 20          Tick 20\nonRepeat         onRepeat\n{ x: 5 }         { x: 5 }\n\nTick 21          Tick 21\nonEveryStart     { x: 5 }\n{ x: 1 }\n```\n\n## Tween State\n\n### `isPlaying`\n\n`tween.isPlaying` is `true` when a tween is started, even if it is paused.\n\nWhen a tween is stopped, `isPlaying` and `isPaused` will both be `false`, so `!tween.isPlaying()` can be used to detect if a tween is stopped (regardless if the tween has completed).\n\n### `isPaused`\n\n`tween.isPaused` is `true` when a tween is paused. `isPlaying` will also be `true`. If a tween is started, but not paused, `isPlaying` will be `true` and `isPaused` will be `false`.\n\n## Advanced tweening\n\n### Relative values\n\nYou can also use relative values when using the `to` method. When the tween is started, Tween.js will read the current property values and apply the relative values to find out the new final values. But **you need to use quotes** or the values will be taken as absolute. Let's see this with an example:\n\n```javascript\n// This will make the `x` property be 100, always\nconst absoluteTween = new Tween(absoluteObj).to({x: 100})\n\n// Suppose absoluteObj.x is 0 now\nabsoluteTween.start() // Makes x go to 100\n\n// Suppose absoluteObj.x is -100 now\nabsoluteTween.start() // Makes x go to 100\n\n// In contrast...\n\n// This will make the `x` property be 100 units more,\n// relative to the actual value when it starts\nconst relativeTween = new Tween(relativeObj).to({x: '+100'})\n\n// Suppose relativeObj.x is 0 now\nrelativeTween.start() // Makes x go to 0 +100 = 100\n\n// Suppose relativeObj.x is -100 now\nrelativeTween.start() // Makes x go to -100 +100 = 0\n```\n\nCheck [09_relative_values](../examples/09_relative_values.html) for an example.\n\n### Tweening nested objects\n\nTween.js can also change properties across nested objects. For example:\n\n```javascript\nconst nestedObject = {scale: {x: 0, y: 0}, alpha: 0}\nconst tween = new Tween(nestedObject).to({scale: {x: 100, y: 100}, alpha: 1})\n```\n\n### Tweening to arrays of values\n\nIn addition to tweening to an absolute or a relative value, you can also have Tween.js change properties across a series of values. To do this, you just need to specify an array of values instead of a single value for a property. For example:\n\n```javascript\nconst tween = new Tween(relativeObj).to({x: [0, -100, 100]})\n```\n\nwill make `x` go from its initial value to 0, -100 and 100.\n\nThe way these values are calculated is as follows:\n\n- first the tween progress is calculated as usual\n- the progress (from 0 to 1) is used as input for the interpolation function\n- based on the progress and the array of values, an interpolated value is generated\n\nFor example, when the tween has just started (progress is 0), the interpolation function will return the first value in the array. When the tween is halfway, the interpolation function will return a value approximately in the middle of the array, and when the tween is at the end, the interpolation function will return the last value.\n\nYou can change the interpolation mode by passing an `Interpolation` function\ninto the `tween.interpolation` method. For example:\n\n```javascript\nimport {Interpolation} from '@tweenjs/tween.js'\n// ...\ntween.interpolation(Interpolation.Bezier)\n```\n\nThe following values are available:\n\n- `Interpolation.Linear`\n- `Interpolation.Bezier`\n- `Interpolation.CatmullRom`\n\nThe default is `Linear`.\n\nNote that the interpolation function is global to all properties that are tweened with arrays in the same tween. You can't make property A change with an array and a Linear function, and property B with an array too and a Bezier function using the same tween; you should use two tween objects running over the same object but modifying different properties and using different interpolation functions.\n\nCheck [06_array_interpolation](../examples/06_array_interpolation.html) for an example.\n\n## Changing the Definition of \"Now\"\n\nWhen working with tweening, you inevitably rely on a definition of what \"now\" is. By default, Tween.js uses performance.now, which is a reliable and precise approach. However, if you need to adjust the flow of time—for instance, to slow it down or manipulate it for a custom purpose—you may encounter discrepancies between your internal definition of \"now\" and what Tween.js considers \"now.\"\n\nTo address this, a new function, setNow, has been introduced. This function allows you to redefine the internal \"now\" used by Tween.js. You can pass a custom function to setNow, which will replace the default definition. This provides greater flexibility and enables synchronization with your specific requirements for time control.\n\n## Getting the best performance\n\nWhile Tween.js tries to be performant on its own, nothing prevents you from using it in a way that is counterperformant. Here are some of the ways you can avoid slowing down your projects when using Tween.js (or when animating in the web, in general).\n\n### Use performant CSS\n\nWhen you try to animate the position of an element in the page, the easiest solution is to animate the `top` and `left` style properties, like this:\n\n```javascript\nconst element = document.getElementById('myElement')\nconst tween = new Tween({top: 0, left: 0}).to({top: 100, left: 100}, 1000).onUpdate(function (object) {\n\telement.style.top = object.top + 'px'\n\telement.style.left = object.left + 'px'\n})\n```\n\nbut this is really inefficient because altering these properties forces the browser to recalculate the layout on each update, and this is a very costly operation. Instead of using these, you should use `transform`, which doesn't invalidate the layout and will also be hardware accelerated when possible, like this:\n\n```javascript\nconst element = document.getElementById('myElement')\nconst tween = new Tween({top: 0, left: 0}).to({top: 100, left: 100}, 1000).onUpdate(function (object) {\n\telement.style.transform = 'translate(' + object.left + 'px, ' + object.top + 'px)'\n})\n```\n\nIf you want to read more about this, have a look at [this article](http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/).\n\nHowever, if your animation needs are _that_ simple, it might be better to just use CSS animations or transitions, where applicable, so that the browser can optimise as much as possible. Tween.js is most useful when your animation needs involve complex arrangements, i.e. you need to sync several tweens together, have some start after one has finished, loop them a number of times, have graphics that are not rendered with CSS but with Canvas or WebGL, etc.\n\n### Be good to the Garbage collector (alias the GC)\n\nIf you use an `onUpdate` callback, you need to be very careful with what you put on it. This function will be called many times per second, so if you're doing costly operations on each update, you might block the main thread and cause horrible _jank_, or---if your operations involve memory allocations, you'll end up getting the garbage collector to run too often, and cause _jank_ too. So just don't do either of those things. Keep your `onUpdate` callbacks very lightweight, and be sure to also use a memory profiler while you're developing.\n\n## Crazy tweening\n\nThis is something you might not use often, but you can use the tweening equations outside of Tween.js. They're just functions, after all. So you could use them to calculate smooth curves as input data. For example, they're used to generate audio data in [this experiment](http://5013.es/toys/tween.audio/).\n"
  },
  {
    "path": "docs/user_guide_zh-CN.md",
    "content": "## tween.js 用户指南\n\n更多语言: [English](./user_guide.md), [简体中文](./user_guide_zh-CN.md)\n\n中文用户指南最近更新为 Tween.js v20.0.3\n\n_**NOTE** 这是一个正在进行的工作。 如果你发现某些内容不清楚或缺少详细信息，请 [提出 issue](https://github.com/tweenjs/tween.js/issues/new) 并帮助改进本指南。 或者，如果你觉得自己也能提供帮助，请随时提交你自己的说明或改进！_\n\n## 什么是 tween ？tween 是如何工作的？为什么要使用 tween ？\n\n补间（动画）（来自 [in-between](https://en.wikipedia.org/wiki/Inbetweening)）是一个概念，允许你以平滑的方式更改对象的属性。你只需告诉它哪些属性要更改，当补间结束运行时它们应该具有哪些最终值，以及这需要多长时间，补间引擎将负责计算从起始点到结束点的值。\n\n例如，`position` 对象拥有 `x` 和 `y` 两个坐标：\n\n```js\nconst position = {x: 100, y: 0}\n```\n\n如果你想将 `x` 坐标的值从 `100` 变成 `200` ，你应该这么做：\n\n```js\n// 首先为位置创建一个补间(tween)\nconst tween = new TWEEN.Tween(position)\n\n// 然后告诉 tween 我们想要在1000毫秒内以动画的形式移动 x 的位置\ntween.to({x: 200}, 1000)\n```\n\n通常来说这样还不够，tween 已经被创建了，但是它还没被激活(使用)，你需要这样启动：\n\n```js\n// 启动\ntween.start()\n```\n\n最后，想要成功的完成这种效果，你需要在主函数中调用 `TWEEN.update` ，如下使用：\n\n```js\nanimate()\n\nfunction animate() {\n\trequestAnimationFrame(animate)\n\t// [...]\n\tTWEEN.update()\n\t// [...]\n}\n```\n\n这样在更新每帧的时候都会运行补间动画；经过 1 秒（1000 毫秒）后 `position.x` 将会变成 `200`。\n\n除非你在控制台中打印出 `x` 的值，不然你看不到它的变化。你可能想要使用 `onUpdate` 回调:\n\n```js\ntween.onUpdate(function (object) {\n\tconsole.log(object.x)\n})\n```\n\n每次更新补间时都会调用此函数； 这种情况发生的频率取决于许多因素——例如，你的计算机或设备的速度有多快（以及有多繁忙！）。\n\n到目前为止，我们只使用 tweens 将值打印到控制台，但你可以将它用于 three.js 对象的动画位置之类的事情：\n\n```js\nconst tween = new TWEEN.Tween(cube.position).to({x: 100, y: 100, z: 100}, 10000).start()\n\nanimate()\n\nfunction animate() {\n\trequestAnimationFrame(animate)\n\tTWEEN.update()\n\n\tthreeRenderer.render(scene, camera)\n}\n```\n\n在这种情况下，因为 three.js 渲染器将在渲染之前查看对象的位置，所以不需要使用的 `onUpdate` 回调。\n\n你可能也注意到了一些不同的地方：tween.js 可以链式调用！ 每个 tween 函数都会返回 tween 实例，所以你可以重写下面的代码：\n\n```js\nconst tween = new TWEEN.Tween(position)\ntween.to({x: 200}, 1000)\ntween.start()\n```\n\n改成这样：\n\n```js\nconst tween = new TWEEN.Tween(position).to({x: 200}, 1000).start()\n```\n\n在将会看到很多例子，所以熟悉它是很好的！比如 [04-simplest](../examples/04_simplest.html) 这个例子。\n\n## tween.js 的动画\n\nTween.js 不会自行运行。你需要显式的调用 `update` 方法来告诉它何时运行。推荐的方法是在主动画循环中执行这个操作。使用 `requestAnimationFrame` 调用此循环以获得最佳的图形性能。\n\n比如之前这个例子：\n\n```js\nanimate()\n\nfunction animate() {\n\trequestAnimationFrame(animate)\n\t// [...]\n\tTWEEN.update()\n\t// [...]\n}\n```\n\n如果不带参数调用，`update` 将会判断当前时间点，以便找出自上次运行以来已经过了多长时间。\n\n当然你也可以传递一个明确的时间参数给 `update` 来更新。因此：\n\n```js\nTWEEN.update(100)\n```\n\n意思是“更新时间 = 100 毫秒”。你可以使用它来确保代码中的所有时间相关函数都使用相同的时间值。例如，假设你有一个播放器，并希望同步运行补间。 你的 `animate` 函数可能看起来像这样：\n\n```js\nconst currentTime = player.currentTime\nTWEEN.update(currentTime)\n```\n\n我们使用明确的时间值进行单元测试。你可以看下 [tests.ts](../src/tests.ts) 这个例子，看看我们如何用不同的值调用`TWEEN.update()` 来模拟时间传递。\n\n## 控制一个补间\n\n### `start` 和 `stop`\n\n到目前为止，我们已经了解了 `Tween.start` 方法，但是还有更多的方法来控制单个补间。也许最重要的一个是 `start` 对应的方法：`stop` 。 如果你想取消一个补间，只要调用这个方法通过一个单独的补间:\n\n```js\ntween.stop()\n```\n\n停止一个从未开始或已经停止的补间没有任何效果。 没有错误被抛出。\n\n`start` 方法还接受一个 `time` 参数。如果你使用它，补间直到那个特定的时刻才会开始；否则它将立即开始（即在下一次调用 `TWEEN.update` 时）。\n\n`start` 方法接受第二个布尔参数：当为 `true` 时，我们之前使用的补间将从目标对象中的值开始，而不是从头开始。用于停止补间，然后启动另一个将从当前位置继续的补间。\n\n### `startFromCurrentValues`\n\n这是 `tween.start(undefined, true)` 的别名，使以前使用的补间从目标对象的最后一个值开始，而不是从头开始。\n\n### `update`\n\n个别补间有一个 `update` 方法。 这实际上是由 `TWEEN.update` 调用的，用于仅使用一个参数构建的补间。\n\n在下面的示例中，第二个参数告诉新的 Tween 不要将自己添加到默认组（`TWEEN` 是 `TWEEN.Group` 的一个实例）。如果补间不与组关联（请注意，可以通过将组作为第二个参数传递给构造函数来关联组），则补间需要使用其 `update` 方法手动更新，如下所示：\n\n```js\nconst tween = new TWEEN.Tween(someObject, false).to(/*...*/).start()\n\nfunction animate(time) {\n\ttween.update(time)\n\trequestAnimationFrame(animate)\n}\n```\n\n> **Note** 如果你使用 `TWEEN.update()` 作为默认控制所有补间的方式，则无需直接调用 `tween.update()`，但是我们建议你直接如上例所示 [创建自己的补间组](#controlling-groups-of-tweens) 或手动更新补间。 使用组或单独控制的补间的概念很像避免在 JavaScript 代码中使用全局变量的做法：它可以防止一个组件意外破坏其他一些不相关组件的行为。\n\n### `chain`\n\n当你按顺序排列不同的补间时，事情会变得更有趣，例如在上一个补间结束的时候立即启动另外一个补间。我们称此为链接补间，它是通过 `chain` 方法完成的。因此，要使 `tweenB` 在 `tweenA` 完成后开始：\n\n```js\ntweenA.chain(tweenB)\n```\n\n或者，可以创造一个无限的链式，`tweenA` 完成时开始 `tweenB`，`tweenB` 完成时开始 `tweenA`：\n\n```js\ntweenA.chain(tweenB)\ntweenB.chain(tweenA)\n```\n\n关于无限的链式查看案例 [Hello world](../examples/00_hello_world.html) 。\n\n在其他情况下，你可能希望将多个补间链接到另一个补间，使它们（链接的补间）都同时开始动画：\n\n```js\ntweenA.chain(tweenB, tweenC)\n```\n\n> **Warning** 调用 `tweenA.chain（tweenB）` 实际上修改了 tweenA，所以 tweenB 总是在 tweenA 完成时启动。 `chain` 的返回值只是 tweenA，不是一个新的 tween。\n\n### `repeat`\n\n如果你想让一个补间永远重复，你可以链接到自己，但更好的方法是使用 `repeat` 方法。它接受一个参数，描述第一个补间完成后需要多少次重复：\n\n```js\ntween.repeat(10) // 循环10次\ntween.repeat(Infinity) // 无限循环\n```\n\n补间的总次数将是重复参数加上一个初始补间。查看 [Repeat](../examples/08_repeat.html) 。\n\n### `yoyo`\n\n此功能仅在与 `repeat` 一起使用时才有效。 激活时，补间的行为将 _像溜溜球一样_，即它会在开始值和结束值之间来回跳动，而不是仅仅从头开始重复相同的顺序：\n\n```js\ntween.yoyo(false) // 默认值，动画只会从开始到结束值\ntween.yoyo(true) // tween 将在起始值和结束值之间“yoyo”\n```\n\n### `delay`\n\n更复杂的安排可能需要在实际开始运行之前延迟补间。 你可以使用 `delay` 方法来做到这一点：\n\n```js\ntween.delay(1000)\ntween.start()\n```\n\n将在调用 `start` 方法后的 1 秒钟后开始执行。\n\n### `repeatDelay`\n\n通常，`delay` 时间应用于补间的重复之间，但如果向 `repeatDelay` 函数提供了一个值，则该值将确定补间重复之间经过的总时间。\n\n参考这个例子：\n\n```js\ntween.delay(1000)\ntween.repeatDelay(500)\ntween.start()\n```\n\n补间的第一次迭代将在一秒后发生，第二次迭代将在第一次迭代结束后半秒发生，第三次迭代将在第二次迭代结束后半秒发生，依此类推。如果你想延迟初始迭代但不希望迭代之间有任何延迟，请确保调用 `tween.repeatDelay(0)` 。\n\n### `dynamic`\n\n如果 `dynamic` 设置为 `true`（默认为 `false`），则传递给 `tween.to()` 的对象可以在补间动画的外部进行修改。这可用于在运行时动态修改补间的结果。\n\n请参阅 [dynamic 示例](http://tweenjs.github.io/tween.js/examples/07_dynamic_to.html)。在那个例子中，在这两个场景中，兔子的位置都在动画期间更新。 兔子的位置恰好是传递给狐狸的 `tween.to()` 方法的对象。 随着兔子位置的更新，在第一个带有 `.dynamic(false)` 的场景中，狐狸向兔子的初始位置移动并且不跟随兔子，而在第二个带有 `.dynamic(true)` 的场景中，狐狸移动到兔子的最终目的地 狐狸因此也被更新，这使得狐狸跟随兔子。\n\n> **Warning** 当 `dynamic` 设置为 `false` 时，Tween 复制传递给 `tween.to()` 的对象并且永远不会修改它（因此从外部更新原始对象不是动态的）。当 `dynamic` 为 `true` 时，Tween 在动画期间使用原始对象作为值的来源（每次更新都读取值，因此可以动态修改它们） **但请注意，在 dynamic 模式下，Tween 将修改传递给 `tween.to()` 的对象的任何插值数组，这可能会对也可能依赖于同一对象的任何外部代码造成副作用。**\n\n## 控制*所有*补间\n\n在 TWEEN 全局对象中可以找到以下方法，除了 `update` 之外，你通常不需要使用其中的大部分方法。\n\n### `TWEEN.update(time)`\n\n我们已经讨论过这种方法。它用于更新所有活动的补间。\n如果 `time` 不指定，它将使用当前时间。\n\n### `TWEEN.getAll` and `TWEEN.removeAll`\n\n用于获取对活动 `tweens` 数组的引用，并分别通过一次调用将它们从数组中移除。\n\n### `TWEEN.add(tween)` and `TWEEN.remove(tween)`\n\n分别用于将补间添加到活动补间列表，或从列表中删除特定补间。\n\n这些方法通常只在内部使用，但如果你想做一些*有趣*的事情，我们会公开这些方法。\n\n## 控制补间集\n\n使用 `TWEEN` 单例来管理补间可能会导致包含许多组件的大型应用程序出现问题。在这些情况下，你可能想要创建自己的更小的补间集。\n\n### 示例：交叉组件冲突\n\n如果你有多个组件使用 `TWEEN`，并且每个组件都想管理自己的补间集，则可能会发生冲突。 如果一个组件调用 `TWEEN.update()` 或 `TWEEN.removeAll()`，其他组件的补间也将被更新或删除。\n\n### 创建你自己的补间集\n\n为了解决这个问题，每个组件都可以创建自己的 `TWEEN.Group` 实例（这是全局 `TWEEN` 对象在内部使用的实例）。 在实例化新补间时，这些组可以作为第二个可选参数传入：\n\n```js\nconst groupA = new TWEEN.Group()\nconst groupB = new TWEEN.Group()\n\nconst tweenA = new TWEEN.Tween({x: 1}, groupA).to({x: 10}, 100).start()\n\nconst tweenB = new TWEEN.Tween({x: 1}, groupB).to({x: 10}, 100).start()\n\nconst tweenC = new TWEEN.Tween({x: 1}).to({x: 10}, 100).start()\n\ngroupA.update() // 只更新tweenA\ngroupB.update() // 只更新tweenB\nTWEEN.update() // 只更新tweenC\n\ngroupA.removeAll() // 只移除tweenA\ngroupB.removeAll() // 只移除tweenB\nTWEEN.removeAll() // 只移除tweenC\n```\n\n这样，每个组件都可以处理创建、更新和销毁自己的补间集。\n\n## 改变缓动功能（别名：让它弹）\n\nTween.js 将以线性方式执行值之间的插值（即缓动），因此变化将与经过的时间成正比。 这是可以预见的，但在视觉上也很无趣。 不用担心——可以使用缓动方法轻松更改此行为。 例如：\n\n```js\ntween.easing(TWEEN.Easing.Quadratic.In)\n```\n\n这将导致补间缓慢开始向最终值变化，向中间加速，然后快速达到其最终值。 相比之下，`TWEEN.Easing.Quadratic.Out` 将开始向该值快速变化，但在接近最终值时会减慢速度。\n\n### 可用的缓动函数：`TWEEN.Easing`\n\ntween.js 提供了一些现成的缓动功能。它们按照它们表示的方程类型进行分组：线性、二次、三次、四次、五次、正弦、指数、圆形、弹性、后退和反弹，然后按缓动类型：In、Out 和 InOut。\n\n除非你已经熟悉这些概念，否则这些名称可能对你没有任何意义，所以现在可能是查看 [图表示例](../examples/17_generate_pow.html) 的时候了，该示例在一页中绘制了所有曲线，以便你可以比较它们的动画。\n\n这些函数源自 Robert Penner 几年前慷慨地作为免费软件提供的原始方程，但已经过优化后，可以很好地与 JavaScript 配合使用。\n\n### 使用自定义缓动功能\n\n你不仅可以使用任何现有的缓动函数，还可以提供自己的函数，只要它遵循一些约定即可：\n\n- 它必须接受一个参数：\n  - `k`: 缓动过程，或我们的补间所处的时间有多长。允许的值在[0, 1]的范围内。\n- 它必须根据输入参数返回一个值。\n\n无论要更改多少属性，每次更新时每个补间只调用一次缓动函数。 然后将结果与初始值以及此值和最终值之间的差值（_deltas_）一起使用，如以下伪代码所示：\n\n```js\neasedElapsed = easing(k);\nfor each property:\n\tnewPropertyValue = initialPropertyValue + propertyDelta * easedElapsed;\n```\n\n对于更注重性能表现的人来说：只有在补间上调用 `start()` 时才会计算 deltas。\n\n因此，假设你想要使用自定义缓动函数来缓动值但将 `Math.floor` 应用于输出，因此只会返回整数部分，从而产生一种阶梯式输出：\n\n```js\nfunction tenStepEasing(k) {\n\treturn Math.floor(k * 10) / 10\n}\n```\n\n你可以通过简单地调用它的缓动方法在补间中使用它，就像我们之前看到的那样：\n\n```js\ntween.easing(tenStepEasing)\n```\n\n查看 [graphs for custom easing functions](../examples/12_graphs_custom_functions.html) 示例，以查看这个动作（还有一些用于生成步进函数的 _metaprogramming_ ）。\n\n## 回调函数\n\n另一个强大的特性是能够在每个补间的生命周期的特定时间运行自己的功能。 当更改属性不够时，通常需要这样做。\n\n例如，假设你正在试图给一些不能直接访问属性的对象设置动画，但是需要你调用 setter。 你可以使用 `update` 回调来读取新的更新值，然后手动调用 setters。 所有的回调函数都将补间对象作为唯一的参数。\n\n```js\nconst trickyObjTween = new TWEEN.Tween({\n\tpropertyA: trickyObj.getPropertyA(),\n\tpropertyB: trickyObj.getPropertyB(),\n})\n\t.to({propertyA: 100, propertyB: 200})\n\t.onUpdate(function (object) {\n\t\tobject.setA(object.propertyA)\n\t\tobject.setB(object.propertyB)\n\t})\n```\n\n或者假设你想在开始补间时播放声音。 你可以使用 `start` 回调：\n\n```js\nconst tween = new TWEEN.Tween(obj).to({x: 100}).onStart(function () {\n\tsound.play()\n})\n```\n\n每个回调的范围是补间对象——在本例中为 `obj`。\n\n### onStart\n\n在补间开始动画之前执行，在 `delay` 方法指定的任何延迟时间之后。 每个补间只会执行一次，即当补间通过 `repeat()` 重复时不会运行。\n\n`onStart` 非常适合与其他事件同步，或触发需要在补间开始时执行的操作。\n\n补间对象作为第一个参数传入。\n\n### onEveryStart\n\n和 `onStart` 类似，单 `onEveryStart` 在每次重复补间时也会运行。\n\n补间对象作为第一个参数传入。\n\n### onStop\n\n当补间通过 `stop()` 显式停止时执行，但不会在它正常完成时执行，并且在停止任何可能的链接补间之前执行。\n\n补间对象作为第一个参数传入。\n\n### onUpdate\n\n每次更新补间时执行，在实际更新值之后。\n\n补间对象作为第一个参数传入。\n\n### onComplete\n\n当补间正常完成（即未停止）时执行。\n\n补间对象作为第一个参数传入。\n\n### onRepeat\n\n每当补间刚刚完成一个重复并将开始另一个重复时执行。\n\n补间对象作为第一个参数传入。\n\n要阐明何时调用 `onStart`、`onEveryStart` 和 `onRepeat`，请参考：\n\n```js\nconst obj = {x: 0}\n\nconst t = new TWEEN.Tween(obj)\n\t.to({x: 5}, 5)\n\t.repeat(Infinity)\n\t.onStart(() => {\n\t\tconsole.log('onStart')\n\t})\n\t.onRepeat(() => {\n\t\tconsole.log('onRepeat')\n\t})\n\t.onEveryStart(() => {\n\t\tconsole.log('onEveryStart')\n\t})\n\t.start(0)\n\nfor (let ticks = 0; ticks < 22; ticks += 1) {\n\tconsole.log('Tick', ticks)\n\tTWEEN.update(ticks)\n\n\tconsole.log(obj)\n\tconsole.log()\n}\n```\n\n输出如下所示，左侧如上，右侧带有 `.delay(5)`：\n\n```txt\nTick 0           Tick 0\nonStart          { x: 0 }\nonEveryStart\n{ x: 0 }\n\nTick 1           Tick 1\n{ x: 1 }         { x: 0 }\n\nTick 2           Tick 2\n{ x: 2 }         { x: 0 }\n\nTick 3           Tick 3\n{ x: 3 }         { x: 0 }\n\nTick 4           Tick 4\n{ x: 4 }         { x: 0 }\n\nTick 5           Tick 5\nonRepeat         onStart\n{ x: 5 }         onEveryStart\n                 { x: 0 }\n\nTick 6           Tick 6\nonEveryStart     { x: 1 }\n{ x: 1 }\n\nTick 7           Tick 7\n{ x: 2 }         { x: 2 }\n\nTick 8           Tick 8\n{ x: 3 }         { x: 3 }\n\nTick 9           Tick 9\n{ x: 4 }         { x: 4 }\n\nTick 10          Tick 10\nonRepeat         onRepeat\n{ x: 5 }         { x: 5 }\n\nTick 11          Tick 11\nonEveryStart     { x: 5 }\n{ x: 1 }\n\nTick 12          Tick 12\n{ x: 2 }         { x: 5 }\n\nTick 13          Tick 13\n{ x: 3 }         { x: 5 }\n\nTick 14          Tick 14\n{ x: 4 }         { x: 5 }\n\nTick 15          Tick 15\nonRepeat         onEveryStart\n{ x: 5 }         { x: 0 }\n\nTick 16          Tick 16\nonEveryStart     { x: 1 }\n{ x: 1 }\n\nTick 17          Tick 17\n{ x: 2 }         { x: 2 }\n\nTick 18          Tick 18\n{ x: 3 }         { x: 3 }\n\nTick 19          Tick 19\n{ x: 4 }         { x: 4 }\n\nTick 20          Tick 20\nonRepeat         onRepeat\n{ x: 5 }         { x: 5 }\n\nTick 21          Tick 21\nonEveryStart     { x: 5 }\n{ x: 1 }\n```\n\n## 补间状态\n\n### `isPlaying`\n\n开始时为 `true`（即使是暂停）。\n\n当补间停止时，`isPlaying` 和 `isPaused` 都将为 `false`。\n\n### `isPaused`\n\n暂停时为 `true`。 `isPlaying` 也将为 `true`。 如果补间已启动但未暂停，则 `isPlaying` 将为 `true` 而 `isPaused` 将为 `false`。\n\n## 高级补间\n\n### 相对值\n\n使用 `to` 方法时，也可以使用相对值。 当 tween 启动时，Tween.js 将读取当前属性值并应用相对值来找出新的最终值。\n**但是你需要使用引号**，否则这些值将被视为绝对的。 我们来看一个例子:\n\n```js\n// 这将使 `x` 属性始终为 100\nconst absoluteTween = new TWEEN.Tween(absoluteObj).to({x: 100})\n\n// 假设 absoluteObj.x 现在为 0\nabsoluteTween.start() // 使 x 变为 100\n\n// 假设 absoluteObj.x 现在是 -100\nabsoluteTween.start() // 使 x 变为 100\n\n// 相比之下...\n\n// 这将使 `x` 属性相对于开始时的实际值多 100 个单位\nconst relativeTween = new TWEEN.Tween(relativeObj).to({x: '+100'})\n\n// 假设 relativeObj.x 现在是 0\nrelativeTween.start() // 使 x 变为 0 +100 = 100\n\n// 假设 relativeObj.x 现在是 -100\nrelativeTween.start() // 使 x 变为 -100 +100 = 0\n```\n\n查看 [09_relative_values](../examples/09_relative_values.html) 示例。\n\n### 补间嵌套对象\n\nTween.js 还可以跨嵌套对象更改属性。 例如：\n\n```js\nconst nestedObject = {scale: {x: 0, y: 0}, alpha: 0}\nconst tween = new TWEEN.Tween(nestedObject).to({scale: {x: 100, y: 100}, alpha: 1})\n```\n\n### 补间值的数组\n\n除了补间到绝对值或相对值之外，你还可以让 Tween.js 更改一系列值的属性。 为此，你只需为属性指定一个值数组而不是单个值。 例如：\n\n```js\nconst tween = new TWEEN.Tween(relativeObj).to({x: [0, -100, 100]})\n```\n\n将使 `x` 从初始值变为 0，-100 和 100。\n\n这些值的计算方法如下：\n\n- 首先，补间进度如常计算\n- 进度（从 0 到 1）用作插值函数的输入\n- 基于进度和值的数组，生成内插值\n\n例如，当补间刚刚启动（进度为 0）时，插值函数将返回数组中的第一个值。 当补间到一半时，插值函数将返回一个大约在数组中间的值，当补间结束时，插值函数将返回最后一个值。\n\n你可以使用插值方法更改插值函数。 例如：\n\n```js\ntween.interpolation(TWEEN.Interpolation.Bezier)\n```\n\n以下值可用：\n\n- TWEEN.Interpolation.Linear\n- TWEEN.Interpolation.Bezier\n- TWEEN.Interpolation.CatmullRom\n\n默认是 `Linear`。\n\n请注意，插值函数对于在同一补间中与数组补间的所有属性都是全局的。\n你不能使用数组和线性函数更改属性 A，也不能使用数组和使用相同补间的贝塞尔函数更改属性 B； 你应该使用两个运行在同一对象上但修改不同属性并使用不同插值函数的补间对象。\n\n查看 [06_array_interpolation](../examples/06_array_interpolation.html) 示例。\n\n## 获得最佳性能\n\n虽然 Tween.js 试图靠自己发挥性能，但没有什么能阻止你以反性能的方式使用它。 以下是一些在使用 Tween.js 时（或通常在 Web 中制作动画时）可以避免拖慢项目速度的方法。\n\n### 使用高性能的 CSS\n\n当你尝试为页面中元素的位置设置动画时，最简单的解决方案是为 `top` 和 `left` 样式属性设置动画，如下所示：\n\n```js\nconst element = document.getElementById('myElement')\nconst tween = new TWEEN.Tween({top: 0, left: 0}).to({top: 100, left: 100}, 1000).onUpdate(function (object) {\n\telement.style.top = object.top + 'px'\n\telement.style.left = object.left + 'px'\n})\n```\n\n但这确实效率低下，因为更改这些属性会强制浏览器在每次更新时重新计算布局，这是一项非常消耗性能的操作。你应该使用 `transform`，它不会使布局无效，并且在可能的情况下也会进行硬件加速，如下所示：\n\n```js\nconst element = document.getElementById('myElement')\nconst tween = new TWEEN.Tween({top: 0, left: 0}).to({top: 100, left: 100}, 1000).onUpdate(function (object) {\n\telement.style.transform = 'translate(' + object.left + 'px, ' + object.top + 'px);'\n})\n```\n\n如果你想了解更多关于高性能的 CSS，看看[这篇文章](https://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/)。\n\n但是，如果你的动画需求就这么简单，最好只使用 CSS 动画或过渡（在适用的情况下），这样浏览器就可以尽可能地进行优化。\n当你的动画需要涉及复杂的操作时，Tween.js 是非常有用，也就是说，你需要将多个补间同步在一起，在一个完成后开始，循环多次，具有不是使用 CSS 而是使用 Canvas 渲染的图形或 WebGL 等等。\n\n### 对垃圾收集器（别名 GC）\n\n如果你使用 `onUpdate` 回调，你需要非常小心你放在它上面的东西。 这个函数每秒会被调用很多次，所以如果你在每次更新时都做代价高昂的操作，你可能会阻塞主线程并导致可怕的卡顿，或者——如果你的操作涉及内存分配，你最终会得到 垃圾收集器运行过于频繁，也会导致卡顿。 所以不要做这两件事。 保持你的 `onUpdate` 回调非常轻量级，并确保在开发时也使用内存分析器。\n\n### 疯狂的补间\n\n这是你可能不经常使用的东西，但你可以在 Tween.js 之外使用补间方程式。 毕竟，它们只是函数。 因此，你可以使用它们来计算平滑曲线作为输入数据。 例如，它们用于在[此实验](<(http://5013.es/toys/tween.audio/)>)中生成音频数据。\n"
  },
  {
    "path": "examples/00_hello_world.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / hello world!</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>00 _ hello world</h2>\n\t\t\t<p>Simple example for illustrating the creation and chaining of tweens.</p>\n\t\t</div>\n\t\t<div\n\t\t\tid=\"target\"\n\t\t\tstyle=\"\n\t\t\t\tposition: absolute;\n\t\t\t\ttransform: translate(100px, 100px);\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tbackground: #a0dde9;\n\t\t\t\tpadding: 1em;\n\t\t\t\"\n\t\t>\n\t\t\thello world!\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport {Tween, Easing, Group} from '../dist/tween.esm.js'\n\n\t\t\tconst position = {x: 100, y: 100, rotation: 10}\n\t\t\tconst target = document.getElementById('target')\n\t\t\tconst tween = new Tween(position)\n\t\t\t\t.to({x: 700, y: 200, rotation: 359}, 2000)\n\t\t\t\t.delay(1000)\n\t\t\t\t.easing(Easing.Elastic.InOut)\n\t\t\t\t.onUpdate(update)\n\n\t\t\tconst tweenBack = new Tween(position)\n\t\t\t\t.to({x: 100, y: 100, rotation: 10}, 3000)\n\t\t\t\t.easing(Easing.Elastic.InOut)\n\t\t\t\t.onUpdate(update)\n\n\t\t\ttween.chain(tweenBack)\n\t\t\t// tweenBack.chain(tween)\n\n\t\t\ttween.start()\n\n\t\t\tconst group = new Group(tween, tweenBack)\n\n\t\t\tanimate(performance.now())\n\n\t\t\tfunction animate(time) {\n\t\t\t\tgroup.update(time)\n\n\t\t\t\t// If the update method returns false, it means all tweens in\n\t\t\t\t// the group are done playing, so we can stop the loop.\n\t\t\t\tconst keepGoing = !group.allStopped()\n\n\t\t\t\tif (keepGoing) requestAnimationFrame(animate)\n\t\t\t}\n\n\t\t\tfunction update() {\n\t\t\t\ttarget.style.transform = `translate3d(${position.x}px, ${position.y}px, 0.0001px) rotateY(${Math.floor(\n\t\t\t\t\tposition.rotation,\n\t\t\t\t)}deg)`\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/01_bars.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / bars</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>01 _ Bars</h2>\n\t\t\t<p>1000 bars, moving horizontally, looped.</p>\n\t\t</div>\n\t\t<div id=\"target\"></div>\n\n\t\t<script src=\"js/stats.min.js\"></script>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst group = new TWEEN.Group()\n\n\t\t\tconst stats = new Stats()\n\t\t\tconst sds = stats.domElement.style\n\t\t\tsds.position = 'absolute'\n\t\t\tsds.right = '0px'\n\t\t\tsds.top = '0px'\n\t\t\tsds.margin = '4em 3em'\n\t\t\tdocument.body.appendChild(stats.domElement)\n\n\t\t\tfor (let i = 0; i < 1000; i++) {\n\t\t\t\tconst startValue = 500 + (Math.random() - Math.random()) * 250\n\t\t\t\tconst endValue = 500 + (Math.random() - Math.random()) * 250\n\n\t\t\t\tconst domElement = document.createElement('div')\n\t\t\t\tconst bg = (Math.random() * 0xffffff) >> 0\n\t\t\t\tdomElement.style.position = 'absolute'\n\t\t\t\tconst y = Math.random() * window.innerHeight\n\t\t\t\tdomElement.style.translate = startValue + 'px ' + y + 'px'\n\t\t\t\tdomElement.style.background = '#' + bg.toString(16)\n\t\t\t\tdomElement.style.width = '100px'\n\t\t\t\tdomElement.style.height = '2px'\n\n\t\t\t\tconst elem = {x: startValue, domElement: domElement, y}\n\n\t\t\t\tconst updateCallback = function (object) {\n\t\t\t\t\tobject.domElement.style.translate = object.x + 'px ' + object.y + 'px'\n\t\t\t\t}\n\n\t\t\t\tconst tween = new TWEEN.Tween(elem)\n\t\t\t\t\t.to({x: endValue}, 4000)\n\t\t\t\t\t.delay(Math.random() * 1000)\n\t\t\t\t\t.onUpdate(updateCallback)\n\t\t\t\t\t.easing(TWEEN.Easing.Back.Out)\n\t\t\t\t\t.start()\n\n\t\t\t\tconst tweenBack = new TWEEN.Tween(elem)\n\t\t\t\t\t.to({x: startValue}, 4000)\n\t\t\t\t\t.delay(Math.random() * 1000)\n\t\t\t\t\t.onUpdate(updateCallback)\n\t\t\t\t\t.easing(TWEEN.Easing.Elastic.InOut)\n\n\t\t\t\ttween.chain(tweenBack)\n\t\t\t\ttweenBack.chain(tween)\n\n\t\t\t\tgroup.add(tween, tweenBack)\n\n\t\t\t\tdocument.body.appendChild(elem.domElement)\n\t\t\t}\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\trequestAnimationFrame(animate)\n\n\t\t\t\tgroup.update(time)\n\t\t\t\tstats.update()\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/02_black_and_red.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / Black and Red</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>02 _ Black and red</h2>\n\t\t\t<p>4096 continuously changing color cells (in a 64x64 table)</p>\n\t\t\t<p></p>\n\t\t</div>\n\t\t<div id=\"target\"></div>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\tfont-family: Arial, Helvetica, sans;\n\t\t\t}\n\t\t\ttable {\n\t\t\t\tborder-collapse: collapse;\n\t\t\t}\n\t\t\ttd {\n\t\t\t\twidth: 5px;\n\t\t\t\theight: 5px;\n\t\t\t}\n\t\t\t#target {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 4em;\n\t\t\t\tright: 3em;\n\t\t\t}\n\t\t</style>\n\n\t\t<script src=\"js/stats.min.js\"></script>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst group = new TWEEN.Group()\n\n\t\t\tconst target = document.getElementById('target')\n\t\t\tconst stats = new Stats()\n\t\t\ttarget.appendChild(stats.domElement)\n\n\t\t\tconst t = document.createElement('table')\n\t\t\tlet index = 0\n\n\t\t\tfor (let i = 0; i < 64; i++) {\n\t\t\t\tconst tr = t.insertRow(-1)\n\t\t\t\tfor (let j = 0; j < 64; j++) {\n\t\t\t\t\tconst td = tr.insertCell(-1)\n\t\t\t\t\ttd.style.background = '#000'\n\t\t\t\t\tconst x = (i + j) * 0.1\n\t\t\t\t\tconst cell = {td: td, value: 0}\n\t\t\t\t\tconst tween = new TWEEN.Tween(cell)\n\t\t\t\t\t\t.to({value: 1}, 8000)\n\t\t\t\t\t\t.delay((0.001 * index + Math.random()) * 500)\n\t\t\t\t\t\t.easing(TWEEN.Easing.Elastic.InOut)\n\t\t\t\t\t\t.onUpdate(function (object) {\n\t\t\t\t\t\t\tconst c = Math.floor(object.value * 0xff)\n\t\t\t\t\t\t\tobject.td.style.background = 'rgb(' + c + ', 0, 0)'\n\t\t\t\t\t\t})\n\n\t\t\t\t\tconst tweenBack = new TWEEN.Tween(cell)\n\t\t\t\t\t\t.to({value: 0}, 4000)\n\t\t\t\t\t\t.delay((0.001 * index + Math.random()) * 500)\n\t\t\t\t\t\t.easing(TWEEN.Easing.Elastic.InOut)\n\t\t\t\t\t\t.onUpdate(function (object) {\n\t\t\t\t\t\t\tconst c = Math.floor(object.value * 0xff)\n\t\t\t\t\t\t\tobject.td.style.background = 'rgb(' + c + ', 0, 0)'\n\t\t\t\t\t\t})\n\n\t\t\t\t\ttween.chain(tweenBack)\n\t\t\t\t\ttweenBack.chain(tween)\n\n\t\t\t\t\tgroup.add(tween, tweenBack)\n\n\t\t\t\t\ttween.start()\n\t\t\t\t\tindex++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttarget.appendChild(t)\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\trequestAnimationFrame(animate)\n\n\t\t\t\tgroup.update(time)\n\t\t\t\tstats.update()\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/03_graphs.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / graphs</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<style>\n\t\t\tbody {\n\t\t\t\tmargin: 0px;\n\t\t\t}\n\n\t\t\t#target {\n\t\t\t\tfont-size: 13px;\n\t\t\t\tpadding: 0px 32px;\n\t\t\t}\n\t\t</style>\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\" style=\"position: relative\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>03 _ graphs</h2>\n\t\t\t<p>The curves, visualised.</p>\n\t\t</div>\n\n\t\t<div id=\"target\"></div>\n\n\t\t<script type=\"module\">\n\t\t\timport {createGraph} from './js/createGraph.js'\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst group = new TWEEN.Group()\n\n\t\t\twindow.addEventListener('load', function () {\n\t\t\t\tinit()\n\t\t\t\tanimate()\n\t\t\t})\n\n\t\t\tfunction init() {\n\t\t\t\tconst target = document.getElementById('target')\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Linear.None', TWEEN.Easing.Linear.None))\n\n\t\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Quadratic.In', TWEEN.Easing.Quadratic.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Quadratic.Out', TWEEN.Easing.Quadratic.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Quadratic.InOut', TWEEN.Easing.Quadratic.InOut))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Cubic.In', TWEEN.Easing.Cubic.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Cubic.Out', TWEEN.Easing.Cubic.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Cubic.InOut', TWEEN.Easing.Cubic.InOut))\n\n\t\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Quartic.In', TWEEN.Easing.Quartic.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Quartic.Out', TWEEN.Easing.Quartic.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Quartic.InOut', TWEEN.Easing.Quartic.InOut))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Quintic.In', TWEEN.Easing.Quintic.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Quintic.Out', TWEEN.Easing.Quintic.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Quintic.InOut', TWEEN.Easing.Quintic.InOut))\n\n\t\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Sinusoidal.In', TWEEN.Easing.Sinusoidal.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Sinusoidal.Out', TWEEN.Easing.Sinusoidal.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Sinusoidal.InOut', TWEEN.Easing.Sinusoidal.InOut))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Exponential.In', TWEEN.Easing.Exponential.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Exponential.Out', TWEEN.Easing.Exponential.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Exponential.InOut', TWEEN.Easing.Exponential.InOut))\n\n\t\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Circular.In', TWEEN.Easing.Circular.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Circular.Out', TWEEN.Easing.Circular.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Circular.InOut', TWEEN.Easing.Circular.InOut))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Elastic.In', TWEEN.Easing.Elastic.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Elastic.Out', TWEEN.Easing.Elastic.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Elastic.InOut', TWEEN.Easing.Elastic.InOut))\n\n\t\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Back.In', TWEEN.Easing.Back.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Back.Out', TWEEN.Easing.Back.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Back.InOut', TWEEN.Easing.Back.InOut))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Bounce.In', TWEEN.Easing.Bounce.In))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Bounce.Out', TWEEN.Easing.Bounce.Out))\n\t\t\t\ttarget.appendChild(createGraph(group, 'Bounce.InOut', TWEEN.Easing.Bounce.InOut))\n\t\t\t}\n\n\t\t\tfunction animate(time) {\n\t\t\t\trequestAnimationFrame(animate)\n\n\t\t\t\tgroup.update(time)\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/04_simplest.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / simplest possible example!</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>04 _ simplest possible example</h2>\n\t\t\t<p>Creating a tween and doing little else apart from that :)</p>\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst output = document.createElement('div')\n\t\t\toutput.style.cssText = 'position: absolute; left: 50px; top: 300px; font-size: 100px'\n\t\t\tdocument.body.appendChild(output)\n\n\t\t\tconst tween = new TWEEN.Tween({x: 50, y: 0})\n\t\t\t\t.to({x: 400}, 2000)\n\t\t\t\t.easing(TWEEN.Easing.Elastic.InOut)\n\t\t\t\t.onUpdate(function (object) {\n\t\t\t\t\toutput.innerHTML = 'x == ' + Math.round(object.x)\n\t\t\t\t\tconst transform = 'translateX(' + object.x + 'px)'\n\t\t\t\t\toutput.style.webkitTransform = transform\n\t\t\t\t\toutput.style.transform = transform\n\t\t\t\t})\n\t\t\t\t.start()\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\trequestAnimationFrame(animate)\n\t\t\t\ttween.update(time)\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/05_video_and_time.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / video and time</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>05 _ video and time</h2>\n\t\t\t<p>Playing a video, synchronizing a tween to it. <button id=\"playButton\">Play</button></p>\n\t\t</div>\n\n\t\t<div\n\t\t\tid=\"target\"\n\t\t\tstyle=\"\n\t\t\t\tposition: absolute;\n\t\t\t\tleft: 0px;\n\t\t\t\ttop: 350px;\n\t\t\t\ttransform: translateX(50px);\n\t\t\t\tfont-size: 100px;\n\t\t\t\tletter-spacing: -7px;\n\t\t\t\"\n\t\t>\n\t\t\t<video id=\"video\" src=\"video/sintel.webm\" width=\"320\" height=\"138\"></video>\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tlet video\n\t\t\tlet tween = null\n\n\t\t\tplayButton.addEventListener('click', function () {\n\t\t\t\tinit()\n\t\t\t\tanimate()\n\t\t\t})\n\n\t\t\tfunction init() {\n\t\t\t\tconst output = document.createElement('div')\n\n\t\t\t\tconst target = document.getElementById('target')\n\t\t\t\ttarget.appendChild(output)\n\n\t\t\t\tvideo = document.getElementById('video')\n\t\t\t\tvideo.addEventListener(\n\t\t\t\t\t'play',\n\t\t\t\t\tfunction () {\n\t\t\t\t\t\ttween = new TWEEN.Tween({x: 50, y: 0})\n\t\t\t\t\t\t\t.to({x: 400}, this.duration)\n\t\t\t\t\t\t\t.easing(TWEEN.Easing.Linear.None)\n\t\t\t\t\t\t\t.onUpdate(function (object) {\n\t\t\t\t\t\t\t\tconst roundX = Math.round(object.x)\n\t\t\t\t\t\t\t\tconst transform = 'translateX(' + roundX + 'px)'\n\t\t\t\t\t\t\t\toutput.innerHTML = 'x == ' + roundX\n\t\t\t\t\t\t\t\ttarget.style.transform = transform\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.start(video.currentTime)\n\t\t\t\t\t},\n\t\t\t\t\tfalse,\n\t\t\t\t)\n\n\t\t\t\tvideo.play()\n\t\t\t}\n\n\t\t\tfunction animate() {\n\t\t\t\tif (tween && video.readyState === video.HAVE_ENOUGH_DATA) {\n\t\t\t\t\ttween.update(video.currentTime)\n\t\t\t\t}\n\n\t\t\t\trequestAnimationFrame(animate)\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/06_array_interpolation.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / array interpolation</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<style>\n\t\t\tbody {\n\t\t\t\tmargin: 0px;\n\t\t\t}\n\n\t\t\t#target {\n\t\t\t\tfont-size: 13px;\n\t\t\t\tpadding: 0px 32px;\n\t\t\t}\n\t\t</style>\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\" style=\"position: relative\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>06 _ array interpolation</h2>\n\t\t\t<p>The different interpolations if arrays are used as values.</p>\n\t\t</div>\n\n\t\t<div id=\"target\"></div>\n\n\t\t<script type=\"module\">\n\t\t\timport {createPath, xA, x0, yA, y0} from './js/createPath.js'\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst group = new TWEEN.Group()\n\n\t\t\tconst target = document.getElementById('target')\n\t\t\tif (!target) throw 'missing element'\n\n\t\t\ttarget.appendChild(createPath(group, 'Linear', TWEEN.Interpolation.Linear))\n\t\t\ttarget.appendChild(createPath(group, 'Bezier', TWEEN.Interpolation.Bezier))\n\t\t\ttarget.appendChild(createPath(group, 'CatmullRom', TWEEN.Interpolation.CatmullRom))\n\n\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\txA.push(x0)\n\t\t\tyA.push(y0)\n\n\t\t\ttarget.appendChild(createPath(group, 'start === end', TWEEN.Interpolation.Linear))\n\t\t\ttarget.appendChild(createPath(group, '', TWEEN.Interpolation.Bezier))\n\t\t\ttarget.appendChild(createPath(group, '', TWEEN.Interpolation.CatmullRom))\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\trequestAnimationFrame(animate)\n\n\t\t\t\tgroup.update(time)\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/07_dynamic_to.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / dynamic to object</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<style>\n\t\t\tbody {\n\t\t\t\tmargin: 0px;\n\t\t\t}\n\n\t\t\t#scene1,\n\t\t\t#scene2 {\n\t\t\t\tdisplay: inline-block;\n\t\t\t\tfont-size: 13px;\n\t\t\t\tpadding-right: 32px;\n\t\t\t}\n\t\t</style>\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\" style=\"position: relative\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>07 _ dynamic to object</h2>\n\t\t\t<p>tweening towards a moving target</p>\n\n\t\t\t<div id=\"scene1\">\n\t\t\t\t<p><code>.dynamic(false)</code></p>\n\t\t\t</div>\n\t\t\t<div id=\"scene2\">\n\t\t\t\t<p><code>.dynamic(true)</code></p>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport {Tween, Group, Easing} from '../dist/tween.esm.js'\n\t\t\timport {drawRabbit, drawFox} from './js/drawings.js'\n\n\t\t\tstartScene('scene1', false)\n\t\t\tstartScene('scene2', true)\n\n\t\t\tfunction startScene(id, dynamic) {\n\t\t\t\tconst group = new Group()\n\n\t\t\t\tconst width = 480\n\t\t\t\tconst height = 320\n\n\t\t\t\tconst scene = document.getElementById(id)\n\n\t\t\t\tconst canvas = document.createElement('canvas')\n\t\t\t\tcanvas.width = width\n\t\t\t\tcanvas.height = height\n\t\t\t\tscene.appendChild(canvas)\n\n\t\t\t\tconst context = canvas.getContext('2d')\n\n\t\t\t\tconst rabbit = {x: width - 50, y: 50}\n\n\t\t\t\tnew Tween(rabbit, group)\n\t\t\t\t\t.to({x: width - 50, y: height - 50}, 3000)\n\t\t\t\t\t.easing(Easing.Exponential.InOut)\n\t\t\t\t\t.start()\n\n\t\t\t\tconst fox = {x: 50, y: 50}\n\n\t\t\t\tnew Tween(fox, group).to(rabbit, 3000).dynamic(dynamic).duration(3000).easing(Easing.Exponential.InOut).start()\n\n\t\t\t\tanimate()\n\n\t\t\t\tfunction animate(time) {\n\t\t\t\t\tgroup.update(time)\n\n\t\t\t\t\t// draw background\n\t\t\t\t\tcontext.fillStyle = 'rgb(240,250,240)'\n\t\t\t\t\tcontext.fillRect(0, 0, width, height)\n\n\t\t\t\t\tdrawRabbit(context, rabbit.x, rabbit.y, 'rgb(150,150,150)')\n\t\t\t\t\tdrawFox(context, fox.x, fox.y, 'rgb(200,80,80)')\n\n\t\t\t\t\trequestAnimationFrame(animate)\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/07a_dynamic_to_two_array_values.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / dynamic to interpolation array</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<style>\n\t\t\tbody {\n\t\t\t\tmargin: 0px;\n\t\t\t}\n\n\t\t\t#scene1,\n\t\t\t#scene2 {\n\t\t\t\tdisplay: inline-block;\n\t\t\t\tfont-size: 13px;\n\t\t\t\tpadding-right: 32px;\n\t\t\t}\n\t\t</style>\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\" style=\"position: relative\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>07a _ dynamic to interpolation array</h2>\n\t\t\t<p>tweening towards two moving targets</p>\n\n\t\t\t<div id=\"scene1\">\n\t\t\t\t<p><code>.dynamic(false)</code></p>\n\t\t\t</div>\n\t\t\t<div id=\"scene2\">\n\t\t\t\t<p><code>.dynamic(true)</code></p>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\t\t\timport {drawRabbit, drawFox} from './js/drawings.js'\n\n\t\t\tstartScene('scene1', false)\n\t\t\tstartScene('scene2', true)\n\n\t\t\tfunction startScene(id, dynamic) {\n\t\t\t\tconst group = new TWEEN.Group()\n\n\t\t\t\tconst width = 480\n\t\t\t\tconst height = 320\n\n\t\t\t\tconst scene = document.getElementById(id)\n\n\t\t\t\tconst canvas = document.createElement('canvas')\n\t\t\t\tcanvas.width = width\n\t\t\t\tcanvas.height = height\n\t\t\t\tscene.appendChild(canvas)\n\n\t\t\t\tconst context = canvas.getContext('2d')\n\n\t\t\t\tconst rabbit1 = {\n\t\t\t\t\tx: width * 0.8,\n\t\t\t\t\ty: 50,\n\t\t\t\t}\n\n\t\t\t\tnew TWEEN.Tween(rabbit1, group)\n\t\t\t\t\t.to({x: width / 2, y: height - 50}, 2000)\n\t\t\t\t\t.easing(TWEEN.Easing.Cubic.InOut)\n\t\t\t\t\t.onUpdate(function ({x, y}) {\n\t\t\t\t\t\trabbits.x[1] = x\n\t\t\t\t\t\trabbits.y[1] = y\n\t\t\t\t\t})\n\t\t\t\t\t.start()\n\n\t\t\t\tconst rabbit2 = {\n\t\t\t\t\tx: width - 50,\n\t\t\t\t\ty: height - 50,\n\t\t\t\t}\n\n\t\t\t\tnew TWEEN.Tween(rabbit2, group)\n\t\t\t\t\t.to({x: width / 3, y: 50}, 3000)\n\t\t\t\t\t.easing(TWEEN.Easing.Cubic.InOut)\n\t\t\t\t\t.onUpdate(function ({x, y}) {\n\t\t\t\t\t\trabbits.x[2] = x\n\t\t\t\t\t\trabbits.y[2] = y\n\t\t\t\t\t})\n\t\t\t\t\t.start()\n\n\t\t\t\tconst rabbits = {\n\t\t\t\t\tx: [rabbit1.x, rabbit2.x],\n\t\t\t\t\ty: [rabbit1.y, rabbit2.y],\n\t\t\t\t}\n\n\t\t\t\tconst fox = {\n\t\t\t\t\tx: 50,\n\t\t\t\t\ty: 50,\n\t\t\t\t}\n\n\t\t\t\tnew TWEEN.Tween(fox, group)\n\t\t\t\t\t.to(rabbits, 3000)\n\t\t\t\t\t.dynamic(dynamic)\n\t\t\t\t\t.interpolation(TWEEN.Interpolation.CatmullRom)\n\t\t\t\t\t.start()\n\n\t\t\t\tanimate()\n\n\t\t\t\tfunction animate(time) {\n\t\t\t\t\tgroup.update(time)\n\n\t\t\t\t\tcontext.fillStyle = 'rgb(240,250,240)'\n\t\t\t\t\tcontext.fillRect(0, 0, width, height)\n\n\t\t\t\t\tdrawRabbit(context, rabbit1.x, rabbit1.y, 'rgb(0,0,150)')\n\t\t\t\t\tdrawRabbit(context, rabbit2.x, rabbit2.y, 'rgb(0,80,80)')\n\t\t\t\t\tdrawFox(context, fox.x, fox.y, 'rgb(200,80,80)')\n\n\t\t\t\t\trequestAnimationFrame(animate)\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/07b_dynamic_to_an_array_of_values.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / dynamic to large interpolation array</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<style>\n\t\t\tbody {\n\t\t\t\tmargin: 0px;\n\t\t\t}\n\n\t\t\t#scene1,\n\t\t\t#scene2 {\n\t\t\t\tdisplay: inline-block;\n\t\t\t\tfont-size: 13px;\n\t\t\t\tpadding-right: 32px;\n\t\t\t}\n\t\t</style>\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\" style=\"position: relative\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>07b _ dynamic to large interpolation array</h2>\n\t\t\t<p>tweening towards many random moving targets</p>\n\n\t\t\t<div id=\"scene1\">\n\t\t\t\t<p><code>.dynamic(false)</code></p>\n\t\t\t</div>\n\t\t\t<div id=\"scene2\">\n\t\t\t\t<p><code>.dynamic(true)</code></p>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\t\t\timport {drawRabbit, drawFox} from './js/drawings.js'\n\n\t\t\tconst width = 480\n\t\t\tconst height = 320\n\t\t\tconst rabbitValues = {x: [], y: [], eatenCounter: []}\n\n\t\t\t// generate random rabbits\n\t\t\tconst rabbitCount = 20\n\t\t\tfor (let i = 0; i < rabbitCount; i++) {\n\t\t\t\trabbitValues.x.push(50 + getRandomInt(width - 100))\n\t\t\t\trabbitValues.y.push(50 + getRandomInt(height - 100))\n\t\t\t\trabbitValues.eatenCounter.push(i + 1)\n\t\t\t}\n\n\t\t\t// or use static population\n\t\t\t// const rabbitCount = 2\n\t\t\t// rabbitValues.x = [Math.random() * width, width - 50]\n\t\t\t// rabbitValues.y = [height - 50, Math.random() * height]\n\t\t\t// rabbitValues.eatenCounter = [1, 2]\n\n\t\t\tconst bunnyDestinations = []\n\n\t\t\tfor (let i = 0; i < rabbitCount; i++) {\n\t\t\t\tbunnyDestinations.push({x: Math.random() * width, y: Math.random() * height})\n\t\t\t}\n\n\t\t\tconst bunnyColors = []\n\t\t\tconst maxColor = 200 // avoiding pale colors\n\n\t\t\tfor (let i = 0; i < rabbitCount; i++) {\n\t\t\t\tbunnyColors.push(`rgb(${getRandomInt(maxColor)}, ${getRandomInt(maxColor)}, ${getRandomInt(maxColor)})`)\n\t\t\t}\n\n\t\t\tstartScene('scene1', false)\n\t\t\tstartScene('scene2', true)\n\n\t\t\tfunction startScene(id, dynamic) {\n\t\t\t\tconst group = new TWEEN.Group()\n\t\t\t\tconst duration = 8000\n\t\t\t\tconst scene = document.getElementById(id)\n\t\t\t\tconst canvas = document.createElement('canvas')\n\n\t\t\t\tcanvas.width = width\n\t\t\t\tcanvas.height = height\n\t\t\t\tscene.appendChild(canvas)\n\n\t\t\t\tconst context = canvas.getContext('2d')\n\n\t\t\t\tconst rabbitTweens = []\n\t\t\t\tconst rabbits = []\n\n\t\t\t\t// clone rabbitValues so it won't be modified (that way it will be unique for each scene)\n\t\t\t\tconst _rabbitValues = {\n\t\t\t\t\tx: [...rabbitValues.x],\n\t\t\t\t\ty: [...rabbitValues.y],\n\t\t\t\t\teatenCounter: [...rabbitValues.eatenCounter],\n\t\t\t\t}\n\n\t\t\t\tfor (let i = 0; i < rabbitCount; i++) {\n\t\t\t\t\tconst rabbit = {\n\t\t\t\t\t\tx: _rabbitValues.x[i],\n\t\t\t\t\t\ty: _rabbitValues.y[i],\n\t\t\t\t\t\tcolor: bunnyColors[i],\n\t\t\t\t\t\talive: true,\n\t\t\t\t\t}\n\t\t\t\t\trabbits.push(rabbit)\n\t\t\t\t\trabbitTweens.push(createRabbitTween(i, rabbit))\n\t\t\t\t}\n\n\t\t\t\tfunction createRabbitTween(index, rabbit) {\n\t\t\t\t\treturn new TWEEN.Tween(rabbit, group)\n\t\t\t\t\t\t.to(bunnyDestinations[index], duration)\n\t\t\t\t\t\t.onUpdate(function (object) {\n\t\t\t\t\t\t\t// We need `index + 1` because Tween modifies the arrays and adds the fox start values to it.\n\t\t\t\t\t\t\t// TODO this is confusing. Better if Tween simply never modified the input object.\n\t\t\t\t\t\t\t_rabbitValues.x[index + 1] = object.x\n\t\t\t\t\t\t\t_rabbitValues.y[index + 1] = object.y\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.start()\n\t\t\t\t}\n\n\t\t\t\tconst fox = {x: 50, y: 50, eatenCounter: 0}\n\t\t\t\tlet rabbitsEaten = 0\n\n\t\t\t\tnew TWEEN.Tween(fox, group)\n\t\t\t\t\t.to(_rabbitValues, duration)\n\t\t\t\t\t.dynamic(dynamic)\n\t\t\t\t\t.onUpdate(function (object) {\n\t\t\t\t\t\trabbitsEaten = Math.floor(object.eatenCounter)\n\t\t\t\t\t\tif (rabbitsEaten > 0) {\n\t\t\t\t\t\t\t// A dead rabbit stops moving.\n\t\t\t\t\t\t\trabbitTweens[rabbitsEaten - 1].stop()\n\t\t\t\t\t\t\trabbits[rabbitsEaten - 1].alive = false\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.start()\n\n\t\t\t\tanimate()\n\n\t\t\t\tfunction animate(time) {\n\t\t\t\t\tgroup.update(time)\n\n\t\t\t\t\tconst stillRunning = !group.allStopped()\n\n\t\t\t\t\t// draw background\n\t\t\t\t\tcontext.fillStyle = 'rgb(240,250,240)'\n\t\t\t\t\tcontext.fillRect(0, 0, width, height)\n\n\t\t\t\t\tfor (const rabbit of rabbits) drawRabbit(context, rabbit.x, rabbit.y, rabbit.color, rabbit.alive ? 1 : 0.1)\n\t\t\t\t\tdrawFox(context, fox.x, fox.y, 'rgb(200,80,80)')\n\n\t\t\t\t\tif (stillRunning) requestAnimationFrame(animate)\n\t\t\t\t\telse console.log('Done with animation, stopped rendering.')\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction getRandomInt(max) {\n\t\t\t\treturn Math.floor(Math.random() * Math.floor(max + 1))\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/08_repeat.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / repeat</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>08 _ repeat</h2>\n\t\t\t<p>Demonstrating the repeat() feature.</p>\n\t\t</div>\n\t\t<div style=\"position: absolute; top: 100px; left: 400px\">\n\t\t\t<div id=\"target1\" data-rotation=\"0\" class=\"box\">no repeat</div>\n\t\t\t<div id=\"target2\" data-rotation=\"0\" class=\"box\">repeat twice</div>\n\t\t\t<div id=\"target3\" data-rotation=\"0\" class=\"box\">repeat forever</div>\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport {Tween, Group, Easing} from '../dist/tween.esm.js'\n\n\t\t\tconst group = new Group()\n\n\t\t\tinit()\n\t\t\tanimate()\n\n\t\t\tfunction init() {\n\t\t\t\tconst target1 = document.getElementById('target1'),\n\t\t\t\t\ttween1 = new Tween(target1.dataset)\n\t\t\t\t\t\t.to({rotation: 360}, 1000)\n\t\t\t\t\t\t.easing(Easing.Exponential.InOut)\n\t\t\t\t\t\t.delay(100)\n\t\t\t\t\t\t.onUpdate(function (object) {\n\t\t\t\t\t\t\tupdateBox(target1, object)\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.start(),\n\t\t\t\t\ttarget2 = document.getElementById('target2'),\n\t\t\t\t\ttween2 = new Tween(target2.dataset)\n\t\t\t\t\t\t.to({rotation: 360}, 1000)\n\t\t\t\t\t\t.easing(Easing.Exponential.InOut)\n\t\t\t\t\t\t.repeat(2)\n\t\t\t\t\t\t.delay(100)\n\t\t\t\t\t\t.onUpdate(function (object) {\n\t\t\t\t\t\t\tupdateBox(target2, object)\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.start(),\n\t\t\t\t\ttarget3 = document.getElementById('target3'),\n\t\t\t\t\ttween3 = new Tween(target3.dataset)\n\t\t\t\t\t\t.to({rotation: 360}, 1000)\n\t\t\t\t\t\t.easing(Easing.Exponential.InOut)\n\t\t\t\t\t\t.repeat(Infinity)\n\t\t\t\t\t\t.delay(100)\n\t\t\t\t\t\t.onUpdate(function (object) {\n\t\t\t\t\t\t\tupdateBox(target3, object)\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.start()\n\n\t\t\t\tgroup.add(tween1, tween2, tween3)\n\t\t\t}\n\n\t\t\tfunction animate(time) {\n\t\t\t\trequestAnimationFrame(animate)\n\n\t\t\t\tgroup.update(time)\n\t\t\t}\n\n\t\t\tfunction updateBox(box, params) {\n\t\t\t\tconst s = box.style,\n\t\t\t\t\ttransform = 'rotate(' + Math.floor(params.rotation) + 'deg)'\n\t\t\t\ts.webkitTransform = transform\n\t\t\t\ts.mozTransform = transform\n\t\t\t\ts.transform = transform\n\t\t\t}\n\t\t</script>\n\n\t\t<style type=\"text/css\">\n\t\t\t.box {\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tmargin: 10px;\n\t\t\t\tpadding: 10px;\n\t\t\t\tdisplay: inline-block;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t\t#target1 {\n\t\t\t\tbackground: #fcc;\n\t\t\t}\n\t\t\t#target2 {\n\t\t\t\tbackground: #cfc;\n\t\t\t}\n\t\t\t#target3 {\n\t\t\t\tbackground: #ccf;\n\t\t\t}\n\t\t</style>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/09_relative_values.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / relative values</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t\t<style type=\"text/css\">\n\t\t\t.box {\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tmargin: 10px;\n\t\t\t\tpadding: 10px;\n\t\t\t\tdisplay: inline-block;\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t\t#target1 {\n\t\t\t\tbackground: #fcc;\n\t\t\t}\n\t\t</style>\n\n\t\t<script type=\"importmap\">\n\t\t\t{\n\t\t\t\t\"imports\": {\n\t\t\t\t\t\"@tweenjs/tween.js\": \"../dist/tween.esm.js\"\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\n\t\t<script type=\"module\" src=\"./09_relative_values.js\"></script>\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>09 _ relative values</h2>\n\t\t\t<p>Tweening to relative values, with repeat.</p>\n\t\t</div>\n\t\t<div style=\"position: absolute; left: 400px\">\n\t\t\t<div id=\"target1\" style=\"position: absolute\" data-top=\"150\" data-left=\"150\" class=\"box\"></div>\n\t\t</div>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/09_relative_values.js",
    "content": "import {Tween, Group, Easing} from '@tweenjs/tween.js'\n\nconst target1 = document.getElementById('target1')\nconst tween = new Tween(target1.dataset)\n\t.to({top: '+20', left: '-20'}, 500)\n\t.repeat(5)\n\t.delay(500)\n\t.easing(Easing.Exponential.In)\n\t.onUpdate(function (object) {\n\t\tobject.top = Math.round(object.top)\n\t\tobject.left = Math.round(object.left)\n\t\tupdateBox(target1, object)\n\t})\n\t.start()\n\nupdateBox(target1, target1.dataset)\n\nanimate()\n\nfunction animate(time) {\n\trequestAnimationFrame(animate)\n\ttween.update(time)\n}\n\nfunction updateBox(box, params) {\n\tconst s = box.style\n\tconst transform = 'translate(' + params.left + 'px, ' + params.top + 'px)'\n\ts.transform = transform\n}\n"
  },
  {
    "path": "examples/10_yoyo.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / yoyo</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\n\t\t<script type=\"importmap\">\n\t\t\t{\n\t\t\t\t\"imports\": {\n\t\t\t\t\t\"tweenjs\": \"../dist/tween.esm.js\"\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\n\t\t<script type=\"module\" src=\"./10_yoyo.js\"></script>\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>10 _ yoyo</h2>\n\t\t\t<p>Demonstrating the yoyo() feature.</p>\n\t\t\t<button onclick=\"restart()\">restart</button>\n\t\t\t<button onclick=\"stop()\">stop</button>\n\t\t\t<button onclick=\"start()\">start</button>\n\t\t\t<button onclick=\"pause()\">pause</button>\n\t\t\t<button onclick=\"resume()\">resume</button>\n\t\t</div>\n\t\t<div style=\"position: absolute; top: 100px; left: 400px\">\n\t\t\t<div id=\"target1\" data-rotation=\"0\" data-y=\"0\" class=\"box\" style=\"left: 0px; top: 0px\">yoyo with repeat once</div>\n\t\t\t<div id=\"target2\" data-rotation=\"0\" data-y=\"0\" class=\"box\" style=\"left: 200px; top: 0px\">\n\t\t\t\tyoyo with repeat forever\n\t\t\t</div>\n\t\t\t<div id=\"target3\" data-rotation=\"0\" data-y=\"0\" class=\"box\" style=\"left: 400px; top: 0px\">\n\t\t\t\tyoyo with repeat once, relative values\n\t\t\t</div>\n\t\t\t<div id=\"target4\" data-rotation=\"0\" data-y=\"0\" class=\"box\" style=\"left: 600px; top: 0px\">\n\t\t\t\tyoyo with repeat forever, relative values\n\t\t\t</div>\n\t\t</div>\n\n\t\t<style type=\"text/css\">\n\t\t\t.box {\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-flow: row;\n\t\t\t\talign-items: center;\n\t\t\t\ttext-align: center;\n\t\t\t\t-webkit-border-radius: 70px;\n\t\t\t\t-moz-border-radius: 70px;\n\t\t\t\tborder-radius: 70px;\n\t\t\t\tposition: absolute;\n\t\t\t\tborder: 1px solid black;\n\t\t\t\tfont-size: 10px;\n\t\t\t\tpadding: 20px;\n\t\t\t}\n\t\t\t#target1 {\n\t\t\t\tbackground: #fcc;\n\t\t\t}\n\t\t\t#target2 {\n\t\t\t\tbackground: #cfc;\n\t\t\t}\n\t\t\t#target3 {\n\t\t\t\tbackground: orange;\n\t\t\t}\n\t\t\t#target4 {\n\t\t\t\tbackground: skyblue;\n\t\t\t}\n\t\t</style>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/10_yoyo.js",
    "content": "// @ts-check\nimport {Tween, Group, Easing} from 'tweenjs'\n\nconst group = new Group()\n\nanimate()\n\nconst target1 = document.getElementById('target1')\nconst tween1 = new Tween(target1.dataset, group)\n\t.to({rotation: 360, y: 300}, 750)\n\t.repeat(1)\n\t.delay(1000)\n\t.yoyo(true)\n\t.easing(Easing.Cubic.InOut)\n\t.onUpdate(function (object) {\n\t\tupdateBox(target1, object)\n\t})\n\t.start()\nconst target2 = document.getElementById('target2')\nconst tween2 = new Tween(target2.dataset, group)\n\t.to({rotation: 360, y: 300}, 750)\n\t.repeat(Infinity)\n\t.delay(1000)\n\t.yoyo(true)\n\t.easing(Easing.Cubic.InOut)\n\t.onUpdate(function (object) {\n\t\tupdateBox(target2, object)\n\t})\n\t.start()\nconst target3 = document.getElementById('target3')\nconst tween3 = new Tween(target3.dataset, group)\n\t.to({rotation: '+360', y: '+300'}, 750)\n\t.repeat(1)\n\t.delay(1000)\n\t.yoyo(true)\n\t.easing(Easing.Cubic.InOut)\n\t.onUpdate(function (object) {\n\t\tupdateBox(target3, object)\n\t})\n\t.start()\nconst target4 = document.getElementById('target4')\nconst tween4 = new Tween(target4.dataset, group)\n\t.to({rotation: '+360', y: '+300'}, 750)\n\t.repeat(Infinity)\n\t.delay(1000)\n\t.yoyo(true)\n\t.easing(Easing.Cubic.InOut)\n\t.onUpdate(function (object) {\n\t\tupdateBox(target4, object)\n\t})\n\t.start()\n\n// TODO perhaps add these methods to Group\n\nconst restart = (window.restart = function () {\n\ttween1.stop().start()\n\ttween2.stop().start()\n\ttween3.stop().start()\n\ttween4.stop().start()\n})\n\nconst stop = (window.stop = function () {\n\ttween1.stop()\n\ttween2.stop()\n\ttween3.stop()\n\ttween4.stop()\n})\n\nconst start = (window.start = function () {\n\ttween1.start()\n\ttween2.start()\n\ttween3.start()\n\ttween4.start()\n})\n\nconst pause = (window.pause = function () {\n\ttween1.pause()\n\ttween2.pause()\n\ttween3.pause()\n\ttween4.pause()\n})\n\nconst resume = (window.resume = function () {\n\ttween1.resume()\n\ttween2.resume()\n\ttween3.resume()\n\ttween4.resume()\n})\n\nfunction animate(time) {\n\trequestAnimationFrame(animate)\n\n\tgroup.update(time)\n}\n\nfunction updateBox(box, params) {\n\tconst s = box.style,\n\t\ttransform = 'translateY(' + Math.round(params.y) + 'px) rotate(' + Math.floor(params.rotation) + 'deg)'\n\ts.webkitTransform = transform\n\ts.mozTransform = transform\n\ts.transform = transform\n}\n"
  },
  {
    "path": "examples/11_stop_all_chained_tweens.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / stop chained</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>11 _ stop all chained tweens.</h2>\n\t\t\t<p>Tween#stopChainedTweens</p>\n\t\t</div>\n\t\t<div style=\"position: absolute; top: 250px; left: 50px\">\n\t\t\t<button id=\"start\">Start</button>\n\t\t\t<button id=\"stop\">Stop</button>\n\t\t\t<div id=\"target1\" data-rotation=\"0\" data-y=\"0\" class=\"box\" style=\"left: 0px; top: 50px\">Box One</div>\n\t\t\t<div id=\"target2\" data-rotation=\"0\" data-y=\"0\" class=\"box\" style=\"left: 0px; top: 200px\">Box Two</div>\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst group = new TWEEN.Group()\n\n\t\t\tfunction animate(time) {\n\t\t\t\tgroup.update(time)\n\t\t\t\trequestAnimationFrame(animate)\n\t\t\t}\n\n\t\t\tanimate()\n\n\t\t\tconst a = document.getElementById('target1')\n\t\t\tconst b = document.getElementById('target2')\n\t\t\tconst start = document.getElementById('start')\n\t\t\tconst stop = document.getElementById('stop')\n\t\t\tlet t0, t1\n\t\t\tconst p0 = {x: 0},\n\t\t\t\tp1 = {x: 0}\n\n\t\t\tstart.onclick = function () {\n\t\t\t\tif (!t0 && !t1) {\n\t\t\t\t\tt0 = new TWEEN.Tween(p0, group)\n\t\t\t\t\t\t.to({x: 700}, 2000)\n\t\t\t\t\t\t.delay(100)\n\t\t\t\t\t\t.easing(TWEEN.Easing.Elastic.InOut)\n\t\t\t\t\t\t.onUpdate(function () {\n\t\t\t\t\t\t\ta.style.left = p0.x + 'px'\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.onComplete(function () {\n\t\t\t\t\t\t\tp0.x = 0\n\t\t\t\t\t\t\ta.style.left = p0.x + 'px'\n\t\t\t\t\t\t})\n\n\t\t\t\t\tt1 = new TWEEN.Tween(p1, group)\n\t\t\t\t\t\t.to({x: 1000}, 3000)\n\t\t\t\t\t\t.delay(100)\n\t\t\t\t\t\t.easing(TWEEN.Easing.Elastic.InOut)\n\t\t\t\t\t\t.onUpdate(function () {\n\t\t\t\t\t\t\tb.style.left = p1.x + 'px'\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.onComplete(function () {\n\t\t\t\t\t\t\tp1.x = 0\n\t\t\t\t\t\t\tb.style.left = p1.x + 'px'\n\t\t\t\t\t\t})\n\n\t\t\t\t\tt0.chain(t1)\n\t\t\t\t\tt1.chain(t0)\n\t\t\t\t}\n\t\t\t\tt0.start()\n\t\t\t}\n\n\t\t\tstop.onclick = function () {\n\t\t\t\tt0.stop()\n\t\t\t}\n\t\t</script>\n\n\t\t<style type=\"text/css\">\n\t\t\t.box {\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-flow: row;\n\t\t\t\talign-items: center;\n\t\t\t\ttext-align: center;\n\t\t\t\t-webkit-border-radius: 70px;\n\t\t\t\t-moz-border-radius: 70px;\n\t\t\t\tborder-radius: 70px;\n\t\t\t\tposition: absolute;\n\t\t\t\tborder: 1px solid black;\n\t\t\t\tfont-size: 10px;\n\t\t\t\tpadding: 20px;\n\t\t\t}\n\n\t\t\t#target1 {\n\t\t\t\tbackground: #fcc;\n\t\t\t}\n\n\t\t\t#target2 {\n\t\t\t\tbackground: #cfc;\n\t\t\t}\n\t\t</style>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/12_graphs_custom_functions.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / graphs for custom easing functions</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<style>\n\t\t\tbody {\n\t\t\t\tmargin: 0px;\n\t\t\t}\n\n\t\t\t#target {\n\t\t\t\tfont-size: 13px;\n\t\t\t\tpadding: 0px 32px;\n\t\t\t}\n\t\t</style>\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\" style=\"position: relative\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>12 _ graphs for custom easing functions</h2>\n\t\t\t<p>\n\t\t\t\tA version of the <a href=\"03_graphs.html\">graphs</a> example, but using custom easing functions (not included in\n\t\t\t\t<a href=\"https://github.com/tween.js/tween.js\">tween.js</a> by default).\n\t\t\t</p>\n\t\t</div>\n\n\t\t<div id=\"target\"></div>\n\n\t\t<script type=\"module\">\n\t\t\timport {createGraph} from './js/createGraph.js'\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst group = new TWEEN.Group()\n\n\t\t\twindow.addEventListener('load', function () {\n\t\t\t\tinit()\n\t\t\t\tanimate()\n\t\t\t})\n\n\t\t\tfunction init() {\n\t\t\t\tconst target = document.getElementById('target')\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Ten Steps', tenStepsEasing))\n\n\t\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\t\tfor (let i = 0; i < 4; i++) {\n\t\t\t\t\tconst numSteps = (i + 1) * 4\n\t\t\t\t\ttarget.appendChild(createGraph(group, numSteps + ' steps', createStepFunction(numSteps)))\n\t\t\t\t}\n\n\t\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\t\ttarget.appendChild(createGraph(group, 'Random', randomEasing))\n\n\t\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\t\ttarget.appendChild(\n\t\t\t\t\tcreateGraph(group, 'Noisy Exponential.InOut', createNoisyEasing(0.1, TWEEN.Easing.Exponential.InOut)),\n\t\t\t\t)\n\t\t\t\ttarget.appendChild(\n\t\t\t\t\tcreateGraph(group, 'Noisy Elastic.InOut', createNoisyEasing(0.1, TWEEN.Easing.Elastic.InOut)),\n\t\t\t\t)\n\t\t\t\ttarget.appendChild(\n\t\t\t\t\tcreateGraph(group, 'Noisy Circular.InOut', createNoisyEasing(0.1, TWEEN.Easing.Circular.InOut)),\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tfunction animate() {\n\t\t\t\trequestAnimationFrame(animate)\n\n\t\t\t\tgroup.update()\n\t\t\t}\n\n\t\t\tfunction tenStepsEasing(k) {\n\t\t\t\treturn Math.floor(k * 10) / 10\n\t\t\t}\n\n\t\t\t// This is where we get very meta and write a function for\n\t\t\t// generating functions! The returned function is similar to\n\t\t\t// the tenStepsEasing function above, but the number of steps\n\t\t\t// is passed as a parameter\n\t\t\tfunction createStepFunction(numSteps) {\n\t\t\t\treturn function (k) {\n\t\t\t\t\treturn Math.floor(k * numSteps) / numSteps\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction randomEasing(k) {\n\t\t\t\treturn Math.random()\n\t\t\t}\n\n\t\t\t// Getting meta again: why not use existing functions as the\n\t\t\t// base for new easing functions?\n\t\t\tfunction createNoisyEasing(randomProportion, easingFunction) {\n\t\t\t\tconst normalProportion = 1.0 - randomProportion\n\t\t\t\treturn function (k) {\n\t\t\t\t\treturn randomProportion * Math.random() + normalProportion * easingFunction(k)\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/13_relative_start_time.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / relative start time</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>13 _ relative start time</h2>\n\t\t\t<br />\n\t\t\t<p>One starts late, Two starts early.</p>\n\t\t</div>\n\t\t<div\n\t\t\tid=\"target1\"\n\t\t\tstyle=\"\n\t\t\t\tposition: absolute;\n\t\t\t\ttransform: translate(100px, 100px);\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tbackground: #a0dde9;\n\t\t\t\tpadding: 1em;\n\t\t\t\"\n\t\t>\n\t\t\tOne\n\t\t</div>\n\n\t\t<div\n\t\t\tid=\"target2\"\n\t\t\tstyle=\"\n\t\t\t\tposition: absolute;\n\t\t\t\ttransform: translate(100px, 300px);\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tbackground: #a0dde9;\n\t\t\t\tpadding: 1em;\n\t\t\t\"\n\t\t>\n\t\t\tTwo\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst position1 = {x: 100, y: 100, rotation: 0}\n\t\t\tconst position2 = {x: 100, y: 300, rotation: 0}\n\t\t\tconst target1 = document.getElementById('target1')\n\t\t\tconst target2 = document.getElementById('target2')\n\n\t\t\tconst tween1 = new TWEEN.Tween(position1)\n\t\t\t\t.to({x: 700, y: 200, rotation: 359}, 2000)\n\t\t\t\t.easing(TWEEN.Easing.Elastic.InOut)\n\t\t\t\t.onUpdate(update1)\n\n\t\t\tconst tween2 = new TWEEN.Tween(position2).to({x: 500, y: 300, rotation: -90}, 2000).onUpdate(update2)\n\n\t\t\ttween1.delay(2000).start()\n\t\t\ttween2.delay(100).start()\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\trequestAnimationFrame(animate)\n\n\t\t\t\ttween1.update(time)\n\t\t\t\ttween2.update(time)\n\t\t\t}\n\n\t\t\tfunction update1() {\n\t\t\t\ttarget1.style.transform = `translate(${position1.x}px, ${position1.y}px) rotate(${Math.floor(\n\t\t\t\t\tposition1.rotation,\n\t\t\t\t)}deg)`\n\t\t\t}\n\n\t\t\tfunction update2() {\n\t\t\t\ttarget2.style.transform = `translate(${position2.x}px, ${position2.y}px) rotate(${Math.floor(\n\t\t\t\t\tposition2.rotation,\n\t\t\t\t)}deg)`\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/14_pause_tween.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / pause tween</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>14 _ pause tween</h2>\n\t\t\t<br />\n\t\t\t<p>\n\t\t\t\t<button type=\"button\" onclick=\"pause()\">Pause</button>\n\t\t\t\t, then\n\t\t\t\t<button type=\"button\" onclick=\"resume()\">Resume</button>.\n\t\t\t</p>\n\t\t</div>\n\t\t<div\n\t\t\tid=\"progress_bar_wrapper\"\n\t\t\tstyle=\"\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 300px;\n\t\t\t\tleft: 100px;\n\t\t\t\twidth: 500px;\n\t\t\t\theight: 100px;\n\t\t\t\tborder: 0.5em solid black;\n\t\t\t\toverflow: hidden;\n\t\t\t\"\n\t\t>\n\t\t\t<div\n\t\t\t\tid=\"progress_bar_fill\"\n\t\t\t\tstyle=\"\n\t\t\t\t\tposition: absolute;\n\t\t\t\t\ttop: 0px;\n\t\t\t\t\tleft: 0px;\n\t\t\t\t\twidth: 0%;\n\t\t\t\t\theight: 100%;\n\t\t\t\t\tbackground: #a0dde9;\n\t\t\t\t\tline-height: 6em;\n\t\t\t\t\ttext-align: center;\n\t\t\t\t\"\n\t\t\t>\n\t\t\t\t0%\n\t\t\t</div>\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst progress = {width: 0}\n\t\t\tconst fill = document.getElementById('progress_bar_fill')\n\n\t\t\tconst tween1 = new TWEEN.Tween(progress)\n\t\t\t\t.to({width: 100}, 2000)\n\t\t\t\t.onUpdate(update1)\n\t\t\t\t.yoyo(true)\n\t\t\t\t.repeat(Infinity)\n\t\t\t\t.delay(500)\n\t\t\t\t.start()\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\trequestAnimationFrame(animate)\n\n\t\t\t\ttween1.update(time)\n\t\t\t}\n\n\t\t\tfunction update1() {\n\t\t\t\tfill.style.width = progress.width + '%'\n\t\t\t\tfill.innerHTML = Math.floor(progress.width) + '%'\n\t\t\t}\n\n\t\t\twindow.pause = () => {\n\t\t\t\ttween1.pause()\n\t\t\t}\n\n\t\t\twindow.resume = () => {\n\t\t\t\ttween1.resume()\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/15_complex_properties.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / complex properties</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>15 _ complex properties</h2>\n\t\t\t<p>Simple example for illustrating animation of nested properties.</p>\n\t\t</div>\n\t\t<div\n\t\t\tid=\"target\"\n\t\t\tstyle=\"\n\t\t\t\tposition: absolute;\n\t\t\t\ttransform: translate(100px, 100px);\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tbackground: #a0dde9;\n\t\t\t\tpadding: 1em;\n\t\t\t\"\n\t\t>\n\t\t\thello world!\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst group = new TWEEN.Group()\n\n\t\t\tconst position = {x: 100, y: 100, styles: {opacity: 1.0}}\n\t\t\tconst target = document.getElementById('target')\n\t\t\tconst tween = new TWEEN.Tween(position, group)\n\t\t\t\t.to({x: 700, y: 200, styles: {opacity: 0}}, 1000)\n\t\t\t\t.delay(1000)\n\t\t\t\t.onUpdate(update)\n\n\t\t\tconst tweenBack = new TWEEN.Tween(position, group)\n\t\t\t\t.to({x: 100, y: 100, styles: {opacity: 1.0}}, 1000)\n\n\t\t\t\t.onUpdate(update)\n\n\t\t\ttween.chain(tweenBack)\n\t\t\ttweenBack.chain(tween)\n\n\t\t\ttween.start()\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\tgroup.update(time)\n\t\t\t\trequestAnimationFrame(animate)\n\t\t\t}\n\n\t\t\tfunction update(values) {\n\t\t\t\ttarget.style.opacity = values.styles.opacity\n\t\t\t\ttarget.style.transform = `translate(${values.x}px, ${values.y}px)`\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/16_animate_an_array_of_values.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / animate an array of values</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>16 _ animate an array of values</h2>\n\t\t\t<p>Animate multiple objects with a single tween using an array of values.</p>\n\t\t</div>\n\t\t<div class=\"container\">\n\t\t\t<div id=\"target0\" class=\"box\">one</div>\n\t\t\t<div id=\"target1\" class=\"box\">two</div>\n\t\t\t<div id=\"target2\" class=\"box\">three</div>\n\t\t</div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst axes = ['Y', 'Z', 'X']\n\t\t\tconst tween1 = new TWEEN.Tween([0, 0, 0])\n\t\t\t\t.to([360, 540, '+180'], 2000)\n\t\t\t\t.repeat(1)\n\t\t\t\t.delay(1000)\n\t\t\t\t.easing(TWEEN.Easing.Cubic.InOut)\n\t\t\t\t.onUpdate(function (rotations) {\n\t\t\t\t\tfor (let i = 0; i < rotations.length; i++)\n\t\t\t\t\t\tdocument.getElementById('target' + i).style.transform =\n\t\t\t\t\t\t\t'rotate' + axes[i] + '(' + Math.floor(rotations[i]) + 'deg)'\n\t\t\t\t})\n\t\t\t\t.start()\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\t// Keep requesting frames only if we still need to update.\n\t\t\t\tif (tween1.update(time)) requestAnimationFrame(animate)\n\t\t\t}\n\t\t</script>\n\n\t\t<style type=\"text/css\">\n\t\t\t.container {\n\t\t\t\tposition: absolute;\n\t\t\t\ttop: 180px;\n\t\t\t\tleft: 400px;\n\t\t\t\tperspective: 400px;\n\t\t\t}\n\t\t\t.box {\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tmargin: 10px;\n\t\t\t\tpadding: 10px;\n\t\t\t\t/* display: inline-block; */\n\t\t\t\tfloat: left;\n\t\t\t}\n\t\t\t#target0 {\n\t\t\t\tbackground: #fcc;\n\t\t\t}\n\t\t\t#target1 {\n\t\t\t\tbackground: #cfc;\n\t\t\t}\n\t\t\t#target2 {\n\t\t\t\tbackground: #ccf;\n\t\t\t}\n\t\t</style>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/17_generate_pow.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / easing with a power of number</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<style>\n\t\t\tbody {\n\t\t\t\tmargin: 0px;\n\t\t\t}\n\n\t\t\t#target {\n\t\t\t\tfont-size: 13px;\n\t\t\t\tpadding: 0px 32px;\n\t\t\t}\n\t\t</style>\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\" style=\"position: relative\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>17 _ Easing with Pow</h2>\n\t\t\t<p>TWEEN.Easing.generatePow() provides easing with a power of number.</p>\n\t\t</div>\n\n\t\t<div id=\"target\"></div>\n\n\t\t<script type=\"module\">\n\t\t\timport {createGraph} from './js/createGraph.js'\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst group = new TWEEN.Group()\n\n\t\t\tconst target = document.getElementById('target')\n\n\t\t\tconst addGraph = pow => {\n\t\t\t\ttarget.appendChild(createGraph(group, `Power\"${pow}\".In`, TWEEN.Easing.generatePow(pow).In))\n\t\t\t\ttarget.appendChild(createGraph(group, `Power\"${pow}\".Out`, TWEEN.Easing.generatePow(pow).Out))\n\t\t\t\ttarget.appendChild(createGraph(group, `Power\"${pow}\".InOut`, TWEEN.Easing.generatePow(pow).InOut))\n\t\t\t}\n\t\t\ttarget.appendChild(createGraph(group, 'Power1', TWEEN.Easing.generatePow(1).In))\n\n\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\taddGraph(2)\n\t\t\taddGraph(3)\n\n\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\taddGraph(4)\n\t\t\taddGraph(5)\n\n\t\t\ttarget.appendChild(document.createElement('br'))\n\n\t\t\taddGraph(5.8)\n\t\t\ttarget.appendChild(createGraph(group, `Exponential.In`, TWEEN.Easing.Exponential.In))\n\t\t\ttarget.appendChild(createGraph(group, `Exponential.Out`, TWEEN.Easing.Exponential.Out))\n\t\t\ttarget.appendChild(createGraph(group, `Exponential.InOut`, TWEEN.Easing.Exponential.InOut))\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\trequestAnimationFrame(animate)\n\n\t\t\t\tgroup.update(time)\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/18_start_from_current_values.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / hello world!</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n\t\t<link href=\"css/style.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>18 _ start from current values</h2>\n\t\t\t<p>Example for illustrating the startFromCurrentValues() functionality.</p>\n\t\t\t<button id=\"start-tween\">Start tween</button>\n\t\t\t<button id=\"up\">↑</button>\n\t\t\t<button id=\"down\">↓</button>\n\t\t\t<button id=\"left\">←</button>\n\t\t\t<button id=\"right\">→</button>\n\t\t</div>\n\t\t<div\n\t\t\tid=\"target\"\n\t\t\tstyle=\"\n\t\t\t\tposition: absolute;\n\t\t\t\ttransform: translate(400px, 200px);\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tbackground: #a0dde9;\n\t\t\t\tpadding: 1em;\n\t\t\t\"\n\t\t></div>\n\n\t\t<script type=\"module\">\n\t\t\timport * as TWEEN from '../dist/tween.esm.js'\n\n\t\t\tconst position = {x: 400, y: 200}\n\t\t\tconst target = document.getElementById('target')\n\t\t\tconst tween = new TWEEN.Tween(position)\n\t\t\t\t.to({x: 700, y: 200}, 2000)\n\t\t\t\t.easing(TWEEN.Easing.Elastic.InOut)\n\t\t\t\t.onUpdate(update)\n\n\t\t\tdocument.getElementById('start-tween').addEventListener('click', () => {\n\t\t\t\ttween.startFromCurrentValues() // start the tween from its current position\n\t\t\t\tanimate() // call animate as we unregister the handler if TWEEN.update(time) returns false\n\t\t\t})\n\n\t\t\tregisterArrowButtonEventListeners()\n\n\t\t\tanimate()\n\n\t\t\tfunction animate(time) {\n\t\t\t\tif (tween.update(time)) requestAnimationFrame(animate)\n\t\t\t}\n\n\t\t\tfunction update() {\n\t\t\t\ttarget.style.transform = `translate(${position.x}px, ${position.y}px)`\n\t\t\t}\n\n\t\t\t//Add event listeners to each of the arrow buttons\n\t\t\tfunction registerArrowButtonEventListeners() {\n\t\t\t\tdocument.getElementById('up').addEventListener('click', moveUp)\n\t\t\t\tdocument.getElementById('down').addEventListener('click', moveDown)\n\t\t\t\tdocument.getElementById('left').addEventListener('click', moveLeft)\n\t\t\t\tdocument.getElementById('right').addEventListener('click', moveRight)\n\t\t\t}\n\n\t\t\t// Arrow button callbacks\n\t\t\tfunction moveLeft() {\n\t\t\t\tposition.x -= 20\n\t\t\t\tupdate()\n\t\t\t}\n\n\t\t\tfunction moveRight() {\n\t\t\t\tposition.x += 20\n\t\t\t\tupdate()\n\t\t\t}\n\n\t\t\tfunction moveUp() {\n\t\t\t\tposition.y -= 20\n\t\t\t\tupdate()\n\t\t\t}\n\n\t\t\tfunction moveDown() {\n\t\t\t\tposition.y += 20\n\t\t\t\tupdate()\n\t\t\t}\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/19_end_tween.html",
    "content": "<!-- shows what happens when we call tween.end() -->\n\n<style>\n\t#box {\n\t\tbackground-color: deeppink;\n\t\twidth: 100px;\n\t\theight: 100px;\n\t}\n</style>\n\n<div id=\"box\"></div>\n\n<button id=\"end\">tween.end()</button>\n\n<script type=\"module\">\n\timport {Tween, Easing} from '../dist/tween.esm.js'\n\n\tconst box = document.getElementById('box') // Get the element we want to animate.\n\n\tconst coords = {x: 0, y: 0} // Start at (0, 0)\n\n\tconst tween = new Tween(coords, false) // Create a new tween that modifies 'coords'.\n\t\t.to({x: 300, y: 200}, 5000) // Move to (300, 200) in 1 second.\n\t\t.easing(Easing.Quadratic.InOut) // Use an easing function to make the animation smooth.\n\t\t.onUpdate(() => {\n\t\t\t// Called after tween.js updates 'coords'.\n\t\t\t// Move 'box' to the position described by 'coords' with a CSS translation.\n\t\t\tbox.style.setProperty('transform', 'translate(' + coords.x + 'px, ' + coords.y + 'px)')\n\n\t\t\t//\n\t\t\tconsole.log(coords, tween.isPlaying())\n\t\t})\n\t\t.onComplete(() => {\n\t\t\tconsole.log('onComplete')\n\t\t})\n\t\t.start() // Start the tween immediately.\n\n\t// Setup the animation loop.\n\tfunction animate(time) {\n\t\ttween.update(time)\n\t\trequestAnimationFrame(animate)\n\t}\n\n\trequestAnimationFrame(animate)\n\n\tdocument.querySelector('#end').addEventListener('click', () => {\n\t\tconsole.log('tween.end')\n\t\ttween.end()\n\t\tconsole.log(tween)\n\t})\n</script>\n"
  },
  {
    "path": "examples/css/style.css",
    "content": "body {\n\tbackground: #fff;\n\tfont-family: Helvetica, Arial, sans;\n}\n\na {\n\tcolor: #333;\n}\n\nh2 {\n\tfont-weight: normal;\n}\n\nbutton {\n\tcursor: pointer;\n\tcolor: #333;\n\tbackground: #fff;\n\tborder: 2px solid #333;\n\tpadding: 10px;\n\tborder-radius: 10px;\n\tfont-weight: bold;\n\tfont-size: 20px;\n\ttransition: all 150ms ease-out;\n}\n\nbutton:hover {\n\tbackground: #333;\n\tcolor: #fff;\n}\n\n#info {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpadding: 1.5em 2em;\n}\n\n#info h1 {\n\tfont-size: 3em;\n\tcolor: #333;\n\tmargin-top: 0;\n\tletter-spacing: -0.05em;\n}\n\n#info h2 {\n\tfont-size: 2.5em;\n\ttext-transform: uppercase;\n\tcolor: #666;\n\tmargin-top: 0;\n}\n\n#info p {\n\tfont-size: 2em;\n\tline-height: 1em;\n\tcolor: #aaa;\n\tmax-width: 10em;\n}\n"
  },
  {
    "path": "examples/example-projects/nodejs-commonjs/README.md",
    "content": "This example shows that Tween.js can be imported into a Node.js project in CommonJS format.\n"
  },
  {
    "path": "examples/example-projects/nodejs-commonjs/index.js",
    "content": "// Ensure we can import into Node CommonJS:\n\nconst TWEEN = require('@tweenjs/tween.js')\n\nconsole.log(Object.keys(TWEEN))\n\nconst tween = new TWEEN.Tween()\n\nconsole.log(Object.keys(tween))\n"
  },
  {
    "path": "examples/example-projects/nodejs-commonjs/package.json",
    "content": "{\n\t\"description\": \"Node.js project in CommonJS format, importing Tween in CommonJS format.\",\n\t\"type\": \"commonjs\",\n\t\"scripts\": {\n\t\t\"start\": \"node ./index.js\"\n\t},\n\t\"dependencies\": {\n\t\t\"@tweenjs/tween.js\": \"file:../../../\"\n\t}\n}\n"
  },
  {
    "path": "examples/example-projects/nodejs-esmodules/README.md",
    "content": "This example shows that Tween.js can be imported into a Node.js project in ES Module format.\n"
  },
  {
    "path": "examples/example-projects/nodejs-esmodules/index.js",
    "content": "// Ensure we can import into Node ESM:\n\nimport * as TWEEN from '@tweenjs/tween.js'\n\nconsole.log(Object.keys(TWEEN))\n\nconst tween = new TWEEN.Tween()\n\nconsole.log(Object.keys(tween))\n"
  },
  {
    "path": "examples/example-projects/nodejs-esmodules/package.json",
    "content": "{\n\t\"description\": \"Node.js project in CommonJS format, importing Tween in CommonJS format.\",\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"start\": \"node ./index.js\"\n\t},\n\t\"dependencies\": {\n\t\t\"@tweenjs/tween.js\": \"file:../../../\"\n\t}\n}\n"
  },
  {
    "path": "examples/example-projects/plain-javascript-modules/README.md",
    "content": "This example is written in JavaScript without any build, using JavaScript\nmodules to organize code into separate files and importing from one file to the\nother using native `import` syntax.\n\nTo set up, run `npm install`.\n\nTo run the project, run `npm start`.\n"
  },
  {
    "path": "examples/example-projects/plain-javascript-modules/animate.js",
    "content": "export function animate(group) {\n\tfunction loop(time) {\n\t\tgroup.update(time)\n\t\tconst stopped = group.allStopped()\n\t\tif (!stopped) requestAnimationFrame(loop)\n\t}\n\n\tloop(performance.now())\n}\n"
  },
  {
    "path": "examples/example-projects/plain-javascript-modules/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / hello world (JS modules)!</title>\n\t\t<link href=\"./style.css\" rel=\"stylesheet\" />\n\n\t\t<style>\n\t\t\t#target {\n\t\t\t\tposition: absolute;\n\t\t\t\ttransform-style: preserve-3d;\n\t\t\t\ttransform: translate3d(100px, 100px, 0.0001px) rotateY(10deg);\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tbackground: #a0dde9;\n\t\t\t\tpadding: 1em;\n\t\t\t}\n\t\t</style>\n\n\t\t<!-- Use an import map to tell the browser where to find the package\n\t\tnamed \"@tweenjs/tween.js\" when a JS module import statement imports\n\t\t`from '@tweenjs/tween.js'`. See the import statement in ./index.js. -->\n\t\t<script type=\"importmap\">\n\t\t\t{\n\t\t\t\t\"imports\": {\n\t\t\t\t\t\"@tweenjs/tween.js\": \"./node_modules/@tweenjs/tween.js/dist/tween.esm.js\"\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>00 _ hello world (using native JS modules)</h2>\n\t\t\t<p>Simple example for illustrating the creation and chaining of tweens.</p>\n\t\t</div>\n\n\t\t<div id=\"target\">hello world!</div>\n\n\t\t<script type=\"module\" src=\"./index.js\"></script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/example-projects/plain-javascript-modules/index.js",
    "content": "import * as TWEEN from '@tweenjs/tween.js'\n\n// For sake of example, we put animate() in a separate file, and import it into index.js.\nimport {animate} from './animate.js'\n\nconst group = new TWEEN.Group()\n\nconst position = {x: 100, y: 100, rotation: 10}\nconst target = document.getElementById('target')\nconst tween = new TWEEN.Tween(position, group)\n\t.to({x: 700, y: 200, rotation: 359}, 2000)\n\t.delay(1000)\n\t.easing(TWEEN.Easing.Elastic.InOut)\n\t.onUpdate(update)\n\nconst tweenBack = new TWEEN.Tween(position, group)\n\t.to({x: 100, y: 100, rotation: 10}, 3000)\n\t.easing(TWEEN.Easing.Elastic.InOut)\n\t.onUpdate(update)\n\ntween.chain(tweenBack)\ntweenBack.chain(tween)\n\ntween.start()\n\nanimate(group)\n\nfunction update() {\n\ttarget.style.transform = `translate3d(${position.x}px, ${position.y}px, 0.0001px) rotateY(${Math.floor(position.rotation)}deg)`\n}\n"
  },
  {
    "path": "examples/example-projects/plain-javascript-modules/package.json",
    "content": "{\n\t\"description\": \"Plain JS modules in a browser.\",\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"start\": \"npm run serve\",\n\t\t\"serve\": \"five-server .\"\n\t},\n\t\"dependencies\": {\n\t\t\"@tweenjs/tween.js\": \"file:../../../\"\n\t},\n\t\"devDependencies\": {\n\t\t\"five-server\": \"^0.3.2\"\n\t}\n}\n"
  },
  {
    "path": "examples/example-projects/plain-javascript-modules/style.css",
    "content": "html {\n\ttransform-style: preserve-3d;\n\tperspective: 800px;\n}\nbody {\n\tbackground: #fff;\n\tfont-family: Helvetica, Arial, sans;\n\ttransform-style: preserve-3d;\n}\n\na {\n\tcolor: #333;\n}\n\nh2 {\n\tfont-weight: normal;\n}\n\nbutton {\n\tcursor: pointer;\n\tcolor: #333;\n\tbackground: #fff;\n\tborder: 2px solid #333;\n\tpadding: 10px;\n\tborder-radius: 10px;\n\tfont-weight: bold;\n\tfont-size: 20px;\n\ttransition: all 150ms ease-out;\n}\n\nbutton:hover {\n\tbackground: #333;\n\tcolor: #fff;\n}\n\n#info {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpadding: 1.5em 2em;\n}\n\n#info h1 {\n\tfont-size: 3em;\n\tcolor: #333;\n\tmargin-top: 0;\n\tletter-spacing: -0.05em;\n}\n\n#info h2 {\n\tfont-size: 2.5em;\n\ttext-transform: uppercase;\n\tcolor: #666;\n\tmargin-top: 0;\n}\n\n#info p {\n\tfont-size: 2em;\n\tline-height: 1em;\n\tcolor: #aaa;\n\tmax-width: 10em;\n}\n"
  },
  {
    "path": "examples/example-projects/plain-typescript-modules/README.md",
    "content": "This example is written in TypeScript and requires running a build step, using\nJavaScript module format to organize code into separate files and importing from\none file to the other using native `import` syntax.\n\nThis example uses the `tsc` (TypeScript compiler) to compile `.ts` files into\n`.js` files. The `tsconfig.json` file specifies the output format to be\n`esnext`, which means the output `.js` files will have `import` statements just\nas we've written them in the `.ts` files, and the output `.js` files will be\nexecuted as native JS modules in the browser.\n\nTo set up, run `npm install`.\n\nTo build and run the project in a single command, run `npm start`.\n\nTo compile only, run `npm run build` to generate `.js` files from `.ts` files.\n\nTo continuously build `.ts` files into `.js` files any time the `.ts` files change, run `npm run dev`.\n"
  },
  {
    "path": "examples/example-projects/plain-typescript-modules/animate.js",
    "content": "export function animate(group) {\n    function loop(time) {\n        group.update(time);\n        const stopped = group.allStopped();\n        if (!stopped)\n            requestAnimationFrame(loop);\n    }\n    loop(performance.now());\n}\n"
  },
  {
    "path": "examples/example-projects/plain-typescript-modules/animate.ts",
    "content": "import type {Group} from '@tweenjs/tween.js'\n\nexport function animate(group: Group) {\n\tfunction loop(time: number) {\n\t\tgroup.update(time)\n\t\tconst stopped = group.allStopped()\n\t\tif (!stopped) requestAnimationFrame(loop)\n\t}\n\n\tloop(performance.now())\n}\n"
  },
  {
    "path": "examples/example-projects/plain-typescript-modules/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<title>Tween.js / hello world (JS modules)!</title>\n\t\t<link href=\"./style.css\" rel=\"stylesheet\" />\n\n\t\t<style>\n\t\t\t#target {\n\t\t\t\tposition: absolute;\n\t\t\t\ttransform-style: preserve-3d;\n\t\t\t\ttransform: translate3d(100px, 100px, 0.0001px) rotateY(10deg);\n\t\t\t\twidth: 100px;\n\t\t\t\theight: 100px;\n\t\t\t\tbackground: #a0dde9;\n\t\t\t\tpadding: 1em;\n\t\t\t}\n\t\t</style>\n\n\t\t<!-- Use an import map to tell the browser where to find the package\n\t\tnamed \"@tweenjs/tween.js\" when a JS module import statement imports\n\t\t`from '@tweenjs/tween.js'`. See the import statement in ./index.js. -->\n\t\t<script type=\"importmap\">\n\t\t\t{\n\t\t\t\t\"imports\": {\n\t\t\t\t\t\"@tweenjs/tween.js\": \"./node_modules/@tweenjs/tween.js/dist/tween.esm.js\"\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"info\">\n\t\t\t<h1><a href=\"http://github.com/tweenjs/tween.js\">tween.js</a></h1>\n\t\t\t<h2>00 _ hello world (using native JS modules)</h2>\n\t\t\t<p>Simple example for illustrating the creation and chaining of tweens.</p>\n\t\t</div>\n\n\t\t<div id=\"target\">hello world!</div>\n\n\t\t<!-- ./index.js is generated from ./index.ts -->\n\t\t<script type=\"module\" src=\"./index.js\"></script>\n\t</body>\n</html>\n"
  },
  {
    "path": "examples/example-projects/plain-typescript-modules/index.js",
    "content": "import * as TWEEN from '@tweenjs/tween.js';\n// For sake of example, we put animate() in a separate file, and import it into index.ts.\n// Note the extension needs to be .js, as TypeScript does modify the import specifiers, and .js is needed once the file is converted to plain JS.\nimport { animate } from './animate.js';\nconst group = new TWEEN.Group();\nconst position = { x: 100, y: 100, rotation: 10 };\nconst target = document.getElementById('target');\nconst tween = new TWEEN.Tween(position, group)\n    .to({ x: 700, y: 200, rotation: 359 }, 2000)\n    .delay(1000)\n    .easing(TWEEN.Easing.Elastic.InOut)\n    .onUpdate(update);\nconst tweenBack = new TWEEN.Tween(position, group)\n    .to({ x: 100, y: 100, rotation: 10 }, 3000)\n    .easing(TWEEN.Easing.Elastic.InOut)\n    .onUpdate(update);\ntween.chain(tweenBack);\ntweenBack.chain(tween);\ntween.start();\nanimate(group);\nfunction update() {\n    target.style.transform = `translate3d(${position.x}px, ${position.y}px, 0.0001px) rotateY(${Math.floor(position.rotation)}deg)`;\n}\n"
  },
  {
    "path": "examples/example-projects/plain-typescript-modules/index.ts",
    "content": "import * as TWEEN from '@tweenjs/tween.js'\n\n// For sake of example, we put animate() in a separate file, and import it into index.ts.\n// Note the extension needs to be .js, as TypeScript does modify the import specifiers, and .js is needed once the file is converted to plain JS.\nimport {animate} from './animate.js'\n\nconst group = new TWEEN.Group()\n\nconst position = {x: 100, y: 100, rotation: 10}\nconst target = document.getElementById('target')\nconst tween = new TWEEN.Tween(position, group)\n\t.to({x: 700, y: 200, rotation: 359}, 2000)\n\t.delay(1000)\n\t.easing(TWEEN.Easing.Elastic.InOut)\n\t.onUpdate(update)\n\nconst tweenBack = new TWEEN.Tween(position, group)\n\t.to({x: 100, y: 100, rotation: 10}, 3000)\n\t.easing(TWEEN.Easing.Elastic.InOut)\n\t.onUpdate(update)\n\ntween.chain(tweenBack)\ntweenBack.chain(tween)\n\ntween.start()\n\nanimate(group)\n\nfunction update() {\n\ttarget.style.transform = `translate3d(${position.x}px, ${position.y}px, 0.0001px) rotateY(${Math.floor(position.rotation)}deg)`\n}\n"
  },
  {
    "path": "examples/example-projects/plain-typescript-modules/package.json",
    "content": "{\n\t\"description\": \"TS compiled to plain JS modules for running in browser.\",\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"start\": \"npm run build && npm run serve\",\n\t\t\"build\": \"tsc\",\n\t\t\"dev\": \"tsc --watch\",\n\t\t\"serve\": \"five-server .\"\n\t},\n\t\"dependencies\": {\n\t\t\"@tweenjs/tween.js\": \"file:../../../\"\n\t},\n\t\"devDependencies\": {\n\t\t\"five-server\": \"^0.3.2\",\n\t\t\"typescript\": \"^5.3.3\"\n\t}\n}\n"
  },
  {
    "path": "examples/example-projects/plain-typescript-modules/style.css",
    "content": "html {\n\ttransform-style: preserve-3d;\n\tperspective: 800px;\n}\nbody {\n\tbackground: #fff;\n\tfont-family: Helvetica, Arial, sans;\n\ttransform-style: preserve-3d;\n}\n\na {\n\tcolor: #333;\n}\n\nh2 {\n\tfont-weight: normal;\n}\n\nbutton {\n\tcursor: pointer;\n\tcolor: #333;\n\tbackground: #fff;\n\tborder: 2px solid #333;\n\tpadding: 10px;\n\tborder-radius: 10px;\n\tfont-weight: bold;\n\tfont-size: 20px;\n\ttransition: all 150ms ease-out;\n}\n\nbutton:hover {\n\tbackground: #333;\n\tcolor: #fff;\n}\n\n#info {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpadding: 1.5em 2em;\n}\n\n#info h1 {\n\tfont-size: 3em;\n\tcolor: #333;\n\tmargin-top: 0;\n\tletter-spacing: -0.05em;\n}\n\n#info h2 {\n\tfont-size: 2.5em;\n\ttext-transform: uppercase;\n\tcolor: #666;\n\tmargin-top: 0;\n}\n\n#info p {\n\tfont-size: 2em;\n\tline-height: 1em;\n\tcolor: #aaa;\n\tmax-width: 10em;\n}\n"
  },
  {
    "path": "examples/example-projects/plain-typescript-modules/tsconfig.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"module\": \"ESNext\",\n\t\t\"moduleResolution\": \"node\",\n\t\t\"target\": \"ESNext\"\n\t},\n\t\"include\": [\"./**/*.ts\"]\n}\n"
  },
  {
    "path": "examples/js/createGraph.js",
    "content": "// @ts-check\nimport {Tween, Easing} from '../../dist/tween.esm.js'\nimport {toPhysicalPx} from './toPhysicalPx.js'\n\nexport function createGraph(group, text, easingFn, width = 180, height = 100) {\n\tconst div = document.createElement('div')\n\tdiv.style.display = 'inline-block'\n\t// +20 for padding\n\tdiv.style.width = width + 20 + 'px'\n\tdiv.style.height = height + 20 + 'px'\n\n\tconst canvas = document.createElement('canvas')\n\tcanvas.style.width = width + 'px'\n\tcanvas.style.height = height + 'px'\n\tcanvas.width = toPhysicalPx(width)\n\tcanvas.height = toPhysicalPx(height)\n\n\tconst context = canvas.getContext('2d')\n\tif (!context) throw 'impossible'\n\n\tcontext.fillStyle = 'rgb(250,250,250)'\n\tcontext.fillRect(0, 0, toPhysicalPx(width), toPhysicalPx(height))\n\n\tcontext.lineWidth = toPhysicalPx(1)\n\tcontext.strokeStyle = 'rgb(230,230,230)'\n\n\tcontext.beginPath()\n\tcontext.moveTo(0, toPhysicalPx(20))\n\tcontext.lineTo(toPhysicalPx(width), toPhysicalPx(20))\n\tcontext.moveTo(0, toPhysicalPx(80))\n\tcontext.lineTo(toPhysicalPx(width), toPhysicalPx(80))\n\tcontext.closePath()\n\tcontext.stroke()\n\n\tcontext.lineWidth = toPhysicalPx(2)\n\tcontext.strokeStyle = 'rgba(255,127,127,0.9)'\n\tcontext.beginPath()\n\tcontext.moveTo(toPhysicalPx(5), toPhysicalPx(80))\n\tcontext.lineCap = 'round'\n\n\tconst position = {x: toPhysicalPx(5), y: toPhysicalPx(80)}\n\n\tnew Tween(position, group)\n\t\t.to({x: toPhysicalPx(175)}, 2000)\n\t\t.easing(Easing.Linear.None)\n\t\t.start()\n\n\tnew Tween(position, group)\n\t\t.to({y: toPhysicalPx(20)}, 2000)\n\t\t.easing(easingFn)\n\t\t.onUpdate(function () {\n\t\t\tcontext.lineTo(position.x, position.y)\n\t\t\tcontext.stroke()\n\t\t})\n\t\t.start()\n\n\tdiv.appendChild(document.createTextNode(text))\n\tdiv.appendChild(document.createElement('br'))\n\tdiv.appendChild(canvas)\n\n\treturn div\n}\n"
  },
  {
    "path": "examples/js/createPath.js",
    "content": "// @ts-check\nimport {Tween, Easing} from '../../dist/tween.esm.js'\nimport {toPhysicalPx} from './toPhysicalPx.js'\n\nconst width = 240,\n\theight = 160\n\n// random points\n\n/*\nexport const x0 = Math.random() * (width - 40) + 20,\n\ty0 = Math.random() * (height - 40) + 20,\n\txA = [],\n\tyA = []\n\nfor (const i = 0; i < 10; i++) {\n\txA.push(Math.random() * (width - 40) + 20)\n\tyA.push(Math.random() * (height - 40) + 20)\n}\n*/\n\n// fixed points\n\nexport const min = 1 / 6,\n\tmax = 5 / 6\n\nexport const x0 = width * min,\n\ty0 = height / 2,\n\txA = [width * max, width / 2],\n\tyA = [height * min, height * max]\n\nexport function createPath(group, text, interpolation, width = 240, height = 160) {\n\tconst div = document.createElement('div')\n\tdiv.style.display = 'inline-block'\n\t// +20 for padding\n\tdiv.style.width = width + 20 + 'px'\n\tdiv.style.height = height + 20 + 'px'\n\n\tconst canvas = document.createElement('canvas')\n\tcanvas.style.width = width + 'px'\n\tcanvas.style.height = height + 'px'\n\tcanvas.width = toPhysicalPx(width)\n\tcanvas.height = toPhysicalPx(height)\n\n\tconst context = canvas.getContext('2d')\n\tif (!context) throw 'doh'\n\tcontext.fillStyle = 'rgb(250,250,250)'\n\tcontext.fillRect(0, 0, toPhysicalPx(width), toPhysicalPx(height))\n\n\tcontext.lineWidth = toPhysicalPx(1)\n\tcontext.strokeStyle = 'rgb(230,230,230)'\n\n\t// points\n\tcontext.fillStyle = 'rgb(200,200,200)'\n\tcontext.fillRect(\n\t\ttoPhysicalPx(x0) - toPhysicalPx(3),\n\t\ttoPhysicalPx(y0) - toPhysicalPx(3),\n\t\ttoPhysicalPx(6),\n\t\ttoPhysicalPx(6),\n\t)\n\tcontext.fillRect(\n\t\ttoPhysicalPx(xA[xA.length - 1]) - toPhysicalPx(3),\n\t\ttoPhysicalPx(yA[yA.length - 1]) - toPhysicalPx(3),\n\t\ttoPhysicalPx(6),\n\t\ttoPhysicalPx(6),\n\t)\n\n\tfor (let i = 0; i < xA.length; i++) {\n\t\tcontext.fillRect(\n\t\t\ttoPhysicalPx(xA[i]) - toPhysicalPx(2),\n\t\t\ttoPhysicalPx(yA[i]) - toPhysicalPx(2),\n\t\t\ttoPhysicalPx(4),\n\t\t\ttoPhysicalPx(4),\n\t\t)\n\t}\n\t//\n\n\tcontext.lineWidth = toPhysicalPx(2)\n\tcontext.strokeStyle = 'rgba(255,127,127,0.9)'\n\tcontext.beginPath()\n\tcontext.moveTo(toPhysicalPx(x0), toPhysicalPx(y0))\n\tcontext.lineCap = 'round'\n\n\tconst position = {x: x0, y: y0}\n\n\tnew Tween(position, group)\n\t\t.to({x: xA, y: yA}, 3000)\n\t\t.easing(Easing.Linear.None)\n\t\t.interpolation(interpolation)\n\t\t.onUpdate(function () {\n\t\t\tcontext.lineTo(toPhysicalPx(position.x), toPhysicalPx(position.y))\n\t\t\tcontext.stroke()\n\t\t})\n\t\t.start()\n\n\tdiv.appendChild(document.createTextNode(text))\n\tdiv.appendChild(document.createElement('br'))\n\tdiv.appendChild(canvas)\n\n\treturn div\n}\n"
  },
  {
    "path": "examples/js/drawings.js",
    "content": "export function drawRabbit(context, x, y, color, opacity = 1) {\n\tcontext.save()\n\n\tcontext.fillStyle = color\n\tcontext.globalAlpha = opacity\n\n\tcontext.translate(x, y)\n\n\tcontext.beginPath()\n\tcontext.moveTo(0, 0)\n\tcontext.bezierCurveTo(15, 0, 15, -40, 5, -30)\n\tcontext.lineTo(0, 0)\n\tcontext.bezierCurveTo(-15, 0, -15, -40, -5, -30)\n\tcontext.lineTo(0, 0)\n\tcontext.closePath()\n\tcontext.fill()\n\n\tcontext.beginPath()\n\tcontext.arc(0, 0, 15, 0, Math.PI * 2, true)\n\tcontext.closePath()\n\tcontext.fill()\n\n\tcontext.restore()\n}\n\nexport function drawFox(context, x, y, color) {\n\tcontext.save()\n\n\tcontext.fillStyle = color\n\n\tcontext.translate(x, y - 13)\n\tcontext.scale(1.2, 1.2)\n\n\tcontext.beginPath()\n\tcontext.moveTo(4, 24)\n\tcontext.lineTo(8, 16)\n\tcontext.lineTo(14, 10)\n\tcontext.lineTo(15, 0)\n\tcontext.lineTo(9, -10)\n\tcontext.lineTo(2, 0)\n\tcontext.lineTo(-2, 0)\n\tcontext.lineTo(-9, -10)\n\tcontext.lineTo(-15, 0)\n\tcontext.lineTo(-14, 10)\n\tcontext.lineTo(-8, 16)\n\tcontext.lineTo(-4, 24)\n\tcontext.closePath()\n\tcontext.fill()\n\n\tcontext.restore()\n}\n"
  },
  {
    "path": "examples/js/toPhysicalPx.js",
    "content": "export const toPhysicalPx = cssPx => cssPx * devicePixelRatio\n"
  },
  {
    "path": "package.json",
    "content": "{\n\t\"name\": \"@tweenjs/tween.js\",\n\t\"description\": \"Simple and fast tweening engine with optimised Robert Penner's equations.\",\n\t\"version\": \"25.0.0\",\n\t\"type\": \"module\",\n\t\"main\": \"dist/tween.cjs\",\n\t\"types\": \"dist/tween.d.ts\",\n\t\"module\": \"dist/tween.esm.js\",\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"import\": \"./dist/tween.esm.js\",\n\t\t\t\"require\": \"./dist/tween.cjs\",\n\t\t\t\"types\": \"./dist/tween.d.ts\"\n\t\t}\n\t},\n\t\"files\": [\n\t\t\"dist\",\n\t\t\"README.md\",\n\t\t\"LICENSE\"\n\t],\n\t\"homepage\": \"https://github.com/tweenjs/tween.js\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/tweenjs/tween.js.git\"\n\t},\n\t\"bugs\": {\n\t\t\"url\": \"https://github.com/tweenjs/tween.js/issues\"\n\t},\n\t\"license\": \"MIT\",\n\t\"keywords\": [\n\t\t\"tween\",\n\t\t\"interpolation\"\n\t],\n\t\"dependencies\": {},\n\t\"scripts\": {\n\t\t\"dev\": \"(npm run tsc-watch -- --preserveWatchOutput & p1=$!; npm run rollup-build -- --watch & p2=$!; wait $p1 $p2)\",\n\t\t\"build\": \"rimraf dist .tmp && node scripts/write-version.js && npm run tsc && npm run rollup-build\",\n\t\t\"rollup-build\": \"rollup -c ./rollup.config.js\",\n\t\t\"tsc\": \"tsc\",\n\t\t\"tsc-watch\": \"tsc --watch\",\n\t\t\"examples\": \"npx serve .\",\n\t\t\"test\": \"npm run build && npm run test-lint && npm run test-unit\",\n\t\t\"test-unit\": \"nodeunit test/unit/nodeunitheadless.cjs\",\n\t\t\"test-lint\": \"npm run prettier -- --check\",\n\t\t\"lint\": \"npm run prettier -- --write\",\n\t\t\"prettier\": \"prettier .\",\n\t\t\"prepare\": \"npm run build\",\n\t\t\"version\": \"npm test && git add .\",\n\t\t\"release:patch\": \"npm version patch --message 'v%s' && npm publish && npm run _release:push-branch\",\n\t\t\"release:minor\": \"npm version minor --message 'v%s' && npm publish && npm run _release:push-branch\",\n\t\t\"release:major\": \"npm version major --message 'v%s' && npm publish && npm run _release:push-branch\",\n\t\t\"_release:push-branch\": \"git push --follow-tags --set-upstream origin `git rev-parse --abbrev-ref HEAD`\"\n\t},\n\t\"author\": \"tween.js contributors (https://github.com/tweenjs/tween.js/graphs/contributors)\",\n\t\"devDependencies\": {\n\t\t\"nodeunit\": \"^0.11.3\",\n\t\t\"prettier\": \"^3.0.0\",\n\t\t\"rimraf\": \"^3.0.0\",\n\t\t\"rollup\": \"3.20.7\",\n\t\t\"rollup-plugin-dts\": \"5.3.0\",\n\t\t\"tslib\": \"^1.10.0\",\n\t\t\"typescript\": \"5.0.4\"\n\t}\n}\n"
  },
  {
    "path": "rollup.config.js",
    "content": "import dts from 'rollup-plugin-dts'\n\nexport default [\n\t{\n\t\tinput: '.tmp/Index.js',\n\t\t// https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined\n\t\tcontext: 'this',\n\t\twatch: {clearScreen: false},\n\t\toutput: [\n\t\t\t{\n\t\t\t\tfile: 'dist/tween.umd.js',\n\t\t\t\tname: 'TWEEN',\n\t\t\t\tformat: 'umd',\n\t\t\t\texports: 'named',\n\t\t\t},\n\t\t\t{\n\t\t\t\tfile: 'dist/tween.amd.js',\n\t\t\t\tformat: 'amd',\n\t\t\t\texports: 'named',\n\t\t\t},\n\t\t\t{\n\t\t\t\tfile: 'dist/tween.cjs',\n\t\t\t\tformat: 'cjs',\n\t\t\t\texports: 'named',\n\t\t\t},\n\t\t\t{\n\t\t\t\tfile: 'dist/tween.esm.js',\n\t\t\t\tformat: 'es',\n\t\t\t\texports: 'named',\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tinput: '.tmp/tests.js',\n\t\tcontext: 'this',\n\t\twatch: {clearScreen: false},\n\t\toutput: [\n\t\t\t{file: '.tmp/tests.cjs', format: 'cjs', exports: 'named'}, // For tests running in Node.js\n\t\t\t{file: '.tmp/tests.umd.js', format: 'umd', exports: 'named', name: 'TWEEN'}, // For the nodeunit.html tests in browser\n\t\t],\n\t},\n\t{\n\t\tinput: './.tmp/Index.d.ts',\n\t\twatch: {clearScreen: false},\n\t\toutput: [{file: 'dist/tween.d.ts', format: 'es'}],\n\t\tplugins: [dts()],\n\t},\n]\n"
  },
  {
    "path": "scripts/write-version.js",
    "content": "import fs from 'fs'\nimport pkg from '../package.json' with {type: 'json'}\n\nconst {version} = pkg\n\nfunction handleError(error) {\n\tif (error) {\n\t\tconsole.error(error)\n\t\tprocess.exit(1)\n\t}\n}\n\nfs.open('./src/Version.ts', 'w', (error, fd) => {\n\thandleError(error)\n\tfs.write(fd, [`const VERSION = '${version}'`, 'export default VERSION', ''].join('\\n'), error => {\n\t\thandleError(error)\n\t})\n})\n"
  },
  {
    "path": "src/Easing.ts",
    "content": "export type EasingFunction = (amount: number) => number\n\nexport type EasingFunctionGroup = {\n\tIn: EasingFunction\n\tOut: EasingFunction\n\tInOut: EasingFunction\n}\n\n/**\n * The Ease class provides a collection of easing functions for use with tween.js.\n */\n\nexport const Easing = Object.freeze({\n\tLinear: Object.freeze<EasingFunctionGroup & {None: EasingFunction}>({\n\t\tNone(amount: number): number {\n\t\t\treturn amount\n\t\t},\n\t\tIn(amount: number): number {\n\t\t\treturn amount\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\treturn amount\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\treturn amount\n\t\t},\n\t}),\n\n\tQuadratic: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\treturn amount * amount\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\treturn amount * (2 - amount)\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\tif ((amount *= 2) < 1) {\n\t\t\t\treturn 0.5 * amount * amount\n\t\t\t}\n\n\t\t\treturn -0.5 * (--amount * (amount - 2) - 1)\n\t\t},\n\t}),\n\n\tCubic: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\treturn amount * amount * amount\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\treturn --amount * amount * amount + 1\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\tif ((amount *= 2) < 1) {\n\t\t\t\treturn 0.5 * amount * amount * amount\n\t\t\t}\n\t\t\treturn 0.5 * ((amount -= 2) * amount * amount + 2)\n\t\t},\n\t}),\n\n\tQuartic: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\treturn amount * amount * amount * amount\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\treturn 1 - --amount * amount * amount * amount\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\tif ((amount *= 2) < 1) {\n\t\t\t\treturn 0.5 * amount * amount * amount * amount\n\t\t\t}\n\n\t\t\treturn -0.5 * ((amount -= 2) * amount * amount * amount - 2)\n\t\t},\n\t}),\n\n\tQuintic: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\treturn amount * amount * amount * amount * amount\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\treturn --amount * amount * amount * amount * amount + 1\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\tif ((amount *= 2) < 1) {\n\t\t\t\treturn 0.5 * amount * amount * amount * amount * amount\n\t\t\t}\n\n\t\t\treturn 0.5 * ((amount -= 2) * amount * amount * amount * amount + 2)\n\t\t},\n\t}),\n\n\tSinusoidal: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\treturn 1 - Math.sin(((1.0 - amount) * Math.PI) / 2)\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\treturn Math.sin((amount * Math.PI) / 2)\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\treturn 0.5 * (1 - Math.sin(Math.PI * (0.5 - amount)))\n\t\t},\n\t}),\n\n\tExponential: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\treturn amount === 0 ? 0 : Math.pow(1024, amount - 1)\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\treturn amount === 1 ? 1 : 1 - Math.pow(2, -10 * amount)\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\tif (amount === 0) {\n\t\t\t\treturn 0\n\t\t\t}\n\n\t\t\tif (amount === 1) {\n\t\t\t\treturn 1\n\t\t\t}\n\n\t\t\tif ((amount *= 2) < 1) {\n\t\t\t\treturn 0.5 * Math.pow(1024, amount - 1)\n\t\t\t}\n\n\t\t\treturn 0.5 * (-Math.pow(2, -10 * (amount - 1)) + 2)\n\t\t},\n\t}),\n\n\tCircular: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\treturn 1 - Math.sqrt(1 - amount * amount)\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\treturn Math.sqrt(1 - --amount * amount)\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\tif ((amount *= 2) < 1) {\n\t\t\t\treturn -0.5 * (Math.sqrt(1 - amount * amount) - 1)\n\t\t\t}\n\t\t\treturn 0.5 * (Math.sqrt(1 - (amount -= 2) * amount) + 1)\n\t\t},\n\t}),\n\n\tElastic: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\tif (amount === 0) {\n\t\t\t\treturn 0\n\t\t\t}\n\n\t\t\tif (amount === 1) {\n\t\t\t\treturn 1\n\t\t\t}\n\n\t\t\treturn -Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI)\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\tif (amount === 0) {\n\t\t\t\treturn 0\n\t\t\t}\n\n\t\t\tif (amount === 1) {\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\treturn Math.pow(2, -10 * amount) * Math.sin((amount - 0.1) * 5 * Math.PI) + 1\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\tif (amount === 0) {\n\t\t\t\treturn 0\n\t\t\t}\n\n\t\t\tif (amount === 1) {\n\t\t\t\treturn 1\n\t\t\t}\n\n\t\t\tamount *= 2\n\n\t\t\tif (amount < 1) {\n\t\t\t\treturn -0.5 * Math.pow(2, 10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI)\n\t\t\t}\n\n\t\t\treturn 0.5 * Math.pow(2, -10 * (amount - 1)) * Math.sin((amount - 1.1) * 5 * Math.PI) + 1\n\t\t},\n\t}),\n\n\tBack: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\tconst s = 1.70158\n\t\t\treturn amount === 1 ? 1 : amount * amount * ((s + 1) * amount - s)\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\tconst s = 1.70158\n\t\t\treturn amount === 0 ? 0 : --amount * amount * ((s + 1) * amount + s) + 1\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\tconst s = 1.70158 * 1.525\n\t\t\tif ((amount *= 2) < 1) {\n\t\t\t\treturn 0.5 * (amount * amount * ((s + 1) * amount - s))\n\t\t\t}\n\t\t\treturn 0.5 * ((amount -= 2) * amount * ((s + 1) * amount + s) + 2)\n\t\t},\n\t}),\n\n\tBounce: Object.freeze(<EasingFunctionGroup>{\n\t\tIn(amount: number): number {\n\t\t\treturn 1 - Easing.Bounce.Out(1 - amount)\n\t\t},\n\t\tOut(amount: number): number {\n\t\t\tif (amount < 1 / 2.75) {\n\t\t\t\treturn 7.5625 * amount * amount\n\t\t\t} else if (amount < 2 / 2.75) {\n\t\t\t\treturn 7.5625 * (amount -= 1.5 / 2.75) * amount + 0.75\n\t\t\t} else if (amount < 2.5 / 2.75) {\n\t\t\t\treturn 7.5625 * (amount -= 2.25 / 2.75) * amount + 0.9375\n\t\t\t} else {\n\t\t\t\treturn 7.5625 * (amount -= 2.625 / 2.75) * amount + 0.984375\n\t\t\t}\n\t\t},\n\t\tInOut(amount: number): number {\n\t\t\tif (amount < 0.5) {\n\t\t\t\treturn Easing.Bounce.In(amount * 2) * 0.5\n\t\t\t}\n\t\t\treturn Easing.Bounce.Out(amount * 2 - 1) * 0.5 + 0.5\n\t\t},\n\t}),\n\n\tgeneratePow(power = 4): EasingFunctionGroup {\n\t\tpower = power < Number.EPSILON ? Number.EPSILON : power\n\t\tpower = power > 10000 ? 10000 : power\n\t\treturn {\n\t\t\tIn(amount: number): number {\n\t\t\t\treturn amount ** power\n\t\t\t},\n\t\t\tOut(amount: number): number {\n\t\t\t\treturn 1 - (1 - amount) ** power\n\t\t\t},\n\t\t\tInOut(amount: number): number {\n\t\t\t\tif (amount < 0.5) {\n\t\t\t\t\treturn (amount * 2) ** power / 2\n\t\t\t\t}\n\t\t\t\treturn (1 - (2 - amount * 2) ** power) / 2 + 0.5\n\t\t\t},\n\t\t}\n\t},\n})\n\nexport default Easing\n"
  },
  {
    "path": "src/Group.ts",
    "content": "import now from './Now'\nimport type {Tween} from './Tween'\n\n/**\n * Controlling groups of tweens\n *\n * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n * In these cases, you may want to create your own smaller groups of tween\n */\nexport default class Group {\n\tprivate _tweens: Record<string, Tween> = {}\n\tprivate _tweensAddedDuringUpdate: Record<string, Tween> = {}\n\n\tconstructor(...tweens: Tween[]) {\n\t\tthis.add(...tweens)\n\t}\n\n\tgetAll(): Array<Tween> {\n\t\treturn Object.keys(this._tweens).map(tweenId => this._tweens[tweenId])\n\t}\n\n\tremoveAll(): void {\n\t\tthis._tweens = {}\n\t}\n\n\tadd(...tweens: Tween[]): void {\n\t\tfor (const tween of tweens) {\n\t\t\t// Remove from any other group first, a tween can only be in one group at a time.\n\t\t\t// @ts-expect-error library internal access\n\t\t\ttween._group?.remove(tween)\n\n\t\t\t// @ts-expect-error library internal access\n\t\t\ttween._group = this\n\n\t\t\tthis._tweens[tween.getId()] = tween\n\t\t\tthis._tweensAddedDuringUpdate[tween.getId()] = tween\n\t\t}\n\t}\n\n\tremove(...tweens: Tween[]): void {\n\t\tfor (const tween of tweens) {\n\t\t\t// @ts-expect-error library internal access\n\t\t\ttween._group = undefined\n\n\t\t\tdelete this._tweens[tween.getId()]\n\t\t\tdelete this._tweensAddedDuringUpdate[tween.getId()]\n\t\t}\n\t}\n\n\t/** Return true if all tweens in the group are not paused or playing. */\n\tallStopped() {\n\t\treturn this.getAll().every(tween => !tween.isPlaying())\n\t}\n\n\tupdate(time?: number): void\n\t/**\n\t * @deprecated The `preserve` parameter is now defaulted to `true` and will\n\t * be removed in a future major release, at which point all tweens of a\n\t * group will always be preserved when calling update. To migrate, always\n\t * use `group.add(tween)` or `group.remove(tween)` to manually add or remove\n\t * tweens, and do not rely on tweens being automatically added or removed.\n\t */\n\tupdate(time?: number, preserve?: boolean): void\n\tupdate(time: number = now(), preserve = true): void {\n\t\tlet tweenIds = Object.keys(this._tweens)\n\n\t\tif (tweenIds.length === 0) return\n\n\t\t// Tweens are updated in \"batches\". If you add a new tween during an\n\t\t// update, then the new tween will be updated in the next batch.\n\t\t// If you remove a tween during an update, it may or may not be updated.\n\t\t// However, if the removed tween was added during the current batch,\n\t\t// then it will not be updated.\n\t\twhile (tweenIds.length > 0) {\n\t\t\tthis._tweensAddedDuringUpdate = {}\n\n\t\t\tfor (let i = 0; i < tweenIds.length; i++) {\n\t\t\t\tconst tween = this._tweens[tweenIds[i]]\n\t\t\t\tconst autoStart = !preserve\n\n\t\t\t\tif (tween && tween.update(time, autoStart) === false && !preserve) this.remove(tween)\n\t\t\t}\n\n\t\t\ttweenIds = Object.keys(this._tweensAddedDuringUpdate)\n\t\t}\n\t}\n\tonComplete(callback: (object: Tween[]) => void) {\n\t\tconst group = this.getAll()\n\t\tgroup.forEach(tween => {\n\t\t\tconst prevCallback = tween.getCompleteCallback()\n\t\t\ttween.onComplete(() => {\n\t\t\t\tprevCallback?.(tween)\n\t\t\t\t// After the onComplete callback completes, _isPlaying is updated to false, so if the total number of completed tweens is -1, then they are all complete.\n\t\t\t\tconst completedGroup = group.filter(tween => !tween.isPlaying())\n\t\t\t\tif (completedGroup.length === group.length - 1) callback(group)\n\t\t\t})\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "src/Index.ts",
    "content": "/**\n * Tween.js - Licensed under the MIT license\n * https://github.com/tweenjs/tween.js\n * ----------------------------------------------\n *\n * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n * Thank you all, you're awesome!\n */\n\nimport Easing from './Easing'\nimport Group from './Group'\nimport Interpolation from './Interpolation'\nimport now, {setNow} from './Now'\nimport Sequence from './Sequence'\nimport Tween from './Tween'\nimport VERSION from './Version'\nimport {mainGroup} from './mainGroup'\n\nconst nextId = Sequence.nextId\n\n/**\n * Controlling groups of tweens\n *\n * Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components.\n * In these cases, you may want to create your own smaller groups of tweens.\n */\nconst TWEEN = mainGroup\n\n// This is the best way to export things in a way that's compatible with both ES\n// Modules and CommonJS, without build hacks, and so as not to break the\n// existing API.\n// https://github.com/rollup/rollup/issues/1961#issuecomment-423037881\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nconst getAll = TWEEN.getAll.bind(TWEEN)\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nconst removeAll = TWEEN.removeAll.bind(TWEEN)\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nconst add = TWEEN.add.bind(TWEEN)\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nconst remove = TWEEN.remove.bind(TWEEN)\n/**\n * @deprecated The global TWEEN Group will be removed in a following major\n * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n * group.\n *\n * Old code:\n *\n * ```js\n * import * as TWEEN from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new TWEEN.Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   TWEEN.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n *\n * New code:\n *\n * ```js\n * import {Tween, Group} from '@tweenjs/tween.js'\n *\n * //...\n *\n * const tween = new Tween(obj)\n * const tween2 = new TWEEN.Tween(obj2)\n *\n * //...\n *\n * const group = new Group()\n * group.add(tween)\n * group.add(tween2)\n *\n * //...\n *\n * requestAnimationFrame(function loop(time) {\n *   group.update(time)\n *   requestAnimationFrame(loop)\n * })\n * ```\n */\nconst update = TWEEN.update.bind(TWEEN)\n\n// NOTE! Make sure both lists of exports below are kept in sync:\n\nexport {\n\tEasing,\n\tGroup,\n\tInterpolation,\n\tnow,\n\tsetNow,\n\tSequence,\n\tnextId,\n\tTween,\n\tVERSION,\n\tgetAll,\n\tremoveAll,\n\tadd,\n\tremove,\n\tupdate,\n}\n\nconst exports = {\n\tEasing,\n\tGroup,\n\tInterpolation,\n\tnow,\n\tsetNow,\n\tSequence,\n\tnextId,\n\tTween,\n\tVERSION,\n\n\t/**\n\t * @deprecated The global TWEEN Group will be removed in a following major\n\t * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n\t * group.\n\t *\n\t * Old code:\n\t *\n\t * ```js\n\t * import * as TWEEN from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new TWEEN.Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   TWEEN.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t *\n\t * New code:\n\t *\n\t * ```js\n\t * import {Tween, Group} from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * const group = new Group()\n\t * group.add(tween)\n\t * group.add(tween2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   group.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t */\n\tgetAll,\n\t/**\n\t * @deprecated The global TWEEN Group will be removed in a following major\n\t * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n\t * group.\n\t *\n\t * Old code:\n\t *\n\t * ```js\n\t * import * as TWEEN from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new TWEEN.Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   TWEEN.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t *\n\t * New code:\n\t *\n\t * ```js\n\t * import {Tween, Group} from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * const group = new Group()\n\t * group.add(tween)\n\t * group.add(tween2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   group.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t */\n\tremoveAll,\n\t/**\n\t * @deprecated The global TWEEN Group will be removed in a following major\n\t * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n\t * group.\n\t *\n\t * Old code:\n\t *\n\t * ```js\n\t * import * as TWEEN from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new TWEEN.Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   TWEEN.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t *\n\t * New code:\n\t *\n\t * ```js\n\t * import {Tween, Group} from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * const group = new Group()\n\t * group.add(tween)\n\t * group.add(tween2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   group.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t */\n\tadd,\n\t/**\n\t * @deprecated The global TWEEN Group will be removed in a following major\n\t * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n\t * group.\n\t *\n\t * Old code:\n\t *\n\t * ```js\n\t * import * as TWEEN from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new TWEEN.Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   TWEEN.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t *\n\t * New code:\n\t *\n\t * ```js\n\t * import {Tween, Group} from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * const group = new Group()\n\t * group.add(tween)\n\t * group.add(tween2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   group.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t */\n\tremove,\n\t/**\n\t * @deprecated The global TWEEN Group will be removed in a following major\n\t * release. To migrate, create a `new Group()` instead of using `TWEEN` as a\n\t * group.\n\t *\n\t * Old code:\n\t *\n\t * ```js\n\t * import * as TWEEN from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new TWEEN.Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   TWEEN.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t *\n\t * New code:\n\t *\n\t * ```js\n\t * import {Tween, Group} from '@tweenjs/tween.js'\n\t *\n\t * //...\n\t *\n\t * const tween = new Tween(obj)\n\t * const tween2 = new TWEEN.Tween(obj2)\n\t *\n\t * //...\n\t *\n\t * const group = new Group()\n\t * group.add(tween)\n\t * group.add(tween2)\n\t *\n\t * //...\n\t *\n\t * requestAnimationFrame(function loop(time) {\n\t *   group.update(time)\n\t *   requestAnimationFrame(loop)\n\t * })\n\t * ```\n\t */\n\tupdate,\n}\n\nexport default exports\n"
  },
  {
    "path": "src/Interpolation.ts",
    "content": "/**\n *\n */\nexport type InterpolationFunction = (v: number[], k: number) => number\n\n/**\n *\n */\nconst Interpolation = {\n\tLinear: function (v: number[], k: number): number {\n\t\tconst m = v.length - 1\n\t\tconst f = m * k\n\t\tconst i = Math.floor(f)\n\t\tconst fn = Interpolation.Utils.Linear\n\n\t\tif (k < 0) {\n\t\t\treturn fn(v[0], v[1], f)\n\t\t}\n\n\t\tif (k > 1) {\n\t\t\treturn fn(v[m], v[m - 1], m - f)\n\t\t}\n\n\t\treturn fn(v[i], v[i + 1 > m ? m : i + 1], f - i)\n\t},\n\n\tBezier: function (v: number[], k: number): number {\n\t\tlet b = 0\n\t\tconst n = v.length - 1\n\t\tconst pw = Math.pow\n\t\tconst bn = Interpolation.Utils.Bernstein\n\n\t\tfor (let i = 0; i <= n; i++) {\n\t\t\tb += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i)\n\t\t}\n\n\t\treturn b\n\t},\n\n\tCatmullRom: function (v: number[], k: number): number {\n\t\tconst m = v.length - 1\n\t\tlet f = m * k\n\t\tlet i = Math.floor(f)\n\t\tconst fn = Interpolation.Utils.CatmullRom\n\n\t\tif (v[0] === v[m]) {\n\t\t\tif (k < 0) {\n\t\t\t\ti = Math.floor((f = m * (1 + k)))\n\t\t\t}\n\n\t\t\treturn fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i)\n\t\t} else {\n\t\t\tif (k < 0) {\n\t\t\t\treturn v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0])\n\t\t\t}\n\n\t\t\tif (k > 1) {\n\t\t\t\treturn v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m])\n\t\t\t}\n\n\t\t\treturn fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i)\n\t\t}\n\t},\n\n\tUtils: {\n\t\tLinear: function (p0: number, p1: number, t: number): number {\n\t\t\treturn (p1 - p0) * t + p0\n\t\t},\n\t\tBernstein: function (n: number, i: number): number {\n\t\t\tconst fc = Interpolation.Utils.Factorial\n\n\t\t\treturn fc(n) / fc(i) / fc(n - i)\n\t\t},\n\t\tFactorial: (function () {\n\t\t\tconst a = [1]\n\n\t\t\treturn function (n: number): number {\n\t\t\t\tlet s = 1\n\n\t\t\t\tif (a[n]) {\n\t\t\t\t\treturn a[n]\n\t\t\t\t}\n\n\t\t\t\tfor (let i = n; i > 1; i--) {\n\t\t\t\t\ts *= i\n\t\t\t\t}\n\n\t\t\t\ta[n] = s\n\t\t\t\treturn s\n\t\t\t}\n\t\t})(),\n\n\t\tCatmullRom: function (p0: number, p1: number, p2: number, p3: number, t: number): number {\n\t\t\tconst v0 = (p2 - p0) * 0.5\n\t\t\tconst v1 = (p3 - p1) * 0.5\n\t\t\tconst t2 = t * t\n\t\t\tconst t3 = t * t2\n\n\t\t\treturn (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1\n\t\t},\n\t},\n}\n\nexport default Interpolation\n"
  },
  {
    "path": "src/Now.ts",
    "content": "let _nowFunc: Function = () => performance.now()\n\nconst now = (): number => {\n\treturn _nowFunc()\n}\n\nexport function setNow(nowFunction: Function) {\n\t_nowFunc = nowFunction\n}\n\nexport default now\n"
  },
  {
    "path": "src/Sequence.ts",
    "content": "/**\n * Utils\n */\nexport default class Sequence {\n\tprivate static _nextId = 0\n\n\tstatic nextId(): number {\n\t\treturn Sequence._nextId++\n\t}\n}\n"
  },
  {
    "path": "src/Tween.ts",
    "content": "/**\n * Tween.js - Licensed under the MIT license\n * https://github.com/tweenjs/tween.js\n * ----------------------------------------------\n *\n * See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.\n * Thank you all, you're awesome!\n */\n\nimport Easing from './Easing'\nimport Interpolation from './Interpolation'\nimport {mainGroup} from './mainGroup'\nimport Sequence from './Sequence'\nimport now from './Now'\n\nimport type {EasingFunction} from './Easing'\nimport type {InterpolationFunction} from './Interpolation'\nimport type Group from './Group'\n\nexport class Tween<T extends UnknownProps = any> {\n\tstatic autoStartOnUpdate = false\n\n\tprivate _isPaused = false\n\tprivate _pauseStart = 0\n\tprivate _valuesStart: UnknownProps = {}\n\tprivate _valuesEnd: Record<string, number | string> = {}\n\tprivate _valuesStartRepeat: UnknownProps = {}\n\tprivate _duration = 1000\n\tprivate _isDynamic = false\n\tprivate _initialRepeat = 0\n\tprivate _repeat = 0\n\tprivate _repeatDelayTime?: number\n\tprivate _yoyo = false\n\tprivate _isPlaying = false\n\tprivate _reversed = false\n\tprivate _delayTime = 0\n\tprivate _startTime = 0\n\tprivate _easingFunction: EasingFunction = Easing.Linear.None\n\tprivate _interpolationFunction: InterpolationFunction = Interpolation.Linear\n\t// eslint-disable-next-line\n\tprivate _chainedTweens: Array<Tween<any>> = []\n\tprivate _onStartCallback?: (object: T) => void\n\tprivate _onStartCallbackFired = false\n\tprivate _onEveryStartCallback?: (object: T) => void\n\tprivate _onEveryStartCallbackFired = false\n\tprivate _onUpdateCallback?: (object: T, elapsed: number) => void\n\tprivate _onRepeatCallback?: (object: T) => void\n\tprivate _onCompleteCallback?: (object: T) => void\n\tprivate _onStopCallback?: (object: T) => void\n\tprivate _id = Sequence.nextId()\n\tprivate _isChainStopped = false\n\tprivate _propertiesAreSetUp = false\n\tprivate _object: T\n\tprivate _group?: Group\n\n\t/**\n\t * @param object - The object whose properties this Tween will animate.\n\t * @param group - The object whose properties this Tween will animate.\n\t */\n\tconstructor(object: T, group?: Group)\n\t/**\n\t * @deprecated The group parameter is now deprecated, instead use `new\n\t * Tween(object)` then `group.add(tween)` to add a tween to a group. Use\n\t * `new Tween(object, true)` to restore the old behavior for now, but this\n\t * will be removed in the future.\n\t */\n\tconstructor(object: T, group: true)\n\tconstructor(object: T, group?: Group | true) {\n\t\tthis._object = object\n\n\t\tif (typeof group === 'object') {\n\t\t\tthis._group = group\n\t\t\tgroup.add(this)\n\t\t}\n\t\t// Use \"true\" to restore old behavior (will be removed in future release).\n\t\telse if (group === true) {\n\t\t\tthis._group = mainGroup\n\t\t\tmainGroup.add(this)\n\t\t}\n\t}\n\n\tgetId(): number {\n\t\treturn this._id\n\t}\n\n\tgetCompleteCallback(): ((object: T) => void) | undefined {\n\t\treturn this._onCompleteCallback\n\t}\n\n\tisPlaying(): boolean {\n\t\treturn this._isPlaying\n\t}\n\n\tisPaused(): boolean {\n\t\treturn this._isPaused\n\t}\n\n\tgetDuration(): number {\n\t\treturn this._duration\n\t}\n\n\tto(target: UnknownProps, duration = 1000): this {\n\t\tif (this._isPlaying)\n\t\t\tthrow new Error('Can not call Tween.to() while Tween is already started or paused. Stop the Tween first.')\n\n\t\tthis._valuesEnd = target\n\t\tthis._propertiesAreSetUp = false\n\t\tthis._duration = duration < 0 ? 0 : duration\n\n\t\treturn this\n\t}\n\n\tduration(duration = 1000): this {\n\t\tthis._duration = duration < 0 ? 0 : duration\n\t\treturn this\n\t}\n\n\tdynamic(dynamic = false): this {\n\t\tthis._isDynamic = dynamic\n\t\treturn this\n\t}\n\n\tstart(time: number = now(), overrideStartingValues = false): this {\n\t\tif (this._isPlaying) {\n\t\t\treturn this\n\t\t}\n\n\t\tthis._repeat = this._initialRepeat\n\n\t\tif (this._reversed) {\n\t\t\t// If we were reversed (f.e. using the yoyo feature) then we need to\n\t\t\t// flip the tween direction back to forward.\n\n\t\t\tthis._reversed = false\n\n\t\t\tfor (const property in this._valuesStartRepeat) {\n\t\t\t\tthis._swapEndStartRepeatValues(property)\n\t\t\t\tthis._valuesStart[property] = this._valuesStartRepeat[property]\n\t\t\t}\n\t\t}\n\n\t\tthis._isPlaying = true\n\n\t\tthis._isPaused = false\n\n\t\tthis._onStartCallbackFired = false\n\t\tthis._onEveryStartCallbackFired = false\n\n\t\tthis._isChainStopped = false\n\n\t\tthis._startTime = time\n\t\tthis._startTime += this._delayTime\n\n\t\tif (!this._propertiesAreSetUp || overrideStartingValues) {\n\t\t\tthis._propertiesAreSetUp = true\n\n\t\t\t// If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n\t\t\tif (!this._isDynamic) {\n\t\t\t\tconst tmp: Record<PropertyKey, string | number> = {}\n\t\t\t\tfor (const prop in this._valuesEnd) tmp[prop] = this._valuesEnd[prop]\n\t\t\t\tthis._valuesEnd = tmp\n\t\t\t}\n\n\t\t\tthis._setupProperties(\n\t\t\t\tthis._object,\n\t\t\t\tthis._valuesStart,\n\t\t\t\tthis._valuesEnd,\n\t\t\t\tthis._valuesStartRepeat,\n\t\t\t\toverrideStartingValues,\n\t\t\t)\n\t\t}\n\n\t\treturn this\n\t}\n\n\tstartFromCurrentValues(time?: number): this {\n\t\treturn this.start(time, true)\n\t}\n\n\tprivate _setupProperties(\n\t\t_object: UnknownProps,\n\t\t_valuesStart: UnknownProps,\n\t\t_valuesEnd: UnknownProps,\n\t\t_valuesStartRepeat: UnknownProps,\n\t\toverrideStartingValues: boolean,\n\t): void {\n\t\tfor (const property in _valuesEnd) {\n\t\t\tconst startValue = _object[property] as number | Record<string, unknown>\n\t\t\tconst startValueIsArray = Array.isArray(startValue)\n\t\t\tconst propType = startValueIsArray ? 'array' : typeof startValue\n\t\t\tlet isInterpolationList = !startValueIsArray && Array.isArray(_valuesEnd[property])\n\n\t\t\t// If `to()` specifies a property that doesn't exist in the source object,\n\t\t\t// we should not set that property in the object\n\t\t\tif (propType === 'undefined' || propType === 'function') {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Check if an Array was provided as property value\n\t\t\tif (isInterpolationList) {\n\t\t\t\tconst endValues = _valuesEnd[property] as Array<number | string>\n\n\t\t\t\tif (endValues.length === 0) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// Handle an array of relative values.\n\t\t\t\t// Creates a local copy of the Array with the start value at the front\n\t\t\t\tconst temp = [startValue as number]\n\t\t\t\tfor (let i = 0, l = endValues.length; i < l; i += 1) {\n\t\t\t\t\tconst value = this._handleRelativeValue(startValue as number, endValues[i])\n\t\t\t\t\tif (isNaN(value)) {\n\t\t\t\t\t\tisInterpolationList = false\n\t\t\t\t\t\tconsole.warn('Found invalid interpolation list. Skipping.')\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\ttemp.push(value)\n\t\t\t\t}\n\n\t\t\t\tif (isInterpolationList) {\n\t\t\t\t\t// if (_valuesStart[property] === undefined) { // handle end values only the first time. NOT NEEDED? setupProperties is now guarded by _propertiesAreSetUp.\n\t\t\t\t\t_valuesEnd[property] = temp\n\t\t\t\t\t// }\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// handle the deepness of the values\n\t\t\tif ((propType === 'object' || startValueIsArray) && startValue && !isInterpolationList) {\n\t\t\t\t_valuesStart[property] = startValueIsArray ? [] : {}\n\t\t\t\tconst nestedObject = startValue as Record<string, unknown>\n\n\t\t\t\tfor (const prop in nestedObject) {\n\t\t\t\t\t_valuesStart[property][prop] = nestedObject[prop]\n\t\t\t\t}\n\n\t\t\t\t// TODO? repeat nested values? And yoyo? And array values?\n\t\t\t\t_valuesStartRepeat[property] = startValueIsArray ? [] : {}\n\n\t\t\t\tlet endValues = _valuesEnd[property]\n\n\t\t\t\t// If dynamic is not enabled, clone the end values instead of using the passed-in end values.\n\t\t\t\tif (!this._isDynamic) {\n\t\t\t\t\tconst tmp: Record<PropertyKey, unknown> = {}\n\t\t\t\t\tfor (const prop in endValues) tmp[prop] = endValues[prop]\n\t\t\t\t\t_valuesEnd[property] = endValues = tmp\n\t\t\t\t}\n\n\t\t\t\tthis._setupProperties(\n\t\t\t\t\tnestedObject,\n\t\t\t\t\t_valuesStart[property],\n\t\t\t\t\tendValues,\n\t\t\t\t\t_valuesStartRepeat[property],\n\t\t\t\t\toverrideStartingValues,\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\t// Save the starting value, but only once unless override is requested.\n\t\t\t\tif (typeof _valuesStart[property] === 'undefined' || overrideStartingValues) {\n\t\t\t\t\t_valuesStart[property] = startValue\n\t\t\t\t}\n\n\t\t\t\tif (!startValueIsArray) {\n\t\t\t\t\t// eslint-disable-next-line\n\t\t\t\t\t// @ts-ignore FIXME?\n\t\t\t\t\t_valuesStart[property] *= 1.0 // Ensures we're using numbers, not strings\n\t\t\t\t}\n\n\t\t\t\tif (isInterpolationList) {\n\t\t\t\t\t// eslint-disable-next-line\n\t\t\t\t\t// @ts-ignore FIXME?\n\t\t\t\t\t_valuesStartRepeat[property] = _valuesEnd[property].slice().reverse()\n\t\t\t\t} else {\n\t\t\t\t\t_valuesStartRepeat[property] = _valuesStart[property] || 0\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tstop(): this {\n\t\tif (!this._isChainStopped) {\n\t\t\tthis._isChainStopped = true\n\t\t\tthis.stopChainedTweens()\n\t\t}\n\n\t\tif (!this._isPlaying) {\n\t\t\treturn this\n\t\t}\n\n\t\tthis._isPlaying = false\n\n\t\tthis._isPaused = false\n\n\t\tif (this._onStopCallback) {\n\t\t\tthis._onStopCallback(this._object)\n\t\t}\n\n\t\treturn this\n\t}\n\n\tend(): this {\n\t\tthis._goToEnd = true\n\t\tthis.update(this._startTime + this._duration)\n\t\treturn this\n\t}\n\n\tpause(time: number = now()): this {\n\t\tif (this._isPaused || !this._isPlaying) {\n\t\t\treturn this\n\t\t}\n\n\t\tthis._isPaused = true\n\n\t\tthis._pauseStart = time\n\n\t\treturn this\n\t}\n\n\tresume(time: number = now()): this {\n\t\tif (!this._isPaused || !this._isPlaying) {\n\t\t\treturn this\n\t\t}\n\n\t\tthis._isPaused = false\n\n\t\tthis._startTime += time - this._pauseStart\n\n\t\tthis._pauseStart = 0\n\n\t\treturn this\n\t}\n\n\tstopChainedTweens(): this {\n\t\tfor (let i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n\t\t\tthis._chainedTweens[i].stop()\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Removes the tween from the current group it is in, if any, then adds the\n\t * tween to the specified `group`.\n\t */\n\tgroup(group: Group): this\n\t/**\n\t * @deprecated The argless call signature has been removed. Use\n\t * `tween.group(group)` or `group.add(tween)`, instead.\n\t */\n\tgroup(): this\n\tgroup(group?: Group): this {\n\t\tif (!group) {\n\t\t\tconsole.warn('tween.group() without args has been removed, use group.add(tween) instead.')\n\t\t\treturn this\n\t\t}\n\n\t\tgroup.add(this)\n\t\treturn this\n\t}\n\n\t/**\n\t * Removes the tween from whichever group it is in.\n\t */\n\tremove() {\n\t\tthis._group?.remove(this)\n\t\treturn this\n\t}\n\n\tdelay(amount = 0): this {\n\t\tthis._delayTime = amount\n\t\treturn this\n\t}\n\n\trepeat(times = 0): this {\n\t\tthis._initialRepeat = times\n\t\tthis._repeat = times\n\t\treturn this\n\t}\n\n\trepeatDelay(amount?: number): this {\n\t\tthis._repeatDelayTime = amount\n\t\treturn this\n\t}\n\n\tyoyo(yoyo = false): this {\n\t\tthis._yoyo = yoyo\n\t\treturn this\n\t}\n\n\teasing(easingFunction: EasingFunction = Easing.Linear.None): this {\n\t\tthis._easingFunction = easingFunction\n\t\treturn this\n\t}\n\n\tinterpolation(interpolationFunction: InterpolationFunction = Interpolation.Linear): this {\n\t\tthis._interpolationFunction = interpolationFunction\n\t\treturn this\n\t}\n\n\t// eslint-disable-next-line\n\tchain(...tweens: Array<Tween<any>>): this {\n\t\tthis._chainedTweens = tweens\n\t\treturn this\n\t}\n\n\tonStart(callback?: (object: T) => void): this {\n\t\tthis._onStartCallback = callback\n\t\treturn this\n\t}\n\n\tonEveryStart(callback?: (object: T) => void): this {\n\t\tthis._onEveryStartCallback = callback\n\t\treturn this\n\t}\n\n\tonUpdate(callback?: (object: T, elapsed: number) => void): this {\n\t\tthis._onUpdateCallback = callback\n\t\treturn this\n\t}\n\n\tonRepeat(callback?: (object: T) => void): this {\n\t\tthis._onRepeatCallback = callback\n\t\treturn this\n\t}\n\n\tonComplete(callback?: (object: T) => void): this {\n\t\tthis._onCompleteCallback = callback\n\t\treturn this\n\t}\n\n\tonStop(callback?: (object: T) => void): this {\n\t\tthis._onStopCallback = callback\n\t\treturn this\n\t}\n\n\tprivate _goToEnd = false\n\n\t/**\n\t * @returns true if the tween is still playing after the update, false\n\t * otherwise (calling update on a paused tween still returns true because\n\t * it is still playing, just paused).\n\t *\n\t * @param autoStart - When true, calling update will implicitly call start()\n\t * as well. Note, if you stop() or end() the tween, but are still calling\n\t * update(), it will start again!\n\t */\n\tupdate(time = now(), autoStart = Tween.autoStartOnUpdate): boolean {\n\t\tif (this._isPaused) return true\n\n\t\tlet property\n\n\t\tif (!this._goToEnd && !this._isPlaying) {\n\t\t\tif (autoStart) this.start(time, true)\n\t\t\telse return false\n\t\t}\n\n\t\tthis._goToEnd = false\n\n\t\tif (time < this._startTime) {\n\t\t\treturn true\n\t\t}\n\n\t\tif (this._onStartCallbackFired === false) {\n\t\t\tif (this._onStartCallback) {\n\t\t\t\tthis._onStartCallback(this._object)\n\t\t\t}\n\n\t\t\tthis._onStartCallbackFired = true\n\t\t}\n\n\t\tif (this._onEveryStartCallbackFired === false) {\n\t\t\tif (this._onEveryStartCallback) {\n\t\t\t\tthis._onEveryStartCallback(this._object)\n\t\t\t}\n\n\t\t\tthis._onEveryStartCallbackFired = true\n\t\t}\n\n\t\tconst elapsedTime = time - this._startTime\n\t\tconst durationAndDelay = this._duration + (this._repeatDelayTime ?? this._delayTime)\n\t\tconst totalTime = this._duration + this._repeat * durationAndDelay\n\n\t\tconst calculateElapsedPortion = () => {\n\t\t\tif (this._duration === 0) return 1\n\t\t\tif (elapsedTime > totalTime) {\n\t\t\t\treturn 1\n\t\t\t}\n\n\t\t\tconst timesRepeated = Math.trunc(elapsedTime / durationAndDelay)\n\t\t\tconst timeIntoCurrentRepeat = elapsedTime - timesRepeated * durationAndDelay\n\t\t\t// TODO use %?\n\t\t\t// const timeIntoCurrentRepeat = elapsedTime % durationAndDelay\n\n\t\t\tconst portion = Math.min(timeIntoCurrentRepeat / this._duration, 1)\n\t\t\tif (portion === 0 && elapsedTime === this._duration) {\n\t\t\t\treturn 1\n\t\t\t}\n\t\t\treturn portion\n\t\t}\n\t\tconst elapsed = calculateElapsedPortion()\n\t\tconst value = this._easingFunction(elapsed)\n\n\t\t// properties transformations\n\t\tthis._updateProperties(this._object, this._valuesStart, this._valuesEnd, value)\n\n\t\tif (this._onUpdateCallback) {\n\t\t\tthis._onUpdateCallback(this._object, elapsed)\n\t\t}\n\n\t\tif (this._duration === 0 || elapsedTime >= this._duration) {\n\t\t\tif (this._repeat > 0) {\n\t\t\t\tconst completeCount = Math.min(Math.trunc((elapsedTime - this._duration) / durationAndDelay) + 1, this._repeat)\n\t\t\t\tif (isFinite(this._repeat)) {\n\t\t\t\t\tthis._repeat -= completeCount\n\t\t\t\t}\n\n\t\t\t\t// Reassign starting values, restart by making startTime = now\n\t\t\t\tfor (property in this._valuesStartRepeat) {\n\t\t\t\t\tif (!this._yoyo && typeof this._valuesEnd[property] === 'string') {\n\t\t\t\t\t\tthis._valuesStartRepeat[property] =\n\t\t\t\t\t\t\t// eslint-disable-next-line\n\t\t\t\t\t\t\t// @ts-ignore FIXME?\n\t\t\t\t\t\t\tthis._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property])\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this._yoyo) {\n\t\t\t\t\t\tthis._swapEndStartRepeatValues(property)\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._valuesStart[property] = this._valuesStartRepeat[property]\n\t\t\t\t}\n\n\t\t\t\tif (this._yoyo) {\n\t\t\t\t\tthis._reversed = !this._reversed\n\t\t\t\t}\n\n\t\t\t\tthis._startTime += durationAndDelay * completeCount\n\n\t\t\t\tif (this._onRepeatCallback) {\n\t\t\t\t\tthis._onRepeatCallback(this._object)\n\t\t\t\t}\n\n\t\t\t\tthis._onEveryStartCallbackFired = false\n\n\t\t\t\treturn true\n\t\t\t} else {\n\t\t\t\tif (this._onCompleteCallback) {\n\t\t\t\t\tthis._onCompleteCallback(this._object)\n\t\t\t\t}\n\n\t\t\t\tfor (let i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {\n\t\t\t\t\t// Make the chained tweens start exactly at the time they should,\n\t\t\t\t\t// even if the `update()` method was called way past the duration of the tween\n\t\t\t\t\tthis._chainedTweens[i].start(this._startTime + this._duration, false)\n\t\t\t\t}\n\n\t\t\t\tthis._isPlaying = false\n\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\n\t\treturn true\n\t}\n\n\tprivate _updateProperties(\n\t\t_object: UnknownProps,\n\t\t_valuesStart: UnknownProps,\n\t\t_valuesEnd: UnknownProps,\n\t\tvalue: number,\n\t): void {\n\t\tfor (const property in _valuesEnd) {\n\t\t\t// Don't update properties that do not exist in the source object\n\t\t\tif (_valuesStart[property] === undefined) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst start = _valuesStart[property] || 0\n\t\t\tlet end = _valuesEnd[property]\n\t\t\tconst startIsArray = Array.isArray(_object[property])\n\t\t\tconst endIsArray = Array.isArray(end)\n\t\t\tconst isInterpolationList = !startIsArray && endIsArray\n\n\t\t\tif (isInterpolationList) {\n\t\t\t\t_object[property] = this._interpolationFunction(end as Array<number>, value)\n\t\t\t} else if (typeof end === 'object' && end) {\n\t\t\t\t// eslint-disable-next-line\n\t\t\t\t// @ts-ignore FIXME?\n\t\t\t\tthis._updateProperties(_object[property], start, end, value)\n\t\t\t} else {\n\t\t\t\t// Parses relative end values with start as base (e.g.: +10, -3)\n\t\t\t\tend = this._handleRelativeValue(start as number, end as number | string)\n\n\t\t\t\t// Protect against non numeric properties.\n\t\t\t\tif (typeof end === 'number') {\n\t\t\t\t\t// eslint-disable-next-line\n\t\t\t\t\t// @ts-ignore FIXME?\n\t\t\t\t\t_object[property] = start + (end - start) * value\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate _handleRelativeValue(start: number, end: number | string): number {\n\t\tif (typeof end !== 'string') {\n\t\t\treturn end\n\t\t}\n\n\t\tif (end.charAt(0) === '+' || end.charAt(0) === '-') {\n\t\t\treturn start + parseFloat(end)\n\t\t}\n\n\t\treturn parseFloat(end)\n\t}\n\n\tprivate _swapEndStartRepeatValues(property: string): void {\n\t\tconst tmp = this._valuesStartRepeat[property]\n\t\tconst endValue = this._valuesEnd[property]\n\n\t\tif (typeof endValue === 'string') {\n\t\t\tthis._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(endValue)\n\t\t} else {\n\t\t\tthis._valuesStartRepeat[property] = this._valuesEnd[property]\n\t\t}\n\n\t\tthis._valuesEnd[property] = tmp\n\t}\n}\n\nexport type UnknownProps = Record<string, any>\n\nexport default Tween\n"
  },
  {
    "path": "src/Version.ts",
    "content": "const VERSION = '25.0.0'\nexport default VERSION\n"
  },
  {
    "path": "src/mainGroup.ts",
    "content": "import Group from './Group'\n\nexport const mainGroup = new Group()\n"
  },
  {
    "path": "src/test-performance-now-fake.ts",
    "content": "/**\n * @fileoverview Tool for patching performance.now so we can fake it in the\n * tests.\n */\n\nlet time = 0\n\nexport function tickTime(t: number): void {\n\ttime = t\n}\n\nexport function patchPerformanceNow(): void {\n\tObject.defineProperties(performance, {\n\t\tnow: {\n\t\t\tvalue: () => {\n\t\t\t\treturn time\n\t\t\t},\n\t\t\tconfigurable: true,\n\t\t},\n\t})\n}\n\nexport function restorePerformanceNow(): void {\n\t// The original is on the prototype, simply delete ours to expose that one again.\n\tdelete (performance as any).now\n}\n"
  },
  {
    "path": "src/tests.ts",
    "content": "import {tickTime, patchPerformanceNow, restorePerformanceNow} from './test-performance-now-fake'\nimport * as TWEEN from './Index'\nimport type {EasingFunctionGroup} from './Easing'\n\nexport const tests = {\n\thello(test: Test): void {\n\t\ttest.ok(TWEEN !== null)\n\t\ttest.done()\n\t},\n\n\t// TWEEN tests\n\t'TWEEN.getAll'(test: Test): void {\n\t\ttest.ok(TWEEN.getAll() instanceof Array)\n\t\ttest.done()\n\t},\n\n\t'TWEEN object stores tweens automatically on start'(test: Test): void {\n\t\tconst numTweensBefore = TWEEN.getAll().length,\n\t\t\tt = new TWEEN.Tween({}, true)\n\n\t\tt.start()\n\n\t\tconst numTweensAfter = TWEEN.getAll().length\n\n\t\ttest.equal(numTweensBefore + 1, numTweensAfter)\n\t\ttest.done()\n\t},\n\n\t'TWEEN.removeAll()'(test: Test): void {\n\t\tconst t = new TWEEN.Tween({}, true)\n\n\t\tTWEEN.removeAll()\n\n\t\ttest.equal(TWEEN.getAll().length, 0, 'No tweens left')\n\n\t\tt.start()\n\n\t\ttest.equal(TWEEN.getAll().length, 0, 'Tweens are not automatically added/removed')\n\n\t\tTWEEN.add(t)\n\n\t\ttest.equal(TWEEN.getAll().length, 1, 'A tween has to be manually added')\n\n\t\tTWEEN.removeAll()\n\n\t\ttest.equal(TWEEN.getAll().length, 0, 'No tweens left')\n\t\ttest.done()\n\t},\n\n\t'TWEEN.add()'(test: Test): void {\n\t\tconst all = TWEEN.getAll(),\n\t\t\tnumTweens = all.length,\n\t\t\tt = new TWEEN.Tween({}, true)\n\n\t\tTWEEN.add(t)\n\n\t\ttest.equal(numTweens + 1, TWEEN.getAll().length)\n\n\t\ttest.done()\n\t},\n\n\t'TWEEN.remove()'(test: Test): void {\n\t\tconst all = TWEEN.getAll(),\n\t\t\tnumTweens = all.length,\n\t\t\tt = new TWEEN.Tween({}, true)\n\n\t\tTWEEN.add(t)\n\n\t\ttest.ok(TWEEN.getAll().indexOf(t) != -1)\n\n\t\tTWEEN.remove(t)\n\n\t\ttest.equal(numTweens, TWEEN.getAll().length)\n\t\ttest.equal(TWEEN.getAll().indexOf(t), -1)\n\t\ttest.done()\n\t},\n\n\t'TWEEN.update() removes tweens when they are finished only if preserve is set to false'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst t1 = new TWEEN.Tween({}, true).to({}, 1000),\n\t\t\tt2 = new TWEEN.Tween({}, true).to({}, 2000)\n\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tt1.start(0)\n\t\tt2.start(0)\n\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tTWEEN.update(0, false)\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tTWEEN.update(999, false)\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tTWEEN.update(1000, false)\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.equal(TWEEN.getAll().indexOf(t1), -1)\n\t\ttest.ok(TWEEN.getAll().indexOf(t2) != -1)\n\t\ttest.done()\n\t},\n\t'TWEEN.update() does not remove tweens when they are finished with preserve true (default)'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst t1 = new TWEEN.Tween({}, true).to({}, 1000),\n\t\t\tt2 = new TWEEN.Tween({}, true).to({}, 2000)\n\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tt1.start(0)\n\t\tt2.start(0)\n\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tTWEEN.update(999)\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tTWEEN.update(1000)\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tTWEEN.update(1001)\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\t\ttest.ok(TWEEN.getAll().indexOf(t1) != -1)\n\t\ttest.ok(TWEEN.getAll().indexOf(t2) != -1)\n\t\ttest.done()\n\t},\n\n\t'Unremoved tweens which have been updated past their finish time may go backward in time'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst target1 = {a: 0}\n\t\tconst target2 = {b: 0}\n\n\t\tconst t1 = new TWEEN.Tween(target1, true).to({a: 1}, 1000),\n\t\t\tt2 = new TWEEN.Tween(target2, true).to({b: 1}, 2000)\n\n\t\tt1.start(0)\n\t\tt2.start(0)\n\n\t\t// To be able to make a tween go backward in time, it must be\n\t\t// updated with preserve set to true (default). Otherwise, the\n\t\t// backward-in-time feature does not apply.\n\t\tTWEEN.update(200, true)\n\t\tTWEEN.update(2500, true)\n\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\t// If you want to go backward in time, start back at the beginning\n\t\t// first, then go to any time between the start and end time.\n\t\tt1.start(0)\n\t\tt2.start(0)\n\n\t\tTWEEN.update(750, true)\n\t\ttest.equal(target1.a, 0.75)\n\t\ttest.equal(target2.b, 0.375)\n\n\t\tTWEEN.update(500)\n\t\ttest.equal(target1.a, 0.5)\n\t\ttest.equal(target2.b, 0.25)\n\n\t\ttest.done()\n\t},\n\n\t// TWEEN.Tween tests\n\n\tconstructor(test: Test): void {\n\t\tconst t = new TWEEN.Tween({})\n\n\t\ttest.ok(t instanceof TWEEN.Tween, 'Pass')\n\t\ttest.done()\n\t},\n\n\t'Return the same tween instance for method chaining'(test: Test): void {\n\t\tconst t = new TWEEN.Tween({})\n\n\t\ttest.ok(t.to({}, 0) instanceof TWEEN.Tween)\n\t\ttest.equal(t.to({}, 0), t)\n\n\t\ttest.ok(t.start() instanceof TWEEN.Tween)\n\t\ttest.equal(t.start(), t)\n\n\t\ttest.ok(t.stop() instanceof TWEEN.Tween)\n\t\ttest.equal(t.stop(), t)\n\n\t\ttest.ok(t.delay() instanceof TWEEN.Tween)\n\t\ttest.equal(t.delay(), t)\n\n\t\ttest.ok(t.easing() instanceof TWEEN.Tween)\n\t\ttest.equal(t.easing(), t)\n\n\t\ttest.ok(t.interpolation() instanceof TWEEN.Tween)\n\t\ttest.equal(t.interpolation(), t)\n\n\t\ttest.ok(t.chain() instanceof TWEEN.Tween)\n\t\ttest.equal(t.chain(), t)\n\n\t\ttest.ok(t.onStart() instanceof TWEEN.Tween)\n\t\ttest.equal(t.onStart(), t)\n\n\t\ttest.ok(t.onEveryStart() instanceof TWEEN.Tween)\n\t\ttest.equal(t.onEveryStart(), t)\n\n\t\ttest.ok(t.onStop() instanceof TWEEN.Tween)\n\t\ttest.equal(t.onStop(), t)\n\n\t\ttest.ok(t.onUpdate() instanceof TWEEN.Tween)\n\t\ttest.equal(t.onUpdate(), t)\n\n\t\ttest.ok(t.onComplete() instanceof TWEEN.Tween)\n\t\ttest.equal(t.onComplete(), t)\n\n\t\ttest.ok(t.duration() instanceof TWEEN.Tween)\n\t\ttest.equal(t.duration(), t)\n\n\t\ttest.ok(t.group() instanceof TWEEN.Tween)\n\t\ttest.equal(t.group(), t)\n\n\t\ttest.done()\n\t},\n\n\t'Tween existing property'(test: Test): void {\n\t\tconst obj = {x: 1},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: 2}, 1000)\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\ttest.deepEqual(obj.x, 2)\n\t\ttest.done()\n\t},\n\n\t'Tween non-existing property'(test: Test): void {\n\t\tconst obj = {x: 1},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({y: 0}, 1000)\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\ttest.deepEqual(obj.x, 1)\n\t\t// eslint-disable-next-line\n\t\t// @ts-ignore\n\t\ttest.equal(obj.y, undefined)\n\t\ttest.done()\n\t},\n\n\t'Tween non-null property'(test: Test): void {\n\t\tconst obj = {x: 1},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: 2}, 1000)\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\ttest.deepEqual(obj.x, 2)\n\t\ttest.ok(obj.x !== null)\n\t\ttest.done()\n\t},\n\n\t'Tween function property'(test: Test): void {\n\t\tconst my_function = new Function()\n\n\t\tconst obj = {x: my_function},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: my_function})\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\ttest.ok(obj.x === my_function)\n\t\ttest.done()\n\t},\n\n\t'Tween boolean property'(test: Test): void {\n\t\tconst obj = {x: true},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: new Function()})\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\ttest.ok(typeof obj.x === 'boolean')\n\t\ttest.ok(obj.x === true)\n\t\ttest.done()\n\t},\n\n\t'Tween null property'(test: Test): void {\n\t\tconst obj = {x: null},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: 2}, 1000)\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\ttest.deepEqual(obj.x, 2)\n\t\ttest.done()\n\t},\n\n\t'Tween undefined property'(test: Test): void {\n\t\tconst obj = {},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: 2}, 1000)\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\t// eslint-disable-next-line\n\t\t// @ts-ignore\n\t\ttest.equal(obj.x, undefined)\n\t\ttest.done()\n\t},\n\n\t'Tween relative positive value'(test: Test): void {\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: '+100'}, 1000)\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\ttest.equal(obj.x, 100)\n\t\ttest.done()\n\t},\n\n\t'Tween relative negative value'(test: Test): void {\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: '-100'}, 1000)\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\ttest.equal(obj.x, -100)\n\t\ttest.done()\n\t},\n\n\t'String values without a + or - sign should not be interpreted as relative'(test: Test): void {\n\t\tconst obj = {x: 100},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: '100'}, 1000)\n\t\tt.start(0)\n\t\tt.update(1000)\n\n\t\ttest.equal(obj.x, 100)\n\t\ttest.done()\n\t},\n\n\t'Tween relative positive value, with yoyo'(test: Test): void {\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: '+100'}, 1000)\n\t\tt.repeat(1)\n\t\tt.yoyo(true)\n\t\tt.start(0)\n\n\t\tt.update(500)\n\t\ttest.equal(obj.x, 50)\n\t\tt.update(1000)\n\t\ttest.equal(obj.x, 100)\n\t\tt.update(1500)\n\t\ttest.equal(obj.x, 50)\n\t\tt.update(2000)\n\t\ttest.equal(obj.x, 0)\n\n\t\ttest.done()\n\t},\n\n\t'Tween relative negative value, with yoyo'(test: Test): void {\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: '-100'}, 1000)\n\t\tt.repeat(1)\n\t\tt.yoyo(true)\n\t\tt.start(0)\n\n\t\tt.update(500)\n\t\ttest.equal(obj.x, -50)\n\t\tt.update(1000)\n\t\ttest.equal(obj.x, -100)\n\t\tt.update(1500)\n\t\ttest.equal(obj.x, -50)\n\t\tt.update(2000)\n\t\ttest.equal(obj.x, -0)\n\n\t\ttest.done()\n\t},\n\n\t'Tween relative positive array interpolation values'(test: Test): void {\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: ['+100', '+0', '-100', '+0']}, 2000)\n\t\tt.start(0)\n\n\t\tt.update(250)\n\t\ttest.equal(obj.x, 50)\n\t\tt.update(500)\n\t\ttest.equal(obj.x, 100)\n\t\tt.update(750)\n\t\ttest.equal(obj.x, 50)\n\t\tt.update(1000)\n\t\ttest.equal(obj.x, 0)\n\t\tt.update(1250)\n\t\ttest.equal(obj.x, -50)\n\t\tt.update(1500)\n\t\ttest.equal(obj.x, -100)\n\t\tt.update(1750)\n\t\ttest.equal(obj.x, -50)\n\t\tt.update(2000)\n\t\ttest.equal(obj.x, 0)\n\n\t\ttest.done()\n\t},\n\n\t'String values without a + or - sign should not be interpreted as relative with array interpolation values'(\n\t\ttest: Test,\n\t): void {\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: ['100', '0', '100', '0']}, 2000)\n\t\tt.start(0)\n\n\t\tt.update(250)\n\t\ttest.equal(obj.x, 50)\n\t\tt.update(500)\n\t\ttest.equal(obj.x, 100)\n\t\tt.update(750)\n\t\ttest.equal(obj.x, 50)\n\t\tt.update(1000)\n\t\ttest.equal(obj.x, 0)\n\t\tt.update(1250)\n\t\ttest.equal(obj.x, 50)\n\t\tt.update(1500)\n\t\ttest.equal(obj.x, 100)\n\t\tt.update(1750)\n\t\ttest.equal(obj.x, 50)\n\t\tt.update(2000)\n\t\ttest.equal(obj.x, 0)\n\n\t\ttest.done()\n\t},\n\n\t'animate values in an array'(test: Test): void {\n\t\tconst obj = [0, 0, 0],\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to([1000, '-2000', '+2000'], 1000)\n\t\tt.start(0)\n\n\t\tt.update(250)\n\t\ttest.equal(obj[0], 250)\n\t\ttest.equal(obj[1], -500)\n\t\ttest.equal(obj[2], 500)\n\t\tt.update(500)\n\t\ttest.equal(obj[0], 500)\n\t\ttest.equal(obj[1], -1000)\n\t\ttest.equal(obj[2], 1000)\n\t\tt.update(750)\n\t\ttest.equal(obj[0], 750)\n\t\ttest.equal(obj[1], -1500)\n\t\ttest.equal(obj[2], 1500)\n\t\tt.update(1000)\n\t\ttest.equal(obj[0], 1000)\n\t\ttest.equal(obj[1], -2000)\n\t\ttest.equal(obj[2], 2000)\n\n\t\ttest.done()\n\t},\n\n\t'animate values in a nested array'(test: Test): void {\n\t\tconst obj = {a: [0, 0, 0]},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({a: [1000, '-2000', '+2000']}, 1000)\n\t\tt.start(0)\n\n\t\tt.update(250)\n\t\ttest.equal(obj.a[0], 250)\n\t\ttest.equal(obj.a[1], -500)\n\t\ttest.equal(obj.a[2], 500)\n\t\tt.update(500)\n\t\ttest.equal(obj.a[0], 500)\n\t\ttest.equal(obj.a[1], -1000)\n\t\ttest.equal(obj.a[2], 1000)\n\t\tt.update(750)\n\t\ttest.equal(obj.a[0], 750)\n\t\ttest.equal(obj.a[1], -1500)\n\t\ttest.equal(obj.a[2], 1500)\n\t\tt.update(1000)\n\t\ttest.equal(obj.a[0], 1000)\n\t\ttest.equal(obj.a[1], -2000)\n\t\ttest.equal(obj.a[2], 2000)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.start()'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\n\t\tt.to({}, 1000)\n\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\n\t\tt.start(0)\n\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.done()\n\t},\n\n\t'Ensure tweens start without calling start() method.'(test: Test): void {\n\t\tTWEEN.Tween.autoStartOnUpdate = true\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: 1000}, 1000)\n\t\tlet started = false\n\t\tt.onStart(() => (started = true))\n\t\tt.onComplete(() => (started = false))\n\n\t\tt.update(0)\n\t\ttest.deepEqual(started, true)\n\t\ttest.deepEqual(obj.x, 0)\n\t\tt.update(500)\n\t\ttest.deepEqual(started, true)\n\t\ttest.deepEqual(obj.x, 500)\n\t\tt.update(1000)\n\t\ttest.deepEqual(obj.x, 1000)\n\t\ttest.deepEqual(started, false)\n\n\t\tTWEEN.Tween.autoStartOnUpdate = false\n\n\t\ttest.done()\n\t},\n\n\t'Test Tween.to() tweening towards a dynamic object'(test: Test): void {\n\t\tconst rabbit = {x: 1000, y: 0}\n\t\tconst tr = new TWEEN.Tween(rabbit)\n\t\ttr.to({y: 1000}, 1000)\n\t\ttr.start(0)\n\n\t\tconst fox = {x: 0, y: 0}\n\t\tconst tf = new TWEEN.Tween(fox)\n\t\ttf.to(rabbit, 1000) // fox chase rabbit!\n\t\ttf.dynamic(true)\n\t\ttf.start(0)\n\n\t\ttr.update(200)\n\t\ttf.update(200)\n\t\ttest.equal(rabbit.x, 1000)\n\t\ttest.equal(rabbit.y, 200)\n\t\ttest.equal(fox.x, 200)\n\t\ttest.equal(fox.y, 40)\n\t\ttr.update(500)\n\t\ttf.update(500)\n\t\ttest.equal(rabbit.x, 1000)\n\t\ttest.equal(rabbit.y, 500)\n\t\ttest.equal(fox.x, 500)\n\t\ttest.equal(fox.y, 250)\n\t\ttr.update(800)\n\t\ttf.update(800)\n\t\ttest.equal(rabbit.x, 1000)\n\t\ttest.equal(rabbit.y, 800)\n\t\ttest.equal(fox.x, 800)\n\t\ttest.equal(fox.y, 640)\n\t\ttr.update(1000)\n\t\ttf.update(1000)\n\t\ttest.equal(rabbit.x, 1000)\n\t\ttest.equal(rabbit.y, 1000)\n\t\ttest.equal(fox.x, 1000)\n\t\ttest.equal(fox.y, 1000)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.stop()'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\n\t\tt.to({x: 2}, 1000)\n\n\t\tt.start()\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\n\t\tt.stop()\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.delay()'(test: Test): void {\n\t\tconst obj = {x: 1},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: 2}, 1000)\n\t\tt.delay(500)\n\t\tt.start(0)\n\n\t\tt.update(100)\n\n\t\ttest.deepEqual(obj.x, 1, \"Tween hasn't started yet\")\n\n\t\tt.update(1000)\n\n\t\ttest.ok(obj.x !== 1 && obj.x !== 2, \"Tween has started but hasn't finished yet\")\n\n\t\tt.update(1500)\n\n\t\ttest.equal(obj.x, 2, 'Tween finishes when expected')\n\t\ttest.done()\n\t},\n\n\t// TODO: not really sure how to test this. Advice appreciated!\n\t'Test TWEEN.Tween.easing()'(test: Test): void {\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: 1}, 1000)\n\n\t\tt.easing(TWEEN.Easing.Quadratic.In)\n\t\tt.start(0)\n\t\tt.update(500)\n\t\ttest.equal(obj.x, TWEEN.Easing.Quadratic.In(0.5))\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.EasingFunctionGroup should be frozen'(test: Test): void {\n\t\tconst replaceEasingFunction = (easingGroup: EasingFunctionGroup) => {\n\t\t\tconst throwsWithReassigned = () => {\n\t\t\t\teasingGroup.In = (amount: number) => {\n\t\t\t\t\treturn 1.0 + amount\n\t\t\t\t}\n\t\t\t\teasingGroup.Out = (amount: number) => {\n\t\t\t\t\treturn 1.0 + amount\n\t\t\t\t}\n\t\t\t\teasingGroup.InOut = (amount: number) => {\n\t\t\t\t\treturn 1.0 + amount\n\t\t\t\t}\n\t\t\t}\n\t\t\ttest.throws(throwsWithReassigned)\n\t\t\ttest.equal(easingGroup.In(0.0), 0.0)\n\t\t\ttest.equal(easingGroup.Out(0.0), 0.0)\n\t\t\ttest.equal(easingGroup.InOut(0.0), 0.0)\n\t\t\ttest.equal(easingGroup.In(1.0), 1.0)\n\t\t\ttest.equal(easingGroup.Out(1.0), 1.0)\n\t\t\ttest.equal(easingGroup.InOut(1.0), 1.0)\n\t\t}\n\n\t\tconst Easing = TWEEN.Easing\n\t\tconst easingGroups = [\n\t\t\tEasing.Quadratic,\n\t\t\tEasing.Cubic,\n\t\t\tEasing.Quartic,\n\t\t\tEasing.Quintic,\n\t\t\tEasing.Sinusoidal,\n\t\t\tEasing.Exponential,\n\t\t\tEasing.Circular,\n\t\t\tEasing.Elastic,\n\t\t\tEasing.Back,\n\t\t\tEasing.Bounce,\n\t\t]\n\t\teasingGroups.forEach(replaceEasingFunction)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Easing should starts at 0.0, ends at 1.0. TWEEN.Easing.InOut() should be 0.5 at midpoint'(\n\t\ttest: Test,\n\t): void {\n\t\tconst checkEdgeValue = (ease: EasingFunctionGroup) => {\n\t\t\ttest.equal(ease.In(0.0), 0.0)\n\t\t\ttest.equal(ease.Out(0.0), 0.0)\n\t\t\ttest.equal(ease.InOut(0.0), 0.0)\n\n\t\t\ttest.equal(ease.In(1.0), 1.0)\n\t\t\ttest.equal(ease.Out(1.0), 1.0)\n\t\t\ttest.equal(ease.InOut(1.0), 1.0)\n\n\t\t\ttest.equal(ease.InOut(0.5), 0.5)\n\t\t}\n\n\t\tcheckEdgeValue(TWEEN.Easing.Quadratic)\n\t\tcheckEdgeValue(TWEEN.Easing.Cubic)\n\t\tcheckEdgeValue(TWEEN.Easing.Quartic)\n\t\tcheckEdgeValue(TWEEN.Easing.Quintic)\n\t\tcheckEdgeValue(TWEEN.Easing.Sinusoidal)\n\t\tcheckEdgeValue(TWEEN.Easing.Exponential)\n\t\tcheckEdgeValue(TWEEN.Easing.Circular)\n\t\tcheckEdgeValue(TWEEN.Easing.Elastic)\n\t\tcheckEdgeValue(TWEEN.Easing.Back)\n\t\tcheckEdgeValue(TWEEN.Easing.Bounce)\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Easing should pass a specific value'(test: Test): void {\n\t\tconst checkEasingGroupPassPoints = (\n\t\t\teasingGroup: EasingFunctionGroup,\n\t\t\texpects: {In: number; Out: number; InOut: number},\n\t\t) => {\n\t\t\tcheckPassPoint(easingGroup.In, expects.In)\n\t\t\tcheckPassPoint(easingGroup.Out, expects.Out)\n\t\t\tcheckPassPoint(easingGroup.InOut, expects.InOut)\n\t\t}\n\t\tconst checkPassPoint = (\n\t\t\teaseFunc: (amount: number) => number,\n\t\t\texpect: number,\n\t\t\tnumDigits = 14,\n\t\t\tamount = Math.LOG10E,\n\t\t) => {\n\t\t\ttoBeCloseTo(test, easeFunc(amount), expect, numDigits)\n\t\t}\n\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Quadratic, {\n\t\t\tIn: 0.18861169701161393,\n\t\t\tOut: 0.6799772667948897,\n\t\t\tInOut: 0.37722339402322785,\n\t\t})\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Cubic, {\n\t\t\tIn: 0.08191301923455198,\n\t\t\tOut: 0.8189613739094657,\n\t\t\tInOut: 0.3276520769382079,\n\t\t})\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Quartic, {\n\t\t\tIn: 0.035574372249600854,\n\t\t\tOut: 0.8975854502319308,\n\t\t\tInOut: 0.28459497799680683,\n\t\t})\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Quintic, {\n\t\t\tIn: 0.015449753565173821,\n\t\t\tOut: 0.9420635240628092,\n\t\t\tInOut: 0.24719605704278114,\n\t\t})\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Sinusoidal, {\n\t\t\tIn: 0.22380505208857682,\n\t\t\tOut: 0.630492983971101,\n\t\t\tInOut: 0.397521402836783,\n\t\t})\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Exponential, {\n\t\t\tIn: 0.01981785759600918,\n\t\t\tOut: 0.9507231043886069,\n\t\t\tInOut: 0.2010867096041978,\n\t\t})\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Circular, {\n\t\t\tIn: 0.09922905076352173,\n\t\t\tOut: 0.8246073409780499,\n\t\t\tInOut: 0.2522333699054974,\n\t\t})\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Elastic, {\n\t\t\tIn: -0.01701121590548648,\n\t\t\tOut: 0.9577017895937282,\n\t\t\tInOut: -0.09523991217687242,\n\t\t})\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Back, {\n\t\t\tIn: -0.09964331689734113,\n\t\t\tOut: 1.055453950893486,\n\t\t\tInOut: 0.19901899530677744,\n\t\t})\n\n\t\tcheckEasingGroupPassPoints(TWEEN.Easing.Bounce, {\n\t\t\tIn: 0.24689860443452594,\n\t\t\tOut: 0.8434464829485027,\n\t\t\tInOut: 0.43470212148602316,\n\t\t})\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.interpolation should starts at values[0], ends at values[values.length-1].'(test: Test): void {\n\t\tconst generateArray = (): number[] => {\n\t\t\treturn [0, Math.PI, Math.SQRT2, Math.E]\n\t\t}\n\n\t\tconst checkStartAndEnd = (interpolation: (v: number[], k: number) => number, values: number[]) => {\n\t\t\tconst originalValue = values.concat()\n\t\t\ttest.equal(interpolation(values, 0.0), originalValue[0])\n\t\t\ttest.equal(interpolation(values, 1.0), originalValue[originalValue.length - 1])\n\t\t\ttest.deepEqual(originalValue, values)\n\t\t}\n\n\t\tconst Interpolations = [TWEEN.Interpolation.Linear, TWEEN.Interpolation.Bezier, TWEEN.Interpolation.CatmullRom]\n\t\tInterpolations.forEach(func => {\n\t\t\tcheckStartAndEnd(func, generateArray())\n\t\t})\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.interpolation.Bezier should return a value equal to Linear if there are two values.'(test: Test): void {\n\t\tconst compareToLinear = (k: number) => {\n\t\t\tconst Interpolation = TWEEN.Interpolation\n\t\t\tconst values = [0, Math.E]\n\t\t\ttest.equal(Interpolation.Bezier(values, k), Interpolation.Linear(values, k))\n\t\t}\n\n\t\tcompareToLinear(0.0)\n\t\tcompareToLinear(0.5)\n\t\tcompareToLinear(1.0)\n\t\tcompareToLinear(Math.LOG10E)\n\t\tcompareToLinear(Math.LN2)\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.interpolation should pass a specific value.'(test: Test): void {\n\t\tconst generateArray = (): number[] => {\n\t\t\treturn [0, Math.PI, Math.SQRT2, Math.E]\n\t\t}\n\n\t\tconst testInterpolationPath = (\n\t\t\tinterpolation: (v: number[], k: number) => number,\n\t\t\tvalues: number[],\n\t\t\tresult: number,\n\t\t) => {\n\t\t\ttoBeCloseTo(test, interpolation(values, Math.LOG10E), result, 14)\n\t\t}\n\t\ttestInterpolationPath(TWEEN.Interpolation.Linear, generateArray(), 2.618398122395094)\n\t\ttestInterpolationPath(TWEEN.Interpolation.Bezier, generateArray(), 1.985241172928958)\n\t\ttestInterpolationPath(TWEEN.Interpolation.CatmullRom, generateArray(), 2.879802635590904)\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.chain --with one tween'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst t = new TWEEN.Tween({}, true),\n\t\t\tt2 = new TWEEN.Tween({}, true)\n\t\tlet tStarted = false,\n\t\t\ttCompleted = false,\n\t\t\tt2Started = false\n\n\t\tt.to({}, 1000)\n\t\tt2.to({}, 1000)\n\n\t\tt.chain(t2)\n\n\t\tt.onStart(function (): void {\n\t\t\ttStarted = true\n\t\t})\n\n\t\tt.onComplete(function (): void {\n\t\t\ttCompleted = true\n\t\t})\n\n\t\tt2.onStart(function (): void {\n\t\t\ttest.equal(tStarted, true)\n\t\t\ttest.equal(tCompleted, true)\n\t\t\ttest.equal(t2Started, false)\n\t\t\tt2Started = true\n\t\t})\n\n\t\ttest.equal(tStarted, false)\n\t\ttest.equal(t2Started, false)\n\n\t\tt.start(0)\n\t\tTWEEN.update(0)\n\n\t\ttest.equal(tStarted, true)\n\t\ttest.equal(t2Started, false)\n\n\t\tTWEEN.update(1000)\n\n\t\ttest.equal(tCompleted, true)\n\n\t\tTWEEN.update(1001)\n\n\t\ttest.equal(t2Started, true, 't2 is automatically started by t')\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.chain --with several tweens in an array'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst t = new TWEEN.Tween({}, true),\n\t\t\tchainedTweens: TWEEN.Tween<any>[] = [],\n\t\t\tnumChained = 3\n\t\tlet numChainedStarted = 0\n\n\t\tt.to({}, 1000)\n\n\t\tfunction onChainedStart(): void {\n\t\t\tnumChainedStarted++\n\t\t}\n\n\t\tfor (let i = 0; i < numChained; i++) {\n\t\t\tconst chained = new TWEEN.Tween({}, true)\n\t\t\tchained.to({}, 1000)\n\n\t\t\tchainedTweens.push(chained)\n\n\t\t\tchained.onStart(onChainedStart)\n\t\t}\n\n\t\tt.chain(...chainedTweens)\n\n\t\ttest.equal(numChainedStarted, 0)\n\n\t\tt.start(0)\n\t\tTWEEN.update(0)\n\t\tTWEEN.update(1000)\n\t\tTWEEN.update(1001)\n\n\t\ttest.equal(numChainedStarted, numChained, 'All chained tweens have been started')\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.chain allows endless loops'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt1 = new TWEEN.Tween(obj, true).to({x: 100}, 1000),\n\t\t\tt2 = new TWEEN.Tween(obj, true).to({x: 0}, 1000)\n\n\t\tt1.chain(t2)\n\t\tt2.chain(t1)\n\n\t\ttest.equal(obj.x, 0)\n\n\t\t// x == 0\n\t\tt1.start(0)\n\t\tTWEEN.update(0)\n\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(500)\n\t\ttest.equal(obj.x, 50)\n\n\t\t// there... (x == 100)\n\n\t\tTWEEN.update(1000)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(1500)\n\t\ttest.equal(obj.x, 50)\n\n\t\t// ... and back again (x == 0)\n\n\t\tTWEEN.update(2000)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(2500)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(3000)\n\t\ttest.equal(obj.x, 100) // and x == 100 again\n\n\t\t// Repeat the same test but with the tweens added in the\n\t\t// opposite order.\n\t\tconst obj2 = {x: 0}\n\t\tconst t3 = new TWEEN.Tween(obj2, true).to({x: 200}, 1000)\n\t\tconst t4 = new TWEEN.Tween(obj2, true).to({x: 100}, 1000)\n\n\t\tt4.chain(t3)\n\t\tt3.chain(t4)\n\n\t\ttest.equal(obj2.x, 0)\n\n\t\tt4.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj2.x, 0)\n\n\t\tTWEEN.update(500)\n\t\ttest.equal(obj2.x, 50)\n\n\t\tTWEEN.update(1000)\n\t\ttest.equal(obj2.x, 100)\n\n\t\tTWEEN.update(1500)\n\t\ttest.equal(obj2.x, 150)\n\n\t\tTWEEN.update(2000)\n\t\ttest.equal(obj2.x, 0)\n\n\t\tTWEEN.update(2500)\n\t\ttest.equal(obj2.x, 50)\n\n\t\tTWEEN.update(3000)\n\t\ttest.equal(obj2.x, 100)\n\n\t\tTWEEN.update(3500)\n\t\ttest.equal(obj2.x, 150)\n\n\t\tTWEEN.update(4000)\n\t\ttest.equal(obj2.x, 0)\n\n\t\tTWEEN.update(4500)\n\t\ttest.equal(obj2.x, 50)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.startFromCurrentValues'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100})\n\n\t\ttest.equal(obj.x, 0)\n\n\t\t// x == 0\n\t\tt.start(0)\n\t\tTWEEN.update(0)\n\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(1500)\n\t\ttest.equal(obj.x, 100)\n\n\t\tobj.x = 200\n\n\t\tt.startFromCurrentValues(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 200)\n\n\t\tTWEEN.update(500)\n\t\ttest.equal(obj.x, 150)\n\n\t\tTWEEN.update(1000)\n\t\ttest.equal(obj.x, 100)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.onStart'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\t\tlet counter = 0\n\n\t\tt.to({x: 2}, 1000)\n\t\tt.onStart(function (): void {\n\t\t\ttest.ok(true, 'onStart callback is called')\n\t\t\tcounter++\n\t\t})\n\n\t\ttest.deepEqual(counter, 0)\n\n\t\tt.start(0)\n\t\tTWEEN.update(0)\n\n\t\ttest.deepEqual(counter, 1)\n\n\t\tTWEEN.update(500)\n\n\t\ttest.deepEqual(counter, 1, 'onStart callback is not called again')\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.onEveryStart'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\t\tlet counter = 0\n\n\t\tt.to({x: 2}, 500)\n\t\tt.delay(500)\n\t\tt.repeat(Infinity)\n\t\tt.onEveryStart(function (): void {\n\t\t\tcounter++\n\t\t})\n\n\t\ttest.deepEqual(counter, 0)\n\n\t\tt.start(0)\n\t\tTWEEN.update(0)\n\t\ttest.deepEqual(counter, 0, 'onEveryStart callback not called before delayed start')\n\n\t\tTWEEN.update(500)\n\t\ttest.deepEqual(counter, 1, 'onEveryStart callback called at delayed start')\n\n\t\tTWEEN.update(1000)\n\t\ttest.deepEqual(counter, 1, 'onEveryStart callback not called before delayed repeat start')\n\n\t\tTWEEN.update(1500)\n\t\ttest.deepEqual(counter, 2, 'onEveryStart callback called at delayed repeat start')\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.onStop'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\t\tlet counter = 0\n\n\t\tt.to({x: 2}, 1000)\n\t\tt.onStop(function (): void {\n\t\t\ttest.ok(true, 'onStop callback is called')\n\t\t\tcounter++\n\t\t})\n\n\t\ttest.deepEqual(counter, 0)\n\n\t\tt.stop()\n\t\tTWEEN.update(0)\n\n\t\ttest.deepEqual(counter, 0, \"onStop callback not called when the tween hasn't started yet\")\n\n\t\tt.start(0)\n\t\tTWEEN.update(0)\n\t\tt.stop()\n\n\t\ttest.deepEqual(counter, 1, 'onStop callback is called if the tween has been started already and stop is invoked')\n\n\t\tTWEEN.update(500)\n\t\tt.stop()\n\n\t\ttest.deepEqual(counter, 1, 'onStop callback is not called again once the tween is stopped')\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.onUpdate'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\t\tlet counter = 0\n\n\t\tt.to({x: 2}, 1000)\n\t\tt.onUpdate(function (): void {\n\t\t\tcounter++\n\t\t})\n\n\t\ttest.deepEqual(counter, 0)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.deepEqual(counter, 1)\n\n\t\tTWEEN.update(500)\n\t\ttest.deepEqual(counter, 2)\n\n\t\tTWEEN.update(600)\n\t\ttest.deepEqual(counter, 3)\n\n\t\tTWEEN.update(1000)\n\t\ttest.deepEqual(counter, 4)\n\n\t\tTWEEN.update(1500)\n\t\ttest.deepEqual(counter, 4, 'onUpdate callback should not be called after the tween has finished')\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.onComplete'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\t\tlet counter = 0\n\n\t\tt.to({x: 2}, 1000)\n\t\tt.onComplete(function (): void {\n\t\t\tcounter++\n\t\t})\n\n\t\ttest.deepEqual(counter, 0)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.deepEqual(counter, 0)\n\n\t\tTWEEN.update(500)\n\t\ttest.deepEqual(counter, 0)\n\n\t\tTWEEN.update(600)\n\t\ttest.deepEqual(counter, 0)\n\n\t\tTWEEN.update(1000)\n\t\ttest.deepEqual(counter, 1)\n\n\t\tTWEEN.update(1500)\n\t\ttest.deepEqual(counter, 1, 'onComplete callback must be called only once')\n\t\ttest.done()\n\t},\n\n\t'TWEEN.Tween does not repeat by default'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(50)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(150)\n\t\ttest.equal(obj.x, 100)\n\t\ttest.done()\n\t},\n\n\t'Test single repeat happens only once'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(1)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(50)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(150)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 100)\n\t\ttest.done()\n\t},\n\n\t'Test Infinity repeat happens forever'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(Infinity)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(50)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(150)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(250)\n\t\ttest.equal(obj.x, 50)\n\t\ttest.done()\n\t},\n\n\t'Test tweening relatively with repeat'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0, y: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: '+100', y: '-100'}, 100).repeat(1)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 0)\n\t\ttest.equal(obj.y, 0)\n\n\t\tTWEEN.update(50)\n\t\ttest.equal(obj.x, 50)\n\t\ttest.equal(obj.y, -50)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\t\ttest.equal(obj.y, -100)\n\n\t\tTWEEN.update(150)\n\t\ttest.equal(obj.x, 150)\n\t\ttest.equal(obj.y, -150)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 200)\n\t\ttest.equal(obj.y, -200)\n\t\ttest.done()\n\t},\n\n\t'Test yoyo with repeat Infinity happens forever'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(Infinity).yoyo(true)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(25)\n\t\ttest.equal(obj.x, 25)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(125)\n\t\ttest.equal(obj.x, 75)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(225)\n\t\ttest.equal(obj.x, 25)\n\t\ttest.done()\n\t},\n\n\t'Test yoyo with repeat 1 happens once'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(1).yoyo(true)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(25)\n\t\ttest.equal(obj.x, 25)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(125)\n\t\ttest.equal(obj.x, 75)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(225)\n\t\ttest.equal(obj.x, 0)\n\t\ttest.done()\n\t},\n\n\t'Test yoyo works with arrays'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\t\t\t\t.to({x: [100, 200]}, 100)\n\t\t\t\t.repeat(1)\n\t\t\t\t.yoyo(true)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(50)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 200)\n\n\t\tTWEEN.update(150)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 0)\n\n\t\ttest.done()\n\t},\n\n\t'Test yoyo can be stopped and restarted properly'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(1).yoyo(true)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(25)\n\t\ttest.equal(obj.x, 25)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(125)\n\t\ttest.equal(obj.x, 75)\n\n\t\tt.stop()\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(25)\n\t\ttest.equal(obj.x, 25)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(125)\n\t\ttest.equal(obj.x, 75)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(225)\n\t\ttest.equal(obj.x, 0)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.stopChainedTweens()'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst t = new TWEEN.Tween({}, true),\n\t\t\tt2 = new TWEEN.Tween({}, true)\n\t\tlet tStarted = false,\n\t\t\ttCompleted = false,\n\t\t\tt2Started = false\n\n\t\tt.to({}, 1000)\n\t\tt2.delay(500).to({}, 1000)\n\n\t\tt.chain(t2)\n\t\tt2.chain(t)\n\n\t\tt.onStart(function (): void {\n\t\t\ttStarted = true\n\t\t})\n\n\t\tt.onComplete(function (): void {\n\t\t\ttCompleted = true\n\t\t})\n\n\t\tt2.onStart(function (): void {\n\t\t\ttest.equal(tStarted, true)\n\t\t\ttest.equal(tCompleted, true)\n\t\t\ttest.equal(t2Started, false)\n\t\t\tt2Started = true\n\t\t})\n\n\t\ttest.equal(tStarted, false)\n\t\ttest.equal(t2Started, false)\n\n\t\tt.start(0)\n\t\tTWEEN.update(1001)\n\t\tt.stop()\n\n\t\ttest.equal(tStarted, true)\n\t\ttest.equal(t2Started, false)\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tTWEEN.update(1501)\n\n\t\ttest.equal(t2Started, false)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.chain progressess into chained tweens'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {t: 1000}\n\n\t\t// 1000 of nothing\n\t\tconst blank = new TWEEN.Tween({}, true).to({}, 1000)\n\n\t\t// tween obj.t from 1000 -> 2000 (in time with update time)\n\t\tconst next = new TWEEN.Tween(obj, true).to({t: 2000}, 1000)\n\n\t\tblank.chain(next).start(0)\n\n\t\tTWEEN.update(1500)\n\t\ttest.equal(obj.t, 1500)\n\n\t\tTWEEN.update(2000)\n\t\ttest.equal(obj.t, 2000)\n\n\t\ttest.done()\n\t},\n\n\t'Test that TWEEN.Tween.end sets the final values.'(test: Test): void {\n\t\tconst object1 = {x: 0, y: -50, z: 1000}\n\t\tconst target1 = {x: 50, y: 123, z: '+234'}\n\n\t\tconst tween1 = new TWEEN.Tween(object1).to(target1, 1000)\n\n\t\ttween1.start()\n\t\ttween1.end()\n\n\t\ttest.equal(object1.x, 50)\n\t\ttest.equal(object1.y, 123)\n\t\ttest.equal(object1.z, 1234)\n\n\t\tconst object2 = {x: 0, y: -50, z: 1000}\n\t\tconst target2 = {x: 50, y: 123, z: '+234'}\n\n\t\tconst tween2 = new TWEEN.Tween(object2).to(target2, 1000)\n\n\t\ttween2.start(300)\n\t\ttween2.update(500)\n\t\ttween2.end()\n\n\t\ttest.equal(object2.x, 50)\n\t\ttest.equal(object2.y, 123)\n\t\ttest.equal(object2.z, 1234)\n\n\t\ttest.done()\n\t},\n\n\t'Test that TWEEN.Tween.end calls the onComplete callback of the tween.'(test: Test): void {\n\t\ttest.expect(1)\n\n\t\tconst tween1 = new TWEEN.Tween({}).to({}, 1000).onComplete(function (): void {\n\t\t\ttest.ok(true)\n\t\t})\n\n\t\ttween1.start()\n\t\ttween1.end()\n\n\t\ttest.done()\n\t},\n\n\t'Ensure Tween.end() works after stopping a tween.'(test: Test): void {\n\t\tconst object = {x: 0, y: -50, z: 1000}\n\t\tconst target = {x: 50, y: 123, z: '+234'}\n\n\t\tconst tween = new TWEEN.Tween(object).to(target, 1000)\n\n\t\ttween.start(300)\n\t\ttween.update(500)\n\t\ttween.stop()\n\t\ttween.end()\n\n\t\ttest.equal(object.x, 50)\n\t\ttest.equal(object.y, 123)\n\t\ttest.equal(object.z, 1234)\n\n\t\ttest.done()\n\t},\n\n\t'Test delay adds delay before each repeat'(test: Test): void {\n\t\t// If repeatDelay isn't specified then delay is used since\n\t\t// that's the way it worked before repeatDelay was added.\n\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(1).delay(100)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(150)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(250)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(300)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(350)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(400)\n\t\ttest.equal(obj.x, 100)\n\n\t\ttest.done()\n\t},\n\n\t'Test repeatDelay adds delay before each repeat'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(1).repeatDelay(200)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(50)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(300)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(350)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(400)\n\t\ttest.equal(obj.x, 100)\n\n\t\ttest.done()\n\t},\n\n\t'Test repeatDelay and delay can be used together'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).delay(100).repeat(1).repeatDelay(200)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(150)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(300)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(400)\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(450)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(500)\n\t\ttest.equal(obj.x, 100)\n\n\t\ttest.done()\n\t},\n\n\t'TWEEN.Tween.onRepeat should not be called if repeat = 0 or default'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0}\n\t\tlet callbackCounter = 0\n\n\t\tconst t = new TWEEN.Tween(obj, true).to({x: 100}, 100).start(0)\n\t\tt.onRepeat(() => {\n\t\t\tcallbackCounter++\n\t\t})\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(callbackCounter, 0)\n\t\tTWEEN.update(50)\n\t\ttest.equal(callbackCounter, 0)\n\t\tTWEEN.update(100)\n\t\ttest.equal(callbackCounter, 0)\n\t\tTWEEN.update(150)\n\t\ttest.equal(callbackCounter, 0)\n\t\ttest.ok(!t.isPlaying())\n\n\t\ttest.done()\n\t},\n\n\t'TWEEN.Tween.onRepeat should be called once if repeat = 1'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0}\n\t\tlet callbackCounter = 0\n\n\t\tconst t = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(1).start(0)\n\t\tt.onRepeat(() => {\n\t\t\tcallbackCounter++\n\t\t})\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(callbackCounter, 0)\n\t\tTWEEN.update(50)\n\t\ttest.equal(callbackCounter, 0)\n\t\tTWEEN.update(99.99999999)\n\t\ttest.equal(callbackCounter, 0)\n\t\tTWEEN.update(100)\n\t\ttest.equal(callbackCounter, 1)\n\t\ttest.ok(t.isPlaying())\n\n\t\tTWEEN.update(150)\n\t\ttest.equal(callbackCounter, 1)\n\t\tTWEEN.update(200)\n\t\ttest.equal(callbackCounter, 1)\n\t\ttest.ok(!t.isPlaying())\n\n\t\ttest.done()\n\t},\n\n\t'TWEEN.Tween.onRepeat should be called every time if repeat = Infinity'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0}\n\t\tlet callbackCounter = 0\n\n\t\tconst t = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(Infinity).start(0)\n\t\tt.onRepeat(() => {\n\t\t\tcallbackCounter++\n\t\t})\n\n\t\tconst repeatTween = (repeatCount: number): void => {\n\t\t\tTWEEN.update(repeatCount * 100)\n\t\t\ttest.equal(callbackCounter, repeatCount)\n\t\t\tTWEEN.update(50 + repeatCount * 100)\n\t\t\ttest.equal(callbackCounter, repeatCount)\n\t\t\tTWEEN.update(99.99999999 + repeatCount * 100)\n\t\t\ttest.equal(callbackCounter, repeatCount)\n\t\t\tTWEEN.update(100 + repeatCount * 100)\n\t\t\ttest.equal(callbackCounter, repeatCount + 1)\n\t\t\ttest.ok(t.isPlaying())\n\t\t}\n\n\t\tfor (let i = 0; i < 10; i++) {\n\t\t\trepeatTween(i)\n\t\t}\n\n\t\ttest.done()\n\t},\n\n\t'TWEEN.Tween.onRepeat should not be called if Tween.pause() or Tween.stop(), and should be called after Tween.resume() or restart'(\n\t\ttest: Test,\n\t): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst generateTween = () => {\n\t\t\tconst obj = {x: 0}\n\t\t\tconst counter = {count: 0}\n\t\t\tconst tween = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(Infinity).start(0)\n\t\t\ttween.onRepeat(() => {\n\t\t\t\tcounter.count++\n\t\t\t})\n\t\t\treturn {\n\t\t\t\ttween,\n\t\t\t\tcounter,\n\t\t\t}\n\t\t}\n\n\t\tconst tweenPause = generateTween()\n\t\tconst tweenStop = generateTween()\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(tweenPause.counter.count, 1, 'repeats after first completion')\n\t\ttest.equal(tweenStop.counter.count, 1, 'repeats after first completion')\n\n\t\tTWEEN.update(200)\n\t\ttest.equal(tweenPause.counter.count, 2, 'repeats after second completion')\n\t\ttest.equal(tweenStop.counter.count, 2, 'repeats after second completion')\n\n\t\ttweenPause.tween.pause(200)\n\t\tTWEEN.update(300)\n\t\ttest.equal(tweenPause.counter.count, 2, 'tween is paused hence it did not repeat')\n\t\ttest.equal(tweenStop.counter.count, 3, 'tween is not stopped hence it repeated')\n\n\t\ttweenPause.tween.resume(300)\n\t\ttweenStop.tween.stop()\n\t\tTWEEN.update(400)\n\t\ttest.equal(tweenPause.counter.count, 3, 'tween is resumed so it repeated')\n\t\ttest.equal(tweenStop.counter.count, 3, 'tween was stopped hence it did not repeat')\n\n\t\ttweenStop.tween.start(400)\n\t\tTWEEN.update(500)\n\t\ttest.equal(tweenPause.counter.count, 4, 'tween is not paused hence it repeated')\n\t\ttest.equal(tweenStop.counter.count, 4, 'tween is not stopped hence it repeated')\n\n\t\ttest.done()\n\t},\n\n\t'If Tween.delay is set, TWEEN.Tween.onRepeat should be called when repeat section finished'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0}\n\t\tlet callbackCounter = 0\n\n\t\tconst t = new TWEEN.Tween(obj, true).to({x: 100}, 100).delay(50).repeat(1).start(0)\n\t\tt.onRepeat(() => {\n\t\t\tcallbackCounter++\n\t\t})\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(callbackCounter, 0)\n\n\t\tTWEEN.update(50) //start first section\n\t\ttest.equal(obj.x, 0)\n\t\ttest.equal(callbackCounter, 0)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 50)\n\t\ttest.equal(callbackCounter, 0)\n\n\t\tTWEEN.update(150) //first section is finished\n\t\ttest.equal(obj.x, 100)\n\t\ttest.equal(callbackCounter, 1)\n\n\t\tTWEEN.update(200) //restart\n\t\ttest.equal(obj.x, 0)\n\t\ttest.equal(callbackCounter, 1)\n\n\t\tTWEEN.update(250)\n\t\ttest.equal(obj.x, 50)\n\t\ttest.equal(callbackCounter, 1)\n\n\t\tTWEEN.update(300) //second section is finished\n\t\ttest.equal(obj.x, 100)\n\t\ttest.equal(callbackCounter, 1)\n\t\ttest.ok(!t.isPlaying())\n\n\t\tTWEEN.update(400)\n\t\ttest.equal(obj.x, 100)\n\t\ttest.equal(callbackCounter, 1)\n\n\t\ttest.done()\n\t},\n\n\t'If Tween.repeatDelay is set, TWEEN.Tween.onRepeat should be called when repeat section finished'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0}\n\t\tlet callbackCounter = 0\n\n\t\tconst t = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeatDelay(100).repeat(1).start(0)\n\t\tt.onRepeat(() => {\n\t\t\tcallbackCounter++\n\t\t})\n\n\t\tTWEEN.update(0)\n\t\ttest.equal(callbackCounter, 0)\n\n\t\tTWEEN.update(50)\n\t\ttest.equal(callbackCounter, 0)\n\n\t\tTWEEN.update(99.99999999)\n\t\ttest.equal(callbackCounter, 0)\n\n\t\tTWEEN.update(100) //first section is finished\n\t\ttest.equal(callbackCounter, 1)\n\n\t\tTWEEN.update(150) //delay\n\t\ttest.equal(callbackCounter, 1)\n\n\t\tTWEEN.update(200) //restart\n\t\ttest.equal(callbackCounter, 1)\n\n\t\tTWEEN.update(300) //second section is finished\n\t\ttest.equal(callbackCounter, 1)\n\t\ttest.ok(!t.isPlaying())\n\n\t\tTWEEN.update(400)\n\t\ttest.equal(callbackCounter, 1)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.update() should reduce the repeat count'(test: Test) {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(5).delay(100)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(100)\n\t\t// @ts-expect-error\n\t\ttest.equal(t._repeat, 5)\n\n\t\tTWEEN.update(150)\n\t\t// @ts-expect-error\n\t\ttest.equal(t._repeat, 5)\n\n\t\tTWEEN.update(200)\n\t\t// @ts-expect-error\n\t\ttest.equal(t._repeat, 4)\n\n\t\tTWEEN.update(250)\n\t\t// @ts-expect-error\n\t\ttest.equal(t._repeat, 4)\n\n\t\tTWEEN.update(300)\n\t\t// @ts-expect-error\n\t\ttest.equal(t._repeat, 4)\n\n\t\tTWEEN.update(350)\n\t\t// @ts-expect-error\n\t\ttest.equal(t._repeat, 4)\n\n\t\tTWEEN.update(400)\n\t\t// @ts-expect-error\n\t\ttest.equal(t._repeat, 3)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.update() should reduce the repeat count multiple times'(test: Test) {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(5).delay(100)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(400)\n\t\t// @ts-expect-error\n\t\ttest.equal(t._repeat, 3)\n\n\t\ttest.done()\n\t},\n\n\t'Test browser tab sleep with delay'(test: Test) {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(Infinity).delay(100)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(350)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(750)\n\t\ttest.equal(obj.x, 50)\n\n\t\ttest.done()\n\t},\n\n\t'Test browser tab sleep with repeatDelay'(test: Test) {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).repeat(1).repeatDelay(200)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(350)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(600)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(Infinity)\n\t\ttest.equal(obj.x, 100)\n\n\t\ttest.done()\n\t},\n\n\t'Test browser tab sleep with repeatDelay and delay'(test: Test) {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj, true).to({x: 100}, 100).delay(100).repeat(1).repeatDelay(200)\n\n\t\tt.start(0)\n\n\t\tTWEEN.update(450)\n\t\ttest.equal(obj.x, 50)\n\n\t\tTWEEN.update(500)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(Infinity)\n\t\ttest.equal(obj.x, 100)\n\n\t\ttest.done()\n\t},\n\n\t'Tween.js compatible with Object.defineProperty getter / setters'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {_x: 0, x: 0}\n\n\t\tObject.defineProperty(obj, 'x', {\n\t\t\tget(): void {\n\t\t\t\treturn this._x\n\t\t\t},\n\t\t\tset(x): void {\n\t\t\t\tthis._x = x\n\t\t\t},\n\t\t})\n\n\t\ttest.equal(obj.x, 0)\n\n\t\tconst t = new TWEEN.Tween(obj, true).to({x: 100}, 100)\n\n\t\tt.start(0)\n\n\t\ttest.equal(obj.x, 0)\n\n\t\tTWEEN.update(37)\n\t\ttest.equal(obj.x, 37)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.x, 100)\n\n\t\tTWEEN.update(115)\n\t\ttest.equal(obj.x, 100)\n\n\t\ttest.done()\n\t},\n\n\t'tween.isPlaying() is false before the tween starts'(test: Test): void {\n\t\tconst t = new TWEEN.Tween({x: 0}).to({x: 1}, 100)\n\n\t\ttest.equal(t.isPlaying(), false)\n\n\t\ttest.done()\n\t},\n\n\t'tween.isPlaying() is true when a tween is started and before it ends'(test: Test): void {\n\t\tconst t = new TWEEN.Tween({x: 0}).to({x: 1}, 100)\n\t\tt.start(0)\n\t\ttest.equal(t.isPlaying(), true)\n\n\t\ttest.done()\n\t},\n\n\t'tween.isPlaying() is false after a tween ends'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst t = new TWEEN.Tween({x: 0}, true).to({x: 1}, 100)\n\t\tt.start(0)\n\t\tTWEEN.update(150)\n\t\ttest.equal(t.isPlaying(), false)\n\n\t\ttest.done()\n\t},\n\n\t'A zero-duration tween finishes at its starting time without an error.'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst object = {x: 0}\n\t\tconst t = new TWEEN.Tween(object, true).to({x: 1}, 0)\n\t\tt.start(0)\n\t\tTWEEN.update(0)\n\n\t\ttest.equal(t.isPlaying(), false)\n\t\ttest.equal(object.x, 1)\n\n\t\ttest.done()\n\t},\n\n\t// Custom TWEEN.Group tests\n\n\t'Custom group.getAll()'(test: Test): void {\n\t\tconst group = new TWEEN.Group()\n\t\ttest.ok(group.getAll() instanceof Array)\n\t\ttest.done()\n\t},\n\t'Custom group.onComplete() should be triggered when all Tweens in the group have reached their completion, and the child Tween.onComplete() should also be fired'(\n\t\ttest: Test,\n\t): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst t = new TWEEN.Tween({x: 1}),\n\t\t\tt2 = new TWEEN.Tween({x: 1}),\n\t\t\tt3 = new TWEEN.Tween({x: 1}),\n\t\t\tgroup = new TWEEN.Group()\n\t\tlet groupCounter = 0,\n\t\t\tchildCounter = 0,\n\t\t\tchildCounter2 = 0,\n\t\t\tchildCounter3 = 0\n\n\t\tgroup.add(t)\n\t\tgroup.add(t2)\n\t\tgroup.add(t3)\n\n\t\tt.to({x: 2}, 1000)\n\t\tt2.to({x: 2}, 2000)\n\t\tt3.to({x: 2}, 3000)\n\n\t\tt.onComplete(function (): void {\n\t\t\tchildCounter++\n\t\t})\n\t\tt2.onComplete(function (): void {\n\t\t\tchildCounter2++\n\t\t})\n\t\tt3.onComplete(function (): void {\n\t\t\tchildCounter3++\n\t\t})\n\t\tgroup.onComplete(function (): void {\n\t\t\tgroupCounter++\n\t\t})\n\n\t\tt.start(0)\n\t\tt2.start(0)\n\t\tt3.start(0)\n\n\t\tgroup.update(0)\n\t\ttest.deepEqual(groupCounter, 0)\n\t\ttest.deepEqual(childCounter, 0)\n\t\ttest.deepEqual(childCounter2, 0)\n\t\ttest.deepEqual(childCounter3, 0)\n\n\t\tgroup.update(1000)\n\t\ttest.deepEqual(groupCounter, 0)\n\t\ttest.deepEqual(childCounter, 1)\n\t\ttest.deepEqual(childCounter2, 0)\n\t\ttest.deepEqual(childCounter3, 0)\n\n\t\tgroup.update(2000)\n\t\ttest.deepEqual(childCounter, 1)\n\t\ttest.deepEqual(groupCounter, 0)\n\t\ttest.deepEqual(childCounter2, 1)\n\t\ttest.deepEqual(childCounter3, 0)\n\n\t\tgroup.update(3000)\n\t\ttest.deepEqual(groupCounter, 1)\n\t\ttest.deepEqual(childCounter, 1)\n\t\ttest.deepEqual(childCounter2, 1)\n\t\ttest.deepEqual(childCounter3, 1)\n\t\ttest.done()\n\t},\n\n\t'Custom group stores tweens instead of global TWEEN group'(test: Test): void {\n\t\tconst group = new TWEEN.Group()\n\n\t\tconst numGlobalTweensBefore = TWEEN.getAll().length\n\t\tconst numGroupTweensBefore = group.getAll().length\n\n\t\tconst globalTween = new TWEEN.Tween({}, true)\n\t\tconst groupTweenA = new TWEEN.Tween({}, group)\n\t\tconst groupTweenB = new TWEEN.Tween({}, group)\n\n\t\tglobalTween.start()\n\t\tgroupTweenA.start()\n\t\tgroupTweenB.start()\n\n\t\ttest.equal(TWEEN.getAll().length, numGlobalTweensBefore + 1)\n\t\ttest.equal(group.getAll().length, numGroupTweensBefore + 2)\n\t\ttest.done()\n\t},\n\n\t\"Custom group.removeAll() doesn't conflict with global TWEEN group\"(test: Test): void {\n\t\tconst group = new TWEEN.Group()\n\n\t\tTWEEN.removeAll()\n\t\tgroup.removeAll()\n\n\t\ttest.equal(TWEEN.getAll().length, 0, 'No global tweens left')\n\t\ttest.equal(group.getAll().length, 0, 'No group tweens left')\n\n\t\tconst globalTween = new TWEEN.Tween({}, true)\n\t\tconst groupTweenA = new TWEEN.Tween({}, group)\n\t\tconst groupTweenB = new TWEEN.Tween({}, group)\n\n\t\tglobalTween.start()\n\t\tgroupTweenA.start()\n\t\tgroupTweenB.start()\n\n\t\ttest.equal(TWEEN.getAll().length, 1, 'One global tween has been added')\n\t\ttest.equal(group.getAll().length, 2, 'Two group tweens have been added')\n\n\t\tgroup.removeAll()\n\n\t\ttest.equal(TWEEN.getAll().length, 1, 'One global tween left')\n\t\ttest.equal(group.getAll().length, 0, 'No group tweens left')\n\n\t\tTWEEN.removeAll()\n\n\t\ttest.equal(TWEEN.getAll().length, 0, 'No global tweens left')\n\n\t\ttest.done()\n\t},\n\n\t\"Global TWEEN.removeAll() doesn't conflict with custom group\"(test: Test): void {\n\t\tconst group = new TWEEN.Group()\n\n\t\tTWEEN.removeAll()\n\t\tgroup.removeAll()\n\n\t\ttest.equal(TWEEN.getAll().length, 0, 'No global tweens left')\n\t\ttest.equal(group.getAll().length, 0, 'No group tweens left')\n\n\t\tconst globalTween = new TWEEN.Tween({}, true)\n\t\tconst groupTweenA = new TWEEN.Tween({}, group)\n\t\tconst groupTweenB = new TWEEN.Tween({}, group)\n\n\t\tglobalTween.start()\n\t\tgroupTweenA.start()\n\t\tgroupTweenB.start()\n\n\t\ttest.equal(TWEEN.getAll().length, 1, 'One global tween has been added')\n\t\ttest.equal(group.getAll().length, 2, 'Two group tweens have been added')\n\n\t\tTWEEN.removeAll()\n\n\t\ttest.equal(TWEEN.getAll().length, 0, 'No global tweens left')\n\t\ttest.equal(group.getAll().length, 2, 'Two group tweens left')\n\n\t\tgroup.removeAll()\n\n\t\ttest.equal(group.getAll().length, 0, 'No group tweens left')\n\n\t\ttest.done()\n\t},\n\n\t\"Custom group.add() doesn't conflict with global TWEEN group, or vice versa\"(test: Test): void {\n\t\tconst group = new TWEEN.Group()\n\n\t\tconst globalTween = new TWEEN.Tween({}, true)\n\t\tconst groupTweenA = new TWEEN.Tween({}, group)\n\t\tconst groupTweenB = new TWEEN.Tween({}, group)\n\n\t\tTWEEN.add(globalTween)\n\t\tgroup.add(groupTweenA)\n\t\tgroup.add(groupTweenB)\n\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.equal(group.getAll().length, 2)\n\n\t\ttest.done()\n\t},\n\n\t\"Custom group.update() doesn't conflict with global TWEEN group\"(test: Test): void {\n\t\tconst group = new TWEEN.Group()\n\n\t\tconst startObj = {x: 1}\n\t\tconst endObj = {x: 2}\n\t\tconst duration = 1000\n\n\t\tconst globalObj = {x: 1}\n\t\tnew TWEEN.Tween(globalObj, true).to(endObj, duration).start(0)\n\n\t\tconst groupObj = {x: 1}\n\t\tnew TWEEN.Tween(groupObj, group).to(endObj, duration).start(0)\n\n\t\tgroup.update(duration)\n\n\t\ttest.deepEqual(globalObj, startObj)\n\t\ttest.deepEqual(groupObj, endObj)\n\t\ttest.done()\n\t},\n\n\t\"Global TWEEN.update() doesn't conflict with custom group\"(test: Test): void {\n\t\tconst group = new TWEEN.Group()\n\n\t\tconst startObj = {x: 1}\n\t\tconst endObj = {x: 2}\n\t\tconst duration = 1000\n\n\t\tconst globalObj = {x: 1}\n\t\tnew TWEEN.Tween(globalObj, true).to(endObj, duration).start(0)\n\n\t\tconst groupObj = {x: 1}\n\t\tnew TWEEN.Tween(groupObj, group).to(endObj, duration).start(0)\n\n\t\tTWEEN.update(duration)\n\n\t\ttest.deepEqual(globalObj, endObj)\n\t\ttest.deepEqual(groupObj, startObj)\n\t\ttest.done()\n\t},\n\n\t'Ensure tweens work without any group'(test: Test): void {\n\t\tconst obj = {x: 0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: 1000}, 1000)\n\n\t\tt.start(0)\n\t\ttest.equal(obj.x, 0)\n\t\tt.update(500)\n\t\ttest.equal(obj.x, 500)\n\t\tt.pause(600)\n\t\ttest.equal(obj.x, 500)\n\t\tt.update(750)\n\t\ttest.equal(obj.x, 500)\n\t\tt.resume(800)\n\t\ttest.equal(obj.x, 500)\n\t\tt.update(1000)\n\t\ttest.equal(obj.x, 800)\n\t\tt.update(1001)\n\t\ttest.equal(obj.x, 801)\n\t\tt.stop().end()\n\t\ttest.equal(obj.x, 1000)\n\n\t\ttest.done()\n\t},\n\n\t'Stopping a tween within an update callback will not cause an error.'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst tweenA = new TWEEN.Tween({x: 1, y: 2}, true)\n\t\t\t.to({x: 3, y: 4}, 1000)\n\t\t\t.onUpdate(function (): void {\n\t\t\t\ttweenB.stop()\n\t\t\t})\n\t\t\t.start(0)\n\t\tconst tweenB = new TWEEN.Tween({x: 5, y: 6}, true)\n\t\t\t.to({x: 7, y: 8})\n\t\t\t.onUpdate(function (): void {\n\t\t\t\ttweenA.stop()\n\t\t\t})\n\t\t\t.start(0)\n\n\t\tlet success = true\n\n\t\ttry {\n\t\t\tTWEEN.update(500)\n\t\t} catch (exception) {\n\t\t\tsuccess = false\n\t\t} finally {\n\t\t\ttest.ok(success)\n\t\t\ttest.done()\n\t\t}\n\t},\n\n\t'Set the duration with .duration'(test: Test): void {\n\t\tconst obj = {x: 1}\n\t\tconst t = new TWEEN.Tween(obj).to({x: 2}).duration(1000).start(0)\n\n\t\tt.update(1000)\n\n\t\ttest.deepEqual(obj.x, 2)\n\t\ttest.done()\n\t},\n\n\t'Get the duration with .getDuration'(test: Test): void {\n\t\tconst obj = {x: 1}\n\t\tconst t = new TWEEN.Tween(obj).to({x: 2}).duration(100)\n\n\t\ttest.deepEqual(t.getDuration(), 100)\n\t\ttest.done()\n\t},\n\n\t\"Tween.group sets the tween's group.\"(test: Test): void {\n\t\tconst group = new TWEEN.Group()\n\n\t\tconst groupTweenA = new TWEEN.Tween({}).group(group)\n\n\t\tgroupTweenA.start()\n\n\t\ttest.equal(group.getAll().length, 1)\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.pause() and TWEEN.Tween.resume()'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0.0},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\n\t\tt.to({x: 1.0}, 1000)\n\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\n\t\tt.start(0)\n\t\ttest.equal(t.isPaused(), false)\n\n\t\tTWEEN.update(400)\n\t\ttest.equal(obj.x, 0.4)\n\n\t\tt.pause(450)\n\t\ttest.equal(t.isPaused(), true)\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.equal(obj.x, 0.4)\n\n\t\tTWEEN.update(900)\n\t\ttest.equal(obj.x, 0.4)\n\n\t\tTWEEN.update(3000)\n\t\ttest.equal(obj.x, 0.4)\n\n\t\tt.resume(3200)\n\t\t// values do not change until an update\n\t\ttest.equal(obj.x, 0.4)\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.equal(t.isPaused(), false)\n\n\t\tTWEEN.update(3500)\n\t\ttest.equal(obj.x, 0.75)\n\n\t\tTWEEN.update(5000)\n\t\ttest.equal(obj.x, 1.0)\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.pause() and TWEEN.Tween.resume(), without groups'(test: Test): void {\n\t\tconst obj = {x: 0.0},\n\t\t\tt = new TWEEN.Tween(obj)\n\n\t\tt.to({x: 1.0}, 1000)\n\n\t\tt.start(0)\n\t\ttest.equal(t.isPaused(), false)\n\n\t\tt.update(400)\n\t\ttest.equal(obj.x, 0.4)\n\n\t\tt.pause(450)\n\t\ttest.equal(t.isPaused(), true)\n\t\ttest.equal(obj.x, 0.4)\n\n\t\tt.update(900)\n\t\ttest.equal(obj.x, 0.4)\n\n\t\tt.update(3000)\n\t\ttest.equal(obj.x, 0.4)\n\n\t\tt.resume(3200)\n\t\t// values do not change until an update\n\t\ttest.equal(obj.x, 0.4)\n\t\ttest.equal(t.isPaused(), false)\n\n\t\tt.update(3500)\n\t\ttest.equal(obj.x, 0.75)\n\n\t\tt.update(5000)\n\t\ttest.equal(obj.x, 1.0)\n\t\ttest.done()\n\t},\n\n\t'Arrays in the object passed to to() are not modified by start() if dynamic is false.'(test: Test): void {\n\t\tconst start = {x: 10, y: 20, z: 30}\n\t\tconst end = {x: 100, y: 200, z: ['+10', '-10']}\n\t\tconst valuesArray = end.z\n\t\tnew TWEEN.Tween(start).to(end).start()\n\t\ttest.equal(valuesArray, end.z)\n\t\ttest.equal(end.z.length, 2)\n\t\ttest.equal(end.z[0], '+10')\n\t\ttest.equal(end.z[1], '-10')\n\t\ttest.done()\n\t},\n\n\t'Arrays in the object passed to to() are modified by start() if dynamic is true.'(test: Test): void {\n\t\tconst start = {x: 10, y: 20, z: 30}\n\t\tconst end = {x: 100, y: 200, z: ['+10', '-10']}\n\t\tconst valuesArray = end.z\n\t\ttest.equal(end.z.length, 2)\n\t\tnew TWEEN.Tween(start).to(end).dynamic(true).start()\n\t\ttest.notEqual(valuesArray, end.z)\n\t\ttest.equal(end.z.length, 3)\n\t\ttest.equal(end.z[0], 30)\n\t\ttest.equal(end.z[1], 40)\n\t\ttest.equal(end.z[2], 20)\n\t\ttest.done()\n\t},\n\n\t'Arrays in the object passed to to() are not modified by start() if they are not interpolation arrays, regardless of dynamic.'(\n\t\ttest: Test,\n\t): void {\n\t\t// eslint-disable-next-line\n\t\tfunction testWithDynamic(start: any, end: any, dynamic: boolean): void {\n\t\t\t// const start = {x: 10, y: 20, z: [1, 2]}\n\t\t\t// const end = {x: 100, y: 200, z: ['a', 'b']}\n\t\t\tconst valuesArray = end.z\n\t\t\tnew TWEEN.Tween(start).to(end).dynamic(dynamic).start()\n\t\t\ttest.equal(valuesArray, end.z)\n\t\t\ttest.equal(end.z.length, 2)\n\t\t\ttest.equal(end.z[0], 'a')\n\t\t\ttest.equal(end.z[1], 'b')\n\t\t}\n\n\t\ttestWithDynamic({x: 10, y: 20, z: [1, 2]}, {x: 100, y: 200, z: ['a', 'b']}, true)\n\t\ttestWithDynamic({x: 10, y: 20, z: [1, 2]}, {x: 100, y: 200, z: ['a', 'b']}, false)\n\t\ttestWithDynamic({x: 10, y: 20, z: 30}, {x: 100, y: 200, z: ['a', 'b']}, true)\n\t\ttestWithDynamic({x: 10, y: 20, z: 30}, {x: 100, y: 200, z: ['a', 'b']}, false)\n\t\ttest.done()\n\t},\n\n\t'Tween.js animate nested object'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {scale: {x: 0}, alpha: 0}\n\n\t\tconst t = new TWEEN.Tween(obj, true).to({scale: {x: 100}, alpha: 100}, 100)\n\t\tt.start(0)\n\n\t\ttest.equal(obj.scale.x, 0)\n\n\t\tTWEEN.update(37)\n\t\ttest.equal(obj.scale.x, 37)\n\t\ttest.equal(obj.alpha, 37)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.scale.x, 100)\n\t\ttest.equal(obj.alpha, 100)\n\n\t\tTWEEN.update(115)\n\t\ttest.equal(obj.scale.x, 100)\n\t\ttest.equal(obj.alpha, 100)\n\n\t\ttest.done()\n\t},\n\n\t'Tween.js animate nested object including relative value'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {world: {hero: {scale: {x: 0}, x: 100}}, time: 0}\n\n\t\tconst t = new TWEEN.Tween(obj, true).to({world: {hero: {scale: {x: 100}, x: '+100'}}, time: 100}, 100)\n\t\tt.start(0)\n\n\t\ttest.equal(obj.world.hero.scale.x, 0)\n\n\t\tTWEEN.update(37)\n\t\ttest.equal(obj.world.hero.scale.x, 37)\n\t\ttest.equal(obj.world.hero.x, 137)\n\t\ttest.equal(obj.time, 37)\n\n\t\tTWEEN.update(100)\n\t\ttest.equal(obj.world.hero.scale.x, 100)\n\t\ttest.equal(obj.world.hero.x, 200)\n\t\ttest.equal(obj.time, 100)\n\n\t\tTWEEN.update(115)\n\t\ttest.equal(obj.world.hero.scale.x, 100)\n\t\ttest.equal(obj.world.hero.x, 200)\n\t\ttest.equal(obj.time, 100)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween with nested objects'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0.0, y: 100, some: {value: 0.0, style: {opacity: 1.0}}},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\n\t\tt.to({x: 1.0, y: 200, some: {value: 1.0, style: {opacity: 0.5}}}, 1000)\n\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\n\t\tt.start(0)\n\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.equal(t.isPaused(), false)\n\n\t\tTWEEN.update(400)\n\n\t\ttest.equal(obj.x, 0.4)\n\t\ttest.equal(obj.y, 140)\n\t\ttest.equal(obj.some.style.opacity, 0.8)\n\t\ttest.equal(obj.some.value, 0.4)\n\n\t\tTWEEN.update(750)\n\n\t\ttest.equal(obj.x, 0.75)\n\t\ttest.equal(obj.y, 175)\n\t\ttest.equal(obj.some.style.opacity, 0.625)\n\t\ttest.equal(obj.some.value, 0.75)\n\n\t\tTWEEN.update(1000)\n\n\t\ttest.equal(obj.x, 1.0)\n\t\ttest.equal(obj.y, 200)\n\t\ttest.equal(obj.some.style.opacity, 0.5)\n\t\ttest.equal(obj.some.value, 1.0)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.pause() and .resume() with nested objects'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst obj = {x: 0.0, y: 100, some: {value: 0.0}},\n\t\t\tt = new TWEEN.Tween(obj, true)\n\n\t\tt.to({x: 1.0, y: 200, some: {value: 1.0}}, 1000)\n\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\n\t\tt.start(0)\n\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.equal(t.isPaused(), false)\n\n\t\tTWEEN.update(400)\n\n\t\ttest.equal(obj.x, 0.4)\n\t\ttest.equal(obj.y, 140)\n\t\ttest.equal(obj.some.value, 0.4)\n\n\t\tt.pause(450)\n\n\t\ttest.equal(t.isPaused(), true)\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.equal(obj.x, 0.4)\n\t\ttest.equal(obj.y, 140)\n\t\ttest.equal(obj.some.value, 0.4)\n\n\t\tTWEEN.update(900)\n\n\t\ttest.equal(obj.x, 0.4)\n\t\ttest.equal(obj.y, 140)\n\t\ttest.equal(obj.some.value, 0.4)\n\n\t\tTWEEN.update(3000)\n\n\t\ttest.equal(obj.x, 0.4)\n\t\ttest.equal(obj.y, 140)\n\t\ttest.equal(obj.some.value, 0.4)\n\n\t\tt.resume(3200)\n\n\t\t// values do not change until an update\n\t\ttest.equal(obj.x, 0.4)\n\t\ttest.equal(obj.y, 140)\n\t\ttest.equal(obj.some.value, 0.4)\n\n\t\ttest.equal(TWEEN.getAll().length, 1)\n\t\ttest.equal(t.isPaused(), false)\n\n\t\tTWEEN.update(3500)\n\n\t\ttest.equal(obj.x, 0.75)\n\t\ttest.equal(obj.y, 175)\n\t\ttest.equal(obj.some.value, 0.75)\n\n\t\tTWEEN.update(5000)\n\n\t\ttest.equal(obj.x, 1.0)\n\t\ttest.equal(obj.y, 200)\n\t\ttest.equal(obj.some.value, 1.0)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Easing.generatePow(1) equals Linear'(test: Test): void {\n\t\tconst ease1 = TWEEN.Easing.generatePow(1)\n\n\t\tconst compareWithLinear = (ease: EasingFunctionGroup, amount: number) => {\n\t\t\tconst linearResult = TWEEN.Easing.Linear.None(amount)\n\t\t\ttest.equal(linearResult, ease.In(amount))\n\t\t\ttest.equal(linearResult, ease.Out(amount))\n\t\t\ttest.equal(linearResult, ease.InOut(amount))\n\t\t}\n\t\tcompareWithLinear(ease1, 0)\n\t\tcompareWithLinear(ease1, 0.25)\n\t\tcompareWithLinear(ease1, 0.5)\n\t\tcompareWithLinear(ease1, 0.75)\n\t\tcompareWithLinear(ease1, 1)\n\t\tcompareWithLinear(ease1, -1)\n\t\tcompareWithLinear(ease1, Infinity)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Easing.generatePow(n) should pass 0.0, 0.5, 1.0'(test: Test): void {\n\t\tconst checkEdgeValue = (ease: EasingFunctionGroup) => {\n\t\t\ttest.equal(ease.InOut(0.0), 0.0)\n\t\t\ttest.equal(ease.In(0.0), 0.0)\n\t\t\ttest.equal(ease.Out(0.0), 0.0)\n\n\t\t\ttest.equal(ease.InOut(0.5), 0.5)\n\n\t\t\ttest.equal(ease.InOut(1.0), 1.0)\n\t\t\ttest.equal(ease.In(1.0), 1.0)\n\t\t\ttest.equal(ease.Out(1.0), 1.0)\n\t\t}\n\t\tcheckEdgeValue(TWEEN.Easing.generatePow(Number.NEGATIVE_INFINITY))\n\t\tcheckEdgeValue(TWEEN.Easing.generatePow(-1.0))\n\t\tcheckEdgeValue(TWEEN.Easing.generatePow(1))\n\t\tcheckEdgeValue(TWEEN.Easing.generatePow(Math.LOG2E))\n\t\tcheckEdgeValue(TWEEN.Easing.generatePow(Math.PI))\n\t\tcheckEdgeValue(TWEEN.Easing.generatePow())\n\t\tcheckEdgeValue(TWEEN.Easing.generatePow(6))\n\t\tcheckEdgeValue(TWEEN.Easing.generatePow(Number.POSITIVE_INFINITY))\n\n\t\ttest.done()\n\t},\n\n\t\"Test TWEEN.to(ends) shouldn't grow endless on ends value\"(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst target = {y: 0}\n\t\tconst ends = {y: [100, 200]}\n\t\tconst tween = new TWEEN.Tween(target, true).to(ends, 1000)\n\n\t\ttween.stop().start(0)\n\t\ttween.stop().start(0)\n\n\t\tTWEEN.update(250)\n\t\ttest.equal(target.y, 50)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.to() with a dynamic target provided as object'(test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst dynamicTargetValue = {x: 5}\n\t\tconst chasingValue = {x: 0}\n\t\tconst duration = 1000 // must be even\n\t\tconst t1 = new TWEEN.Tween(dynamicTargetValue, true).to({x: 10}, duration),\n\t\t\tt2 = new TWEEN.Tween(chasingValue, true).to(dynamicTargetValue, duration).dynamic(true)\n\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tt1.start(0)\n\t\tt2.start(0)\n\t\ttest.notDeepEqual(chasingValue, dynamicTargetValue)\n\n\t\tTWEEN.update(duration / 2, true)\n\t\ttest.notDeepEqual(chasingValue, dynamicTargetValue)\n\n\t\tTWEEN.update(duration, true)\n\t\ttest.deepEqual(chasingValue, dynamicTargetValue)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.to() with a dynamic target provided as array': function (test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst dynamicTargetValue = [5]\n\t\tconst chasingValue = [0]\n\t\tconst duration = 1000 // must be even\n\t\tconst t1 = new TWEEN.Tween(dynamicTargetValue, true).to([10], duration),\n\t\t\tt2 = new TWEEN.Tween(chasingValue, true).to(dynamicTargetValue, duration).dynamic(true)\n\n\t\ttest.equal(TWEEN.getAll().length, 2)\n\n\t\tt1.start(0)\n\t\tt2.start(0)\n\t\ttest.notDeepEqual(chasingValue, dynamicTargetValue)\n\n\t\tTWEEN.update(duration / 2, true)\n\t\ttest.notDeepEqual(chasingValue, dynamicTargetValue)\n\n\t\tTWEEN.update(duration, true)\n\t\ttest.deepEqual(chasingValue, dynamicTargetValue)\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.to() with multiple dynamic targets provided as array': function (test: Test): void {\n\t\tTWEEN.removeAll()\n\n\t\tconst dynamicTargetValues = {x: [4, 10, 12, 20]}\n\t\tconst chasingValue = {x: 0}\n\t\tconst duration = 1000 // must be even\n\t\tconst tweens = []\n\n\t\tconst observedValues = []\n\t\tfor (let i = 0; i < dynamicTargetValues.x.length; i++) {\n\t\t\tconst initialValue = {x: 0}\n\t\t\tobservedValues.push(initialValue)\n\t\t\ttweens.push(\n\t\t\t\tnew TWEEN.Tween(initialValue, true).to({x: dynamicTargetValues.x[i]}, duration).onUpdate(function (object) {\n\t\t\t\t\t// TODO the fact that we need `index + 1` instead of just\n\t\t\t\t\t// `index` here is confusing. It is because Tween adds an\n\t\t\t\t\t// axtra start value at the beginning of the array. Update\n\t\t\t\t\t// Tween so it does not add the start value to the array,\n\t\t\t\t\t// and instead reads it from _valuesStart.\n\t\t\t\t\tdynamicTargetValues.x[i + 1] = object.x\n\t\t\t\t}),\n\t\t\t)\n\t\t}\n\n\t\tconst t = new TWEEN.Tween(chasingValue, true).to(dynamicTargetValues, duration).dynamic(true)\n\n\t\ttest.equal(TWEEN.getAll().length, 5)\n\n\t\ttweens.forEach(tween => tween.start(0))\n\t\tt.start(0)\n\n\t\ttest.equal(TWEEN.getAll().length, tweens.length + 1)\n\n\t\tfor (let i = 0; i < tweens.length; i++) {\n\t\t\tconst progress = ((i + 1) * duration) / tweens.length\n\t\t\tTWEEN.update(progress, true)\n\t\t\ttest.equal(chasingValue.x, observedValues[i].x)\n\t\t}\n\n\t\ttest.done()\n\t},\n\n\t'Test TWEEN.Tween.update() with no arguments'(test: Test): void {\n\t\tpatchPerformanceNow()\n\n\t\tconst targetNow = {x: 0.0}\n\t\tconst targetTime = {x: 0.0}\n\n\t\tconst tweenNow = new TWEEN.Tween(targetNow).to({x: 1.0}).start()\n\t\tconst tweenTime = new TWEEN.Tween(targetTime).to({x: 1.0}).start(0)\n\n\t\tconst tick = (time: number) => {\n\t\t\ttickTime(time)\n\t\t\ttweenNow.update()\n\t\t\ttweenTime.update(time)\n\t\t\ttest.equal(targetNow.x, targetTime.x)\n\t\t}\n\n\t\ttick(0)\n\t\ttick(16)\n\t\ttick(16.66)\n\t\ttick(100)\n\t\ttick(20000)\n\n\t\trestorePerformanceNow()\n\n\t\ttest.done()\n\t},\n}\n\ntype Test = {\n\tok(a: unknown, failMessage?: string): void\n\tequal(a: unknown, b: unknown, failMessage?: string): void\n\tnotEqual(a: unknown, b: unknown, failMessage?: string): void\n\tdeepEqual(a: unknown, b: unknown, failMessage?: string): void\n\tnotDeepEqual(a: unknown, b: unknown, failMessage?: string): void\n\texpect(n: number): void\n\tthrows(block: unknown, error?: unknown, message?: string): void\n\tdone(): void\n}\n\nfunction toBeCloseTo(test: Test, numberA: number, numberB: number, numDigits = 2): void {\n\tconst diff = Math.abs(numberA - numberB)\n\ttest.ok(\n\t\tdiff < 10 ** -numDigits / 2,\n\t\t`\nactual : ${numberA}\nexpect : ${numberB}\ndiff : ${diff}`,\n\t)\n}\n\n// TODO test that starting and stopping a tween multiple times doesn't cause\n// interpolation arrays to modified yet again (and similar with other\n// initialization items). Initialization should happen only once, on first\n// start.\n\n// TODO test onRepeat\n"
  },
  {
    "path": "test/unit/nodeunit.html",
    "content": "<html>\n\t<head>\n\t\t<title>nodeunit based tests</title>\n\t\t<script src=\"nodeunit.js\"></script>\n\t\t<script src=\"../../dist/tween.umd.js\"></script>\n\t\t<!-- Run the build first for this file to exist. -->\n\t\t<script src=\"../../.tmp/tests.umd.js\"></script>\n\t</head>\n\t<body>\n\t\t<script>\n\t\t\tnodeunit.run({tween: TWEEN.tests})\n\t\t</script>\n\t</body>\n</html>\n"
  },
  {
    "path": "test/unit/nodeunit.js",
    "content": "/*!\n * Nodeunit\n * https://github.com/caolan/nodeunit\n * Copyright (c) 2010 Caolan McMahon\n * MIT Licensed\n *\n * json2.js\n * http://www.JSON.org/json2.js\n * Public Domain.\n * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n */\nnodeunit = (function () {\n\t/*\n    http://www.JSON.org/json2.js\n    2010-11-17\n\n    Public Domain.\n\n    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n\n    See http://www.JSON.org/js.html\n\n\n    This code should be minified before deployment.\n    See http://javascript.crockford.com/jsmin.html\n\n    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO\n    NOT CONTROL.\n\n\n    This file creates a global JSON object containing two methods: stringify\n    and parse.\n\n        JSON.stringify(value, replacer, space)\n            value       any JavaScript value, usually an object or array.\n\n            replacer    an optional parameter that determines how object\n                        values are stringified for objects. It can be a\n                        function or an array of strings.\n\n            space       an optional parameter that specifies the indentation\n                        of nested structures. If it is omitted, the text will\n                        be packed without extra whitespace. If it is a number,\n                        it will specify the number of spaces to indent at each\n                        level. If it is a string (such as '\\t' or '&nbsp;'),\n                        it contains the characters used to indent at each level.\n\n            This method produces a JSON text from a JavaScript value.\n\n            When an object value is found, if the object contains a toJSON\n            method, its toJSON method will be called and the result will be\n            stringified. A toJSON method does not serialize: it returns the\n            value represented by the name/value pair that should be serialized,\n            or undefined if nothing should be serialized. The toJSON method\n            will be passed the key associated with the value, and this will be\n            bound to the value\n\n            For example, this would serialize Dates as ISO strings.\n\n                Date.prototype.toJSON = function (key) {\n                    function f(n) {\n                        // Format integers to have at least two digits.\n                        return n < 10 ? '0' + n : n;\n                    }\n\n                    return this.getUTCFullYear()   + '-' +\n                         f(this.getUTCMonth() + 1) + '-' +\n                         f(this.getUTCDate())      + 'T' +\n                         f(this.getUTCHours())     + ':' +\n                         f(this.getUTCMinutes())   + ':' +\n                         f(this.getUTCSeconds())   + 'Z';\n                };\n\n            You can provide an optional replacer method. It will be passed the\n            key and value of each member, with this bound to the containing\n            object. The value that is returned from your method will be\n            serialized. If your method returns undefined, then the member will\n            be excluded from the serialization.\n\n            If the replacer parameter is an array of strings, then it will be\n            used to select the members to be serialized. It filters the results\n            such that only members with keys listed in the replacer array are\n            stringified.\n\n            Values that do not have JSON representations, such as undefined or\n            functions, will not be serialized. Such values in objects will be\n            dropped; in arrays they will be replaced with null. You can use\n            a replacer function to replace those with JSON values.\n            JSON.stringify(undefined) returns undefined.\n\n            The optional space parameter produces a stringification of the\n            value that is filled with line breaks and indentation to make it\n            easier to read.\n\n            If the space parameter is a non-empty string, then that string will\n            be used for indentation. If the space parameter is a number, then\n            the indentation will be that many spaces.\n\n            Example:\n\n            text = JSON.stringify(['e', {pluribus: 'unum'}]);\n            // text is '[\"e\",{\"pluribus\":\"unum\"}]'\n\n\n            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\\t');\n            // text is '[\\n\\t\"e\",\\n\\t{\\n\\t\\t\"pluribus\": \"unum\"\\n\\t}\\n]'\n\n            text = JSON.stringify([new Date()], function (key, value) {\n                return this[key] instanceof Date ?\n                    'Date(' + this[key] + ')' : value;\n            });\n            // text is '[\"Date(---current time---)\"]'\n\n\n        JSON.parse(text, reviver)\n            This method parses a JSON text to produce an object or array.\n            It can throw a SyntaxError exception.\n\n            The optional reviver parameter is a function that can filter and\n            transform the results. It receives each of the keys and values,\n            and its return value is used instead of the original value.\n            If it returns what it received, then the structure is not modified.\n            If it returns undefined then the member is deleted.\n\n            Example:\n\n            // Parse the text. Values that look like ISO date strings will\n            // be converted to Date objects.\n\n            myData = JSON.parse(text, function (key, value) {\n                var a;\n                if (typeof value === 'string') {\n                    a =\n/^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2}(?:\\.\\d*)?)Z$/.exec(value);\n                    if (a) {\n                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],\n                            +a[5], +a[6]));\n                    }\n                }\n                return value;\n            });\n\n            myData = JSON.parse('[\"Date(09/09/2001)\"]', function (key, value) {\n                var d;\n                if (typeof value === 'string' &&\n                        value.slice(0, 5) === 'Date(' &&\n                        value.slice(-1) === ')') {\n                    d = new Date(value.slice(5, -1));\n                    if (d) {\n                        return d;\n                    }\n                }\n                return value;\n            });\n\n\n    This is a reference implementation. You are free to copy, modify, or\n    redistribute.\n*/\n\n\t/*jslint evil: true, strict: false, regexp: false */\n\n\t/*members \"\", \"\\b\", \"\\t\", \"\\n\", \"\\f\", \"\\r\", \"\\\"\", JSON, \"\\\\\", apply,\n    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,\n    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,\n    lastIndex, length, parse, prototype, push, replace, slice, stringify,\n    test, toJSON, toString, valueOf\n*/\n\n\t// Create a JSON object only if one does not already exist. We create the\n\t// methods in a closure to avoid creating global variables.\n\n\tvar JSON = {}\n\n\t;(function () {\n\t\t'use strict'\n\n\t\tfunction f(n) {\n\t\t\t// Format integers to have at least two digits.\n\t\t\treturn n < 10 ? '0' + n : n\n\t\t}\n\n\t\tif (typeof Date.prototype.toJSON !== 'function') {\n\t\t\tDate.prototype.toJSON = function (key) {\n\t\t\t\treturn isFinite(this.valueOf())\n\t\t\t\t\t? this.getUTCFullYear() +\n\t\t\t\t\t\t\t'-' +\n\t\t\t\t\t\t\tf(this.getUTCMonth() + 1) +\n\t\t\t\t\t\t\t'-' +\n\t\t\t\t\t\t\tf(this.getUTCDate()) +\n\t\t\t\t\t\t\t'T' +\n\t\t\t\t\t\t\tf(this.getUTCHours()) +\n\t\t\t\t\t\t\t':' +\n\t\t\t\t\t\t\tf(this.getUTCMinutes()) +\n\t\t\t\t\t\t\t':' +\n\t\t\t\t\t\t\tf(this.getUTCSeconds()) +\n\t\t\t\t\t\t\t'Z'\n\t\t\t\t\t: null\n\t\t\t}\n\n\t\t\tString.prototype.toJSON =\n\t\t\t\tNumber.prototype.toJSON =\n\t\t\t\tBoolean.prototype.toJSON =\n\t\t\t\t\tfunction (key) {\n\t\t\t\t\t\treturn this.valueOf()\n\t\t\t\t\t}\n\t\t}\n\n\t\tvar cx = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n\t\t\tescapable =\n\t\t\t\t/[\\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g,\n\t\t\tgap,\n\t\t\tindent,\n\t\t\tmeta = {\n\t\t\t\t// table of character substitutions\n\t\t\t\t'\\b': '\\\\b',\n\t\t\t\t'\\t': '\\\\t',\n\t\t\t\t'\\n': '\\\\n',\n\t\t\t\t'\\f': '\\\\f',\n\t\t\t\t'\\r': '\\\\r',\n\t\t\t\t'\"': '\\\\\"',\n\t\t\t\t'\\\\': '\\\\\\\\',\n\t\t\t},\n\t\t\trep\n\n\t\tfunction quote(string) {\n\t\t\t// If the string contains no control characters, no quote characters, and no\n\t\t\t// backslash characters, then we can safely slap some quotes around it.\n\t\t\t// Otherwise we must also replace the offending characters with safe escape\n\t\t\t// sequences.\n\n\t\t\tescapable.lastIndex = 0\n\t\t\treturn escapable.test(string)\n\t\t\t\t? '\"' +\n\t\t\t\t\t\tstring.replace(escapable, function (a) {\n\t\t\t\t\t\t\tvar c = meta[a]\n\t\t\t\t\t\t\treturn typeof c === 'string' ? c : '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)\n\t\t\t\t\t\t}) +\n\t\t\t\t\t\t'\"'\n\t\t\t\t: '\"' + string + '\"'\n\t\t}\n\n\t\tfunction str(key, holder) {\n\t\t\t// Produce a string from holder[key].\n\n\t\t\tvar i, // The loop counter.\n\t\t\t\tk, // The member key.\n\t\t\t\tv, // The member value.\n\t\t\t\tlength,\n\t\t\t\tmind = gap,\n\t\t\t\tpartial,\n\t\t\t\tvalue = holder[key]\n\n\t\t\t// If the value has a toJSON method, call it to obtain a replacement value.\n\n\t\t\tif (value && typeof value === 'object' && typeof value.toJSON === 'function') {\n\t\t\t\tvalue = value.toJSON(key)\n\t\t\t}\n\n\t\t\t// If we were called with a replacer function, then call the replacer to\n\t\t\t// obtain a replacement value.\n\n\t\t\tif (typeof rep === 'function') {\n\t\t\t\tvalue = rep.call(holder, key, value)\n\t\t\t}\n\n\t\t\t// What happens next depends on the value's type.\n\n\t\t\tswitch (typeof value) {\n\t\t\t\tcase 'string':\n\t\t\t\t\treturn quote(value)\n\n\t\t\t\tcase 'number':\n\t\t\t\t\t// JSON numbers must be finite. Encode non-finite numbers as null.\n\n\t\t\t\t\treturn isFinite(value) ? String(value) : 'null'\n\n\t\t\t\tcase 'boolean':\n\t\t\t\tcase 'null':\n\t\t\t\t\t// If the value is a boolean or null, convert it to a string. Note:\n\t\t\t\t\t// typeof null does not produce 'null'. The case is included here in\n\t\t\t\t\t// the remote chance that this gets fixed someday.\n\n\t\t\t\t\treturn String(value)\n\n\t\t\t\t// If the type is 'object', we might be dealing with an object or an array or\n\t\t\t\t// null.\n\n\t\t\t\tcase 'object':\n\t\t\t\t\t// Due to a specification blunder in ECMAScript, typeof null is 'object',\n\t\t\t\t\t// so watch out for that case.\n\n\t\t\t\t\tif (!value) {\n\t\t\t\t\t\treturn 'null'\n\t\t\t\t\t}\n\n\t\t\t\t\t// Make an array to hold the partial results of stringifying this object value.\n\n\t\t\t\t\tgap += indent\n\t\t\t\t\tpartial = []\n\n\t\t\t\t\t// Is the value an array?\n\n\t\t\t\t\tif (Object.prototype.toString.apply(value) === '[object Array]') {\n\t\t\t\t\t\t// The value is an array. Stringify every element. Use null as a placeholder\n\t\t\t\t\t\t// for non-JSON values.\n\n\t\t\t\t\t\tlength = value.length\n\t\t\t\t\t\tfor (i = 0; i < length; i += 1) {\n\t\t\t\t\t\t\tpartial[i] = str(i, value) || 'null'\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Join all of the elements together, separated with commas, and wrap them in\n\t\t\t\t\t\t// brackets.\n\n\t\t\t\t\t\tv =\n\t\t\t\t\t\t\tpartial.length === 0\n\t\t\t\t\t\t\t\t? '[]'\n\t\t\t\t\t\t\t\t: gap\n\t\t\t\t\t\t\t\t\t? '[\\n' + gap + partial.join(',\\n' + gap) + '\\n' + mind + ']'\n\t\t\t\t\t\t\t\t\t: '[' + partial.join(',') + ']'\n\t\t\t\t\t\tgap = mind\n\t\t\t\t\t\treturn v\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the replacer is an array, use it to select the members to be stringified.\n\n\t\t\t\t\tif (rep && typeof rep === 'object') {\n\t\t\t\t\t\tlength = rep.length\n\t\t\t\t\t\tfor (i = 0; i < length; i += 1) {\n\t\t\t\t\t\t\tk = rep[i]\n\t\t\t\t\t\t\tif (typeof k === 'string') {\n\t\t\t\t\t\t\t\tv = str(k, value)\n\t\t\t\t\t\t\t\tif (v) {\n\t\t\t\t\t\t\t\t\tpartial.push(quote(k) + (gap ? ': ' : ':') + v)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Otherwise, iterate through all of the keys in the object.\n\n\t\t\t\t\t\tfor (k in value) {\n\t\t\t\t\t\t\tif (Object.hasOwnProperty.call(value, k)) {\n\t\t\t\t\t\t\t\tv = str(k, value)\n\t\t\t\t\t\t\t\tif (v) {\n\t\t\t\t\t\t\t\t\tpartial.push(quote(k) + (gap ? ': ' : ':') + v)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Join all of the member texts together, separated with commas,\n\t\t\t\t\t// and wrap them in braces.\n\n\t\t\t\t\tv =\n\t\t\t\t\t\tpartial.length === 0\n\t\t\t\t\t\t\t? '{}'\n\t\t\t\t\t\t\t: gap\n\t\t\t\t\t\t\t\t? '{\\n' + gap + partial.join(',\\n' + gap) + '\\n' + mind + '}'\n\t\t\t\t\t\t\t\t: '{' + partial.join(',') + '}'\n\t\t\t\t\tgap = mind\n\t\t\t\t\treturn v\n\t\t\t}\n\t\t}\n\n\t\t// If the JSON object does not yet have a stringify method, give it one.\n\n\t\tif (typeof JSON.stringify !== 'function') {\n\t\t\tJSON.stringify = function (value, replacer, space) {\n\t\t\t\t// The stringify method takes a value and an optional replacer, and an optional\n\t\t\t\t// space parameter, and returns a JSON text. The replacer can be a function\n\t\t\t\t// that can replace values, or an array of strings that will select the keys.\n\t\t\t\t// A default replacer method can be provided. Use of the space parameter can\n\t\t\t\t// produce text that is more easily readable.\n\n\t\t\t\tvar i\n\t\t\t\tgap = ''\n\t\t\t\tindent = ''\n\n\t\t\t\t// If the space parameter is a number, make an indent string containing that\n\t\t\t\t// many spaces.\n\n\t\t\t\tif (typeof space === 'number') {\n\t\t\t\t\tfor (i = 0; i < space; i += 1) {\n\t\t\t\t\t\tindent += ' '\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the space parameter is a string, it will be used as the indent string.\n\t\t\t\t} else if (typeof space === 'string') {\n\t\t\t\t\tindent = space\n\t\t\t\t}\n\n\t\t\t\t// If there is a replacer, it must be a function or an array.\n\t\t\t\t// Otherwise, throw an error.\n\n\t\t\t\trep = replacer\n\t\t\t\tif (\n\t\t\t\t\treplacer &&\n\t\t\t\t\ttypeof replacer !== 'function' &&\n\t\t\t\t\t(typeof replacer !== 'object' || typeof replacer.length !== 'number')\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error('JSON.stringify')\n\t\t\t\t}\n\n\t\t\t\t// Make a fake root object containing our value under the key of ''.\n\t\t\t\t// Return the result of stringifying the value.\n\n\t\t\t\treturn str('', {'': value})\n\t\t\t}\n\t\t}\n\n\t\t// If the JSON object does not yet have a parse method, give it one.\n\n\t\tif (typeof JSON.parse !== 'function') {\n\t\t\tJSON.parse = function (text, reviver) {\n\t\t\t\t// The parse method takes a text and an optional reviver function, and returns\n\t\t\t\t// a JavaScript value if the text is a valid JSON text.\n\n\t\t\t\tvar j\n\n\t\t\t\tfunction walk(holder, key) {\n\t\t\t\t\t// The walk method is used to recursively walk the resulting structure so\n\t\t\t\t\t// that modifications can be made.\n\n\t\t\t\t\tvar k,\n\t\t\t\t\t\tv,\n\t\t\t\t\t\tvalue = holder[key]\n\t\t\t\t\tif (value && typeof value === 'object') {\n\t\t\t\t\t\tfor (k in value) {\n\t\t\t\t\t\t\tif (Object.hasOwnProperty.call(value, k)) {\n\t\t\t\t\t\t\t\tv = walk(value, k)\n\t\t\t\t\t\t\t\tif (v !== undefined) {\n\t\t\t\t\t\t\t\t\tvalue[k] = v\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tdelete value[k]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn reviver.call(holder, key, value)\n\t\t\t\t}\n\n\t\t\t\t// Parsing happens in four stages. In the first stage, we replace certain\n\t\t\t\t// Unicode characters with escape sequences. JavaScript handles many characters\n\t\t\t\t// incorrectly, either silently deleting them, or treating them as line endings.\n\n\t\t\t\ttext = String(text)\n\t\t\t\tcx.lastIndex = 0\n\t\t\t\tif (cx.test(text)) {\n\t\t\t\t\ttext = text.replace(cx, function (a) {\n\t\t\t\t\t\treturn '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4)\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\t// In the second stage, we run the text against regular expressions that look\n\t\t\t\t// for non-JSON patterns. We are especially concerned with '()' and 'new'\n\t\t\t\t// because they can cause invocation, and '=' because it can cause mutation.\n\t\t\t\t// But just to be safe, we want to reject all unexpected forms.\n\n\t\t\t\t// We split the second stage into 4 regexp operations in order to work around\n\t\t\t\t// crippling inefficiencies in IE's and Safari's regexp engines. First we\n\t\t\t\t// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we\n\t\t\t\t// replace all simple value tokens with ']' characters. Third, we delete all\n\t\t\t\t// open brackets that follow a colon or comma or that begin the text. Finally,\n\t\t\t\t// we look to see that the remaining characters are only whitespace or ']' or\n\t\t\t\t// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.\n\n\t\t\t\tif (\n\t\t\t\t\t/^[\\],:{}\\s]*$/.test(\n\t\t\t\t\t\ttext\n\t\t\t\t\t\t\t.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')\n\t\t\t\t\t\t\t.replace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']')\n\t\t\t\t\t\t\t.replace(/(?:^|:|,)(?:\\s*\\[)+/g, ''),\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t// In the third stage we use the eval function to compile the text into a\n\t\t\t\t\t// JavaScript structure. The '{' operator is subject to a syntactic ambiguity\n\t\t\t\t\t// in JavaScript: it can begin a block or an object literal. We wrap the text\n\t\t\t\t\t// in parens to eliminate the ambiguity.\n\n\t\t\t\t\tj = eval('(' + text + ')')\n\n\t\t\t\t\t// In the optional fourth stage, we recursively walk the new structure, passing\n\t\t\t\t\t// each name/value pair to a reviver function for possible transformation.\n\n\t\t\t\t\treturn typeof reviver === 'function' ? walk({'': j}, '') : j\n\t\t\t\t}\n\n\t\t\t\t// If the text is not JSON parseable, then a SyntaxError is thrown.\n\n\t\t\t\tthrow new SyntaxError('JSON.parse')\n\t\t\t}\n\t\t}\n\t})()\n\tvar assert = (this.assert = {})\n\tvar types = {}\n\tvar core = {}\n\tvar nodeunit = {}\n\tvar reporter = {}\n\t/*global setTimeout: false, console: false */\n\t;(function () {\n\t\tvar async = {}\n\n\t\t// global on the server, window in the browser\n\t\tvar root = this,\n\t\t\tprevious_async = root.async\n\n\t\tif (typeof module !== 'undefined' && module.exports) {\n\t\t\tmodule.exports = async\n\t\t} else {\n\t\t\troot.async = async\n\t\t}\n\n\t\tasync.noConflict = function () {\n\t\t\troot.async = previous_async\n\t\t\treturn async\n\t\t}\n\n\t\t//// cross-browser compatiblity functions ////\n\n\t\tvar _forEach = function (arr, iterator) {\n\t\t\tif (arr.forEach) {\n\t\t\t\treturn arr.forEach(iterator)\n\t\t\t}\n\t\t\tfor (var i = 0; i < arr.length; i += 1) {\n\t\t\t\titerator(arr[i], i, arr)\n\t\t\t}\n\t\t}\n\n\t\tvar _map = function (arr, iterator) {\n\t\t\tif (arr.map) {\n\t\t\t\treturn arr.map(iterator)\n\t\t\t}\n\t\t\tvar results = []\n\t\t\t_forEach(arr, function (x, i, a) {\n\t\t\t\tresults.push(iterator(x, i, a))\n\t\t\t})\n\t\t\treturn results\n\t\t}\n\n\t\tvar _reduce = function (arr, iterator, memo) {\n\t\t\tif (arr.reduce) {\n\t\t\t\treturn arr.reduce(iterator, memo)\n\t\t\t}\n\t\t\t_forEach(arr, function (x, i, a) {\n\t\t\t\tmemo = iterator(memo, x, i, a)\n\t\t\t})\n\t\t\treturn memo\n\t\t}\n\n\t\tvar _keys = function (obj) {\n\t\t\tif (Object.keys) {\n\t\t\t\treturn Object.keys(obj)\n\t\t\t}\n\t\t\tvar keys = []\n\t\t\tfor (var k in obj) {\n\t\t\t\tif (obj.hasOwnProperty(k)) {\n\t\t\t\t\tkeys.push(k)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn keys\n\t\t}\n\n\t\tvar _indexOf = function (arr, item) {\n\t\t\tif (arr.indexOf) {\n\t\t\t\treturn arr.indexOf(item)\n\t\t\t}\n\t\t\tfor (var i = 0; i < arr.length; i += 1) {\n\t\t\t\tif (arr[i] === item) {\n\t\t\t\t\treturn i\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn -1\n\t\t}\n\n\t\t//// exported async module functions ////\n\n\t\t//// nextTick implementation with browser-compatible fallback ////\n\t\tif (typeof setImmediate === 'function') {\n\t\t\tasync.nextTick = function (fn) {\n\t\t\t\tsetImmediate(fn)\n\t\t\t}\n\t\t} else if (typeof process !== 'undefined' && process.nextTick) {\n\t\t\tasync.nextTick = process.nextTick\n\t\t} else {\n\t\t\tasync.nextTick = function (fn) {\n\t\t\t\tsetTimeout(fn, 0)\n\t\t\t}\n\t\t}\n\n\t\tasync.forEach = function (arr, iterator, callback) {\n\t\t\tif (!arr.length) {\n\t\t\t\treturn callback()\n\t\t\t}\n\t\t\tvar completed = 0\n\t\t\t_forEach(arr, function (x) {\n\t\t\t\titerator(x, function (err) {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\tcallback(err)\n\t\t\t\t\t\tcallback = function () {}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcompleted += 1\n\t\t\t\t\t\tif (completed === arr.length) {\n\t\t\t\t\t\t\tcallback()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\n\t\tasync.forEachSeries = function (arr, iterator, callback) {\n\t\t\tif (!arr.length) {\n\t\t\t\treturn callback()\n\t\t\t}\n\t\t\tvar completed = 0\n\t\t\tvar iterate = function () {\n\t\t\t\titerator(arr[completed], function (err) {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\tcallback(err)\n\t\t\t\t\t\tcallback = function () {}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcompleted += 1\n\t\t\t\t\t\tif (completed === arr.length) {\n\t\t\t\t\t\t\tcallback()\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\titerate()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\t\t\titerate()\n\t\t}\n\n\t\tvar doParallel = function (fn) {\n\t\t\treturn function () {\n\t\t\t\tvar args = Array.prototype.slice.call(arguments)\n\t\t\t\treturn fn.apply(null, [async.forEach].concat(args))\n\t\t\t}\n\t\t}\n\t\tvar doSeries = function (fn) {\n\t\t\treturn function () {\n\t\t\t\tvar args = Array.prototype.slice.call(arguments)\n\t\t\t\treturn fn.apply(null, [async.forEachSeries].concat(args))\n\t\t\t}\n\t\t}\n\n\t\tvar _asyncMap = function (eachfn, arr, iterator, callback) {\n\t\t\tvar results = []\n\t\t\tarr = _map(arr, function (x, i) {\n\t\t\t\treturn {index: i, value: x}\n\t\t\t})\n\t\t\teachfn(\n\t\t\t\tarr,\n\t\t\t\tfunction (x, callback) {\n\t\t\t\t\titerator(x.value, function (err, v) {\n\t\t\t\t\t\tresults[x.index] = v\n\t\t\t\t\t\tcallback(err)\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tfunction (err) {\n\t\t\t\t\tcallback(err, results)\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\tasync.map = doParallel(_asyncMap)\n\t\tasync.mapSeries = doSeries(_asyncMap)\n\n\t\t// reduce only has a series version, as doing reduce in parallel won't\n\t\t// work in many situations.\n\t\tasync.reduce = function (arr, memo, iterator, callback) {\n\t\t\tasync.forEachSeries(\n\t\t\t\tarr,\n\t\t\t\tfunction (x, callback) {\n\t\t\t\t\titerator(memo, x, function (err, v) {\n\t\t\t\t\t\tmemo = v\n\t\t\t\t\t\tcallback(err)\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tfunction (err) {\n\t\t\t\t\tcallback(err, memo)\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\t// inject alias\n\t\tasync.inject = async.reduce\n\t\t// foldl alias\n\t\tasync.foldl = async.reduce\n\n\t\tasync.reduceRight = function (arr, memo, iterator, callback) {\n\t\t\tvar reversed = _map(arr, function (x) {\n\t\t\t\treturn x\n\t\t\t}).reverse()\n\t\t\tasync.reduce(reversed, memo, iterator, callback)\n\t\t}\n\t\t// foldr alias\n\t\tasync.foldr = async.reduceRight\n\n\t\tvar _filter = function (eachfn, arr, iterator, callback) {\n\t\t\tvar results = []\n\t\t\tarr = _map(arr, function (x, i) {\n\t\t\t\treturn {index: i, value: x}\n\t\t\t})\n\t\t\teachfn(\n\t\t\t\tarr,\n\t\t\t\tfunction (x, callback) {\n\t\t\t\t\titerator(x.value, function (v) {\n\t\t\t\t\t\tif (v) {\n\t\t\t\t\t\t\tresults.push(x)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcallback()\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tfunction (err) {\n\t\t\t\t\tcallback(\n\t\t\t\t\t\t_map(\n\t\t\t\t\t\t\tresults.sort(function (a, b) {\n\t\t\t\t\t\t\t\treturn a.index - b.index\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tfunction (x) {\n\t\t\t\t\t\t\t\treturn x.value\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\tasync.filter = doParallel(_filter)\n\t\tasync.filterSeries = doSeries(_filter)\n\t\t// select alias\n\t\tasync.select = async.filter\n\t\tasync.selectSeries = async.filterSeries\n\n\t\tvar _reject = function (eachfn, arr, iterator, callback) {\n\t\t\tvar results = []\n\t\t\tarr = _map(arr, function (x, i) {\n\t\t\t\treturn {index: i, value: x}\n\t\t\t})\n\t\t\teachfn(\n\t\t\t\tarr,\n\t\t\t\tfunction (x, callback) {\n\t\t\t\t\titerator(x.value, function (v) {\n\t\t\t\t\t\tif (!v) {\n\t\t\t\t\t\t\tresults.push(x)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcallback()\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tfunction (err) {\n\t\t\t\t\tcallback(\n\t\t\t\t\t\t_map(\n\t\t\t\t\t\t\tresults.sort(function (a, b) {\n\t\t\t\t\t\t\t\treturn a.index - b.index\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\tfunction (x) {\n\t\t\t\t\t\t\t\treturn x.value\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t),\n\t\t\t\t\t)\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\tasync.reject = doParallel(_reject)\n\t\tasync.rejectSeries = doSeries(_reject)\n\n\t\tvar _detect = function (eachfn, arr, iterator, main_callback) {\n\t\t\teachfn(\n\t\t\t\tarr,\n\t\t\t\tfunction (x, callback) {\n\t\t\t\t\titerator(x, function (result) {\n\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\tmain_callback(x)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcallback()\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tfunction (err) {\n\t\t\t\t\tmain_callback()\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\tasync.detect = doParallel(_detect)\n\t\tasync.detectSeries = doSeries(_detect)\n\n\t\tasync.some = function (arr, iterator, main_callback) {\n\t\t\tasync.forEach(\n\t\t\t\tarr,\n\t\t\t\tfunction (x, callback) {\n\t\t\t\t\titerator(x, function (v) {\n\t\t\t\t\t\tif (v) {\n\t\t\t\t\t\t\tmain_callback(true)\n\t\t\t\t\t\t\tmain_callback = function () {}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcallback()\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tfunction (err) {\n\t\t\t\t\tmain_callback(false)\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\t// any alias\n\t\tasync.any = async.some\n\n\t\tasync.every = function (arr, iterator, main_callback) {\n\t\t\tasync.forEach(\n\t\t\t\tarr,\n\t\t\t\tfunction (x, callback) {\n\t\t\t\t\titerator(x, function (v) {\n\t\t\t\t\t\tif (!v) {\n\t\t\t\t\t\t\tmain_callback(false)\n\t\t\t\t\t\t\tmain_callback = function () {}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcallback()\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tfunction (err) {\n\t\t\t\t\tmain_callback(true)\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\t// all alias\n\t\tasync.all = async.every\n\n\t\tasync.sortBy = function (arr, iterator, callback) {\n\t\t\tasync.map(\n\t\t\t\tarr,\n\t\t\t\tfunction (x, callback) {\n\t\t\t\t\titerator(x, function (err, criteria) {\n\t\t\t\t\t\tif (err) {\n\t\t\t\t\t\t\tcallback(err)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcallback(null, {value: x, criteria: criteria})\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tfunction (err, results) {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treturn callback(err)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar fn = function (left, right) {\n\t\t\t\t\t\t\tvar a = left.criteria,\n\t\t\t\t\t\t\t\tb = right.criteria\n\t\t\t\t\t\t\treturn a < b ? -1 : a > b ? 1 : 0\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcallback(\n\t\t\t\t\t\t\tnull,\n\t\t\t\t\t\t\t_map(results.sort(fn), function (x) {\n\t\t\t\t\t\t\t\treturn x.value\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\tasync.auto = function (tasks, callback) {\n\t\t\tcallback = callback || function () {}\n\t\t\tvar keys = _keys(tasks)\n\t\t\tif (!keys.length) {\n\t\t\t\treturn callback(null)\n\t\t\t}\n\n\t\t\tvar completed = []\n\n\t\t\tvar listeners = []\n\t\t\tvar addListener = function (fn) {\n\t\t\t\tlisteners.unshift(fn)\n\t\t\t}\n\t\t\tvar removeListener = function (fn) {\n\t\t\t\tfor (var i = 0; i < listeners.length; i += 1) {\n\t\t\t\t\tif (listeners[i] === fn) {\n\t\t\t\t\t\tlisteners.splice(i, 1)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar taskComplete = function () {\n\t\t\t\t_forEach(listeners, function (fn) {\n\t\t\t\t\tfn()\n\t\t\t\t})\n\t\t\t}\n\n\t\t\taddListener(function () {\n\t\t\t\tif (completed.length === keys.length) {\n\t\t\t\t\tcallback(null)\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t_forEach(keys, function (k) {\n\t\t\t\tvar task = tasks[k] instanceof Function ? [tasks[k]] : tasks[k]\n\t\t\t\tvar taskCallback = function (err) {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\tcallback(err)\n\t\t\t\t\t\t// stop subsequent errors hitting callback multiple times\n\t\t\t\t\t\tcallback = function () {}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcompleted.push(k)\n\t\t\t\t\t\ttaskComplete()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvar requires = task.slice(0, Math.abs(task.length - 1)) || []\n\t\t\t\tvar ready = function () {\n\t\t\t\t\treturn _reduce(\n\t\t\t\t\t\trequires,\n\t\t\t\t\t\tfunction (a, x) {\n\t\t\t\t\t\t\treturn a && _indexOf(completed, x) !== -1\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tif (ready()) {\n\t\t\t\t\ttask[task.length - 1](taskCallback)\n\t\t\t\t} else {\n\t\t\t\t\tvar listener = function () {\n\t\t\t\t\t\tif (ready()) {\n\t\t\t\t\t\t\tremoveListener(listener)\n\t\t\t\t\t\t\ttask[task.length - 1](taskCallback)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\taddListener(listener)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\n\t\tasync.waterfall = function (tasks, callback) {\n\t\t\tif (!tasks.length) {\n\t\t\t\treturn callback()\n\t\t\t}\n\t\t\tcallback = callback || function () {}\n\t\t\tvar wrapIterator = function (iterator) {\n\t\t\t\treturn function (err) {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\tcallback(err)\n\t\t\t\t\t\tcallback = function () {}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar args = Array.prototype.slice.call(arguments, 1)\n\t\t\t\t\t\tvar next = iterator.next()\n\t\t\t\t\t\tif (next) {\n\t\t\t\t\t\t\targs.push(wrapIterator(next))\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\targs.push(callback)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tasync.nextTick(function () {\n\t\t\t\t\t\t\titerator.apply(null, args)\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\twrapIterator(async.iterator(tasks))()\n\t\t}\n\n\t\tasync.parallel = function (tasks, callback) {\n\t\t\tcallback = callback || function () {}\n\t\t\tif (tasks.constructor === Array) {\n\t\t\t\tasync.map(\n\t\t\t\t\ttasks,\n\t\t\t\t\tfunction (fn, callback) {\n\t\t\t\t\t\tif (fn) {\n\t\t\t\t\t\t\tfn(function (err) {\n\t\t\t\t\t\t\t\tvar args = Array.prototype.slice.call(arguments, 1)\n\t\t\t\t\t\t\t\tif (args.length <= 1) {\n\t\t\t\t\t\t\t\t\targs = args[0]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcallback.call(null, err, args || null)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tcallback,\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tvar results = {}\n\t\t\t\tasync.forEach(\n\t\t\t\t\t_keys(tasks),\n\t\t\t\t\tfunction (k, callback) {\n\t\t\t\t\t\ttasks[k](function (err) {\n\t\t\t\t\t\t\tvar args = Array.prototype.slice.call(arguments, 1)\n\t\t\t\t\t\t\tif (args.length <= 1) {\n\t\t\t\t\t\t\t\targs = args[0]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresults[k] = args\n\t\t\t\t\t\t\tcallback(err)\n\t\t\t\t\t\t})\n\t\t\t\t\t},\n\t\t\t\t\tfunction (err) {\n\t\t\t\t\t\tcallback(err, results)\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tasync.series = function (tasks, callback) {\n\t\t\tcallback = callback || function () {}\n\t\t\tif (tasks.constructor === Array) {\n\t\t\t\tasync.mapSeries(\n\t\t\t\t\ttasks,\n\t\t\t\t\tfunction (fn, callback) {\n\t\t\t\t\t\tif (fn) {\n\t\t\t\t\t\t\tfn(function (err) {\n\t\t\t\t\t\t\t\tvar args = Array.prototype.slice.call(arguments, 1)\n\t\t\t\t\t\t\t\tif (args.length <= 1) {\n\t\t\t\t\t\t\t\t\targs = args[0]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcallback.call(null, err, args || null)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tcallback,\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tvar results = {}\n\t\t\t\tasync.forEachSeries(\n\t\t\t\t\t_keys(tasks),\n\t\t\t\t\tfunction (k, callback) {\n\t\t\t\t\t\ttasks[k](function (err) {\n\t\t\t\t\t\t\tvar args = Array.prototype.slice.call(arguments, 1)\n\t\t\t\t\t\t\tif (args.length <= 1) {\n\t\t\t\t\t\t\t\targs = args[0]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tresults[k] = args\n\t\t\t\t\t\t\tcallback(err)\n\t\t\t\t\t\t})\n\t\t\t\t\t},\n\t\t\t\t\tfunction (err) {\n\t\t\t\t\t\tcallback(err, results)\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tasync.iterator = function (tasks) {\n\t\t\tvar makeCallback = function (index) {\n\t\t\t\tvar fn = function () {\n\t\t\t\t\tif (tasks.length) {\n\t\t\t\t\t\ttasks[index].apply(null, arguments)\n\t\t\t\t\t}\n\t\t\t\t\treturn fn.next()\n\t\t\t\t}\n\t\t\t\tfn.next = function () {\n\t\t\t\t\treturn index < tasks.length - 1 ? makeCallback(index + 1) : null\n\t\t\t\t}\n\t\t\t\treturn fn\n\t\t\t}\n\t\t\treturn makeCallback(0)\n\t\t}\n\n\t\tasync.apply = function (fn) {\n\t\t\tvar args = Array.prototype.slice.call(arguments, 1)\n\t\t\treturn function () {\n\t\t\t\treturn fn.apply(null, args.concat(Array.prototype.slice.call(arguments)))\n\t\t\t}\n\t\t}\n\n\t\tvar _concat = function (eachfn, arr, fn, callback) {\n\t\t\tvar r = []\n\t\t\teachfn(\n\t\t\t\tarr,\n\t\t\t\tfunction (x, cb) {\n\t\t\t\t\tfn(x, function (err, y) {\n\t\t\t\t\t\tr = r.concat(y || [])\n\t\t\t\t\t\tcb(err)\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tfunction (err) {\n\t\t\t\t\tcallback(err, r)\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\t\tasync.concat = doParallel(_concat)\n\t\tasync.concatSeries = doSeries(_concat)\n\n\t\tasync.whilst = function (test, iterator, callback) {\n\t\t\tif (test()) {\n\t\t\t\titerator(function (err) {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treturn callback(err)\n\t\t\t\t\t}\n\t\t\t\t\tasync.whilst(test, iterator, callback)\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tcallback()\n\t\t\t}\n\t\t}\n\n\t\tasync.until = function (test, iterator, callback) {\n\t\t\tif (!test()) {\n\t\t\t\titerator(function (err) {\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\treturn callback(err)\n\t\t\t\t\t}\n\t\t\t\t\tasync.until(test, iterator, callback)\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tcallback()\n\t\t\t}\n\t\t}\n\n\t\tasync.queue = function (worker, concurrency) {\n\t\t\tvar workers = 0\n\t\t\tvar tasks = []\n\t\t\tvar q = {\n\t\t\t\tconcurrency: concurrency,\n\t\t\t\tpush: function (data, callback) {\n\t\t\t\t\ttasks.push({data: data, callback: callback})\n\t\t\t\t\tasync.nextTick(q.process)\n\t\t\t\t},\n\t\t\t\tprocess: function () {\n\t\t\t\t\tif (workers < q.concurrency && tasks.length) {\n\t\t\t\t\t\tvar task = tasks.splice(0, 1)[0]\n\t\t\t\t\t\tworkers += 1\n\t\t\t\t\t\tworker(task.data, function () {\n\t\t\t\t\t\t\tworkers -= 1\n\t\t\t\t\t\t\tif (task.callback) {\n\t\t\t\t\t\t\t\ttask.callback.apply(task, arguments)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tq.process()\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tlength: function () {\n\t\t\t\t\treturn tasks.length\n\t\t\t\t},\n\t\t\t}\n\t\t\treturn q\n\t\t}\n\n\t\tvar _console_fn = function (name) {\n\t\t\treturn function (fn) {\n\t\t\t\tvar args = Array.prototype.slice.call(arguments, 1)\n\t\t\t\tfn.apply(\n\t\t\t\t\tnull,\n\t\t\t\t\targs.concat([\n\t\t\t\t\t\tfunction (err) {\n\t\t\t\t\t\t\tvar args = Array.prototype.slice.call(arguments, 1)\n\t\t\t\t\t\t\tif (typeof console !== 'undefined') {\n\t\t\t\t\t\t\t\tif (err) {\n\t\t\t\t\t\t\t\t\tif (console.error) {\n\t\t\t\t\t\t\t\t\t\tconsole.error(err)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if (console[name]) {\n\t\t\t\t\t\t\t\t\t_forEach(args, function (x) {\n\t\t\t\t\t\t\t\t\t\tconsole[name](x)\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t]),\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\tasync.log = _console_fn('log')\n\t\tasync.dir = _console_fn('dir')\n\t\t/*async.info = _console_fn('info');\n    async.warn = _console_fn('warn');\n    async.error = _console_fn('error');*/\n\n\t\tasync.memoize = function (fn, hasher) {\n\t\t\tvar memo = {}\n\t\t\thasher =\n\t\t\t\thasher ||\n\t\t\t\tfunction (x) {\n\t\t\t\t\treturn x\n\t\t\t\t}\n\t\t\treturn function () {\n\t\t\t\tvar args = Array.prototype.slice.call(arguments)\n\t\t\t\tvar callback = args.pop()\n\t\t\t\tvar key = hasher.apply(null, args)\n\t\t\t\tif (key in memo) {\n\t\t\t\t\tcallback.apply(null, memo[key])\n\t\t\t\t} else {\n\t\t\t\t\tfn.apply(\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\targs.concat([\n\t\t\t\t\t\t\tfunction () {\n\t\t\t\t\t\t\t\tmemo[key] = arguments\n\t\t\t\t\t\t\t\tcallback.apply(null, arguments)\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}).call(this)\n\t;(function (exports) {\n\t\t/**\n\t\t * This file is based on the node.js assert module, but with some small\n\t\t * changes for browser-compatibility\n\t\t * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!\n\t\t */\n\n\t\t/**\n\t\t * Added for browser compatibility\n\t\t */\n\n\t\tvar _keys = function (obj) {\n\t\t\tif (Object.keys) return Object.keys(obj)\n\t\t\tif (typeof obj != 'object' && typeof obj != 'function') {\n\t\t\t\tthrow new TypeError('-')\n\t\t\t}\n\t\t\tvar keys = []\n\t\t\tfor (var k in obj) {\n\t\t\t\tif (obj.hasOwnProperty(k)) keys.push(k)\n\t\t\t}\n\t\t\treturn keys\n\t\t}\n\n\t\t// http://wiki.commonjs.org/wiki/Unit_Testing/1.0\n\t\t//\n\t\t// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!\n\t\t//\n\t\t// Originally from narwhal.js (http://narwhaljs.org)\n\t\t// Copyright (c) 2009 Thomas Robinson <280north.com>\n\t\t//\n\t\t// Permission is hereby granted, free of charge, to any person obtaining a copy\n\t\t// of this software and associated documentation files (the 'Software'), to\n\t\t// deal in the Software without restriction, including without limitation the\n\t\t// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n\t\t// sell copies of the Software, and to permit persons to whom the Software is\n\t\t// furnished to do so, subject to the following conditions:\n\t\t//\n\t\t// The above copyright notice and this permission notice shall be included in\n\t\t// all copies or substantial portions of the Software.\n\t\t//\n\t\t// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\t\t// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\t\t// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\t\t// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n\t\t// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n\t\t// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\t\tvar pSlice = Array.prototype.slice\n\n\t\t// 1. The assert module provides functions that throw\n\t\t// AssertionError's when particular conditions are not met. The\n\t\t// assert module must conform to the following interface.\n\n\t\tvar assert = exports\n\n\t\t// 2. The AssertionError is defined in assert.\n\t\t// new assert.AssertionError({message: message, actual: actual, expected: expected})\n\n\t\tassert.AssertionError = function AssertionError(options) {\n\t\t\tthis.name = 'AssertionError'\n\t\t\tthis.message = options.message\n\t\t\tthis.actual = options.actual\n\t\t\tthis.expected = options.expected\n\t\t\tthis.operator = options.operator\n\t\t\tvar stackStartFunction = options.stackStartFunction || fail\n\n\t\t\tif (Error.captureStackTrace) {\n\t\t\t\tError.captureStackTrace(this, stackStartFunction)\n\t\t\t}\n\t\t}\n\t\t// code from util.inherits in node\n\t\tassert.AssertionError.super_ = Error\n\n\t\t// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call\n\t\t// TODO: test what effect this may have\n\t\tvar ctor = function () {\n\t\t\tthis.constructor = assert.AssertionError\n\t\t}\n\t\tctor.prototype = Error.prototype\n\t\tassert.AssertionError.prototype = new ctor()\n\n\t\tassert.AssertionError.prototype.toString = function () {\n\t\t\tif (this.message) {\n\t\t\t\treturn [this.name + ':', this.message].join(' ')\n\t\t\t} else {\n\t\t\t\treturn [\n\t\t\t\t\tthis.name + ':',\n\t\t\t\t\ttypeof this.expected !== 'undefined' ? JSON.stringify(this.expected) : 'undefined',\n\t\t\t\t\tthis.operator,\n\t\t\t\t\ttypeof this.actual !== 'undefined' ? JSON.stringify(this.actual) : 'undefined',\n\t\t\t\t].join(' ')\n\t\t\t}\n\t\t}\n\n\t\t// assert.AssertionError instanceof Error\n\n\t\tassert.AssertionError.__proto__ = Error.prototype\n\n\t\t// At present only the three keys mentioned above are used and\n\t\t// understood by the spec. Implementations or sub modules can pass\n\t\t// other keys to the AssertionError's constructor - they will be\n\t\t// ignored.\n\n\t\t// 3. All of the following functions must throw an AssertionError\n\t\t// when a corresponding condition is not met, with a message that\n\t\t// may be undefined if not provided.  All assertion methods provide\n\t\t// both the actual and expected values to the assertion error for\n\t\t// display purposes.\n\n\t\tfunction fail(actual, expected, message, operator, stackStartFunction) {\n\t\t\tthrow new assert.AssertionError({\n\t\t\t\tmessage: message,\n\t\t\t\tactual: actual,\n\t\t\t\texpected: expected,\n\t\t\t\toperator: operator,\n\t\t\t\tstackStartFunction: stackStartFunction,\n\t\t\t})\n\t\t}\n\n\t\t// EXTENSION! allows for well behaved errors defined elsewhere.\n\t\tassert.fail = fail\n\n\t\t// 4. Pure assertion tests whether a value is truthy, as determined\n\t\t// by !!guard.\n\t\t// assert.ok(guard, message_opt);\n\t\t// This statement is equivalent to assert.equal(true, guard,\n\t\t// message_opt);. To test strictly for the value true, use\n\t\t// assert.strictEqual(true, guard, message_opt);.\n\n\t\tassert.ok = function ok(value, message) {\n\t\t\tif (!!!value) fail(value, true, message, '==', assert.ok)\n\t\t}\n\n\t\t// 5. The equality assertion tests shallow, coercive equality with\n\t\t// ==.\n\t\t// assert.equal(actual, expected, message_opt);\n\n\t\tassert.equal = function equal(actual, expected, message) {\n\t\t\tif (actual != expected) fail(actual, expected, message, '==', assert.equal)\n\t\t}\n\n\t\t// 6. The non-equality assertion tests for whether two objects are not equal\n\t\t// with != assert.notEqual(actual, expected, message_opt);\n\n\t\tassert.notEqual = function notEqual(actual, expected, message) {\n\t\t\tif (actual == expected) {\n\t\t\t\tfail(actual, expected, message, '!=', assert.notEqual)\n\t\t\t}\n\t\t}\n\n\t\t// 7. The equivalence assertion tests a deep equality relation.\n\t\t// assert.deepEqual(actual, expected, message_opt);\n\n\t\tassert.deepEqual = function deepEqual(actual, expected, message) {\n\t\t\tif (!_deepEqual(actual, expected)) {\n\t\t\t\tfail(actual, expected, message, 'deepEqual', assert.deepEqual)\n\t\t\t}\n\t\t}\n\n\t\tvar Buffer = null\n\t\tif (typeof require !== 'undefined' && typeof process !== 'undefined') {\n\t\t\ttry {\n\t\t\t\tBuffer = require('buffer').Buffer\n\t\t\t} catch (e) {\n\t\t\t\t// May be a CommonJS environment other than Node.js\n\t\t\t\tBuffer = null\n\t\t\t}\n\t\t}\n\n\t\tfunction _deepEqual(actual, expected) {\n\t\t\t// 7.1. All identical values are equivalent, as determined by ===.\n\t\t\tif (actual === expected) return true\n\n\t\t\t// Convert to primitives, if supported\n\t\t\tactual = actual.valueOf ? actual.valueOf() : actual\n\t\t\texpected = expected.valueOf ? expected.valueOf() : expected\n\n\t\t\t// 7.2. If the expected value is a Date object, the actual value is\n\t\t\t// equivalent if it is also a Date object that refers to the same time.\n\t\t\tif (actual instanceof Date && expected instanceof Date) {\n\t\t\t\treturn actual.getTime() === expected.getTime()\n\n\t\t\t\t// 7.2.1 If the expcted value is a RegExp object, the actual value is\n\t\t\t\t// equivalent if it is also a RegExp object that refers to the same source and options\n\t\t\t} else if (actual instanceof RegExp && expected instanceof RegExp) {\n\t\t\t\treturn (\n\t\t\t\t\tactual.source === expected.source &&\n\t\t\t\t\tactual.global === expected.global &&\n\t\t\t\t\tactual.ignoreCase === expected.ignoreCase &&\n\t\t\t\t\tactual.multiline === expected.multiline\n\t\t\t\t)\n\t\t\t} else if (Buffer && actual instanceof Buffer && expected instanceof Buffer) {\n\t\t\t\treturn (function () {\n\t\t\t\t\tvar i, len\n\n\t\t\t\t\tfor (i = 0, len = expected.length; i < len; i++) {\n\t\t\t\t\t\tif (actual[i] !== expected[i]) {\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn actual.length === expected.length\n\t\t\t\t})()\n\t\t\t\t// 7.3. Other pairs that do not both pass typeof value == \"object\",\n\t\t\t\t// equivalence is determined by ==.\n\t\t\t} else if (typeof actual != 'object' && typeof expected != 'object') {\n\t\t\t\treturn actual == expected\n\n\t\t\t\t// 7.4. For all other Object pairs, including Array objects, equivalence is\n\t\t\t\t// determined by having the same number of owned properties (as verified\n\t\t\t\t// with Object.prototype.hasOwnProperty.call), the same set of keys\n\t\t\t\t// (although not necessarily the same order), equivalent values for every\n\t\t\t\t// corresponding key, and an identical \"prototype\" property. Note: this\n\t\t\t\t// accounts for both named and indexed properties on Arrays.\n\t\t\t} else {\n\t\t\t\treturn objEquiv(actual, expected)\n\t\t\t}\n\t\t}\n\n\t\tfunction isUndefinedOrNull(value) {\n\t\t\treturn value === null || value === undefined\n\t\t}\n\n\t\tfunction isArguments(object) {\n\t\t\treturn Object.prototype.toString.call(object) == '[object Arguments]'\n\t\t}\n\n\t\tfunction objEquiv(a, b) {\n\t\t\tif (isUndefinedOrNull(a) || isUndefinedOrNull(b)) return false\n\n\t\t\t// an identical \"prototype\" property.\n\t\t\tif (a.prototype !== b.prototype) return false\n\t\t\t//~~~I've managed to break Object.keys through screwy arguments passing.\n\t\t\t//   Converting to array solves the problem.\n\t\t\tif (isArguments(a)) {\n\t\t\t\tif (!isArguments(b)) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\ta = pSlice.call(a)\n\t\t\t\tb = pSlice.call(b)\n\t\t\t\treturn _deepEqual(a, b)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tvar ka = _keys(a),\n\t\t\t\t\tkb = _keys(b),\n\t\t\t\t\tkey,\n\t\t\t\t\ti\n\t\t\t} catch (e) {\n\t\t\t\t//happens when one is a string literal and the other isn't\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// having the same number of owned properties (keys incorporates hasOwnProperty)\n\t\t\tif (ka.length != kb.length) return false\n\t\t\t//the same set of keys (although not necessarily the same order),\n\t\t\tka.sort()\n\t\t\tkb.sort()\n\t\t\t//~~~cheap key test\n\t\t\tfor (i = ka.length - 1; i >= 0; i--) {\n\t\t\t\tif (ka[i] != kb[i]) return false\n\t\t\t}\n\t\t\t//equivalent values for every corresponding key, and\n\t\t\t//~~~possibly expensive deep test\n\t\t\tfor (i = ka.length - 1; i >= 0; i--) {\n\t\t\t\tkey = ka[i]\n\t\t\t\tif (!_deepEqual(a[key], b[key])) return false\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\n\t\t// 8. The non-equivalence assertion tests for any deep inequality.\n\t\t// assert.notDeepEqual(actual, expected, message_opt);\n\n\t\tassert.notDeepEqual = function notDeepEqual(actual, expected, message) {\n\t\t\tif (_deepEqual(actual, expected)) {\n\t\t\t\tfail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual)\n\t\t\t}\n\t\t}\n\n\t\t// 9. The strict equality assertion tests strict equality, as determined by ===.\n\t\t// assert.strictEqual(actual, expected, message_opt);\n\n\t\tassert.strictEqual = function strictEqual(actual, expected, message) {\n\t\t\tif (actual !== expected) {\n\t\t\t\tfail(actual, expected, message, '===', assert.strictEqual)\n\t\t\t}\n\t\t}\n\n\t\t// 10. The strict non-equality assertion tests for strict inequality, as determined by !==.\n\t\t// assert.notStrictEqual(actual, expected, message_opt);\n\n\t\tassert.notStrictEqual = function notStrictEqual(actual, expected, message) {\n\t\t\tif (actual === expected) {\n\t\t\t\tfail(actual, expected, message, '!==', assert.notStrictEqual)\n\t\t\t}\n\t\t}\n\n\t\tfunction expectedException(actual, expected) {\n\t\t\tif (!actual || !expected) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tif (expected instanceof RegExp) {\n\t\t\t\treturn expected.test(actual.message || actual)\n\t\t\t} else if (actual instanceof expected) {\n\t\t\t\treturn true\n\t\t\t} else if (expected.call({}, actual) === true) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\treturn false\n\t\t}\n\n\t\tfunction _throws(shouldThrow, block, expected, message) {\n\t\t\tvar actual\n\n\t\t\tif (typeof expected === 'string') {\n\t\t\t\tmessage = expected\n\t\t\t\texpected = null\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tblock()\n\t\t\t} catch (e) {\n\t\t\t\tactual = e\n\t\t\t}\n\n\t\t\tmessage = (expected && expected.name ? ' (' + expected.name + ').' : '.') + (message ? ' ' + message : '.')\n\n\t\t\tif (shouldThrow && !actual) {\n\t\t\t\tfail('Missing expected exception' + message)\n\t\t\t}\n\n\t\t\tif (!shouldThrow && expectedException(actual, expected)) {\n\t\t\t\tfail('Got unwanted exception' + message)\n\t\t\t}\n\n\t\t\tif ((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) {\n\t\t\t\tthrow actual\n\t\t\t}\n\t\t}\n\n\t\t// 11. Expected to throw an error:\n\t\t// assert.throws(block, Error_opt, message_opt);\n\n\t\tassert.throws = function (block, /*optional*/ error, /*optional*/ message) {\n\t\t\t_throws.apply(this, [true].concat(pSlice.call(arguments)))\n\t\t}\n\n\t\t// EXTENSION! This is annoying to write outside this module.\n\t\tassert.doesNotThrow = function (block, /*optional*/ error, /*optional*/ message) {\n\t\t\t_throws.apply(this, [false].concat(pSlice.call(arguments)))\n\t\t}\n\n\t\tassert.ifError = function (err) {\n\t\t\tif (err) {\n\t\t\t\tthrow err\n\t\t\t}\n\t\t}\n\t})(assert)\n\t;(function (exports) {\n\t\t/*!\n\t\t * Nodeunit\n\t\t * Copyright (c) 2010 Caolan McMahon\n\t\t * MIT Licensed\n\t\t *\n\t\t * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!\n\t\t * Only code on that line will be removed, it's mostly to avoid requiring code\n\t\t * that is node specific\n\t\t */\n\n\t\t/**\n\t\t * Module dependencies\n\t\t */\n\n\t\t/**\n\t\t * Creates assertion objects representing the result of an assert call.\n\t\t * Accepts an object or AssertionError as its argument.\n\t\t *\n\t\t * @param {object} obj\n\t\t * @api public\n\t\t */\n\n\t\texports.assertion = function (obj) {\n\t\t\treturn {\n\t\t\t\tmethod: obj.method || '',\n\t\t\t\tmessage: obj.message || (obj.error && obj.error.message) || '',\n\t\t\t\terror: obj.error,\n\t\t\t\tpassed: function () {\n\t\t\t\t\treturn !this.error\n\t\t\t\t},\n\t\t\t\tfailed: function () {\n\t\t\t\t\treturn Boolean(this.error)\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Creates an assertion list object representing a group of assertions.\n\t\t * Accepts an array of assertion objects.\n\t\t *\n\t\t * @param {Array} arr\n\t\t * @param {Number} duration\n\t\t * @api public\n\t\t */\n\n\t\texports.assertionList = function (arr, duration) {\n\t\t\tvar that = arr || []\n\t\t\tthat.failures = function () {\n\t\t\t\tvar failures = 0\n\t\t\t\tfor (var i = 0; i < this.length; i += 1) {\n\t\t\t\t\tif (this[i].failed()) {\n\t\t\t\t\t\tfailures += 1\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn failures\n\t\t\t}\n\t\t\tthat.passes = function () {\n\t\t\t\treturn that.length - that.failures()\n\t\t\t}\n\t\t\tthat.duration = duration || 0\n\t\t\treturn that\n\t\t}\n\n\t\t/**\n\t\t * Create a wrapper function for assert module methods. Executes a callback\n\t\t * after it's complete with an assertion object representing the result.\n\t\t *\n\t\t * @param {Function} callback\n\t\t * @api private\n\t\t */\n\n\t\tvar assertWrapper = function (callback) {\n\t\t\treturn function (new_method, assert_method, arity) {\n\t\t\t\treturn function () {\n\t\t\t\t\tvar message = arguments[arity - 1]\n\t\t\t\t\tvar a = exports.assertion({method: new_method, message: message})\n\t\t\t\t\ttry {\n\t\t\t\t\t\tassert[assert_method].apply(null, arguments)\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\ta.error = e\n\t\t\t\t\t}\n\t\t\t\t\tcallback(a)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Creates the 'test' object that gets passed to every test function.\n\t\t * Accepts the name of the test function as its first argument, followed by\n\t\t * the start time in ms, the options object and a callback function.\n\t\t *\n\t\t * @param {String} name\n\t\t * @param {Number} start\n\t\t * @param {Object} options\n\t\t * @param {Function} callback\n\t\t * @api public\n\t\t */\n\n\t\texports.test = function (name, start, options, callback) {\n\t\t\tvar expecting\n\t\t\tvar a_list = []\n\n\t\t\tvar wrapAssert = assertWrapper(function (a) {\n\t\t\t\ta_list.push(a)\n\t\t\t\tif (options.log) {\n\t\t\t\t\tasync.nextTick(function () {\n\t\t\t\t\t\toptions.log(a)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tvar test = {\n\t\t\t\tdone: function (err) {\n\t\t\t\t\tif (expecting !== undefined && expecting !== a_list.length) {\n\t\t\t\t\t\tvar e = new Error('Expected ' + expecting + ' assertions, ' + a_list.length + ' ran')\n\t\t\t\t\t\tvar a1 = exports.assertion({method: 'expect', error: e})\n\t\t\t\t\t\ta_list.push(a1)\n\t\t\t\t\t\tif (options.log) {\n\t\t\t\t\t\t\tasync.nextTick(function () {\n\t\t\t\t\t\t\t\toptions.log(a1)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (err) {\n\t\t\t\t\t\tvar a2 = exports.assertion({error: err})\n\t\t\t\t\t\ta_list.push(a2)\n\t\t\t\t\t\tif (options.log) {\n\t\t\t\t\t\t\tasync.nextTick(function () {\n\t\t\t\t\t\t\t\toptions.log(a2)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvar end = new Date().getTime()\n\t\t\t\t\tasync.nextTick(function () {\n\t\t\t\t\t\tvar assertion_list = exports.assertionList(a_list, end - start)\n\t\t\t\t\t\toptions.testDone(name, assertion_list)\n\t\t\t\t\t\tcallback(null, a_list)\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tok: wrapAssert('ok', 'ok', 2),\n\t\t\t\tsame: wrapAssert('same', 'deepEqual', 3),\n\t\t\t\tequals: wrapAssert('equals', 'equal', 3),\n\t\t\t\texpect: function (num) {\n\t\t\t\t\texpecting = num\n\t\t\t\t},\n\t\t\t\t_assertion_list: a_list,\n\t\t\t}\n\t\t\t// add all functions from the assert module\n\t\t\tfor (var k in assert) {\n\t\t\t\tif (assert.hasOwnProperty(k)) {\n\t\t\t\t\ttest[k] = wrapAssert(k, k, assert[k].length)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn test\n\t\t}\n\n\t\t/**\n\t\t * Ensures an options object has all callbacks, adding empty callback functions\n\t\t * if any are missing.\n\t\t *\n\t\t * @param {Object} opt\n\t\t * @return {Object}\n\t\t * @api public\n\t\t */\n\n\t\texports.options = function (opt) {\n\t\t\tvar optionalCallback = function (name) {\n\t\t\t\topt[name] = opt[name] || function () {}\n\t\t\t}\n\n\t\t\toptionalCallback('moduleStart')\n\t\t\toptionalCallback('moduleDone')\n\t\t\toptionalCallback('testStart')\n\t\t\toptionalCallback('testReady')\n\t\t\toptionalCallback('testDone')\n\t\t\t//optionalCallback('log');\n\n\t\t\t// 'done' callback is not optional.\n\n\t\t\treturn opt\n\t\t}\n\t})(types)\n\t;(function (exports) {\n\t\t/*!\n\t\t * Nodeunit\n\t\t * Copyright (c) 2010 Caolan McMahon\n\t\t * MIT Licensed\n\t\t *\n\t\t * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!\n\t\t * Only code on that line will be removed, it's mostly to avoid requiring code\n\t\t * that is node specific\n\t\t */\n\n\t\t/**\n\t\t * Module dependencies\n\t\t */\n\n\t\t/**\n\t\t * Added for browser compatibility\n\t\t */\n\n\t\tvar _keys = function (obj) {\n\t\t\tif (Object.keys) {\n\t\t\t\treturn Object.keys(obj)\n\t\t\t}\n\t\t\tvar keys = []\n\t\t\tfor (var k in obj) {\n\t\t\t\tif (obj.hasOwnProperty(k)) {\n\t\t\t\t\tkeys.push(k)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn keys\n\t\t}\n\n\t\tvar _copy = function (obj) {\n\t\t\tvar nobj = {}\n\t\t\tvar keys = _keys(obj)\n\t\t\tfor (var i = 0; i < keys.length; i += 1) {\n\t\t\t\tnobj[keys[i]] = obj[keys[i]]\n\t\t\t}\n\t\t\treturn nobj\n\t\t}\n\n\t\t/**\n\t\t * Runs a test function (fn) from a loaded module. After the test function\n\t\t * calls test.done(), the callback is executed with an assertionList as its\n\t\t * second argument.\n\t\t *\n\t\t * @param {String} name\n\t\t * @param {Function} fn\n\t\t * @param {Object} opt\n\t\t * @param {Function} callback\n\t\t * @api public\n\t\t */\n\n\t\texports.runTest = function (name, fn, opt, callback) {\n\t\t\tvar options = types.options(opt)\n\n\t\t\toptions.testStart(name)\n\t\t\tvar start = new Date().getTime()\n\t\t\tvar test = types.test(name, start, options, callback)\n\n\t\t\toptions.testReady(test)\n\t\t\ttry {\n\t\t\t\tfn(test)\n\t\t\t} catch (e) {\n\t\t\t\ttest.done(e)\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Takes an object containing test functions or other test suites as properties\n\t\t * and runs each in series. After all tests have completed, the callback is\n\t\t * called with a list of all assertions as the second argument.\n\t\t *\n\t\t * If a name is passed to this function it is prepended to all test and suite\n\t\t * names that run within it.\n\t\t *\n\t\t * @param {String} name\n\t\t * @param {Object} suite\n\t\t * @param {Object} opt\n\t\t * @param {Function} callback\n\t\t * @api public\n\t\t */\n\n\t\texports.runSuite = function (name, suite, opt, callback) {\n\t\t\tsuite = wrapGroup(suite)\n\t\t\tvar keys = _keys(suite)\n\n\t\t\tasync.concatSeries(\n\t\t\t\tkeys,\n\t\t\t\tfunction (k, cb) {\n\t\t\t\t\tvar prop = suite[k],\n\t\t\t\t\t\t_name\n\n\t\t\t\t\t_name = name ? [].concat(name, k) : [k]\n\t\t\t\t\t_name.toString = function () {\n\t\t\t\t\t\t// fallback for old one\n\t\t\t\t\t\treturn this.join(' - ')\n\t\t\t\t\t}\n\n\t\t\t\t\tif (typeof prop === 'function') {\n\t\t\t\t\t\tvar in_name = false,\n\t\t\t\t\t\t\tin_specific_test = _name.toString() === opt.testFullSpec ? true : false\n\t\t\t\t\t\tfor (var i = 0; i < _name.length; i += 1) {\n\t\t\t\t\t\t\tif (_name[i] === opt.testspec) {\n\t\t\t\t\t\t\t\tin_name = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ((!opt.testFullSpec || in_specific_test) && (!opt.testspec || in_name)) {\n\t\t\t\t\t\t\tif (opt.moduleStart) {\n\t\t\t\t\t\t\t\topt.moduleStart()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\texports.runTest(_name, suite[k], opt, cb)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn cb()\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\texports.runSuite(_name, suite[k], opt, cb)\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcallback,\n\t\t\t)\n\t\t}\n\n\t\t/**\n\t\t * Run each exported test function or test suite from a loaded module.\n\t\t *\n\t\t * @param {String} name\n\t\t * @param {Object} mod\n\t\t * @param {Object} opt\n\t\t * @param {Function} callback\n\t\t * @api public\n\t\t */\n\n\t\texports.runModule = function (name, mod, opt, callback) {\n\t\t\tvar options = _copy(types.options(opt))\n\n\t\t\tvar _run = false\n\t\t\tvar _moduleStart = options.moduleStart\n\n\t\t\tmod = wrapGroup(mod)\n\n\t\t\tfunction run_once() {\n\t\t\t\tif (!_run) {\n\t\t\t\t\t_run = true\n\t\t\t\t\t_moduleStart(name)\n\t\t\t\t}\n\t\t\t}\n\t\t\toptions.moduleStart = run_once\n\n\t\t\tvar start = new Date().getTime()\n\n\t\t\texports.runSuite(null, mod, options, function (err, a_list) {\n\t\t\t\tvar end = new Date().getTime()\n\t\t\t\tvar assertion_list = types.assertionList(a_list, end - start)\n\t\t\t\toptions.moduleDone(name, assertion_list)\n\t\t\t\tif (nodeunit.complete) {\n\t\t\t\t\tnodeunit.complete(name, assertion_list)\n\t\t\t\t}\n\t\t\t\tcallback(null, a_list)\n\t\t\t})\n\t\t}\n\n\t\t/**\n\t\t * Treats an object literal as a list of modules keyed by name. Runs each\n\t\t * module and finished with calling 'done'. You can think of this as a browser\n\t\t * safe alternative to runFiles in the nodeunit module.\n\t\t *\n\t\t * @param {Object} modules\n\t\t * @param {Object} opt\n\t\t * @api public\n\t\t */\n\n\t\t// TODO: add proper unit tests for this function\n\t\texports.runModules = function (modules, opt) {\n\t\t\tvar all_assertions = []\n\t\t\tvar options = types.options(opt)\n\t\t\tvar start = new Date().getTime()\n\n\t\t\tasync.concatSeries(\n\t\t\t\t_keys(modules),\n\t\t\t\tfunction (k, cb) {\n\t\t\t\t\texports.runModule(k, modules[k], options, cb)\n\t\t\t\t},\n\t\t\t\tfunction (err, all_assertions) {\n\t\t\t\t\tvar end = new Date().getTime()\n\t\t\t\t\toptions.done(types.assertionList(all_assertions, end - start))\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\t/**\n\t\t * Wraps a test function with setUp and tearDown functions.\n\t\t * Used by testCase.\n\t\t *\n\t\t * @param {Function} setUp\n\t\t * @param {Function} tearDown\n\t\t * @param {Function} fn\n\t\t * @api private\n\t\t */\n\n\t\tvar wrapTest = function (setUp, tearDown, fn) {\n\t\t\treturn function (test) {\n\t\t\t\tvar context = {}\n\t\t\t\tif (tearDown) {\n\t\t\t\t\tvar done = test.done\n\t\t\t\t\ttest.done = function (err) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\ttearDown.call(context, function (err2) {\n\t\t\t\t\t\t\t\tif (err && err2) {\n\t\t\t\t\t\t\t\t\ttest._assertion_list.push(types.assertion({error: err}))\n\t\t\t\t\t\t\t\t\treturn done(err2)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tdone(err || err2)\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tdone(e)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (setUp) {\n\t\t\t\t\tsetUp.call(context, function (err) {\n\t\t\t\t\t\tif (err) {\n\t\t\t\t\t\t\treturn test.done(err)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfn.call(context, test)\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tfn.call(context, test)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Returns a serial callback from two functions.\n\t\t *\n\t\t * @param {Function} funcFirst\n\t\t * @param {Function} funcSecond\n\t\t * @api private\n\t\t */\n\n\t\tvar getSerialCallback = function (fns) {\n\t\t\tif (!fns.length) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn function (callback) {\n\t\t\t\tvar that = this\n\t\t\t\tvar bound_fns = []\n\t\t\t\tfor (var i = 0, len = fns.length; i < len; i++) {\n\t\t\t\t\t;(function (j) {\n\t\t\t\t\t\tbound_fns.push(function () {\n\t\t\t\t\t\t\treturn fns[j].apply(that, arguments)\n\t\t\t\t\t\t})\n\t\t\t\t\t})(i)\n\t\t\t\t}\n\t\t\t\treturn async.series(bound_fns, callback)\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Wraps a group of tests with setUp and tearDown functions.\n\t\t * Used by testCase.\n\t\t *\n\t\t * @param {Object} group\n\t\t * @param {Array} setUps - parent setUp functions\n\t\t * @param {Array} tearDowns - parent tearDown functions\n\t\t * @api private\n\t\t */\n\n\t\tvar wrapGroup = function (group, setUps, tearDowns) {\n\t\t\tvar tests = {}\n\n\t\t\tvar setUps = setUps ? setUps.slice() : []\n\t\t\tvar tearDowns = tearDowns ? tearDowns.slice() : []\n\n\t\t\tif (group.setUp) {\n\t\t\t\tsetUps.push(group.setUp)\n\t\t\t\tdelete group.setUp\n\t\t\t}\n\t\t\tif (group.tearDown) {\n\t\t\t\ttearDowns.unshift(group.tearDown)\n\t\t\t\tdelete group.tearDown\n\t\t\t}\n\n\t\t\tvar keys = _keys(group)\n\n\t\t\tfor (var i = 0; i < keys.length; i += 1) {\n\t\t\t\tvar k = keys[i]\n\t\t\t\tif (typeof group[k] === 'function') {\n\t\t\t\t\ttests[k] = wrapTest(getSerialCallback(setUps), getSerialCallback(tearDowns), group[k])\n\t\t\t\t} else if (typeof group[k] === 'object') {\n\t\t\t\t\ttests[k] = wrapGroup(group[k], setUps, tearDowns)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn tests\n\t\t}\n\n\t\t/**\n\t\t * Backwards compatibility for test suites using old testCase API\n\t\t */\n\n\t\texports.testCase = function (suite) {\n\t\t\treturn suite\n\t\t}\n\t})(core)\n\t;(function (exports) {\n\t\t/*!\n\t\t * Nodeunit\n\t\t * Copyright (c) 2010 Caolan McMahon\n\t\t * MIT Licensed\n\t\t *\n\t\t * THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!\n\t\t * Only code on that line will be removed, its mostly to avoid requiring code\n\t\t * that is node specific\n\t\t */\n\n\t\t/**\n\t\t * NOTE: this test runner is not listed in index.js because it cannot be\n\t\t * used with the command-line tool, only inside the browser.\n\t\t */\n\n\t\t/**\n\t\t * Reporter info string\n\t\t */\n\n\t\texports.info = 'Browser-based test reporter'\n\n\t\t/**\n\t\t * Run all tests within each module, reporting the results\n\t\t *\n\t\t * @param {Array} files\n\t\t * @api public\n\t\t */\n\n\t\texports.run = function (modules, options, callback) {\n\t\t\tvar start = new Date().getTime(),\n\t\t\t\tdiv,\n\t\t\t\ttextareas,\n\t\t\t\tdisplayErrorsByDefault\n\t\t\toptions = options || {}\n\t\t\tdiv = options.div || document.body\n\t\t\ttextareas = options.textareas\n\t\t\tdisplayErrorsByDefault = options.displayErrorsByDefault\n\n\t\t\tfunction setText(el, txt) {\n\t\t\t\tif ('innerText' in el) {\n\t\t\t\t\tel.innerText = txt\n\t\t\t\t} else if ('textContent' in el) {\n\t\t\t\t\tel.textContent = txt\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction getOrCreate(tag, id) {\n\t\t\t\tvar el = document.getElementById(id)\n\t\t\t\tif (!el) {\n\t\t\t\t\tel = document.createElement(tag)\n\t\t\t\t\tel.id = id\n\t\t\t\t\tdiv.appendChild(el)\n\t\t\t\t}\n\t\t\t\treturn el\n\t\t\t}\n\n\t\t\tvar header = getOrCreate('h1', 'nodeunit-header')\n\t\t\tvar banner = getOrCreate('h2', 'nodeunit-banner')\n\t\t\tvar userAgent = getOrCreate('h2', 'nodeunit-userAgent')\n\t\t\tvar tests = getOrCreate('ol', 'nodeunit-tests')\n\t\t\tvar result = getOrCreate('p', 'nodeunit-testresult')\n\n\t\t\tsetText(userAgent, navigator.userAgent)\n\n\t\t\tnodeunit.runModules(modules, {\n\t\t\t\tmoduleStart: function (name) {\n\t\t\t\t\t/*var mheading = document.createElement('h2');\n            mheading.innerText = name;\n            results.appendChild(mheading);\n            module = document.createElement('ol');\n            results.appendChild(module);*/\n\t\t\t\t},\n\t\t\t\ttestDone: function (name, assertions) {\n\t\t\t\t\tvar test = document.createElement('li')\n\t\t\t\t\tvar strong = document.createElement('strong')\n\t\t\t\t\tstrong.innerHTML =\n\t\t\t\t\t\tname +\n\t\t\t\t\t\t' <b style=\"color: black;\">(' +\n\t\t\t\t\t\t'<b class=\"fail\">' +\n\t\t\t\t\t\tassertions.failures() +\n\t\t\t\t\t\t'</b>, ' +\n\t\t\t\t\t\t'<b class=\"pass\">' +\n\t\t\t\t\t\tassertions.passes() +\n\t\t\t\t\t\t'</b>, ' +\n\t\t\t\t\t\tassertions.length +\n\t\t\t\t\t\t')</b>'\n\t\t\t\t\ttest.className = assertions.failures() ? 'fail' : 'pass'\n\t\t\t\t\ttest.appendChild(strong)\n\n\t\t\t\t\tvar aList = document.createElement('ol')\n\t\t\t\t\taList.style.display = displayErrorsByDefault ? 'block' : 'none'\n\t\t\t\t\t;(displayErrorsByDefault ? strong : test).onclick = function () {\n\t\t\t\t\t\tvar d = aList.style.display\n\t\t\t\t\t\taList.style.display = d == 'none' ? 'block' : 'none'\n\t\t\t\t\t}\n\t\t\t\t\tfor (var i = 0; i < assertions.length; i++) {\n\t\t\t\t\t\tvar li = document.createElement('li')\n\t\t\t\t\t\tvar a = assertions[i]\n\t\t\t\t\t\tif (a.failed()) {\n\t\t\t\t\t\t\tli.innerHTML =\n\t\t\t\t\t\t\t\t(a.message || a.method || 'no message') +\n\t\t\t\t\t\t\t\t(textareas\n\t\t\t\t\t\t\t\t\t? '<textarea rows=\"20\" cols=\"100\">' + (a.error.stack || a.error) + '</textarea>'\n\t\t\t\t\t\t\t\t\t: '<pre>' + (a.error.stack || a.error) + '</pre>')\n\t\t\t\t\t\t\tli.className = 'fail'\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tli.innerHTML = a.message || a.method || 'no message'\n\t\t\t\t\t\t\tli.className = 'pass'\n\t\t\t\t\t\t}\n\t\t\t\t\t\taList.appendChild(li)\n\t\t\t\t\t}\n\t\t\t\t\ttest.appendChild(aList)\n\t\t\t\t\ttests.appendChild(test)\n\t\t\t\t},\n\t\t\t\tdone: function (assertions) {\n\t\t\t\t\tvar end = new Date().getTime()\n\t\t\t\t\tvar duration = end - start\n\n\t\t\t\t\tvar failures = assertions.failures()\n\t\t\t\t\tbanner.className = failures ? 'fail' : 'pass'\n\n\t\t\t\t\tresult.innerHTML =\n\t\t\t\t\t\t'Tests completed in ' +\n\t\t\t\t\t\tduration +\n\t\t\t\t\t\t' milliseconds.<br/><span class=\"passed\">' +\n\t\t\t\t\t\tassertions.passes() +\n\t\t\t\t\t\t'</span> assertions of ' +\n\t\t\t\t\t\t'<span class=\"all\">' +\n\t\t\t\t\t\tassertions.length +\n\t\t\t\t\t\t'<span> passed, ' +\n\t\t\t\t\t\tassertions.failures() +\n\t\t\t\t\t\t' failed.'\n\n\t\t\t\t\tif (callback) callback(assertions.failures() ? new Error('We have got test failures.') : undefined)\n\t\t\t\t},\n\t\t\t})\n\t\t}\n\t})(reporter)\n\tnodeunit = core\n\tnodeunit.assert = assert\n\tnodeunit.reporter = reporter\n\tnodeunit.run = reporter.run\n\treturn nodeunit\n})()\n"
  },
  {
    "path": "test/unit/nodeunitheadless.cjs",
    "content": "const {tests} = require('../../.tmp/tests.cjs')\nmodule.exports = {tween: tests}\n\n// CONTINUE: got html tests running, had to convert to CJS files, ammend the infrastructure update commit with these changes\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"baseUrl\": \".\",\n\t\t\"outDir\": \"./.tmp\",\n\t\t\"declaration\": true,\n\t\t\"strict\": true,\n\t\t\"sourceMap\": true,\n\t\t\"module\": \"es2015\",\n\t\t\"target\": \"es5\",\n\t\t\"moduleResolution\": \"node\",\n\t\t\"lib\": [\"dom\", \"es2015\"],\n\n\t\t// TODO will be removed in TS 5.5\n\t\t\"ignoreDeprecations\": \"5.0\",\n\t\t\"importsNotUsedAsValues\": \"error\"\n\t},\n\t\"exclude\": [\"node_modules\", \"examples\"]\n}\n"
  }
]