[
  {
    "path": ".eslintrc.json",
    "content": "{\n\t\"env\": {\n\t\t\"es6\": true,\n\t\t\"amd\": true,\n\t\t\"browser\": true,\n\t\t\"mocha\": true,\n\t\t\"node\": true\n\t},\n\t\"extends\": \"eslint:recommended\",\n\t\"parserOptions\": {\n\t\t\"sourceType\": \"module\"\n\t},\n\t\"globals\": {\n\t\t\"describe\": true,\n\t\t\"it\": true,\n\t\t\"expect\": true,\n\t\t\"sinon\": true\n\t},\n\t\"rules\": {\n\t\t\"no-cond-assign\": 2,\n\t\t\"no-console\": 1,\n\t\t\"no-const-assign\": 2,\n\t\t\"no-class-assign\": 2,\n\t\t\"no-this-before-super\": 2,\n\t\t\"no-unused-vars\": 1,\n\t\t\"no-var\": 2,\n\t\t\"object-shorthand\": [2, \"always\"]\n\t}\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "*.js eol=lf\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!--\n\nThanks for raising an issue! To help us help you, if you've found a bug please consider the following:\n\n* If you can demonstrate the bug using JSBin: https://goo.gl/6b4OeX — please do.\n* If that's not possible, perhaps because your bug involves plugins, we recommend creating a small repo that illustrates the problem.\n\nAnd please, search existing issues before creating a new one.\n\n-->\n\n### Environment\n\n* Operating System:\n* Browser Version:\n* ScrollReveal Version:\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\n\nThank you for creating a pull request. Before submitting, please note the following:\n\n* If your pull request implements a new feature, please raise an issue to discuss it before sending code.\n* This message body should clearly illustrate what problems it solves.\n* If there are related issues, remember to reference them.\n* Ideally, include a test that fails without this PR but passes with it. PRs will only be merged once they pass CI.\n\n-->\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.ignore/\n.vscode/\nnode_modules/\nyarn.lock\npackage-lock.json\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\ndist: trusty\nnode_js:\n  - '9'\naddons:\n  chrome: stable\n  hosts: localsauce\nsudo: required\nbefore_script:\n  - 'sudo chown root /opt/google/chrome/chrome-sandbox'\n  - 'sudo chmod 4755 /opt/google/chrome/chrome-sandbox'\nafter_success:\n  - npm run coverage\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\n## [4.0.9] - 2021-03-04\n\n### Fixed\n\n- Styles applied using CSSOM don't drop `:` characters.\n\n## [4.0.8] - 2021-03-02\n\n### Fixed\n\n- Avoid Content Security Policy (CSP) violations. [@lambdacasserole](https://github.com/lambdacasserole) [#431](https://github.com/jlmakes/scrollreveal/pull/431)\n\n## [4.0.7] - 2020-07-15\n\n### Fixed\n\n- Ensure element geometry exists. [#437](https://github.com/jlmakes/scrollreveal/issues/437)\n\n## [4.0.6] - 2020-03-15\n\n### Fixed\n\n- Default transition values of `none` are now correctly ignored. [#231](https://github.com/jlmakes/scrollreveal/issues/231)\n\n### Fixed\n\n## [4.0.5] - 2018-10-20\n\n### Fixed\n\n- Calling `reveal()` on the same `target` breaking animation. [#468](https://github.com/jlmakes/scrollreveal/issues/468)\n\n## [4.0.4] - 2018-09-22\n\n### Fixed\n\n- Malformed `package.json`\n\n## [4.0.3] - 2018-09-21\n\n### Fixed\n\n– `options.cleanup` is now correctly set to `false` by default. [#457](https://github.com/jlmakes/scrollreveal/issues/457)\n\n## [4.0.2] - 2018-09-11\n\n### Fixed\n\n- Null property assignment regression in mount function. [#456](https://github.com/jlmakes/scrollreveal/issues/456)\n\n## [4.0.1] - 2018-09-09\n\n### Fixed\n\n- Noop instances were not correctly unmounting from the DOM. [#455](https://github.com/jlmakes/scrollreveal/issues/455)\n- Readme links to pricing page no longer 404.\n\n## [4.0.0] - 2018-08-06\n\n### Added\n\n- ScrollReveal can be enabled/disabled on desktops using `options.desktop`.\n- The class `sr` is added to `<html>` during instantiation when supported. [#294](https://github.com/jlmakes/scrollreveal/issues/294)\n- `height: 100%` is added to `<body>` during instantiation when supported. [#298](https://github.com/jlmakes/scrollreveal/issues/298)\n- Unused containers are removed from the store, and their event listeners destroyed.\n- ScrollReveal skips generating opacity styles when `options.opacity` is set to `null`.\n- ScrollReveal retains element CSS transformations. [#251](https://github.comjlmakes/scrollreveal/issues/251)\n- New `options.cleanup` toggles whether generated styles are removed upon reveal completion (when `options.reset` is `false`). [#292](https://github.comjlmakes/scrollreveal/issues/292)\n- ScrollReveal tracks scroll direction as container store data. [#384](https://github.com/jlmakes/scrollreveal/issues/384)\n- New `clean()` method removes specific generated styles and event listeners. [#227](https://github.com/jlmakes/scrollreveal/issues/227)\n- New `destroy()` method removes all generated styles and event listeners. [#227](https://github.com/jlmakes/scrollreveal/issues/227)\n- New `debug` static property toggles error messages in console. [#351](https://github.com/jlmakes/scrollreveal/issues/351)\n- Instance methods now accept native arrays of HTML elements.\n\n### Changed\n\n- **Breaking:** The `reveal()` method no longer accepts an `interval` parameter. Instead, sequence intervals are now defined with `options.interval`.\n- **Breaking:** The instance method `isSupported()` is now static.\n- **Breaking:** `options.distance` supports only `em` `px` and `%` values.\n- **Breaking:** ScrollReveal methods are no longer chainable.\n- **Breaking:** ScrollReveal requires a commercial license, unless for [GPL-3.0](https://opensource.org/licenses/GPL-3.0) compatible open source projects.\n- Elements in a reveal sequence are no longer grouped, and reveal progressively when visible.\n- ScrollReveal uses a single `matrix3d()` property, with the correct prefix and only when necessary. [#292](https://github.com/jlmakes/scrollreveal/issues/292)\n- ScrollReveal returns a non-operational instance when instantiated in unsupported browsers.\n- ScrollReveal `version` is now a read-only instance property.\n- ScrollReveal methods are now bound read-only instance properties.\n- `options.viewFactor` clamps values outside of `0.0` to `1.0`.\n- ScrollReveal constructor now returns a singleton.\n\n### Fixed\n\n- The `requestAnimationFrame` polyfill now reliably throttles callback invocations.\n\n## [3.3.6] - 2017-06-23\n\n### Fixed\n\n- Element visibility now checks left and right boundaries correctly. [#352](https://github.com/jlmakes/scrollreveal/issues/352)\n- Library version instance property is again accurate.\n\n## [3.3.5] - 2017-04-05\n\n### Fixed\n\n- Patched to ensure version 3 is the default NPM package.\n\n## [3.3.4] - 2017-02-18\n\n### Fixed\n\n- Update stale CDN link in README.\n\n### Changed\n\n- Add deprecation warnings to README.\n\n## [3.3.3] - 2017-02-18\n\n### Fixed\n\n- Fix error when using Bower and Wordpress due to missing semi-colon. [#278](https://github.com/jlmakes/scrollreveal/issues/278)\n\n## [3.3.2] - 2016-10-02\n\n### Changed\n\n- Updated Starting Defaults section in README. [#273](https://github.comjlmakes/scrollreveal/issues/273)\n\n### Fixed\n\n- Using a selector to define a default container during instantiation now works. [#289](https://github.com/jlmakes/scrollreveal/issues/289)\n\n## [3.3.1] - 2016-07-22\n\n### Fixed\n\n- Instance variable `version` updated with correct library version.\n\n## [3.3.0] - 2016-07-22\n\n### Added\n\n- New callback `beforeReveal(el)`. [#273](https://github.comjlmakes/scrollreveal/issues/273)\n- New callback `beforeReset(el)`. [#273](https://github.com/jlmakes/scrollreveal/issues/273)\n\n## [3.2.0] - 2016-07-08\n\n### Added\n\n- New `isNodeList()` method added to `Tools`.\n- New `version` instance variable contains library version.\n- HTML Collections are now supported as the first argument in `reveal()`. [#246](https://github.com/jlmakes/scrollreveal/issues/246)\n- Added fallback for `requestAnimationFrame`. [#267](https://github.comjlmakes/scrollreveal/issues/267)\n\n### Changed\n\n- Updated Starting Defaults section in README.\n\n### Fixed\n\n- Calling `reveal()` multiple times on an element with `config.origin` as `top` or `left` no longer produces invalid CSS. [#270](https://github.com/jlmakes/scrollreveal/issues/270)\n- Refactored AMD/CommonJS module wrapper to work with Codekit. [#253](https://github.com/jlmakes/scrollreveal/issues/253)\n\n## [3.1.5] - 2016-07-06\n\n### Fixed\n\n- `sync()` method now properly supports sequences.\n\n## [3.1.4] - 2016-03-28\n\n### Changed\n\n- Added `console.log` calls back to non-minified distribution. [#235](https://github.com/jlmakes/scrollreveal/issues/235)\n\n## [3.1.3] - 2016-03-28\n\n### Removed\n\n- Removed `console.log` calls from distribution. [#235](https://github.comjlmakes/scrollreveal/issues/235)\n\n## [3.1.2] - 2016-03-23\n\n### Fixed\n\n- Removed stray quotation mark in `reveal()` error message.\n\n## [3.1.1] - 2016-03-08\n\n### Fixed\n\n- `config.reset` now works properly with sequences. [#241](https://github.comjlmakes/scrollreveal/issues/241)\n\n## [3.1.0] - 2016-03-07\n\n### Added\n\n- New `isNode()` method added to `Tools`.\n- HTML elements are now supported as the first argument in `reveal()`.\n- Selector strings assigned to `config.container` are now supported.\n- `reveal()` now accepts an `interval` as it's last argument to create sequences. [#86](https://github.com/jlmakes/scrollreveal/issues/86) [#180](https://github.com/jlmakes/scrollreveal/issues/180) [#187](https://github.comjlmakes/scrollreveal/issues/187) [#215](https://github.com/jlmakes/scrollreveal/issues/215) [#234](https://github.com/jlmakes/scrollreveal/issues/234)\n- New section on sequenced animations added to README.\n\n### Changed\n\n- Messages logged to console are now prepended with `ScrollReveal:` for clarity.\n- Revised and renamed `supported()` method to `isSupported()`.\n- Updated Custom Containers section in README with an example using a selector.\n- Updated Tips section in README.\n\n### Fixed\n\n- Added semi-colon before global IIFE to improve reliability. [#228](https://github.com/jlmakes/scrollreveal/issues/228)\n- The existence of `console.log` is now confirmed for IE9. [#230](https://github.com/jlmakes/scrollreveal/issues/230)\n- Typos, indentation and semicolons corrected in README.\n\n## [3.0.9] - 2016-01-14\n\n### Changed\n\n- Updated example site links in the README.\n\n### Fixed\n\n- Fixed operator mismatch inside `supported()`. [#220](https://github.comjlmakes/scrollreveal/issues/220)\n\n## [3.0.8] - 2016-01-13\n\n### Changed\n\n- Public methods now verify that ScrollReveal is supported.\n\n### Fixed\n\n- Updated Tips section in README.\n\n## [3.0.7] - 2016-01-13\n\n### Added\n\n- Added brower support information to README. [#219](https://github.comjlmakes/scrollreveal/issues/219)\n\n### Changed\n\n- `console.log` is now used instead of `console.warn`. [#215](https://github.com/jlmakes/scrollreveal/issues/215)\n- Moved `tools.isSupported` method to `ScrollReveal.prototype.supported`.\n- Updated the configuration and tips documentation in the README.\n\n### Removed\n\n- The `init()` method was removed.\n\n### Fixed\n\n- Using `config.mobile` in `reveal()` now works. [#216](https://github.comjlmakes/scrollreveal/issues/216)\n\n## [3.0.6] - 2016-01-02\n\n### Fixed\n\n- Custom default containers are now used.\n- Critical issues affecting Chrome on iOS were (finally) solved. [#196](https://github.com/jlmakes/scrollreveal/issues/196)\n- Revisited `3.0.4` changes to chaining `reveal()` calls. [#212](https://github.com/jlmakes/scrollreveal/issues/212)\n\n## [3.0.5] - 2015-12-30\n\n### Fixed\n\n- Fixed compatibility issues with Webpack. [#209](https://github.comjlmakes/scrollreveal/issues/209)\n\n## [3.0.4] - 2015-12-30\n\n### Fixed\n\n- Squashed Webkit browser bugs due to syntax errors. [#208](https://github.comjlmakes/scrollreveal/issues/208)\n- Chaining `reveal()` calls no longer prematurely initialize animation.\n- Cleaned up README typos, and stale reference to `config.wait`.\n\n## [3.0.3] - 2015-12-22\n\n### Changed\n\n- `reveal()` and `sync()` now return the ScrollReveal instance even on failure. [#198](https://github.com/jlmakes/scrollreveal/issues/198)\n\n## [3.0.2] - 2015-12-22\n\n### Added\n\n- Added `bower.json` to release package. [#199](https://github.comjlmakes/scrollreveal/issues/199)\n\n### Fixed\n\n- Preexisting CSS transition styles are no longer destroyed. [#197](https://github.com/jlmakes/scrollreveal/issues/197)\n\n## [3.0.1] - 2015-12-21\n\n### Changed\n\n- Updated Getting Started section in the README.\n\n### Fixed\n\n- Hard learned NPM and Bower issues related to release management were endured.\n- Issues related to element visibility and animation behavior were addressed. [#193](https://github.com/jlmakes/scrollreveal/issues/193) [#196](https://github.comjlmakes/scrollreveal/issues/196)\n\n## [3.0.0] - 2015-12-15\n\nThis version marks a significant change in how developers use ScrollReveal, introducing a JavaScript API to replace the inline attribute parser. It's a big shift, but prioritizes maintainability and flexibility over the novelty of natural language parsing.\n\n### Added\n\n- New method `reveal()`. [#1](https://github.com/jlmakes/scrollreveal/issues/1) [#122](https://github.com/jlmakes/scrollreveal/issues/122)\n- New method `sync()`.\n- New callback `config.afterReset`.\n- Horizontal scrolling is now supported. [#184](https://github.comjlmakes/scrollreveal/issues/184)\n\n### Changed\n\n- **Breaking:** `config.enter` renamed `config.origin`.\n- **Breaking:** `config.wait` renamed `config.delay`.\n- **Breaking:** `config.delay` renamed `config.useDelay`.\n- **Breaking:** `config.over` renamed `config.duration`.\n- **Breaking:** `config.move` renamed `config.distance`.\n- **Breaking:** `config.viewport` renamed `config.container`.\n- **Breaking:** `config.vFactor` renamed `config.viewFactor`.\n- **Breaking:** `config.complete` renamed `config.afterReveal`.\n- **Breaking:** Time values are now expected in milliseconds (instead of `string`).\n- **Breaking:** `config.scale` expects value type `number` (instead of `object`).\n- **Breaking:** `config.rotation` axis values require `string` with unit type (instead of `number`).\n- **Breaking:** ScrollReveal constructor is now capitalized.\n- Reveals now resolve to element's computed opacity, instead of `1`. [#185](https://github.com/jlmakes/scrollreveal/issues/185)\n\n### Removed\n\n- ScrollReveal no longer recognizes `data-sr` attributes.\n\n### Fixed\n\n- Improved reliability of callback timers.\n\n## [2.3.2] - 2015-06-15\n\n### Changed\n\n- Updated `bower.json` syntax. [#150](https://github.com/jlmakes/scrollreveal/issues/150)\n\n## [2.3.1] - 2015-06-04\n\n### Added\n\n- Simple instantiation (without `new` keyword) is now supported. [#148](https://github.com/jlmakes/scrollreveal/issues/148)\n\n## [2.3.0] - 2015-04-25\n\n### Added\n\n- New keyword `vFactor` and alias `vF` control when an element is considered visible.\n- New keyword `opacity` controls starting opacity.\n\n### Removed\n\n- The easing keyword `hustle` was removed.\n\n## [2.2.0] - 2015-03-18\n\n### Added\n\n- New keyword `spin` controls yaw.\n- New keyword `roll` controls roll.\n- New keyword `flip` controls pitch.\n\n### Changed\n\n- Improved Basic Usage examples in README.\n\n## [2.1.0] - 2014-11-25\n\n### Added\n\n- Various tablets added to mobile device detection. [#32](https://github.comjlmakes/scrollreveal/issues/32) [#81](https://github.com/jlmakes/scrollreveal/issues/81)\n- CSS Transition support is now confirmed during instantiation. [#109](https://github.com/jlmakes/scrollreveal/issues/109)\n\n## [2.0.5] - 2014-11-23\n\n### Changed\n\n- Reverted `2.0.4` change to element animation logic. [#108](https://github.comjlmakes/scrollreveal/issues/108)\n\n## [2.0.4] - 2014-11-21\n\n### Changed\n\n- Revised how element animations are handled.\n- Reverted `2.0.3` change to element visibility logic. [#106](https://github.com/jlmakes/scrollreveal/issues/106)\n\n## [2.0.3] - 2014-11-14\n\n### Added\n\n- `data-sr` attributes are now stripped from initialized elements. [#100](https://github.com/jlmakes/scrollreveal/issues/100) @orapouso.\n- Live Reload added to development environment.\n\n### Changed\n\n- Revised how element visibility is determined.\n\n### Removed\n\n- Multiple instances sharing the same viewport element no longer throw an error. [#98](https://github.com/jlmakes/scrollreveal/issues/98) @orapouso.\n\n### Fixed\n\n- Incomplete support for `config.delay = \"onload\"` was addressed.\n- Issues related to `setTimeout`, `config.complete` and incorrect animation timing were addressed. [#96](https://github.com/jlmakes/scrollreveal/issues/96)\n\n## [2.0.2] - 2014-10-23\n\n### Added\n\n- An error is now thrown when multiple instances share the same viewport element. [#91](https://github.com/jlmakes/scrollreveal/issues/91)\n\n### Fixed\n\n- Updated NPM and Bower references with new distribution path.\n\n## [2.0.1] - 2014-10-18\n\n### Fixed\n\n- Incomplete support for `config.viewport` was addressed. [#67](https://github.com/jlmakes/scrollreveal/issues/67) [#68](https://github.comjlmakes/scrollreveal/issues/68)\n\n## [2.0.0] - 2014-10-17\n\n### Added\n\n- New keyword `scale` controls element starting size.\n- New option `config.complete` defines a callback for when reveals finish.\n- New option `config.viewport` defines custom viewports.\n- New option `config.mobile` enables/disables ScrollReveal on mobile devices.\n- New option `config.delay` controls when animations are delayed.\n\n### Changed\n\n- **BREAKING:** ScrollReveal now uses the `data-sr` instead of `data-scroll-reveal`.\n- Repository now follows [Semantic Versioning](http://semver.org/).\n\n### Removed\n\n- The `after` keyword was removed.\n\n## 0.1.3 - 2014-05-26 [YANKED]\n\n### Added\n\n- Configuration now includes starting opacity. [#33](https://github.comjlmakes/scrollreveal/issues/33) @kierzniak\n- New `data-scroll-reveal-id` attribute added to revealed DOM elements.\n\n### Changed\n\n- Scroll event handling now uses `requestAnimationFrame`. [#48](https://github.com/jlmakes/scrollreveal/issues/48) @pazguille\n- Generated styles are now stored in an object corresponding to the `data-scroll-reveal-id` attribute on each element. [#38](https://github.com/jlmakes/scrollreveal/pull/38) @georgelee1\n\n## 0.1.2 - 2014-03-13 [YANKED]\n\n### Added\n\n- Elements with `position: fixed` are now supported. [#35](https://github.comjlmakes/scrollreveal/issues/35)\n\n### Fixed\n\n- Generated styles are now more specific. [#37](https://github.comjlmakes/scrollreveal/issues/37)\n\n## 0.1.1 - 2014-03-06 [YANKED]\n\n### Fixed\n\n- Squashed bug with `enter top` and `enter left`. [#13](https://github.comjlmakes/scrollreveal/issues/13) [#31](https://github.com/jlmakes/scrollreveal/issues/31) @sherban @danycerone\n\n## 0.1.0 - 2014-03-05 [YANKED]\n\n### Added\n\n- Distribution now supports AMD/CommonJS.\n- Repository now uses Gulp.\n- Boilerplate Testline suite added to repository.\n\n### Changed\n\n- **BREAKING:** ScrollReveal now uses the `data-scroll-reveal` attribute to parse animation instructions, in place of `data-scrollReveal`.\n\n## 0.0.4 - 2014-02-28 [YANKED]\n\n### Fixed\n\n- ScrollReveal no longer destroys the existing style attribute on revealed elements, but instead, now appends the necessary animation styles to existing inline styles.\n\n## 0.0.3 - 2014-02-22 [YANKED]\n\n### Fixed\n\n- Removed unused CSS Transition/Transform prefixes for Mozilla and Opera.\n\n## 0.0.2 - 2014-02-13 [YANKED]\n\n### Added\n\n- Constructor now accepts a configuration object to customize defaults.\n- New `reset` keyword allows elements to reveal each time they enter the viewport.\n- The `move` keyword can now be replaced with with CSS easing keywords (e.g. `ease-in-out`).\n- Library documentation and code examples added to README.\n\n### Changed\n\n- ScrollReveal is no longer automatically instantiated by the `DOMContentLoaded` event.\n\n## 0.0.1 - 2014-01-22 [YANKED]\n\n### Hello World\n\n[4.0.9]: https://github.com/jlmakes/scrollreveal/compare/v4.0.8...v4.0.9\n[4.0.8]: https://github.com/jlmakes/scrollreveal/compare/v4.0.7...v4.0.8\n[4.0.7]: https://github.com/jlmakes/scrollreveal/compare/v4.0.6...v4.0.7\n[4.0.6]: https://github.com/jlmakes/scrollreveal/compare/v4.0.5...v4.0.6\n[4.0.5]: https://github.com/jlmakes/scrollreveal/compare/v4.0.4...v4.0.5\n[4.0.4]: https://github.com/jlmakes/scrollreveal/compare/v4.0.3...v4.0.4\n[4.0.3]: https://github.com/jlmakes/scrollreveal/compare/v4.0.2...v4.0.3\n[4.0.2]: https://github.com/jlmakes/scrollreveal/compare/v4.0.1...v4.0.2\n[4.0.1]: https://github.com/jlmakes/scrollreveal/compare/v4.0.0...v4.0.1\n[4.0.0]: https://github.com/jlmakes/scrollreveal/compare/v3.3.6...v4.0.0\n[3.3.6]: https://github.com/jlmakes/scrollreveal/compare/v3.3.5...v3.3.6\n[3.3.5]: https://github.com/jlmakes/scrollreveal/compare/v3.3.4...v3.3.5\n[3.3.4]: https://github.com/jlmakes/scrollreveal/compare/v3.3.3...v3.3.4\n[3.3.3]: https://github.com/jlmakes/scrollreveal/compare/v3.2.2...v3.3.3\n[3.3.2]: https://github.com/jlmakes/scrollreveal/compare/v3.3.1...v3.3.2\n[3.3.1]: https://github.com/jlmakes/scrollreveal/compare/v3.3.0...v3.3.1\n[3.3.0]: https://github.com/jlmakes/scrollreveal/compare/v3.2.0...v3.3.0\n[3.2.0]: https://github.com/jlmakes/scrollreveal/compare/v3.1.5...v3.2.0\n[3.1.5]: https://github.com/jlmakes/scrollreveal/compare/v3.1.4...v3.1.5\n[3.1.4]: https://github.com/jlmakes/scrollreveal/compare/v3.1.3...v3.1.4\n[3.1.3]: https://github.com/jlmakes/scrollreveal/compare/v3.1.2...v3.1.3\n[3.1.2]: https://github.com/jlmakes/scrollreveal/compare/v3.1.1...v3.1.2\n[3.1.1]: https://github.com/jlmakes/scrollreveal/compare/v3.1.0...v3.1.1\n[3.1.0]: https://github.com/jlmakes/scrollreveal/compare/v3.0.9...v3.1.0\n[3.0.9]: https://github.com/jlmakes/scrollreveal/compare/v3.0.8...v3.0.9\n[3.0.8]: https://github.com/jlmakes/scrollreveal/compare/v3.0.7...v3.0.8\n[3.0.7]: https://github.com/jlmakes/scrollreveal/compare/v3.0.6...v3.0.7\n[3.0.6]: https://github.com/jlmakes/scrollreveal/compare/v3.0.5...v3.0.6\n[3.0.5]: https://github.com/jlmakes/scrollreveal/compare/v3.0.4...v3.0.5\n[3.0.4]: https://github.com/jlmakes/scrollreveal/compare/v3.0.3...v3.0.4\n[3.0.3]: https://github.com/jlmakes/scrollreveal/compare/v3.0.2...v3.0.3\n[3.0.2]: https://github.com/jlmakes/scrollreveal/compare/v3.0.1...v3.0.2\n[3.0.1]: https://github.com/jlmakes/scrollreveal/compare/v3.0.0...v3.0.1\n[3.0.0]: https://github.com/jlmakes/scrollreveal/compare/v2.3.2...v3.0.0\n[2.3.2]: https://github.com/jlmakes/scrollreveal/compare/v2.3.1...v2.3.2\n[2.3.1]: https://github.com/jlmakes/scrollreveal/compare/v2.3.0...v2.3.1\n[2.3.0]: https://github.com/jlmakes/scrollreveal/compare/v2.2.0...v2.3.0\n[2.2.0]: https://github.com/jlmakes/scrollreveal/compare/v2.1.0...v2.2.0\n[2.1.0]: https://github.com/jlmakes/scrollreveal/compare/v2.0.5...v2.1.0\n[2.0.5]: https://github.com/jlmakes/scrollreveal/compare/v2.0.4...v2.0.5\n[2.0.4]: https://github.com/jlmakes/scrollreveal/compare/v2.0.3...v2.0.4\n[2.0.3]: https://github.com/jlmakes/scrollreveal/compare/v2.0.2...v2.0.3\n[2.0.2]: https://github.com/jlmakes/scrollreveal/compare/v2.0.1...v2.0.2\n[2.0.1]: https://github.com/jlmakes/scrollreveal/compare/v2.0.0...v2.0.1\n[2.0.0]: https://github.com/jlmakes/scrollreveal/tree/v2.0.0\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n\t<a href=\"https://scrollrevealjs.org\" title=\"Visit ScrollReveal home page\">\n\t\t<img src=\"https://scrollrevealjs.org/img/logomark.svg\" alt=\"ScrollReveal\" width=\"120\">\n\t</a>\n</p>\n<br>\n<p align=\"center\">\n\t<a href=\"https://scrollrevealjs.org\" title=\"Visit ScrollReveal home page\">\n\t\t<img width=\"200\" src=\"https://scrollrevealjs.org/img/scrollreveal-logotype-dark.svg\" alt=\"ScrollReveal\">\n\t</a>\n</p>\n<p align=\"center\">Animate elements as they scroll into view.</p>\n\n<p align=\"center\">\n\t<a href=\"https://travis-ci.org/jlmakes/scrollreveal\">\n\t\t<img src=\"https://img.shields.io/travis/jlmakes/scrollreveal.svg\" alt=\"Build status\">\n\t</a>\n\t<a href=\"https://www.npmjs.com/package/scrollreveal\">\n\t\t<img src=\"https://img.shields.io/npm/dm/scrollreveal.svg\" alt=\"Monthly downloads\">\n\t</a>\n\t<a href=\"https://www.npmjs.com/package/scrollreveal\">\n\t\t<img src=\"https://img.shields.io/npm/v/scrollreveal.svg\" alt=\"Version\">\n\t</a>\n\t<img src=\"https://img.shields.io/badge/min+gzip-5.7_kB-blue.svg\" alt=\"5.7 kB min+gzip\">\n\t<a href=\"https://opensource.org/licenses/GPL-3.0\">\n\t\t<img src=\"https://img.shields.io/badge/license-GPLv3-blue.svg\" alt=\"GPLv3 License\">\n\t</a>\n</p>\n\n<br>\n\n# Installation\n\n## Browser\n\nA simple and fast way to get started is to include this script on your page:\n\n```html\n<script src=\"https://unpkg.com/scrollreveal\"></script>\n```\n\nThis will create the global variable `ScrollReveal`\n\n> Be careful using this method in production. Without specifying a fixed version number, Unpkg may delay your page load while it resolves the latest version. Learn more at [unpkg.com](https://unpkg.com)\n\n## Module\n\n```bash\n$ npm install scrollreveal\n```\n\n#### CommonJS\n\n```js\nconst ScrollReveal = require('scrollreveal')\n```\n\n#### ES2015\n\n```js\nimport ScrollReveal from 'scrollreveal'\n```\n\n<br>\n\n# Usage\n\nInstallation provides us with the constructor function [`ScrollReveal()`](https://scrollrevealjs.org/api/constructor.html). Calling this function returns the ScrollReveal instance, the “brain” behind the magic.\n\n> ScrollReveal employs the singleton pattern; no matter how many times the constructor is called, it will always return the same instance. This means we can call it anywhere, worry-free.\n\nThere’s a lot we can do with this instance, but most of the time we’ll be using the [`reveal()`](https://scrollrevealjs.org/api/reveal.html) method to create animation. Fundamentally, this is how to use ScrollReveal:\n\n```html\n<h1 class=\"headline\">\n\tWidget Inc.\n</h1>\n```\n\n```js\nScrollReveal().reveal('.headline')\n```\n\n**🔎 See this demo live on [JSBin](http://jsbin.com/jufohaxonu/edit?html,output)**\n\n<br>\n\n---\n\n### The full documentation can be found at [https://scrollrevealjs.org](https://scrollrevealjs.org)\n\n> If you’re using an older version of ScrollReveal, you can find legacy documentation in the [wiki](https://github.com/jlmakes/scrollreveal/wiki)\n\n---\n\n<br>\n\n<a href=\"https://scrollrevealjs.org/pricing/\" title=\"Visit ScrollReveal pricing page\">\n\t<img align=\"right\" height=\"300\" src=\"https://scrollrevealjs.org/img/license.svg\" alt=\"Commercial License Badge\">\n</a>\n\n<br>\n\n# License\n\n**For commercial sites, themes, projects, and applications, keep your source code private/proprietary by purchasing a [Commercial License](https://scrollrevealjs.org/pricing/).**\n\nLicensed under the GNU General Public License 3.0 for compatible open source projects and non-commercial use.\n\n<br>\n\nCopyright 2023 Fisssion LLC\n"
  },
  {
    "path": "build/rollup.conf.banner.js",
    "content": "const { version } = require('../package.json')\n\nconst banner = `/*! @license ScrollReveal v${version}\n\n\tCopyright 2021 Fisssion LLC.\n\n\tLicensed under the GNU General Public License 3.0 for\n\tcompatible open source projects and non-commercial use.\n\n\tFor commercial sites, themes, projects, and applications,\n\tkeep your source code private/proprietary by purchasing\n\ta commercial license from https://scrollrevealjs.org/\n*/`\n\nexport default banner\n"
  },
  {
    "path": "build/rollup.conf.js",
    "content": "import buble from 'rollup-plugin-buble'\nimport json from 'rollup-plugin-json'\nimport pkg from '../package.json'\nimport nodeResolve from 'rollup-plugin-node-resolve'\nimport banner from './rollup.conf.banner'\n\nconst base = {\n\tinput: './src/index.js',\n\tplugins: [json(), nodeResolve(), buble()]\n}\n\nconst es = Object.assign({}, base, {\n\texternal: [...Object.keys(pkg.dependencies || {})],\n\toutput: { banner, format: 'es', file: './dist/scrollreveal.es.js' }\n})\n\nconst umd = Object.assign({}, base, {\n\toutput: {\n\t\tbanner,\n\t\tformat: 'umd',\n\t\tfile: './dist/scrollreveal.js',\n\t\tname: 'ScrollReveal'\n\t}\n})\n\nexport default [es, umd]\n"
  },
  {
    "path": "dist/scrollreveal.es.js",
    "content": "/*! @license ScrollReveal v4.0.9\n\n\tCopyright 2021 Fisssion LLC.\n\n\tLicensed under the GNU General Public License 3.0 for\n\tcompatible open source projects and non-commercial use.\n\n\tFor commercial sites, themes, projects, and applications,\n\tkeep your source code private/proprietary by purchasing\n\ta commercial license from https://scrollrevealjs.org/\n*/\nimport $ from 'tealight';\nimport { translateY, translateX, rotateX, rotateY, rotateZ, scale, parse, multiply } from 'rematrix';\nimport raf from 'miniraf';\n\nvar defaults = {\n\tdelay: 0,\n\tdistance: '0',\n\tduration: 600,\n\teasing: 'cubic-bezier(0.5, 0, 0, 1)',\n\tinterval: 0,\n\topacity: 0,\n\torigin: 'bottom',\n\trotate: {\n\t\tx: 0,\n\t\ty: 0,\n\t\tz: 0\n\t},\n\tscale: 1,\n\tcleanup: false,\n\tcontainer: document.documentElement,\n\tdesktop: true,\n\tmobile: true,\n\treset: false,\n\tuseDelay: 'always',\n\tviewFactor: 0.0,\n\tviewOffset: {\n\t\ttop: 0,\n\t\tright: 0,\n\t\tbottom: 0,\n\t\tleft: 0\n\t},\n\tafterReset: function afterReset() {},\n\tafterReveal: function afterReveal() {},\n\tbeforeReset: function beforeReset() {},\n\tbeforeReveal: function beforeReveal() {}\n};\n\nfunction failure() {\n\tdocument.documentElement.classList.remove('sr');\n\n\treturn {\n\t\tclean: function clean() {},\n\t\tdestroy: function destroy() {},\n\t\treveal: function reveal() {},\n\t\tsync: function sync() {},\n\t\tget noop() {\n\t\t\treturn true\n\t\t}\n\t}\n}\n\nfunction success() {\n\tdocument.documentElement.classList.add('sr');\n\n\tif (document.body) {\n\t\tdocument.body.style.height = '100%';\n\t} else {\n\t\tdocument.addEventListener('DOMContentLoaded', function () {\n\t\t\tdocument.body.style.height = '100%';\n\t\t});\n\t}\n}\n\nvar mount = { success: success, failure: failure };\n\nfunction isObject(x) {\n\treturn (\n\t\tx !== null &&\n\t\tx instanceof Object &&\n\t\t(x.constructor === Object ||\n\t\t\tObject.prototype.toString.call(x) === '[object Object]')\n\t)\n}\n\nfunction each(collection, callback) {\n\tif (isObject(collection)) {\n\t\tvar keys = Object.keys(collection);\n\t\treturn keys.forEach(function (key) { return callback(collection[key], key, collection); })\n\t}\n\tif (collection instanceof Array) {\n\t\treturn collection.forEach(function (item, i) { return callback(item, i, collection); })\n\t}\n\tthrow new TypeError('Expected either an array or object literal.')\n}\n\nfunction logger(message) {\n\tvar details = [], len = arguments.length - 1;\n\twhile ( len-- > 0 ) details[ len ] = arguments[ len + 1 ];\n\n\tif (this.constructor.debug && console) {\n\t\tvar report = \"%cScrollReveal: \" + message;\n\t\tdetails.forEach(function (detail) { return (report += \"\\n — \" + detail); });\n\t\tconsole.log(report, 'color: #ea654b;'); // eslint-disable-line no-console\n\t}\n}\n\nfunction rinse() {\n\tvar this$1 = this;\n\n\tvar struct = function () { return ({\n\t\tactive: [],\n\t\tstale: []\n\t}); };\n\n\tvar elementIds = struct();\n\tvar sequenceIds = struct();\n\tvar containerIds = struct();\n\n\t/**\n\t * Take stock of active element IDs.\n\t */\n\ttry {\n\t\teach($('[data-sr-id]'), function (node) {\n\t\t\tvar id = parseInt(node.getAttribute('data-sr-id'));\n\t\t\telementIds.active.push(id);\n\t\t});\n\t} catch (e) {\n\t\tthrow e\n\t}\n\t/**\n\t * Destroy stale elements.\n\t */\n\teach(this.store.elements, function (element) {\n\t\tif (elementIds.active.indexOf(element.id) === -1) {\n\t\t\telementIds.stale.push(element.id);\n\t\t}\n\t});\n\n\teach(elementIds.stale, function (staleId) { return delete this$1.store.elements[staleId]; });\n\n\t/**\n\t * Take stock of active container and sequence IDs.\n\t */\n\teach(this.store.elements, function (element) {\n\t\tif (containerIds.active.indexOf(element.containerId) === -1) {\n\t\t\tcontainerIds.active.push(element.containerId);\n\t\t}\n\t\tif (element.hasOwnProperty('sequence')) {\n\t\t\tif (sequenceIds.active.indexOf(element.sequence.id) === -1) {\n\t\t\t\tsequenceIds.active.push(element.sequence.id);\n\t\t\t}\n\t\t}\n\t});\n\n\t/**\n\t * Destroy stale containers.\n\t */\n\teach(this.store.containers, function (container) {\n\t\tif (containerIds.active.indexOf(container.id) === -1) {\n\t\t\tcontainerIds.stale.push(container.id);\n\t\t}\n\t});\n\n\teach(containerIds.stale, function (staleId) {\n\t\tvar stale = this$1.store.containers[staleId].node;\n\t\tstale.removeEventListener('scroll', this$1.delegate);\n\t\tstale.removeEventListener('resize', this$1.delegate);\n\t\tdelete this$1.store.containers[staleId];\n\t});\n\n\t/**\n\t * Destroy stale sequences.\n\t */\n\teach(this.store.sequences, function (sequence) {\n\t\tif (sequenceIds.active.indexOf(sequence.id) === -1) {\n\t\t\tsequenceIds.stale.push(sequence.id);\n\t\t}\n\t});\n\n\teach(sequenceIds.stale, function (staleId) { return delete this$1.store.sequences[staleId]; });\n}\n\nvar getPrefixedCssProp = (function () {\n\tvar properties = {};\n\tvar style = document.documentElement.style;\n\n\tfunction getPrefixedCssProperty(name, source) {\n\t\tif ( source === void 0 ) source = style;\n\n\t\tif (name && typeof name === 'string') {\n\t\t\tif (properties[name]) {\n\t\t\t\treturn properties[name]\n\t\t\t}\n\t\t\tif (typeof source[name] === 'string') {\n\t\t\t\treturn (properties[name] = name)\n\t\t\t}\n\t\t\tif (typeof source[(\"-webkit-\" + name)] === 'string') {\n\t\t\t\treturn (properties[name] = \"-webkit-\" + name)\n\t\t\t}\n\t\t\tthrow new RangeError((\"Unable to find \\\"\" + name + \"\\\" style property.\"))\n\t\t}\n\t\tthrow new TypeError('Expected a string.')\n\t}\n\n\tgetPrefixedCssProperty.clearCache = function () { return (properties = {}); };\n\n\treturn getPrefixedCssProperty\n})();\n\nfunction style(element) {\n\tvar computed = window.getComputedStyle(element.node);\n\tvar position = computed.position;\n\tvar config = element.config;\n\n\t/**\n\t * Generate inline styles\n\t */\n\tvar inline = {};\n\tvar inlineStyle = element.node.getAttribute('style') || '';\n\tvar inlineMatch = inlineStyle.match(/[\\w-]+\\s*:\\s*[^;]+\\s*/gi) || [];\n\n\tinline.computed = inlineMatch ? inlineMatch.map(function (m) { return m.trim(); }).join('; ') + ';' : '';\n\n\tinline.generated = inlineMatch.some(function (m) { return m.match(/visibility\\s?:\\s?visible/i); })\n\t\t? inline.computed\n\t\t: inlineMatch.concat( ['visibility: visible']).map(function (m) { return m.trim(); }).join('; ') + ';';\n\n\t/**\n\t * Generate opacity styles\n\t */\n\tvar computedOpacity = parseFloat(computed.opacity);\n\tvar configOpacity = !isNaN(parseFloat(config.opacity))\n\t\t? parseFloat(config.opacity)\n\t\t: parseFloat(computed.opacity);\n\n\tvar opacity = {\n\t\tcomputed: computedOpacity !== configOpacity ? (\"opacity: \" + computedOpacity + \";\") : '',\n\t\tgenerated: computedOpacity !== configOpacity ? (\"opacity: \" + configOpacity + \";\") : ''\n\t};\n\n\t/**\n\t * Generate transformation styles\n\t */\n\tvar transformations = [];\n\n\tif (parseFloat(config.distance)) {\n\t\tvar axis = config.origin === 'top' || config.origin === 'bottom' ? 'Y' : 'X';\n\n\t\t/**\n\t\t * Let’s make sure our our pixel distances are negative for top and left.\n\t\t * e.g. { origin: 'top', distance: '25px' } starts at `top: -25px` in CSS.\n\t\t */\n\t\tvar distance = config.distance;\n\t\tif (config.origin === 'top' || config.origin === 'left') {\n\t\t\tdistance = /^-/.test(distance) ? distance.substr(1) : (\"-\" + distance);\n\t\t}\n\n\t\tvar ref = distance.match(/(^-?\\d+\\.?\\d?)|(em$|px$|%$)/g);\n\t\tvar value = ref[0];\n\t\tvar unit = ref[1];\n\n\t\tswitch (unit) {\n\t\t\tcase 'em':\n\t\t\t\tdistance = parseInt(computed.fontSize) * value;\n\t\t\t\tbreak\n\t\t\tcase 'px':\n\t\t\t\tdistance = value;\n\t\t\t\tbreak\n\t\t\tcase '%':\n\t\t\t\t/**\n\t\t\t\t * Here we use `getBoundingClientRect` instead of\n\t\t\t\t * the existing data attached to `element.geometry`\n\t\t\t\t * because only the former includes any transformations\n\t\t\t\t * current applied to the element.\n\t\t\t\t *\n\t\t\t\t * If that behavior ends up being unintuitive, this\n\t\t\t\t * logic could instead utilize `element.geometry.height`\n\t\t\t\t * and `element.geoemetry.width` for the distance calculation\n\t\t\t\t */\n\t\t\t\tdistance =\n\t\t\t\t\taxis === 'Y'\n\t\t\t\t\t\t? (element.node.getBoundingClientRect().height * value) / 100\n\t\t\t\t\t\t: (element.node.getBoundingClientRect().width * value) / 100;\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\tthrow new RangeError('Unrecognized or missing distance unit.')\n\t\t}\n\n\t\tif (axis === 'Y') {\n\t\t\ttransformations.push(translateY(distance));\n\t\t} else {\n\t\t\ttransformations.push(translateX(distance));\n\t\t}\n\t}\n\n\tif (config.rotate.x) { transformations.push(rotateX(config.rotate.x)); }\n\tif (config.rotate.y) { transformations.push(rotateY(config.rotate.y)); }\n\tif (config.rotate.z) { transformations.push(rotateZ(config.rotate.z)); }\n\tif (config.scale !== 1) {\n\t\tif (config.scale === 0) {\n\t\t\t/**\n\t\t\t * The CSS Transforms matrix interpolation specification\n\t\t\t * basically disallows transitions of non-invertible\n\t\t\t * matrixes, which means browsers won't transition\n\t\t\t * elements with zero scale.\n\t\t\t *\n\t\t\t * That’s inconvenient for the API and developer\n\t\t\t * experience, so we simply nudge their value\n\t\t\t * slightly above zero; this allows browsers\n\t\t\t * to transition our element as expected.\n\t\t\t *\n\t\t\t * `0.0002` was the smallest number\n\t\t\t * that performed across browsers.\n\t\t\t */\n\t\t\ttransformations.push(scale(0.0002));\n\t\t} else {\n\t\t\ttransformations.push(scale(config.scale));\n\t\t}\n\t}\n\n\tvar transform = {};\n\tif (transformations.length) {\n\t\ttransform.property = getPrefixedCssProp('transform');\n\t\t/**\n\t\t * The default computed transform value should be one of:\n\t\t * undefined || 'none' || 'matrix()' || 'matrix3d()'\n\t\t */\n\t\ttransform.computed = {\n\t\t\traw: computed[transform.property],\n\t\t\tmatrix: parse(computed[transform.property])\n\t\t};\n\n\t\ttransformations.unshift(transform.computed.matrix);\n\t\tvar product = transformations.reduce(multiply);\n\n\t\ttransform.generated = {\n\t\t\tinitial: ((transform.property) + \": matrix3d(\" + (product.join(', ')) + \");\"),\n\t\t\tfinal: ((transform.property) + \": matrix3d(\" + (transform.computed.matrix.join(', ')) + \");\")\n\t\t};\n\t} else {\n\t\ttransform.generated = {\n\t\t\tinitial: '',\n\t\t\tfinal: ''\n\t\t};\n\t}\n\n\t/**\n\t * Generate transition styles\n\t */\n\tvar transition = {};\n\tif (opacity.generated || transform.generated.initial) {\n\t\ttransition.property = getPrefixedCssProp('transition');\n\t\ttransition.computed = computed[transition.property];\n\t\ttransition.fragments = [];\n\n\t\tvar delay = config.delay;\n\t\tvar duration = config.duration;\n\t\tvar easing = config.easing;\n\n\t\tif (opacity.generated) {\n\t\t\ttransition.fragments.push({\n\t\t\t\tdelayed: (\"opacity \" + (duration / 1000) + \"s \" + easing + \" \" + (delay / 1000) + \"s\"),\n\t\t\t\tinstant: (\"opacity \" + (duration / 1000) + \"s \" + easing + \" 0s\")\n\t\t\t});\n\t\t}\n\n\t\tif (transform.generated.initial) {\n\t\t\ttransition.fragments.push({\n\t\t\t\tdelayed: ((transform.property) + \" \" + (duration / 1000) + \"s \" + easing + \" \" + (delay / 1000) + \"s\"),\n\t\t\t\tinstant: ((transform.property) + \" \" + (duration / 1000) + \"s \" + easing + \" 0s\")\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * The default computed transition property should be undefined, or one of:\n\t\t * '' || 'none 0s ease 0s' || 'all 0s ease 0s' || 'all 0s 0s cubic-bezier()'\n\t\t */\n\t\tvar hasCustomTransition =\n\t\t\ttransition.computed && !transition.computed.match(/all 0s|none 0s/);\n\n\t\tif (hasCustomTransition) {\n\t\t\ttransition.fragments.unshift({\n\t\t\t\tdelayed: transition.computed,\n\t\t\t\tinstant: transition.computed\n\t\t\t});\n\t\t}\n\n\t\tvar composed = transition.fragments.reduce(\n\t\t\tfunction (composition, fragment, i) {\n\t\t\t\tcomposition.delayed += i === 0 ? fragment.delayed : (\", \" + (fragment.delayed));\n\t\t\t\tcomposition.instant += i === 0 ? fragment.instant : (\", \" + (fragment.instant));\n\t\t\t\treturn composition\n\t\t\t},\n\t\t\t{\n\t\t\t\tdelayed: '',\n\t\t\t\tinstant: ''\n\t\t\t}\n\t\t);\n\n\t\ttransition.generated = {\n\t\t\tdelayed: ((transition.property) + \": \" + (composed.delayed) + \";\"),\n\t\t\tinstant: ((transition.property) + \": \" + (composed.instant) + \";\")\n\t\t};\n\t} else {\n\t\ttransition.generated = {\n\t\t\tdelayed: '',\n\t\t\tinstant: ''\n\t\t};\n\t}\n\n\treturn {\n\t\tinline: inline,\n\t\topacity: opacity,\n\t\tposition: position,\n\t\ttransform: transform,\n\t\ttransition: transition\n\t}\n}\n\n/**\n * apply a CSS string to an element using the CSSOM (element.style) rather\n * than setAttribute, which may violate the content security policy.\n *\n * @param {Node}   [el]  Element to receive styles.\n * @param {string} [declaration] Styles to apply.\n */\nfunction applyStyle (el, declaration) {\n\tdeclaration.split(';').forEach(function (pair) {\n\t\tvar ref = pair.split(':');\n\t\tvar property = ref[0];\n\t\tvar value = ref.slice(1);\n\t\tif (property && value) {\n\t\t\tel.style[property.trim()] = value.join(':');\n\t\t}\n\t});\n}\n\nfunction clean(target) {\n\tvar this$1 = this;\n\n\tvar dirty;\n\ttry {\n\t\teach($(target), function (node) {\n\t\t\tvar id = node.getAttribute('data-sr-id');\n\t\t\tif (id !== null) {\n\t\t\t\tdirty = true;\n\t\t\t\tvar element = this$1.store.elements[id];\n\t\t\t\tif (element.callbackTimer) {\n\t\t\t\t\twindow.clearTimeout(element.callbackTimer.clock);\n\t\t\t\t}\n\t\t\t\tapplyStyle(element.node, element.styles.inline.generated);\n\t\t\t\tnode.removeAttribute('data-sr-id');\n\t\t\t\tdelete this$1.store.elements[id];\n\t\t\t}\n\t\t});\n\t} catch (e) {\n\t\treturn logger.call(this, 'Clean failed.', e.message)\n\t}\n\n\tif (dirty) {\n\t\ttry {\n\t\t\trinse.call(this);\n\t\t} catch (e) {\n\t\t\treturn logger.call(this, 'Clean failed.', e.message)\n\t\t}\n\t}\n}\n\nfunction destroy() {\n\tvar this$1 = this;\n\n\t/**\n\t * Remove all generated styles and element ids\n\t */\n\teach(this.store.elements, function (element) {\n\t\tapplyStyle(element.node, element.styles.inline.generated);\n\t\telement.node.removeAttribute('data-sr-id');\n\t});\n\n\t/**\n\t * Remove all event listeners.\n\t */\n\teach(this.store.containers, function (container) {\n\t\tvar target =\n\t\t\tcontainer.node === document.documentElement ? window : container.node;\n\t\ttarget.removeEventListener('scroll', this$1.delegate);\n\t\ttarget.removeEventListener('resize', this$1.delegate);\n\t});\n\n\t/**\n\t * Clear all data from the store\n\t */\n\tthis.store = {\n\t\tcontainers: {},\n\t\telements: {},\n\t\thistory: [],\n\t\tsequences: {}\n\t};\n}\n\nfunction deepAssign(target) {\n\tvar sources = [], len = arguments.length - 1;\n\twhile ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];\n\n\tif (isObject(target)) {\n\t\teach(sources, function (source) {\n\t\t\teach(source, function (data, key) {\n\t\t\t\tif (isObject(data)) {\n\t\t\t\t\tif (!target[key] || !isObject(target[key])) {\n\t\t\t\t\t\ttarget[key] = {};\n\t\t\t\t\t}\n\t\t\t\t\tdeepAssign(target[key], data);\n\t\t\t\t} else {\n\t\t\t\t\ttarget[key] = data;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\treturn target\n\t} else {\n\t\tthrow new TypeError('Target must be an object literal.')\n\t}\n}\n\nfunction isMobile(agent) {\n\tif ( agent === void 0 ) agent = navigator.userAgent;\n\n\treturn /Android|iPhone|iPad|iPod/i.test(agent)\n}\n\nvar nextUniqueId = (function () {\n\tvar uid = 0;\n\treturn function () { return uid++; }\n})();\n\nfunction initialize() {\n\tvar this$1 = this;\n\n\trinse.call(this);\n\n\teach(this.store.elements, function (element) {\n\t\tvar styles = [element.styles.inline.generated];\n\n\t\tif (element.visible) {\n\t\t\tstyles.push(element.styles.opacity.computed);\n\t\t\tstyles.push(element.styles.transform.generated.final);\n\t\t\telement.revealed = true;\n\t\t} else {\n\t\t\tstyles.push(element.styles.opacity.generated);\n\t\t\tstyles.push(element.styles.transform.generated.initial);\n\t\t\telement.revealed = false;\n\t\t}\n\n\t\tapplyStyle(element.node, styles.filter(function (s) { return s !== ''; }).join(' '));\n\t});\n\n\teach(this.store.containers, function (container) {\n\t\tvar target =\n\t\t\tcontainer.node === document.documentElement ? window : container.node;\n\t\ttarget.addEventListener('scroll', this$1.delegate);\n\t\ttarget.addEventListener('resize', this$1.delegate);\n\t});\n\n\t/**\n\t * Manually invoke delegate once to capture\n\t * element and container dimensions, container\n\t * scroll position, and trigger any valid reveals\n\t */\n\tthis.delegate();\n\n\t/**\n\t * Wipe any existing `setTimeout` now\n\t * that initialization has completed.\n\t */\n\tthis.initTimeout = null;\n}\n\nfunction animate(element, force) {\n\tif ( force === void 0 ) force = {};\n\n\tvar pristine = force.pristine || this.pristine;\n\tvar delayed =\n\t\telement.config.useDelay === 'always' ||\n\t\t(element.config.useDelay === 'onload' && pristine) ||\n\t\t(element.config.useDelay === 'once' && !element.seen);\n\n\tvar shouldReveal = element.visible && !element.revealed;\n\tvar shouldReset = !element.visible && element.revealed && element.config.reset;\n\n\tif (force.reveal || shouldReveal) {\n\t\treturn triggerReveal.call(this, element, delayed)\n\t}\n\n\tif (force.reset || shouldReset) {\n\t\treturn triggerReset.call(this, element)\n\t}\n}\n\nfunction triggerReveal(element, delayed) {\n\tvar styles = [\n\t\telement.styles.inline.generated,\n\t\telement.styles.opacity.computed,\n\t\telement.styles.transform.generated.final\n\t];\n\tif (delayed) {\n\t\tstyles.push(element.styles.transition.generated.delayed);\n\t} else {\n\t\tstyles.push(element.styles.transition.generated.instant);\n\t}\n\telement.revealed = element.seen = true;\n\tapplyStyle(element.node, styles.filter(function (s) { return s !== ''; }).join(' '));\n\tregisterCallbacks.call(this, element, delayed);\n}\n\nfunction triggerReset(element) {\n\tvar styles = [\n\t\telement.styles.inline.generated,\n\t\telement.styles.opacity.generated,\n\t\telement.styles.transform.generated.initial,\n\t\telement.styles.transition.generated.instant\n\t];\n\telement.revealed = false;\n\tapplyStyle(element.node, styles.filter(function (s) { return s !== ''; }).join(' '));\n\tregisterCallbacks.call(this, element);\n}\n\nfunction registerCallbacks(element, isDelayed) {\n\tvar this$1 = this;\n\n\tvar duration = isDelayed\n\t\t? element.config.duration + element.config.delay\n\t\t: element.config.duration;\n\n\tvar beforeCallback = element.revealed\n\t\t? element.config.beforeReveal\n\t\t: element.config.beforeReset;\n\n\tvar afterCallback = element.revealed\n\t\t? element.config.afterReveal\n\t\t: element.config.afterReset;\n\n\tvar elapsed = 0;\n\tif (element.callbackTimer) {\n\t\telapsed = Date.now() - element.callbackTimer.start;\n\t\twindow.clearTimeout(element.callbackTimer.clock);\n\t}\n\n\tbeforeCallback(element.node);\n\n\telement.callbackTimer = {\n\t\tstart: Date.now(),\n\t\tclock: window.setTimeout(function () {\n\t\t\tafterCallback(element.node);\n\t\t\telement.callbackTimer = null;\n\t\t\tif (element.revealed && !element.config.reset && element.config.cleanup) {\n\t\t\t\tclean.call(this$1, element.node);\n\t\t\t}\n\t\t}, duration - elapsed)\n\t};\n}\n\nfunction sequence(element, pristine) {\n\tif ( pristine === void 0 ) pristine = this.pristine;\n\n\t/**\n\t * We first check if the element should reset.\n\t */\n\tif (!element.visible && element.revealed && element.config.reset) {\n\t\treturn animate.call(this, element, { reset: true })\n\t}\n\n\tvar seq = this.store.sequences[element.sequence.id];\n\tvar i = element.sequence.index;\n\n\tif (seq) {\n\t\tvar visible = new SequenceModel(seq, 'visible', this.store);\n\t\tvar revealed = new SequenceModel(seq, 'revealed', this.store);\n\n\t\tseq.models = { visible: visible, revealed: revealed };\n\n\t\t/**\n\t\t * If the sequence has no revealed members,\n\t\t * then we reveal the first visible element\n\t\t * within that sequence.\n\t\t *\n\t\t * The sequence then cues a recursive call\n\t\t * in both directions.\n\t\t */\n\t\tif (!revealed.body.length) {\n\t\t\tvar nextId = seq.members[visible.body[0]];\n\t\t\tvar nextElement = this.store.elements[nextId];\n\n\t\t\tif (nextElement) {\n\t\t\t\tcue.call(this, seq, visible.body[0], -1, pristine);\n\t\t\t\tcue.call(this, seq, visible.body[0], +1, pristine);\n\t\t\t\treturn animate.call(this, nextElement, { reveal: true, pristine: pristine })\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * If our element isn’t resetting, we check the\n\t\t * element sequence index against the head, and\n\t\t * then the foot of the sequence.\n\t\t */\n\t\tif (\n\t\t\t!seq.blocked.head &&\n\t\t\ti === [].concat( revealed.head ).pop() &&\n\t\t\ti >= [].concat( visible.body ).shift()\n\t\t) {\n\t\t\tcue.call(this, seq, i, -1, pristine);\n\t\t\treturn animate.call(this, element, { reveal: true, pristine: pristine })\n\t\t}\n\n\t\tif (\n\t\t\t!seq.blocked.foot &&\n\t\t\ti === [].concat( revealed.foot ).shift() &&\n\t\t\ti <= [].concat( visible.body ).pop()\n\t\t) {\n\t\t\tcue.call(this, seq, i, +1, pristine);\n\t\t\treturn animate.call(this, element, { reveal: true, pristine: pristine })\n\t\t}\n\t}\n}\n\nfunction Sequence(interval) {\n\tvar i = Math.abs(interval);\n\tif (!isNaN(i)) {\n\t\tthis.id = nextUniqueId();\n\t\tthis.interval = Math.max(i, 16);\n\t\tthis.members = [];\n\t\tthis.models = {};\n\t\tthis.blocked = {\n\t\t\thead: false,\n\t\t\tfoot: false\n\t\t};\n\t} else {\n\t\tthrow new RangeError('Invalid sequence interval.')\n\t}\n}\n\nfunction SequenceModel(seq, prop, store) {\n\tvar this$1 = this;\n\n\tthis.head = [];\n\tthis.body = [];\n\tthis.foot = [];\n\n\teach(seq.members, function (id, index) {\n\t\tvar element = store.elements[id];\n\t\tif (element && element[prop]) {\n\t\t\tthis$1.body.push(index);\n\t\t}\n\t});\n\n\tif (this.body.length) {\n\t\teach(seq.members, function (id, index) {\n\t\t\tvar element = store.elements[id];\n\t\t\tif (element && !element[prop]) {\n\t\t\t\tif (index < this$1.body[0]) {\n\t\t\t\t\tthis$1.head.push(index);\n\t\t\t\t} else {\n\t\t\t\t\tthis$1.foot.push(index);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n}\n\nfunction cue(seq, i, direction, pristine) {\n\tvar this$1 = this;\n\n\tvar blocked = ['head', null, 'foot'][1 + direction];\n\tvar nextId = seq.members[i + direction];\n\tvar nextElement = this.store.elements[nextId];\n\n\tseq.blocked[blocked] = true;\n\n\tsetTimeout(function () {\n\t\tseq.blocked[blocked] = false;\n\t\tif (nextElement) {\n\t\t\tsequence.call(this$1, nextElement, pristine);\n\t\t}\n\t}, seq.interval);\n}\n\nfunction reveal(target, options, syncing) {\n\tvar this$1 = this;\n\tif ( options === void 0 ) options = {};\n\tif ( syncing === void 0 ) syncing = false;\n\n\tvar containerBuffer = [];\n\tvar sequence$$1;\n\tvar interval = options.interval || defaults.interval;\n\n\ttry {\n\t\tif (interval) {\n\t\t\tsequence$$1 = new Sequence(interval);\n\t\t}\n\n\t\tvar nodes = $(target);\n\t\tif (!nodes.length) {\n\t\t\tthrow new Error('Invalid reveal target.')\n\t\t}\n\n\t\tvar elements = nodes.reduce(function (elementBuffer, elementNode) {\n\t\t\tvar element = {};\n\t\t\tvar existingId = elementNode.getAttribute('data-sr-id');\n\n\t\t\tif (existingId) {\n\t\t\t\tdeepAssign(element, this$1.store.elements[existingId]);\n\n\t\t\t\t/**\n\t\t\t\t * In order to prevent previously generated styles\n\t\t\t\t * from throwing off the new styles, the style tag\n\t\t\t\t * has to be reverted to its pre-reveal state.\n\t\t\t\t */\n\t\t\t\tapplyStyle(element.node, element.styles.inline.computed);\n\t\t\t} else {\n\t\t\t\telement.id = nextUniqueId();\n\t\t\t\telement.node = elementNode;\n\t\t\t\telement.seen = false;\n\t\t\t\telement.revealed = false;\n\t\t\t\telement.visible = false;\n\t\t\t}\n\n\t\t\tvar config = deepAssign({}, element.config || this$1.defaults, options);\n\n\t\t\tif ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) {\n\t\t\t\tif (existingId) {\n\t\t\t\t\tclean.call(this$1, element);\n\t\t\t\t}\n\t\t\t\treturn elementBuffer // skip elements that are disabled\n\t\t\t}\n\n\t\t\tvar containerNode = $(config.container)[0];\n\t\t\tif (!containerNode) {\n\t\t\t\tthrow new Error('Invalid container.')\n\t\t\t}\n\t\t\tif (!containerNode.contains(elementNode)) {\n\t\t\t\treturn elementBuffer // skip elements found outside the container\n\t\t\t}\n\n\t\t\tvar containerId;\n\t\t\t{\n\t\t\t\tcontainerId = getContainerId(\n\t\t\t\t\tcontainerNode,\n\t\t\t\t\tcontainerBuffer,\n\t\t\t\t\tthis$1.store.containers\n\t\t\t\t);\n\t\t\t\tif (containerId === null) {\n\t\t\t\t\tcontainerId = nextUniqueId();\n\t\t\t\t\tcontainerBuffer.push({ id: containerId, node: containerNode });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\telement.config = config;\n\t\t\telement.containerId = containerId;\n\t\t\telement.styles = style(element);\n\n\t\t\tif (sequence$$1) {\n\t\t\t\telement.sequence = {\n\t\t\t\t\tid: sequence$$1.id,\n\t\t\t\t\tindex: sequence$$1.members.length\n\t\t\t\t};\n\t\t\t\tsequence$$1.members.push(element.id);\n\t\t\t}\n\n\t\t\telementBuffer.push(element);\n\t\t\treturn elementBuffer\n\t\t}, []);\n\n\t\t/**\n\t\t * Modifying the DOM via setAttribute needs to be handled\n\t\t * separately from reading computed styles in the map above\n\t\t * for the browser to batch DOM changes (limiting reflows)\n\t\t */\n\t\teach(elements, function (element) {\n\t\t\tthis$1.store.elements[element.id] = element;\n\t\t\telement.node.setAttribute('data-sr-id', element.id);\n\t\t});\n\t} catch (e) {\n\t\treturn logger.call(this, 'Reveal failed.', e.message)\n\t}\n\n\t/**\n\t * Now that element set-up is complete...\n\t * Let’s commit any container and sequence data we have to the store.\n\t */\n\teach(containerBuffer, function (container) {\n\t\tthis$1.store.containers[container.id] = {\n\t\t\tid: container.id,\n\t\t\tnode: container.node\n\t\t};\n\t});\n\tif (sequence$$1) {\n\t\tthis.store.sequences[sequence$$1.id] = sequence$$1;\n\t}\n\n\t/**\n\t * If reveal wasn't invoked by sync, we want to\n\t * make sure to add this call to the history.\n\t */\n\tif (syncing !== true) {\n\t\tthis.store.history.push({ target: target, options: options });\n\n\t\t/**\n\t\t * Push initialization to the event queue, giving\n\t\t * multiple reveal calls time to be interpreted.\n\t\t */\n\t\tif (this.initTimeout) {\n\t\t\twindow.clearTimeout(this.initTimeout);\n\t\t}\n\t\tthis.initTimeout = window.setTimeout(initialize.bind(this), 0);\n\t}\n}\n\nfunction getContainerId(node) {\n\tvar collections = [], len = arguments.length - 1;\n\twhile ( len-- > 0 ) collections[ len ] = arguments[ len + 1 ];\n\n\tvar id = null;\n\teach(collections, function (collection) {\n\t\teach(collection, function (container) {\n\t\t\tif (id === null && container.node === node) {\n\t\t\t\tid = container.id;\n\t\t\t}\n\t\t});\n\t});\n\treturn id\n}\n\n/**\n * Re-runs the reveal method for each record stored in history,\n * for capturing new content asynchronously loaded into the DOM.\n */\nfunction sync() {\n\tvar this$1 = this;\n\n\teach(this.store.history, function (record) {\n\t\treveal.call(this$1, record.target, record.options, true);\n\t});\n\n\tinitialize.call(this);\n}\n\nvar polyfill = function (x) { return (x > 0) - (x < 0) || +x; };\nvar mathSign = Math.sign || polyfill;\n\nfunction getGeometry(target, isContainer) {\n\t/**\n\t * We want to ignore padding and scrollbars for container elements.\n\t * More information here: https://goo.gl/vOZpbz\n\t */\n\tvar height = isContainer ? target.node.clientHeight : target.node.offsetHeight;\n\tvar width = isContainer ? target.node.clientWidth : target.node.offsetWidth;\n\n\tvar offsetTop = 0;\n\tvar offsetLeft = 0;\n\tvar node = target.node;\n\n\tdo {\n\t\tif (!isNaN(node.offsetTop)) {\n\t\t\toffsetTop += node.offsetTop;\n\t\t}\n\t\tif (!isNaN(node.offsetLeft)) {\n\t\t\toffsetLeft += node.offsetLeft;\n\t\t}\n\t\tnode = node.offsetParent;\n\t} while (node)\n\n\treturn {\n\t\tbounds: {\n\t\t\ttop: offsetTop,\n\t\t\tright: offsetLeft + width,\n\t\t\tbottom: offsetTop + height,\n\t\t\tleft: offsetLeft\n\t\t},\n\t\theight: height,\n\t\twidth: width\n\t}\n}\n\nfunction getScrolled(container) {\n\tvar top, left;\n\tif (container.node === document.documentElement) {\n\t\ttop = window.pageYOffset;\n\t\tleft = window.pageXOffset;\n\t} else {\n\t\ttop = container.node.scrollTop;\n\t\tleft = container.node.scrollLeft;\n\t}\n\treturn { top: top, left: left }\n}\n\nfunction isElementVisible(element) {\n\tif ( element === void 0 ) element = {};\n\n\tvar container = this.store.containers[element.containerId];\n\tif (!container) { return }\n\n\tvar viewFactor = Math.max(0, Math.min(1, element.config.viewFactor));\n\tvar viewOffset = element.config.viewOffset;\n\n\tvar elementBounds = {\n\t\ttop: element.geometry.bounds.top + element.geometry.height * viewFactor,\n\t\tright: element.geometry.bounds.right - element.geometry.width * viewFactor,\n\t\tbottom: element.geometry.bounds.bottom - element.geometry.height * viewFactor,\n\t\tleft: element.geometry.bounds.left + element.geometry.width * viewFactor\n\t};\n\n\tvar containerBounds = {\n\t\ttop: container.geometry.bounds.top + container.scroll.top + viewOffset.top,\n\t\tright: container.geometry.bounds.right + container.scroll.left - viewOffset.right,\n\t\tbottom:\n\t\t\tcontainer.geometry.bounds.bottom + container.scroll.top - viewOffset.bottom,\n\t\tleft: container.geometry.bounds.left + container.scroll.left + viewOffset.left\n\t};\n\n\treturn (\n\t\t(elementBounds.top < containerBounds.bottom &&\n\t\t\telementBounds.right > containerBounds.left &&\n\t\t\telementBounds.bottom > containerBounds.top &&\n\t\t\telementBounds.left < containerBounds.right) ||\n\t\telement.styles.position === 'fixed'\n\t)\n}\n\nfunction delegate(\n\tevent,\n\telements\n) {\n\tvar this$1 = this;\n\tif ( event === void 0 ) event = { type: 'init' };\n\tif ( elements === void 0 ) elements = this.store.elements;\n\n\traf(function () {\n\t\tvar stale = event.type === 'init' || event.type === 'resize';\n\n\t\teach(this$1.store.containers, function (container) {\n\t\t\tif (stale) {\n\t\t\t\tcontainer.geometry = getGeometry.call(this$1, container, true);\n\t\t\t}\n\t\t\tvar scroll = getScrolled.call(this$1, container);\n\t\t\tif (container.scroll) {\n\t\t\t\tcontainer.direction = {\n\t\t\t\t\tx: mathSign(scroll.left - container.scroll.left),\n\t\t\t\t\ty: mathSign(scroll.top - container.scroll.top)\n\t\t\t\t};\n\t\t\t}\n\t\t\tcontainer.scroll = scroll;\n\t\t});\n\n\t\t/**\n\t\t * Due to how the sequencer is implemented, it’s\n\t\t * important that we update the state of all\n\t\t * elements, before any animation logic is\n\t\t * evaluated (in the second loop below).\n\t\t */\n\t\teach(elements, function (element) {\n\t\t\tif (stale || element.geometry === undefined) {\n\t\t\t\telement.geometry = getGeometry.call(this$1, element);\n\t\t\t}\n\t\t\telement.visible = isElementVisible.call(this$1, element);\n\t\t});\n\n\t\teach(elements, function (element) {\n\t\t\tif (element.sequence) {\n\t\t\t\tsequence.call(this$1, element);\n\t\t\t} else {\n\t\t\t\tanimate.call(this$1, element);\n\t\t\t}\n\t\t});\n\n\t\tthis$1.pristine = false;\n\t});\n}\n\nfunction isTransformSupported() {\n\tvar style = document.documentElement.style;\n\treturn 'transform' in style || 'WebkitTransform' in style\n}\n\nfunction isTransitionSupported() {\n\tvar style = document.documentElement.style;\n\treturn 'transition' in style || 'WebkitTransition' in style\n}\n\nvar version = \"4.0.9\";\n\nvar boundDelegate;\nvar boundDestroy;\nvar boundReveal;\nvar boundClean;\nvar boundSync;\nvar config;\nvar debug;\nvar instance;\n\nfunction ScrollReveal(options) {\n\tif ( options === void 0 ) options = {};\n\n\tvar invokedWithoutNew =\n\t\ttypeof this === 'undefined' ||\n\t\tObject.getPrototypeOf(this) !== ScrollReveal.prototype;\n\n\tif (invokedWithoutNew) {\n\t\treturn new ScrollReveal(options)\n\t}\n\n\tif (!ScrollReveal.isSupported()) {\n\t\tlogger.call(this, 'Instantiation failed.', 'This browser is not supported.');\n\t\treturn mount.failure()\n\t}\n\n\tvar buffer;\n\ttry {\n\t\tbuffer = config\n\t\t\t? deepAssign({}, config, options)\n\t\t\t: deepAssign({}, defaults, options);\n\t} catch (e) {\n\t\tlogger.call(this, 'Invalid configuration.', e.message);\n\t\treturn mount.failure()\n\t}\n\n\ttry {\n\t\tvar container = $(buffer.container)[0];\n\t\tif (!container) {\n\t\t\tthrow new Error('Invalid container.')\n\t\t}\n\t} catch (e) {\n\t\tlogger.call(this, e.message);\n\t\treturn mount.failure()\n\t}\n\n\tconfig = buffer;\n\n\tif ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) {\n\t\tlogger.call(\n\t\t\tthis,\n\t\t\t'This device is disabled.',\n\t\t\t(\"desktop: \" + (config.desktop)),\n\t\t\t(\"mobile: \" + (config.mobile))\n\t\t);\n\t\treturn mount.failure()\n\t}\n\n\tmount.success();\n\n\tthis.store = {\n\t\tcontainers: {},\n\t\telements: {},\n\t\thistory: [],\n\t\tsequences: {}\n\t};\n\n\tthis.pristine = true;\n\n\tboundDelegate = boundDelegate || delegate.bind(this);\n\tboundDestroy = boundDestroy || destroy.bind(this);\n\tboundReveal = boundReveal || reveal.bind(this);\n\tboundClean = boundClean || clean.bind(this);\n\tboundSync = boundSync || sync.bind(this);\n\n\tObject.defineProperty(this, 'delegate', { get: function () { return boundDelegate; } });\n\tObject.defineProperty(this, 'destroy', { get: function () { return boundDestroy; } });\n\tObject.defineProperty(this, 'reveal', { get: function () { return boundReveal; } });\n\tObject.defineProperty(this, 'clean', { get: function () { return boundClean; } });\n\tObject.defineProperty(this, 'sync', { get: function () { return boundSync; } });\n\n\tObject.defineProperty(this, 'defaults', { get: function () { return config; } });\n\tObject.defineProperty(this, 'version', { get: function () { return version; } });\n\tObject.defineProperty(this, 'noop', { get: function () { return false; } });\n\n\treturn instance ? instance : (instance = this)\n}\n\nScrollReveal.isSupported = function () { return isTransformSupported() && isTransitionSupported(); };\n\nObject.defineProperty(ScrollReveal, 'debug', {\n\tget: function () { return debug || false; },\n\tset: function (value) { return (debug = typeof value === 'boolean' ? value : debug); }\n});\n\nScrollReveal();\n\nexport default ScrollReveal;\n"
  },
  {
    "path": "dist/scrollreveal.js",
    "content": "/*! @license ScrollReveal v4.0.9\n\n\tCopyright 2021 Fisssion LLC.\n\n\tLicensed under the GNU General Public License 3.0 for\n\tcompatible open source projects and non-commercial use.\n\n\tFor commercial sites, themes, projects, and applications,\n\tkeep your source code private/proprietary by purchasing\n\ta commercial license from https://scrollrevealjs.org/\n*/\n(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(global = global || self, global.ScrollReveal = factory());\n}(this, function () { 'use strict';\n\n\tvar defaults = {\n\t\tdelay: 0,\n\t\tdistance: '0',\n\t\tduration: 600,\n\t\teasing: 'cubic-bezier(0.5, 0, 0, 1)',\n\t\tinterval: 0,\n\t\topacity: 0,\n\t\torigin: 'bottom',\n\t\trotate: {\n\t\t\tx: 0,\n\t\t\ty: 0,\n\t\t\tz: 0\n\t\t},\n\t\tscale: 1,\n\t\tcleanup: false,\n\t\tcontainer: document.documentElement,\n\t\tdesktop: true,\n\t\tmobile: true,\n\t\treset: false,\n\t\tuseDelay: 'always',\n\t\tviewFactor: 0.0,\n\t\tviewOffset: {\n\t\t\ttop: 0,\n\t\t\tright: 0,\n\t\t\tbottom: 0,\n\t\t\tleft: 0\n\t\t},\n\t\tafterReset: function afterReset() {},\n\t\tafterReveal: function afterReveal() {},\n\t\tbeforeReset: function beforeReset() {},\n\t\tbeforeReveal: function beforeReveal() {}\n\t};\n\n\tfunction failure() {\n\t\tdocument.documentElement.classList.remove('sr');\n\n\t\treturn {\n\t\t\tclean: function clean() {},\n\t\t\tdestroy: function destroy() {},\n\t\t\treveal: function reveal() {},\n\t\t\tsync: function sync() {},\n\t\t\tget noop() {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction success() {\n\t\tdocument.documentElement.classList.add('sr');\n\n\t\tif (document.body) {\n\t\t\tdocument.body.style.height = '100%';\n\t\t} else {\n\t\t\tdocument.addEventListener('DOMContentLoaded', function () {\n\t\t\t\tdocument.body.style.height = '100%';\n\t\t\t});\n\t\t}\n\t}\n\n\tvar mount = { success: success, failure: failure };\n\n\t/*! @license is-dom-node v1.0.4\n\n\t\tCopyright 2018 Fisssion LLC.\n\n\t\tPermission is hereby granted, free of charge, to any person obtaining a copy\n\t\tof this software and associated documentation files (the \"Software\"), to deal\n\t\tin the Software without restriction, including without limitation the rights\n\t\tto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\t\tcopies of the Software, and to permit persons to whom the Software is\n\t\tfurnished to do so, subject to the following conditions:\n\n\t\tThe above copyright notice and this permission notice shall be included in all\n\t\tcopies or substantial portions of the Software.\n\n\t\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\t\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\t\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\t\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\t\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\t\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\t\tSOFTWARE.\n\n\t*/\n\tfunction isDomNode(x) {\n\t\treturn typeof window.Node === 'object'\n\t\t\t? x instanceof window.Node\n\t\t\t: x !== null &&\n\t\t\t\t\ttypeof x === 'object' &&\n\t\t\t\t\ttypeof x.nodeType === 'number' &&\n\t\t\t\t\ttypeof x.nodeName === 'string'\n\t}\n\n\t/*! @license is-dom-node-list v1.2.1\n\n\t\tCopyright 2018 Fisssion LLC.\n\n\t\tPermission is hereby granted, free of charge, to any person obtaining a copy\n\t\tof this software and associated documentation files (the \"Software\"), to deal\n\t\tin the Software without restriction, including without limitation the rights\n\t\tto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\t\tcopies of the Software, and to permit persons to whom the Software is\n\t\tfurnished to do so, subject to the following conditions:\n\n\t\tThe above copyright notice and this permission notice shall be included in all\n\t\tcopies or substantial portions of the Software.\n\n\t\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\t\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\t\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\t\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\t\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\t\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\t\tSOFTWARE.\n\n\t*/\n\n\tfunction isDomNodeList(x) {\n\t\tvar prototypeToString = Object.prototype.toString.call(x);\n\t\tvar regex = /^\\[object (HTMLCollection|NodeList|Object)\\]$/;\n\n\t\treturn typeof window.NodeList === 'object'\n\t\t\t? x instanceof window.NodeList\n\t\t\t: x !== null &&\n\t\t\t\t\ttypeof x === 'object' &&\n\t\t\t\t\ttypeof x.length === 'number' &&\n\t\t\t\t\tregex.test(prototypeToString) &&\n\t\t\t\t\t(x.length === 0 || isDomNode(x[0]))\n\t}\n\n\t/*! @license Tealight v0.3.6\n\n\t\tCopyright 2018 Fisssion LLC.\n\n\t\tPermission is hereby granted, free of charge, to any person obtaining a copy\n\t\tof this software and associated documentation files (the \"Software\"), to deal\n\t\tin the Software without restriction, including without limitation the rights\n\t\tto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\t\tcopies of the Software, and to permit persons to whom the Software is\n\t\tfurnished to do so, subject to the following conditions:\n\n\t\tThe above copyright notice and this permission notice shall be included in all\n\t\tcopies or substantial portions of the Software.\n\n\t\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\t\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\t\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\t\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\t\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\t\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\t\tSOFTWARE.\n\n\t*/\n\n\tfunction tealight(target, context) {\n\t  if ( context === void 0 ) { context = document; }\n\n\t  if (target instanceof Array) { return target.filter(isDomNode); }\n\t  if (isDomNode(target)) { return [target]; }\n\t  if (isDomNodeList(target)) { return Array.prototype.slice.call(target); }\n\t  if (typeof target === \"string\") {\n\t    try {\n\t      var query = context.querySelectorAll(target);\n\t      return Array.prototype.slice.call(query);\n\t    } catch (err) {\n\t      return [];\n\t    }\n\t  }\n\t  return [];\n\t}\n\n\tfunction isObject(x) {\n\t\treturn (\n\t\t\tx !== null &&\n\t\t\tx instanceof Object &&\n\t\t\t(x.constructor === Object ||\n\t\t\t\tObject.prototype.toString.call(x) === '[object Object]')\n\t\t)\n\t}\n\n\tfunction each(collection, callback) {\n\t\tif (isObject(collection)) {\n\t\t\tvar keys = Object.keys(collection);\n\t\t\treturn keys.forEach(function (key) { return callback(collection[key], key, collection); })\n\t\t}\n\t\tif (collection instanceof Array) {\n\t\t\treturn collection.forEach(function (item, i) { return callback(item, i, collection); })\n\t\t}\n\t\tthrow new TypeError('Expected either an array or object literal.')\n\t}\n\n\tfunction logger(message) {\n\t\tvar details = [], len = arguments.length - 1;\n\t\twhile ( len-- > 0 ) details[ len ] = arguments[ len + 1 ];\n\n\t\tif (this.constructor.debug && console) {\n\t\t\tvar report = \"%cScrollReveal: \" + message;\n\t\t\tdetails.forEach(function (detail) { return (report += \"\\n — \" + detail); });\n\t\t\tconsole.log(report, 'color: #ea654b;'); // eslint-disable-line no-console\n\t\t}\n\t}\n\n\tfunction rinse() {\n\t\tvar this$1 = this;\n\n\t\tvar struct = function () { return ({\n\t\t\tactive: [],\n\t\t\tstale: []\n\t\t}); };\n\n\t\tvar elementIds = struct();\n\t\tvar sequenceIds = struct();\n\t\tvar containerIds = struct();\n\n\t\t/**\n\t\t * Take stock of active element IDs.\n\t\t */\n\t\ttry {\n\t\t\teach(tealight('[data-sr-id]'), function (node) {\n\t\t\t\tvar id = parseInt(node.getAttribute('data-sr-id'));\n\t\t\t\telementIds.active.push(id);\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow e\n\t\t}\n\t\t/**\n\t\t * Destroy stale elements.\n\t\t */\n\t\teach(this.store.elements, function (element) {\n\t\t\tif (elementIds.active.indexOf(element.id) === -1) {\n\t\t\t\telementIds.stale.push(element.id);\n\t\t\t}\n\t\t});\n\n\t\teach(elementIds.stale, function (staleId) { return delete this$1.store.elements[staleId]; });\n\n\t\t/**\n\t\t * Take stock of active container and sequence IDs.\n\t\t */\n\t\teach(this.store.elements, function (element) {\n\t\t\tif (containerIds.active.indexOf(element.containerId) === -1) {\n\t\t\t\tcontainerIds.active.push(element.containerId);\n\t\t\t}\n\t\t\tif (element.hasOwnProperty('sequence')) {\n\t\t\t\tif (sequenceIds.active.indexOf(element.sequence.id) === -1) {\n\t\t\t\t\tsequenceIds.active.push(element.sequence.id);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t/**\n\t\t * Destroy stale containers.\n\t\t */\n\t\teach(this.store.containers, function (container) {\n\t\t\tif (containerIds.active.indexOf(container.id) === -1) {\n\t\t\t\tcontainerIds.stale.push(container.id);\n\t\t\t}\n\t\t});\n\n\t\teach(containerIds.stale, function (staleId) {\n\t\t\tvar stale = this$1.store.containers[staleId].node;\n\t\t\tstale.removeEventListener('scroll', this$1.delegate);\n\t\t\tstale.removeEventListener('resize', this$1.delegate);\n\t\t\tdelete this$1.store.containers[staleId];\n\t\t});\n\n\t\t/**\n\t\t * Destroy stale sequences.\n\t\t */\n\t\teach(this.store.sequences, function (sequence) {\n\t\t\tif (sequenceIds.active.indexOf(sequence.id) === -1) {\n\t\t\t\tsequenceIds.stale.push(sequence.id);\n\t\t\t}\n\t\t});\n\n\t\teach(sequenceIds.stale, function (staleId) { return delete this$1.store.sequences[staleId]; });\n\t}\n\n\t/*! @license Rematrix v0.3.0\n\n\t\tCopyright 2018 Julian Lloyd.\n\n\t\tPermission is hereby granted, free of charge, to any person obtaining a copy\n\t\tof this software and associated documentation files (the \"Software\"), to deal\n\t\tin the Software without restriction, including without limitation the rights\n\t\tto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\t\tcopies of the Software, and to permit persons to whom the Software is\n\t\tfurnished to do so, subject to the following conditions:\n\n\t\tThe above copyright notice and this permission notice shall be included in\n\t\tall copies or substantial portions of the Software.\n\n\t\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\t\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\t\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\t\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\t\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\t\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n\t\tTHE SOFTWARE.\n\t*/\n\t/**\n\t * @module Rematrix\n\t */\n\n\t/**\n\t * Transformation matrices in the browser come in two flavors:\n\t *\n\t *  - `matrix` using 6 values (short)\n\t *  - `matrix3d` using 16 values (long)\n\t *\n\t * This utility follows this [conversion guide](https://goo.gl/EJlUQ1)\n\t * to expand short form matrices to their equivalent long form.\n\t *\n\t * @param  {array} source - Accepts both short and long form matrices.\n\t * @return {array}\n\t */\n\tfunction format(source) {\n\t\tif (source.constructor !== Array) {\n\t\t\tthrow new TypeError('Expected array.')\n\t\t}\n\t\tif (source.length === 16) {\n\t\t\treturn source\n\t\t}\n\t\tif (source.length === 6) {\n\t\t\tvar matrix = identity();\n\t\t\tmatrix[0] = source[0];\n\t\t\tmatrix[1] = source[1];\n\t\t\tmatrix[4] = source[2];\n\t\t\tmatrix[5] = source[3];\n\t\t\tmatrix[12] = source[4];\n\t\t\tmatrix[13] = source[5];\n\t\t\treturn matrix\n\t\t}\n\t\tthrow new RangeError('Expected array with either 6 or 16 values.')\n\t}\n\n\t/**\n\t * Returns a matrix representing no transformation. The product of any matrix\n\t * multiplied by the identity matrix will be the original matrix.\n\t *\n\t * > **Tip:** Similar to how `5 * 1 === 5`, where `1` is the identity.\n\t *\n\t * @return {array}\n\t */\n\tfunction identity() {\n\t\tvar matrix = [];\n\t\tfor (var i = 0; i < 16; i++) {\n\t\t\ti % 5 == 0 ? matrix.push(1) : matrix.push(0);\n\t\t}\n\t\treturn matrix\n\t}\n\n\t/**\n\t * Returns a 4x4 matrix describing the combined transformations\n\t * of both arguments.\n\t *\n\t * > **Note:** Order is very important. For example, rotating 45°\n\t * along the Z-axis, followed by translating 500 pixels along the\n\t * Y-axis... is not the same as translating 500 pixels along the\n\t * Y-axis, followed by rotating 45° along on the Z-axis.\n\t *\n\t * @param  {array} m - Accepts both short and long form matrices.\n\t * @param  {array} x - Accepts both short and long form matrices.\n\t * @return {array}\n\t */\n\tfunction multiply(m, x) {\n\t\tvar fm = format(m);\n\t\tvar fx = format(x);\n\t\tvar product = [];\n\n\t\tfor (var i = 0; i < 4; i++) {\n\t\t\tvar row = [fm[i], fm[i + 4], fm[i + 8], fm[i + 12]];\n\t\t\tfor (var j = 0; j < 4; j++) {\n\t\t\t\tvar k = j * 4;\n\t\t\t\tvar col = [fx[k], fx[k + 1], fx[k + 2], fx[k + 3]];\n\t\t\t\tvar result =\n\t\t\t\t\trow[0] * col[0] + row[1] * col[1] + row[2] * col[2] + row[3] * col[3];\n\n\t\t\t\tproduct[i + k] = result;\n\t\t\t}\n\t\t}\n\n\t\treturn product\n\t}\n\n\t/**\n\t * Attempts to return a 4x4 matrix describing the CSS transform\n\t * matrix passed in, but will return the identity matrix as a\n\t * fallback.\n\t *\n\t * > **Tip:** This method is used to convert a CSS matrix (retrieved as a\n\t * `string` from computed styles) to its equivalent array format.\n\t *\n\t * @param  {string} source - `matrix` or `matrix3d` CSS Transform value.\n\t * @return {array}\n\t */\n\tfunction parse(source) {\n\t\tif (typeof source === 'string') {\n\t\t\tvar match = source.match(/matrix(3d)?\\(([^)]+)\\)/);\n\t\t\tif (match) {\n\t\t\t\tvar raw = match[2].split(', ').map(parseFloat);\n\t\t\t\treturn format(raw)\n\t\t\t}\n\t\t}\n\t\treturn identity()\n\t}\n\n\t/**\n\t * Returns a 4x4 matrix describing X-axis rotation.\n\t *\n\t * @param  {number} angle - Measured in degrees.\n\t * @return {array}\n\t */\n\tfunction rotateX(angle) {\n\t\tvar theta = Math.PI / 180 * angle;\n\t\tvar matrix = identity();\n\n\t\tmatrix[5] = matrix[10] = Math.cos(theta);\n\t\tmatrix[6] = matrix[9] = Math.sin(theta);\n\t\tmatrix[9] *= -1;\n\n\t\treturn matrix\n\t}\n\n\t/**\n\t * Returns a 4x4 matrix describing Y-axis rotation.\n\t *\n\t * @param  {number} angle - Measured in degrees.\n\t * @return {array}\n\t */\n\tfunction rotateY(angle) {\n\t\tvar theta = Math.PI / 180 * angle;\n\t\tvar matrix = identity();\n\n\t\tmatrix[0] = matrix[10] = Math.cos(theta);\n\t\tmatrix[2] = matrix[8] = Math.sin(theta);\n\t\tmatrix[2] *= -1;\n\n\t\treturn matrix\n\t}\n\n\t/**\n\t * Returns a 4x4 matrix describing Z-axis rotation.\n\t *\n\t * @param  {number} angle - Measured in degrees.\n\t * @return {array}\n\t */\n\tfunction rotateZ(angle) {\n\t\tvar theta = Math.PI / 180 * angle;\n\t\tvar matrix = identity();\n\n\t\tmatrix[0] = matrix[5] = Math.cos(theta);\n\t\tmatrix[1] = matrix[4] = Math.sin(theta);\n\t\tmatrix[4] *= -1;\n\n\t\treturn matrix\n\t}\n\n\t/**\n\t * Returns a 4x4 matrix describing 2D scaling. The first argument\n\t * is used for both X and Y-axis scaling, unless an optional\n\t * second argument is provided to explicitly define Y-axis scaling.\n\t *\n\t * @param  {number} scalar    - Decimal multiplier.\n\t * @param  {number} [scalarY] - Decimal multiplier.\n\t * @return {array}\n\t */\n\tfunction scale(scalar, scalarY) {\n\t\tvar matrix = identity();\n\n\t\tmatrix[0] = scalar;\n\t\tmatrix[5] = typeof scalarY === 'number' ? scalarY : scalar;\n\n\t\treturn matrix\n\t}\n\n\t/**\n\t * Returns a 4x4 matrix describing X-axis translation.\n\t *\n\t * @param  {number} distance - Measured in pixels.\n\t * @return {array}\n\t */\n\tfunction translateX(distance) {\n\t\tvar matrix = identity();\n\t\tmatrix[12] = distance;\n\t\treturn matrix\n\t}\n\n\t/**\n\t * Returns a 4x4 matrix describing Y-axis translation.\n\t *\n\t * @param  {number} distance - Measured in pixels.\n\t * @return {array}\n\t */\n\tfunction translateY(distance) {\n\t\tvar matrix = identity();\n\t\tmatrix[13] = distance;\n\t\treturn matrix\n\t}\n\n\tvar getPrefixedCssProp = (function () {\n\t\tvar properties = {};\n\t\tvar style = document.documentElement.style;\n\n\t\tfunction getPrefixedCssProperty(name, source) {\n\t\t\tif ( source === void 0 ) source = style;\n\n\t\t\tif (name && typeof name === 'string') {\n\t\t\t\tif (properties[name]) {\n\t\t\t\t\treturn properties[name]\n\t\t\t\t}\n\t\t\t\tif (typeof source[name] === 'string') {\n\t\t\t\t\treturn (properties[name] = name)\n\t\t\t\t}\n\t\t\t\tif (typeof source[(\"-webkit-\" + name)] === 'string') {\n\t\t\t\t\treturn (properties[name] = \"-webkit-\" + name)\n\t\t\t\t}\n\t\t\t\tthrow new RangeError((\"Unable to find \\\"\" + name + \"\\\" style property.\"))\n\t\t\t}\n\t\t\tthrow new TypeError('Expected a string.')\n\t\t}\n\n\t\tgetPrefixedCssProperty.clearCache = function () { return (properties = {}); };\n\n\t\treturn getPrefixedCssProperty\n\t})();\n\n\tfunction style(element) {\n\t\tvar computed = window.getComputedStyle(element.node);\n\t\tvar position = computed.position;\n\t\tvar config = element.config;\n\n\t\t/**\n\t\t * Generate inline styles\n\t\t */\n\t\tvar inline = {};\n\t\tvar inlineStyle = element.node.getAttribute('style') || '';\n\t\tvar inlineMatch = inlineStyle.match(/[\\w-]+\\s*:\\s*[^;]+\\s*/gi) || [];\n\n\t\tinline.computed = inlineMatch ? inlineMatch.map(function (m) { return m.trim(); }).join('; ') + ';' : '';\n\n\t\tinline.generated = inlineMatch.some(function (m) { return m.match(/visibility\\s?:\\s?visible/i); })\n\t\t\t? inline.computed\n\t\t\t: inlineMatch.concat( ['visibility: visible']).map(function (m) { return m.trim(); }).join('; ') + ';';\n\n\t\t/**\n\t\t * Generate opacity styles\n\t\t */\n\t\tvar computedOpacity = parseFloat(computed.opacity);\n\t\tvar configOpacity = !isNaN(parseFloat(config.opacity))\n\t\t\t? parseFloat(config.opacity)\n\t\t\t: parseFloat(computed.opacity);\n\n\t\tvar opacity = {\n\t\t\tcomputed: computedOpacity !== configOpacity ? (\"opacity: \" + computedOpacity + \";\") : '',\n\t\t\tgenerated: computedOpacity !== configOpacity ? (\"opacity: \" + configOpacity + \";\") : ''\n\t\t};\n\n\t\t/**\n\t\t * Generate transformation styles\n\t\t */\n\t\tvar transformations = [];\n\n\t\tif (parseFloat(config.distance)) {\n\t\t\tvar axis = config.origin === 'top' || config.origin === 'bottom' ? 'Y' : 'X';\n\n\t\t\t/**\n\t\t\t * Let’s make sure our our pixel distances are negative for top and left.\n\t\t\t * e.g. { origin: 'top', distance: '25px' } starts at `top: -25px` in CSS.\n\t\t\t */\n\t\t\tvar distance = config.distance;\n\t\t\tif (config.origin === 'top' || config.origin === 'left') {\n\t\t\t\tdistance = /^-/.test(distance) ? distance.substr(1) : (\"-\" + distance);\n\t\t\t}\n\n\t\t\tvar ref = distance.match(/(^-?\\d+\\.?\\d?)|(em$|px$|%$)/g);\n\t\t\tvar value = ref[0];\n\t\t\tvar unit = ref[1];\n\n\t\t\tswitch (unit) {\n\t\t\t\tcase 'em':\n\t\t\t\t\tdistance = parseInt(computed.fontSize) * value;\n\t\t\t\t\tbreak\n\t\t\t\tcase 'px':\n\t\t\t\t\tdistance = value;\n\t\t\t\t\tbreak\n\t\t\t\tcase '%':\n\t\t\t\t\t/**\n\t\t\t\t\t * Here we use `getBoundingClientRect` instead of\n\t\t\t\t\t * the existing data attached to `element.geometry`\n\t\t\t\t\t * because only the former includes any transformations\n\t\t\t\t\t * current applied to the element.\n\t\t\t\t\t *\n\t\t\t\t\t * If that behavior ends up being unintuitive, this\n\t\t\t\t\t * logic could instead utilize `element.geometry.height`\n\t\t\t\t\t * and `element.geoemetry.width` for the distance calculation\n\t\t\t\t\t */\n\t\t\t\t\tdistance =\n\t\t\t\t\t\taxis === 'Y'\n\t\t\t\t\t\t\t? (element.node.getBoundingClientRect().height * value) / 100\n\t\t\t\t\t\t\t: (element.node.getBoundingClientRect().width * value) / 100;\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new RangeError('Unrecognized or missing distance unit.')\n\t\t\t}\n\n\t\t\tif (axis === 'Y') {\n\t\t\t\ttransformations.push(translateY(distance));\n\t\t\t} else {\n\t\t\t\ttransformations.push(translateX(distance));\n\t\t\t}\n\t\t}\n\n\t\tif (config.rotate.x) { transformations.push(rotateX(config.rotate.x)); }\n\t\tif (config.rotate.y) { transformations.push(rotateY(config.rotate.y)); }\n\t\tif (config.rotate.z) { transformations.push(rotateZ(config.rotate.z)); }\n\t\tif (config.scale !== 1) {\n\t\t\tif (config.scale === 0) {\n\t\t\t\t/**\n\t\t\t\t * The CSS Transforms matrix interpolation specification\n\t\t\t\t * basically disallows transitions of non-invertible\n\t\t\t\t * matrixes, which means browsers won't transition\n\t\t\t\t * elements with zero scale.\n\t\t\t\t *\n\t\t\t\t * That’s inconvenient for the API and developer\n\t\t\t\t * experience, so we simply nudge their value\n\t\t\t\t * slightly above zero; this allows browsers\n\t\t\t\t * to transition our element as expected.\n\t\t\t\t *\n\t\t\t\t * `0.0002` was the smallest number\n\t\t\t\t * that performed across browsers.\n\t\t\t\t */\n\t\t\t\ttransformations.push(scale(0.0002));\n\t\t\t} else {\n\t\t\t\ttransformations.push(scale(config.scale));\n\t\t\t}\n\t\t}\n\n\t\tvar transform = {};\n\t\tif (transformations.length) {\n\t\t\ttransform.property = getPrefixedCssProp('transform');\n\t\t\t/**\n\t\t\t * The default computed transform value should be one of:\n\t\t\t * undefined || 'none' || 'matrix()' || 'matrix3d()'\n\t\t\t */\n\t\t\ttransform.computed = {\n\t\t\t\traw: computed[transform.property],\n\t\t\t\tmatrix: parse(computed[transform.property])\n\t\t\t};\n\n\t\t\ttransformations.unshift(transform.computed.matrix);\n\t\t\tvar product = transformations.reduce(multiply);\n\n\t\t\ttransform.generated = {\n\t\t\t\tinitial: ((transform.property) + \": matrix3d(\" + (product.join(', ')) + \");\"),\n\t\t\t\tfinal: ((transform.property) + \": matrix3d(\" + (transform.computed.matrix.join(', ')) + \");\")\n\t\t\t};\n\t\t} else {\n\t\t\ttransform.generated = {\n\t\t\t\tinitial: '',\n\t\t\t\tfinal: ''\n\t\t\t};\n\t\t}\n\n\t\t/**\n\t\t * Generate transition styles\n\t\t */\n\t\tvar transition = {};\n\t\tif (opacity.generated || transform.generated.initial) {\n\t\t\ttransition.property = getPrefixedCssProp('transition');\n\t\t\ttransition.computed = computed[transition.property];\n\t\t\ttransition.fragments = [];\n\n\t\t\tvar delay = config.delay;\n\t\t\tvar duration = config.duration;\n\t\t\tvar easing = config.easing;\n\n\t\t\tif (opacity.generated) {\n\t\t\t\ttransition.fragments.push({\n\t\t\t\t\tdelayed: (\"opacity \" + (duration / 1000) + \"s \" + easing + \" \" + (delay / 1000) + \"s\"),\n\t\t\t\t\tinstant: (\"opacity \" + (duration / 1000) + \"s \" + easing + \" 0s\")\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (transform.generated.initial) {\n\t\t\t\ttransition.fragments.push({\n\t\t\t\t\tdelayed: ((transform.property) + \" \" + (duration / 1000) + \"s \" + easing + \" \" + (delay / 1000) + \"s\"),\n\t\t\t\t\tinstant: ((transform.property) + \" \" + (duration / 1000) + \"s \" + easing + \" 0s\")\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * The default computed transition property should be undefined, or one of:\n\t\t\t * '' || 'none 0s ease 0s' || 'all 0s ease 0s' || 'all 0s 0s cubic-bezier()'\n\t\t\t */\n\t\t\tvar hasCustomTransition =\n\t\t\t\ttransition.computed && !transition.computed.match(/all 0s|none 0s/);\n\n\t\t\tif (hasCustomTransition) {\n\t\t\t\ttransition.fragments.unshift({\n\t\t\t\t\tdelayed: transition.computed,\n\t\t\t\t\tinstant: transition.computed\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvar composed = transition.fragments.reduce(\n\t\t\t\tfunction (composition, fragment, i) {\n\t\t\t\t\tcomposition.delayed += i === 0 ? fragment.delayed : (\", \" + (fragment.delayed));\n\t\t\t\t\tcomposition.instant += i === 0 ? fragment.instant : (\", \" + (fragment.instant));\n\t\t\t\t\treturn composition\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdelayed: '',\n\t\t\t\t\tinstant: ''\n\t\t\t\t}\n\t\t\t);\n\n\t\t\ttransition.generated = {\n\t\t\t\tdelayed: ((transition.property) + \": \" + (composed.delayed) + \";\"),\n\t\t\t\tinstant: ((transition.property) + \": \" + (composed.instant) + \";\")\n\t\t\t};\n\t\t} else {\n\t\t\ttransition.generated = {\n\t\t\t\tdelayed: '',\n\t\t\t\tinstant: ''\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tinline: inline,\n\t\t\topacity: opacity,\n\t\t\tposition: position,\n\t\t\ttransform: transform,\n\t\t\ttransition: transition\n\t\t}\n\t}\n\n\t/**\n\t * apply a CSS string to an element using the CSSOM (element.style) rather\n\t * than setAttribute, which may violate the content security policy.\n\t *\n\t * @param {Node}   [el]  Element to receive styles.\n\t * @param {string} [declaration] Styles to apply.\n\t */\n\tfunction applyStyle (el, declaration) {\n\t\tdeclaration.split(';').forEach(function (pair) {\n\t\t\tvar ref = pair.split(':');\n\t\t\tvar property = ref[0];\n\t\t\tvar value = ref.slice(1);\n\t\t\tif (property && value) {\n\t\t\t\tel.style[property.trim()] = value.join(':');\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction clean(target) {\n\t\tvar this$1 = this;\n\n\t\tvar dirty;\n\t\ttry {\n\t\t\teach(tealight(target), function (node) {\n\t\t\t\tvar id = node.getAttribute('data-sr-id');\n\t\t\t\tif (id !== null) {\n\t\t\t\t\tdirty = true;\n\t\t\t\t\tvar element = this$1.store.elements[id];\n\t\t\t\t\tif (element.callbackTimer) {\n\t\t\t\t\t\twindow.clearTimeout(element.callbackTimer.clock);\n\t\t\t\t\t}\n\t\t\t\t\tapplyStyle(element.node, element.styles.inline.generated);\n\t\t\t\t\tnode.removeAttribute('data-sr-id');\n\t\t\t\t\tdelete this$1.store.elements[id];\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (e) {\n\t\t\treturn logger.call(this, 'Clean failed.', e.message)\n\t\t}\n\n\t\tif (dirty) {\n\t\t\ttry {\n\t\t\t\trinse.call(this);\n\t\t\t} catch (e) {\n\t\t\t\treturn logger.call(this, 'Clean failed.', e.message)\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction destroy() {\n\t\tvar this$1 = this;\n\n\t\t/**\n\t\t * Remove all generated styles and element ids\n\t\t */\n\t\teach(this.store.elements, function (element) {\n\t\t\tapplyStyle(element.node, element.styles.inline.generated);\n\t\t\telement.node.removeAttribute('data-sr-id');\n\t\t});\n\n\t\t/**\n\t\t * Remove all event listeners.\n\t\t */\n\t\teach(this.store.containers, function (container) {\n\t\t\tvar target =\n\t\t\t\tcontainer.node === document.documentElement ? window : container.node;\n\t\t\ttarget.removeEventListener('scroll', this$1.delegate);\n\t\t\ttarget.removeEventListener('resize', this$1.delegate);\n\t\t});\n\n\t\t/**\n\t\t * Clear all data from the store\n\t\t */\n\t\tthis.store = {\n\t\t\tcontainers: {},\n\t\t\telements: {},\n\t\t\thistory: [],\n\t\t\tsequences: {}\n\t\t};\n\t}\n\n\tfunction deepAssign(target) {\n\t\tvar sources = [], len = arguments.length - 1;\n\t\twhile ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];\n\n\t\tif (isObject(target)) {\n\t\t\teach(sources, function (source) {\n\t\t\t\teach(source, function (data, key) {\n\t\t\t\t\tif (isObject(data)) {\n\t\t\t\t\t\tif (!target[key] || !isObject(target[key])) {\n\t\t\t\t\t\t\ttarget[key] = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdeepAssign(target[key], data);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttarget[key] = data;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t\treturn target\n\t\t} else {\n\t\t\tthrow new TypeError('Target must be an object literal.')\n\t\t}\n\t}\n\n\tfunction isMobile(agent) {\n\t\tif ( agent === void 0 ) agent = navigator.userAgent;\n\n\t\treturn /Android|iPhone|iPad|iPod/i.test(agent)\n\t}\n\n\tvar nextUniqueId = (function () {\n\t\tvar uid = 0;\n\t\treturn function () { return uid++; }\n\t})();\n\n\tfunction initialize() {\n\t\tvar this$1 = this;\n\n\t\trinse.call(this);\n\n\t\teach(this.store.elements, function (element) {\n\t\t\tvar styles = [element.styles.inline.generated];\n\n\t\t\tif (element.visible) {\n\t\t\t\tstyles.push(element.styles.opacity.computed);\n\t\t\t\tstyles.push(element.styles.transform.generated.final);\n\t\t\t\telement.revealed = true;\n\t\t\t} else {\n\t\t\t\tstyles.push(element.styles.opacity.generated);\n\t\t\t\tstyles.push(element.styles.transform.generated.initial);\n\t\t\t\telement.revealed = false;\n\t\t\t}\n\n\t\t\tapplyStyle(element.node, styles.filter(function (s) { return s !== ''; }).join(' '));\n\t\t});\n\n\t\teach(this.store.containers, function (container) {\n\t\t\tvar target =\n\t\t\t\tcontainer.node === document.documentElement ? window : container.node;\n\t\t\ttarget.addEventListener('scroll', this$1.delegate);\n\t\t\ttarget.addEventListener('resize', this$1.delegate);\n\t\t});\n\n\t\t/**\n\t\t * Manually invoke delegate once to capture\n\t\t * element and container dimensions, container\n\t\t * scroll position, and trigger any valid reveals\n\t\t */\n\t\tthis.delegate();\n\n\t\t/**\n\t\t * Wipe any existing `setTimeout` now\n\t\t * that initialization has completed.\n\t\t */\n\t\tthis.initTimeout = null;\n\t}\n\n\tfunction animate(element, force) {\n\t\tif ( force === void 0 ) force = {};\n\n\t\tvar pristine = force.pristine || this.pristine;\n\t\tvar delayed =\n\t\t\telement.config.useDelay === 'always' ||\n\t\t\t(element.config.useDelay === 'onload' && pristine) ||\n\t\t\t(element.config.useDelay === 'once' && !element.seen);\n\n\t\tvar shouldReveal = element.visible && !element.revealed;\n\t\tvar shouldReset = !element.visible && element.revealed && element.config.reset;\n\n\t\tif (force.reveal || shouldReveal) {\n\t\t\treturn triggerReveal.call(this, element, delayed)\n\t\t}\n\n\t\tif (force.reset || shouldReset) {\n\t\t\treturn triggerReset.call(this, element)\n\t\t}\n\t}\n\n\tfunction triggerReveal(element, delayed) {\n\t\tvar styles = [\n\t\t\telement.styles.inline.generated,\n\t\t\telement.styles.opacity.computed,\n\t\t\telement.styles.transform.generated.final\n\t\t];\n\t\tif (delayed) {\n\t\t\tstyles.push(element.styles.transition.generated.delayed);\n\t\t} else {\n\t\t\tstyles.push(element.styles.transition.generated.instant);\n\t\t}\n\t\telement.revealed = element.seen = true;\n\t\tapplyStyle(element.node, styles.filter(function (s) { return s !== ''; }).join(' '));\n\t\tregisterCallbacks.call(this, element, delayed);\n\t}\n\n\tfunction triggerReset(element) {\n\t\tvar styles = [\n\t\t\telement.styles.inline.generated,\n\t\t\telement.styles.opacity.generated,\n\t\t\telement.styles.transform.generated.initial,\n\t\t\telement.styles.transition.generated.instant\n\t\t];\n\t\telement.revealed = false;\n\t\tapplyStyle(element.node, styles.filter(function (s) { return s !== ''; }).join(' '));\n\t\tregisterCallbacks.call(this, element);\n\t}\n\n\tfunction registerCallbacks(element, isDelayed) {\n\t\tvar this$1 = this;\n\n\t\tvar duration = isDelayed\n\t\t\t? element.config.duration + element.config.delay\n\t\t\t: element.config.duration;\n\n\t\tvar beforeCallback = element.revealed\n\t\t\t? element.config.beforeReveal\n\t\t\t: element.config.beforeReset;\n\n\t\tvar afterCallback = element.revealed\n\t\t\t? element.config.afterReveal\n\t\t\t: element.config.afterReset;\n\n\t\tvar elapsed = 0;\n\t\tif (element.callbackTimer) {\n\t\t\telapsed = Date.now() - element.callbackTimer.start;\n\t\t\twindow.clearTimeout(element.callbackTimer.clock);\n\t\t}\n\n\t\tbeforeCallback(element.node);\n\n\t\telement.callbackTimer = {\n\t\t\tstart: Date.now(),\n\t\t\tclock: window.setTimeout(function () {\n\t\t\t\tafterCallback(element.node);\n\t\t\t\telement.callbackTimer = null;\n\t\t\t\tif (element.revealed && !element.config.reset && element.config.cleanup) {\n\t\t\t\t\tclean.call(this$1, element.node);\n\t\t\t\t}\n\t\t\t}, duration - elapsed)\n\t\t};\n\t}\n\n\tfunction sequence(element, pristine) {\n\t\tif ( pristine === void 0 ) pristine = this.pristine;\n\n\t\t/**\n\t\t * We first check if the element should reset.\n\t\t */\n\t\tif (!element.visible && element.revealed && element.config.reset) {\n\t\t\treturn animate.call(this, element, { reset: true })\n\t\t}\n\n\t\tvar seq = this.store.sequences[element.sequence.id];\n\t\tvar i = element.sequence.index;\n\n\t\tif (seq) {\n\t\t\tvar visible = new SequenceModel(seq, 'visible', this.store);\n\t\t\tvar revealed = new SequenceModel(seq, 'revealed', this.store);\n\n\t\t\tseq.models = { visible: visible, revealed: revealed };\n\n\t\t\t/**\n\t\t\t * If the sequence has no revealed members,\n\t\t\t * then we reveal the first visible element\n\t\t\t * within that sequence.\n\t\t\t *\n\t\t\t * The sequence then cues a recursive call\n\t\t\t * in both directions.\n\t\t\t */\n\t\t\tif (!revealed.body.length) {\n\t\t\t\tvar nextId = seq.members[visible.body[0]];\n\t\t\t\tvar nextElement = this.store.elements[nextId];\n\n\t\t\t\tif (nextElement) {\n\t\t\t\t\tcue.call(this, seq, visible.body[0], -1, pristine);\n\t\t\t\t\tcue.call(this, seq, visible.body[0], +1, pristine);\n\t\t\t\t\treturn animate.call(this, nextElement, { reveal: true, pristine: pristine })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * If our element isn’t resetting, we check the\n\t\t\t * element sequence index against the head, and\n\t\t\t * then the foot of the sequence.\n\t\t\t */\n\t\t\tif (\n\t\t\t\t!seq.blocked.head &&\n\t\t\t\ti === [].concat( revealed.head ).pop() &&\n\t\t\t\ti >= [].concat( visible.body ).shift()\n\t\t\t) {\n\t\t\t\tcue.call(this, seq, i, -1, pristine);\n\t\t\t\treturn animate.call(this, element, { reveal: true, pristine: pristine })\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t!seq.blocked.foot &&\n\t\t\t\ti === [].concat( revealed.foot ).shift() &&\n\t\t\t\ti <= [].concat( visible.body ).pop()\n\t\t\t) {\n\t\t\t\tcue.call(this, seq, i, +1, pristine);\n\t\t\t\treturn animate.call(this, element, { reveal: true, pristine: pristine })\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction Sequence(interval) {\n\t\tvar i = Math.abs(interval);\n\t\tif (!isNaN(i)) {\n\t\t\tthis.id = nextUniqueId();\n\t\t\tthis.interval = Math.max(i, 16);\n\t\t\tthis.members = [];\n\t\t\tthis.models = {};\n\t\t\tthis.blocked = {\n\t\t\t\thead: false,\n\t\t\t\tfoot: false\n\t\t\t};\n\t\t} else {\n\t\t\tthrow new RangeError('Invalid sequence interval.')\n\t\t}\n\t}\n\n\tfunction SequenceModel(seq, prop, store) {\n\t\tvar this$1 = this;\n\n\t\tthis.head = [];\n\t\tthis.body = [];\n\t\tthis.foot = [];\n\n\t\teach(seq.members, function (id, index) {\n\t\t\tvar element = store.elements[id];\n\t\t\tif (element && element[prop]) {\n\t\t\t\tthis$1.body.push(index);\n\t\t\t}\n\t\t});\n\n\t\tif (this.body.length) {\n\t\t\teach(seq.members, function (id, index) {\n\t\t\t\tvar element = store.elements[id];\n\t\t\t\tif (element && !element[prop]) {\n\t\t\t\t\tif (index < this$1.body[0]) {\n\t\t\t\t\t\tthis$1.head.push(index);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis$1.foot.push(index);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction cue(seq, i, direction, pristine) {\n\t\tvar this$1 = this;\n\n\t\tvar blocked = ['head', null, 'foot'][1 + direction];\n\t\tvar nextId = seq.members[i + direction];\n\t\tvar nextElement = this.store.elements[nextId];\n\n\t\tseq.blocked[blocked] = true;\n\n\t\tsetTimeout(function () {\n\t\t\tseq.blocked[blocked] = false;\n\t\t\tif (nextElement) {\n\t\t\t\tsequence.call(this$1, nextElement, pristine);\n\t\t\t}\n\t\t}, seq.interval);\n\t}\n\n\tfunction reveal(target, options, syncing) {\n\t\tvar this$1 = this;\n\t\tif ( options === void 0 ) options = {};\n\t\tif ( syncing === void 0 ) syncing = false;\n\n\t\tvar containerBuffer = [];\n\t\tvar sequence$$1;\n\t\tvar interval = options.interval || defaults.interval;\n\n\t\ttry {\n\t\t\tif (interval) {\n\t\t\t\tsequence$$1 = new Sequence(interval);\n\t\t\t}\n\n\t\t\tvar nodes = tealight(target);\n\t\t\tif (!nodes.length) {\n\t\t\t\tthrow new Error('Invalid reveal target.')\n\t\t\t}\n\n\t\t\tvar elements = nodes.reduce(function (elementBuffer, elementNode) {\n\t\t\t\tvar element = {};\n\t\t\t\tvar existingId = elementNode.getAttribute('data-sr-id');\n\n\t\t\t\tif (existingId) {\n\t\t\t\t\tdeepAssign(element, this$1.store.elements[existingId]);\n\n\t\t\t\t\t/**\n\t\t\t\t\t * In order to prevent previously generated styles\n\t\t\t\t\t * from throwing off the new styles, the style tag\n\t\t\t\t\t * has to be reverted to its pre-reveal state.\n\t\t\t\t\t */\n\t\t\t\t\tapplyStyle(element.node, element.styles.inline.computed);\n\t\t\t\t} else {\n\t\t\t\t\telement.id = nextUniqueId();\n\t\t\t\t\telement.node = elementNode;\n\t\t\t\t\telement.seen = false;\n\t\t\t\t\telement.revealed = false;\n\t\t\t\t\telement.visible = false;\n\t\t\t\t}\n\n\t\t\t\tvar config = deepAssign({}, element.config || this$1.defaults, options);\n\n\t\t\t\tif ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) {\n\t\t\t\t\tif (existingId) {\n\t\t\t\t\t\tclean.call(this$1, element);\n\t\t\t\t\t}\n\t\t\t\t\treturn elementBuffer // skip elements that are disabled\n\t\t\t\t}\n\n\t\t\t\tvar containerNode = tealight(config.container)[0];\n\t\t\t\tif (!containerNode) {\n\t\t\t\t\tthrow new Error('Invalid container.')\n\t\t\t\t}\n\t\t\t\tif (!containerNode.contains(elementNode)) {\n\t\t\t\t\treturn elementBuffer // skip elements found outside the container\n\t\t\t\t}\n\n\t\t\t\tvar containerId;\n\t\t\t\t{\n\t\t\t\t\tcontainerId = getContainerId(\n\t\t\t\t\t\tcontainerNode,\n\t\t\t\t\t\tcontainerBuffer,\n\t\t\t\t\t\tthis$1.store.containers\n\t\t\t\t\t);\n\t\t\t\t\tif (containerId === null) {\n\t\t\t\t\t\tcontainerId = nextUniqueId();\n\t\t\t\t\t\tcontainerBuffer.push({ id: containerId, node: containerNode });\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telement.config = config;\n\t\t\t\telement.containerId = containerId;\n\t\t\t\telement.styles = style(element);\n\n\t\t\t\tif (sequence$$1) {\n\t\t\t\t\telement.sequence = {\n\t\t\t\t\t\tid: sequence$$1.id,\n\t\t\t\t\t\tindex: sequence$$1.members.length\n\t\t\t\t\t};\n\t\t\t\t\tsequence$$1.members.push(element.id);\n\t\t\t\t}\n\n\t\t\t\telementBuffer.push(element);\n\t\t\t\treturn elementBuffer\n\t\t\t}, []);\n\n\t\t\t/**\n\t\t\t * Modifying the DOM via setAttribute needs to be handled\n\t\t\t * separately from reading computed styles in the map above\n\t\t\t * for the browser to batch DOM changes (limiting reflows)\n\t\t\t */\n\t\t\teach(elements, function (element) {\n\t\t\t\tthis$1.store.elements[element.id] = element;\n\t\t\t\telement.node.setAttribute('data-sr-id', element.id);\n\t\t\t});\n\t\t} catch (e) {\n\t\t\treturn logger.call(this, 'Reveal failed.', e.message)\n\t\t}\n\n\t\t/**\n\t\t * Now that element set-up is complete...\n\t\t * Let’s commit any container and sequence data we have to the store.\n\t\t */\n\t\teach(containerBuffer, function (container) {\n\t\t\tthis$1.store.containers[container.id] = {\n\t\t\t\tid: container.id,\n\t\t\t\tnode: container.node\n\t\t\t};\n\t\t});\n\t\tif (sequence$$1) {\n\t\t\tthis.store.sequences[sequence$$1.id] = sequence$$1;\n\t\t}\n\n\t\t/**\n\t\t * If reveal wasn't invoked by sync, we want to\n\t\t * make sure to add this call to the history.\n\t\t */\n\t\tif (syncing !== true) {\n\t\t\tthis.store.history.push({ target: target, options: options });\n\n\t\t\t/**\n\t\t\t * Push initialization to the event queue, giving\n\t\t\t * multiple reveal calls time to be interpreted.\n\t\t\t */\n\t\t\tif (this.initTimeout) {\n\t\t\t\twindow.clearTimeout(this.initTimeout);\n\t\t\t}\n\t\t\tthis.initTimeout = window.setTimeout(initialize.bind(this), 0);\n\t\t}\n\t}\n\n\tfunction getContainerId(node) {\n\t\tvar collections = [], len = arguments.length - 1;\n\t\twhile ( len-- > 0 ) collections[ len ] = arguments[ len + 1 ];\n\n\t\tvar id = null;\n\t\teach(collections, function (collection) {\n\t\t\teach(collection, function (container) {\n\t\t\t\tif (id === null && container.node === node) {\n\t\t\t\t\tid = container.id;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\treturn id\n\t}\n\n\t/**\n\t * Re-runs the reveal method for each record stored in history,\n\t * for capturing new content asynchronously loaded into the DOM.\n\t */\n\tfunction sync() {\n\t\tvar this$1 = this;\n\n\t\teach(this.store.history, function (record) {\n\t\t\treveal.call(this$1, record.target, record.options, true);\n\t\t});\n\n\t\tinitialize.call(this);\n\t}\n\n\tvar polyfill = function (x) { return (x > 0) - (x < 0) || +x; };\n\tvar mathSign = Math.sign || polyfill;\n\n\t/*! @license miniraf v1.0.1\n\n\t\tCopyright 2018 Fisssion LLC.\n\n\t\tPermission is hereby granted, free of charge, to any person obtaining a copy\n\t\tof this software and associated documentation files (the \"Software\"), to deal\n\t\tin the Software without restriction, including without limitation the rights\n\t\tto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\t\tcopies of the Software, and to permit persons to whom the Software is\n\t\tfurnished to do so, subject to the following conditions:\n\n\t\tThe above copyright notice and this permission notice shall be included in all\n\t\tcopies or substantial portions of the Software.\n\n\t\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\t\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\t\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\t\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\t\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\t\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\t\tSOFTWARE.\n\n\t*/\n\tvar polyfill$1 = (function () {\n\t\tvar clock = Date.now();\n\n\t\treturn function (callback) {\n\t\t\tvar currentTime = Date.now();\n\t\t\tif (currentTime - clock > 16) {\n\t\t\t\tclock = currentTime;\n\t\t\t\tcallback(currentTime);\n\t\t\t} else {\n\t\t\t\tsetTimeout(function () { return polyfill$1(callback); }, 0);\n\t\t\t}\n\t\t}\n\t})();\n\n\tvar miniraf = window.requestAnimationFrame ||\n\t\twindow.webkitRequestAnimationFrame ||\n\t\twindow.mozRequestAnimationFrame ||\n\t\tpolyfill$1;\n\n\tfunction getGeometry(target, isContainer) {\n\t\t/**\n\t\t * We want to ignore padding and scrollbars for container elements.\n\t\t * More information here: https://goo.gl/vOZpbz\n\t\t */\n\t\tvar height = isContainer ? target.node.clientHeight : target.node.offsetHeight;\n\t\tvar width = isContainer ? target.node.clientWidth : target.node.offsetWidth;\n\n\t\tvar offsetTop = 0;\n\t\tvar offsetLeft = 0;\n\t\tvar node = target.node;\n\n\t\tdo {\n\t\t\tif (!isNaN(node.offsetTop)) {\n\t\t\t\toffsetTop += node.offsetTop;\n\t\t\t}\n\t\t\tif (!isNaN(node.offsetLeft)) {\n\t\t\t\toffsetLeft += node.offsetLeft;\n\t\t\t}\n\t\t\tnode = node.offsetParent;\n\t\t} while (node)\n\n\t\treturn {\n\t\t\tbounds: {\n\t\t\t\ttop: offsetTop,\n\t\t\t\tright: offsetLeft + width,\n\t\t\t\tbottom: offsetTop + height,\n\t\t\t\tleft: offsetLeft\n\t\t\t},\n\t\t\theight: height,\n\t\t\twidth: width\n\t\t}\n\t}\n\n\tfunction getScrolled(container) {\n\t\tvar top, left;\n\t\tif (container.node === document.documentElement) {\n\t\t\ttop = window.pageYOffset;\n\t\t\tleft = window.pageXOffset;\n\t\t} else {\n\t\t\ttop = container.node.scrollTop;\n\t\t\tleft = container.node.scrollLeft;\n\t\t}\n\t\treturn { top: top, left: left }\n\t}\n\n\tfunction isElementVisible(element) {\n\t\tif ( element === void 0 ) element = {};\n\n\t\tvar container = this.store.containers[element.containerId];\n\t\tif (!container) { return }\n\n\t\tvar viewFactor = Math.max(0, Math.min(1, element.config.viewFactor));\n\t\tvar viewOffset = element.config.viewOffset;\n\n\t\tvar elementBounds = {\n\t\t\ttop: element.geometry.bounds.top + element.geometry.height * viewFactor,\n\t\t\tright: element.geometry.bounds.right - element.geometry.width * viewFactor,\n\t\t\tbottom: element.geometry.bounds.bottom - element.geometry.height * viewFactor,\n\t\t\tleft: element.geometry.bounds.left + element.geometry.width * viewFactor\n\t\t};\n\n\t\tvar containerBounds = {\n\t\t\ttop: container.geometry.bounds.top + container.scroll.top + viewOffset.top,\n\t\t\tright: container.geometry.bounds.right + container.scroll.left - viewOffset.right,\n\t\t\tbottom:\n\t\t\t\tcontainer.geometry.bounds.bottom + container.scroll.top - viewOffset.bottom,\n\t\t\tleft: container.geometry.bounds.left + container.scroll.left + viewOffset.left\n\t\t};\n\n\t\treturn (\n\t\t\t(elementBounds.top < containerBounds.bottom &&\n\t\t\t\telementBounds.right > containerBounds.left &&\n\t\t\t\telementBounds.bottom > containerBounds.top &&\n\t\t\t\telementBounds.left < containerBounds.right) ||\n\t\t\telement.styles.position === 'fixed'\n\t\t)\n\t}\n\n\tfunction delegate(\n\t\tevent,\n\t\telements\n\t) {\n\t\tvar this$1 = this;\n\t\tif ( event === void 0 ) event = { type: 'init' };\n\t\tif ( elements === void 0 ) elements = this.store.elements;\n\n\t\tminiraf(function () {\n\t\t\tvar stale = event.type === 'init' || event.type === 'resize';\n\n\t\t\teach(this$1.store.containers, function (container) {\n\t\t\t\tif (stale) {\n\t\t\t\t\tcontainer.geometry = getGeometry.call(this$1, container, true);\n\t\t\t\t}\n\t\t\t\tvar scroll = getScrolled.call(this$1, container);\n\t\t\t\tif (container.scroll) {\n\t\t\t\t\tcontainer.direction = {\n\t\t\t\t\t\tx: mathSign(scroll.left - container.scroll.left),\n\t\t\t\t\t\ty: mathSign(scroll.top - container.scroll.top)\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcontainer.scroll = scroll;\n\t\t\t});\n\n\t\t\t/**\n\t\t\t * Due to how the sequencer is implemented, it’s\n\t\t\t * important that we update the state of all\n\t\t\t * elements, before any animation logic is\n\t\t\t * evaluated (in the second loop below).\n\t\t\t */\n\t\t\teach(elements, function (element) {\n\t\t\t\tif (stale || element.geometry === undefined) {\n\t\t\t\t\telement.geometry = getGeometry.call(this$1, element);\n\t\t\t\t}\n\t\t\t\telement.visible = isElementVisible.call(this$1, element);\n\t\t\t});\n\n\t\t\teach(elements, function (element) {\n\t\t\t\tif (element.sequence) {\n\t\t\t\t\tsequence.call(this$1, element);\n\t\t\t\t} else {\n\t\t\t\t\tanimate.call(this$1, element);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis$1.pristine = false;\n\t\t});\n\t}\n\n\tfunction isTransformSupported() {\n\t\tvar style = document.documentElement.style;\n\t\treturn 'transform' in style || 'WebkitTransform' in style\n\t}\n\n\tfunction isTransitionSupported() {\n\t\tvar style = document.documentElement.style;\n\t\treturn 'transition' in style || 'WebkitTransition' in style\n\t}\n\n\tvar version = \"4.0.9\";\n\n\tvar boundDelegate;\n\tvar boundDestroy;\n\tvar boundReveal;\n\tvar boundClean;\n\tvar boundSync;\n\tvar config;\n\tvar debug;\n\tvar instance;\n\n\tfunction ScrollReveal(options) {\n\t\tif ( options === void 0 ) options = {};\n\n\t\tvar invokedWithoutNew =\n\t\t\ttypeof this === 'undefined' ||\n\t\t\tObject.getPrototypeOf(this) !== ScrollReveal.prototype;\n\n\t\tif (invokedWithoutNew) {\n\t\t\treturn new ScrollReveal(options)\n\t\t}\n\n\t\tif (!ScrollReveal.isSupported()) {\n\t\t\tlogger.call(this, 'Instantiation failed.', 'This browser is not supported.');\n\t\t\treturn mount.failure()\n\t\t}\n\n\t\tvar buffer;\n\t\ttry {\n\t\t\tbuffer = config\n\t\t\t\t? deepAssign({}, config, options)\n\t\t\t\t: deepAssign({}, defaults, options);\n\t\t} catch (e) {\n\t\t\tlogger.call(this, 'Invalid configuration.', e.message);\n\t\t\treturn mount.failure()\n\t\t}\n\n\t\ttry {\n\t\t\tvar container = tealight(buffer.container)[0];\n\t\t\tif (!container) {\n\t\t\t\tthrow new Error('Invalid container.')\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tlogger.call(this, e.message);\n\t\t\treturn mount.failure()\n\t\t}\n\n\t\tconfig = buffer;\n\n\t\tif ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) {\n\t\t\tlogger.call(\n\t\t\t\tthis,\n\t\t\t\t'This device is disabled.',\n\t\t\t\t(\"desktop: \" + (config.desktop)),\n\t\t\t\t(\"mobile: \" + (config.mobile))\n\t\t\t);\n\t\t\treturn mount.failure()\n\t\t}\n\n\t\tmount.success();\n\n\t\tthis.store = {\n\t\t\tcontainers: {},\n\t\t\telements: {},\n\t\t\thistory: [],\n\t\t\tsequences: {}\n\t\t};\n\n\t\tthis.pristine = true;\n\n\t\tboundDelegate = boundDelegate || delegate.bind(this);\n\t\tboundDestroy = boundDestroy || destroy.bind(this);\n\t\tboundReveal = boundReveal || reveal.bind(this);\n\t\tboundClean = boundClean || clean.bind(this);\n\t\tboundSync = boundSync || sync.bind(this);\n\n\t\tObject.defineProperty(this, 'delegate', { get: function () { return boundDelegate; } });\n\t\tObject.defineProperty(this, 'destroy', { get: function () { return boundDestroy; } });\n\t\tObject.defineProperty(this, 'reveal', { get: function () { return boundReveal; } });\n\t\tObject.defineProperty(this, 'clean', { get: function () { return boundClean; } });\n\t\tObject.defineProperty(this, 'sync', { get: function () { return boundSync; } });\n\n\t\tObject.defineProperty(this, 'defaults', { get: function () { return config; } });\n\t\tObject.defineProperty(this, 'version', { get: function () { return version; } });\n\t\tObject.defineProperty(this, 'noop', { get: function () { return false; } });\n\n\t\treturn instance ? instance : (instance = this)\n\t}\n\n\tScrollReveal.isSupported = function () { return isTransformSupported() && isTransitionSupported(); };\n\n\tObject.defineProperty(ScrollReveal, 'debug', {\n\t\tget: function () { return debug || false; },\n\t\tset: function (value) { return (debug = typeof value === 'boolean' ? value : debug); }\n\t});\n\n\tScrollReveal();\n\n\treturn ScrollReveal;\n\n}));\n"
  },
  {
    "path": "package.json",
    "content": "{\n\t\"name\": \"scrollreveal\",\n\t\"version\": \"4.0.9\",\n\t\"description\": \"Animate elements as they scroll into view\",\n\t\"homepage\": \"https://scrollrevealjs.org\",\n\t\"main\": \"dist/scrollreveal.js\",\n\t\"module\": \"dist/scrollreveal.es.js\",\n\t\"jsnext:main\": \"dist/scrollreveal.es.js\",\n\t\"files\": [\n\t\t\"dist\"\n\t],\n\t\"scripts\": {\n\t\t\"prebuild\": \"rm -rf dist/*\",\n\t\t\"build\": \"npm run bundle && npm run bundle:min\",\n\t\t\"bundle\": \"./node_modules/rollup/bin/rollup -c ./build/rollup.conf.js\",\n\t\t\"bundle:min\": \"./node_modules/rollup/bin/rollup -c ./build/rollup.conf.min.js\",\n\t\t\"lint\": \"./node_modules/eslint/bin/eslint.js src test\",\n\t\t\"pretest\": \"rm -rf .ignore/coverage/**/ && npm run lint\",\n\t\t\"test\": \"./node_modules/karma/bin/karma start ./test/karma.conf.js\",\n\t\t\"testing\": \"cross-env COVERAGE=true npm test -- --no-single-run\",\n\t\t\"coverage\": \"cross-env COVERAGE=true npm test\",\n\t\t\"sandbox:bundle\": \"./node_modules/rollup/bin/rollup -w -c ./.ignore/sandbox/rollup.conf.sandbox.js\",\n\t\t\"sandbox:server\": \"node ./.ignore/sandbox/server.sandbox.js\",\n\t\t\"coverage:server\": \"node ./.ignore/coverage/server.coverage.js\",\n\t\t\"postinstall\": \"node -e \\\"console.log('\\\\u001b[35m\\\\u001b[1mLove ScrollReveal? 🔑  Buy a license!\\\\u001b[22m\\\\u001b[35m\\\\n >> \\\\u001b[33mhttps://scrollrevealjs.org/pricing/\\\\u001b[0m\\\\n')\\\"\"\n\t},\n\t\"keywords\": [\n\t\t\"scroll\",\n\t\t\"animation\",\n\t\t\"reveal\",\n\t\t\"css\",\n\t\t\"transform\",\n\t\t\"transition\"\n\t],\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/jlmakes/scrollreveal.git\"\n\t},\n\t\"bugs\": {\n\t\t\"url\": \"https://github.com/jlmakes/scrollreveal/issues\"\n\t},\n\t\"dependencies\": {\n\t\t\"miniraf\": \"1.0.0\",\n\t\t\"rematrix\": \"0.3.0\",\n\t\t\"tealight\": \"0.3.6\"\n\t},\n\t\"devDependencies\": {\n\t\t\"chai\": \"^4.1.2\",\n\t\t\"cross-env\": \"^5.1.3\",\n\t\t\"eslint\": \"^4.16.0\",\n\t\t\"karma\": \"^2.0.0\",\n\t\t\"karma-chrome-launcher\": \"^2.0.0\",\n\t\t\"karma-coverage\": \"^1.1.1\",\n\t\t\"karma-coveralls\": \"^1.1.2\",\n\t\t\"karma-mocha\": \"^1.3.0\",\n\t\t\"karma-mocha-reporter\": \"^2.2.5\",\n\t\t\"karma-rollup-preprocessor\": \"^5.1.1\",\n\t\t\"karma-sauce-launcher\": \"^1.1.0\",\n\t\t\"karma-sinon-chai\": \"^1.3.3\",\n\t\t\"live-server\": \"jlmakes/live-server\",\n\t\t\"mocha\": \"^4.0.1\",\n\t\t\"rollup\": \"^0.55.0\",\n\t\t\"rollup-plugin-buble\": \"^0.x\",\n\t\t\"rollup-plugin-istanbul\": \"^1.1.0\",\n\t\t\"rollup-plugin-json\": \"^2.1.0\",\n\t\t\"rollup-plugin-node-resolve\": \"^3.0.0\",\n\t\t\"rollup-plugin-strip\": \"^1.1.1\",\n\t\t\"rollup-plugin-uglify\": \"^2.0.1\",\n\t\t\"rollup-watch\": \"^4.3.1\",\n\t\t\"sinon\": \"^4.2.0\",\n\t\t\"sinon-chai\": \"^2.8.0\"\n\t},\n\t\"author\": \"Julian Lloyd\",\n\t\"license\": \"GPL-3.0\"\n}\n"
  },
  {
    "path": "src/index.js",
    "content": "import Constructor from './instance/constructor'\n\nConstructor()\n\nexport default Constructor\n"
  },
  {
    "path": "src/instance/constructor.js",
    "content": "import defaults from './defaults'\nimport mount from './mount'\n\nimport clean from './methods/clean'\nimport destroy from './methods/destroy'\nimport reveal from './methods/reveal'\nimport sync from './methods/sync'\n\nimport delegate from './functions/delegate'\n\nimport isMobile from '../utils/is-mobile'\nimport isTransformSupported from '../utils/is-transform-supported'\nimport isTransitionSupported from '../utils/is-transition-supported'\n\nimport deepAssign from '../utils/deep-assign'\nimport logger from '../utils/logger'\nimport $ from 'tealight'\n\nimport { version } from '../../package.json'\n\nlet boundDelegate\nlet boundDestroy\nlet boundReveal\nlet boundClean\nlet boundSync\nlet config\nlet debug\nlet instance\n\nexport default function ScrollReveal(options = {}) {\n\tconst invokedWithoutNew =\n\t\ttypeof this === 'undefined' ||\n\t\tObject.getPrototypeOf(this) !== ScrollReveal.prototype\n\n\tif (invokedWithoutNew) {\n\t\treturn new ScrollReveal(options)\n\t}\n\n\tif (!ScrollReveal.isSupported()) {\n\t\tlogger.call(this, 'Instantiation failed.', 'This browser is not supported.')\n\t\treturn mount.failure()\n\t}\n\n\tlet buffer\n\ttry {\n\t\tbuffer = config\n\t\t\t? deepAssign({}, config, options)\n\t\t\t: deepAssign({}, defaults, options)\n\t} catch (e) {\n\t\tlogger.call(this, 'Invalid configuration.', e.message)\n\t\treturn mount.failure()\n\t}\n\n\ttry {\n\t\tconst container = $(buffer.container)[0]\n\t\tif (!container) {\n\t\t\tthrow new Error('Invalid container.')\n\t\t}\n\t} catch (e) {\n\t\tlogger.call(this, e.message)\n\t\treturn mount.failure()\n\t}\n\n\tconfig = buffer\n\n\tif ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) {\n\t\tlogger.call(\n\t\t\tthis,\n\t\t\t'This device is disabled.',\n\t\t\t`desktop: ${config.desktop}`,\n\t\t\t`mobile: ${config.mobile}`\n\t\t)\n\t\treturn mount.failure()\n\t}\n\n\tmount.success()\n\n\tthis.store = {\n\t\tcontainers: {},\n\t\telements: {},\n\t\thistory: [],\n\t\tsequences: {}\n\t}\n\n\tthis.pristine = true\n\n\tboundDelegate = boundDelegate || delegate.bind(this)\n\tboundDestroy = boundDestroy || destroy.bind(this)\n\tboundReveal = boundReveal || reveal.bind(this)\n\tboundClean = boundClean || clean.bind(this)\n\tboundSync = boundSync || sync.bind(this)\n\n\tObject.defineProperty(this, 'delegate', { get: () => boundDelegate })\n\tObject.defineProperty(this, 'destroy', { get: () => boundDestroy })\n\tObject.defineProperty(this, 'reveal', { get: () => boundReveal })\n\tObject.defineProperty(this, 'clean', { get: () => boundClean })\n\tObject.defineProperty(this, 'sync', { get: () => boundSync })\n\n\tObject.defineProperty(this, 'defaults', { get: () => config })\n\tObject.defineProperty(this, 'version', { get: () => version })\n\tObject.defineProperty(this, 'noop', { get: () => false })\n\n\treturn instance ? instance : (instance = this)\n}\n\nScrollReveal.isSupported = () =>\n\tisTransformSupported() && isTransitionSupported()\n\nObject.defineProperty(ScrollReveal, 'debug', {\n\tget: () => debug || false,\n\tset: value => (debug = typeof value === 'boolean' ? value : debug)\n})\n"
  },
  {
    "path": "src/instance/defaults.js",
    "content": "export default {\n\tdelay: 0,\n\tdistance: '0',\n\tduration: 600,\n\teasing: 'cubic-bezier(0.5, 0, 0, 1)',\n\tinterval: 0,\n\topacity: 0,\n\torigin: 'bottom',\n\trotate: {\n\t\tx: 0,\n\t\ty: 0,\n\t\tz: 0\n\t},\n\tscale: 1,\n\tcleanup: false,\n\tcontainer: document.documentElement,\n\tdesktop: true,\n\tmobile: true,\n\treset: false,\n\tuseDelay: 'always',\n\tviewFactor: 0.0,\n\tviewOffset: {\n\t\ttop: 0,\n\t\tright: 0,\n\t\tbottom: 0,\n\t\tleft: 0\n\t},\n\tafterReset() {},\n\tafterReveal() {},\n\tbeforeReset() {},\n\tbeforeReveal() {}\n}\n"
  },
  {
    "path": "src/instance/functions/animate.js",
    "content": "import { applyStyle } from '../functions/style'\nimport clean from '../methods/clean'\n\nexport default function animate(element, force = {}) {\n\tconst pristine = force.pristine || this.pristine\n\tconst delayed =\n\t\telement.config.useDelay === 'always' ||\n\t\t(element.config.useDelay === 'onload' && pristine) ||\n\t\t(element.config.useDelay === 'once' && !element.seen)\n\n\tconst shouldReveal = element.visible && !element.revealed\n\tconst shouldReset = !element.visible && element.revealed && element.config.reset\n\n\tif (force.reveal || shouldReveal) {\n\t\treturn triggerReveal.call(this, element, delayed)\n\t}\n\n\tif (force.reset || shouldReset) {\n\t\treturn triggerReset.call(this, element)\n\t}\n}\n\nfunction triggerReveal(element, delayed) {\n\tconst styles = [\n\t\telement.styles.inline.generated,\n\t\telement.styles.opacity.computed,\n\t\telement.styles.transform.generated.final\n\t]\n\tif (delayed) {\n\t\tstyles.push(element.styles.transition.generated.delayed)\n\t} else {\n\t\tstyles.push(element.styles.transition.generated.instant)\n\t}\n\telement.revealed = element.seen = true\n\tapplyStyle(element.node, styles.filter((s) => s !== '').join(' '))\n\tregisterCallbacks.call(this, element, delayed)\n}\n\nfunction triggerReset(element) {\n\tconst styles = [\n\t\telement.styles.inline.generated,\n\t\telement.styles.opacity.generated,\n\t\telement.styles.transform.generated.initial,\n\t\telement.styles.transition.generated.instant\n\t]\n\telement.revealed = false\n\tapplyStyle(element.node, styles.filter((s) => s !== '').join(' '))\n\tregisterCallbacks.call(this, element)\n}\n\nfunction registerCallbacks(element, isDelayed) {\n\tconst duration = isDelayed\n\t\t? element.config.duration + element.config.delay\n\t\t: element.config.duration\n\n\tconst beforeCallback = element.revealed\n\t\t? element.config.beforeReveal\n\t\t: element.config.beforeReset\n\n\tconst afterCallback = element.revealed\n\t\t? element.config.afterReveal\n\t\t: element.config.afterReset\n\n\tlet elapsed = 0\n\tif (element.callbackTimer) {\n\t\telapsed = Date.now() - element.callbackTimer.start\n\t\twindow.clearTimeout(element.callbackTimer.clock)\n\t}\n\n\tbeforeCallback(element.node)\n\n\telement.callbackTimer = {\n\t\tstart: Date.now(),\n\t\tclock: window.setTimeout(() => {\n\t\t\tafterCallback(element.node)\n\t\t\telement.callbackTimer = null\n\t\t\tif (element.revealed && !element.config.reset && element.config.cleanup) {\n\t\t\t\tclean.call(this, element.node)\n\t\t\t}\n\t\t}, duration - elapsed)\n\t}\n}\n"
  },
  {
    "path": "src/instance/functions/delegate.js",
    "content": "import animate from './animate'\nimport sequence from './sequence'\nimport mathSign from '../../polyfills/math-sign'\nimport raf from 'miniraf'\nimport each from '../../utils/each'\nimport getGeometry from '../../utils/get-geometry'\nimport getScrolled from '../../utils/get-scrolled'\nimport isElementVisible from '../../utils/is-element-visible'\n\nexport default function delegate(\n\tevent = { type: 'init' },\n\telements = this.store.elements\n) {\n\traf(() => {\n\t\tconst stale = event.type === 'init' || event.type === 'resize'\n\n\t\teach(this.store.containers, container => {\n\t\t\tif (stale) {\n\t\t\t\tcontainer.geometry = getGeometry.call(this, container, true)\n\t\t\t}\n\t\t\tconst scroll = getScrolled.call(this, container)\n\t\t\tif (container.scroll) {\n\t\t\t\tcontainer.direction = {\n\t\t\t\t\tx: mathSign(scroll.left - container.scroll.left),\n\t\t\t\t\ty: mathSign(scroll.top - container.scroll.top)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontainer.scroll = scroll\n\t\t})\n\n\t\t/**\n\t\t * Due to how the sequencer is implemented, it’s\n\t\t * important that we update the state of all\n\t\t * elements, before any animation logic is\n\t\t * evaluated (in the second loop below).\n\t\t */\n\t\teach(elements, element => {\n\t\t\tif (stale || element.geometry === undefined) {\n\t\t\t\telement.geometry = getGeometry.call(this, element)\n\t\t\t}\n\t\t\telement.visible = isElementVisible.call(this, element)\n\t\t})\n\n\t\teach(elements, element => {\n\t\t\tif (element.sequence) {\n\t\t\t\tsequence.call(this, element)\n\t\t\t} else {\n\t\t\t\tanimate.call(this, element)\n\t\t\t}\n\t\t})\n\n\t\tthis.pristine = false\n\t})\n}\n"
  },
  {
    "path": "src/instance/functions/initialize.js",
    "content": "import each from '../../utils/each'\nimport { applyStyle } from '../functions/style'\nimport rinse from './rinse'\n\nexport default function initialize() {\n\trinse.call(this)\n\n\teach(this.store.elements, element => {\n\t\tlet styles = [element.styles.inline.generated]\n\n\t\tif (element.visible) {\n\t\t\tstyles.push(element.styles.opacity.computed)\n\t\t\tstyles.push(element.styles.transform.generated.final)\n\t\t\telement.revealed = true\n\t\t} else {\n\t\t\tstyles.push(element.styles.opacity.generated)\n\t\t\tstyles.push(element.styles.transform.generated.initial)\n\t\t\telement.revealed = false\n\t\t}\n\n\t\tapplyStyle(element.node, styles.filter((s) => s !== '').join(' '))\n\t})\n\n\teach(this.store.containers, container => {\n\t\tconst target =\n\t\t\tcontainer.node === document.documentElement ? window : container.node\n\t\ttarget.addEventListener('scroll', this.delegate)\n\t\ttarget.addEventListener('resize', this.delegate)\n\t})\n\n\t/**\n\t * Manually invoke delegate once to capture\n\t * element and container dimensions, container\n\t * scroll position, and trigger any valid reveals\n\t */\n\tthis.delegate()\n\n\t/**\n\t * Wipe any existing `setTimeout` now\n\t * that initialization has completed.\n\t */\n\tthis.initTimeout = null\n}\n"
  },
  {
    "path": "src/instance/functions/rinse.js",
    "content": "import $ from 'tealight'\nimport each from '../../utils/each'\n\nexport default function rinse() {\n\tconst struct = () => ({\n\t\tactive: [],\n\t\tstale: []\n\t})\n\n\tconst elementIds = struct()\n\tconst sequenceIds = struct()\n\tconst containerIds = struct()\n\n\t/**\n\t * Take stock of active element IDs.\n\t */\n\ttry {\n\t\teach($('[data-sr-id]'), node => {\n\t\t\tconst id = parseInt(node.getAttribute('data-sr-id'))\n\t\t\telementIds.active.push(id)\n\t\t})\n\t} catch (e) {\n\t\tthrow e\n\t}\n\t/**\n\t * Destroy stale elements.\n\t */\n\teach(this.store.elements, element => {\n\t\tif (elementIds.active.indexOf(element.id) === -1) {\n\t\t\telementIds.stale.push(element.id)\n\t\t}\n\t})\n\n\teach(elementIds.stale, staleId => delete this.store.elements[staleId])\n\n\t/**\n\t * Take stock of active container and sequence IDs.\n\t */\n\teach(this.store.elements, element => {\n\t\tif (containerIds.active.indexOf(element.containerId) === -1) {\n\t\t\tcontainerIds.active.push(element.containerId)\n\t\t}\n\t\tif (element.hasOwnProperty('sequence')) {\n\t\t\tif (sequenceIds.active.indexOf(element.sequence.id) === -1) {\n\t\t\t\tsequenceIds.active.push(element.sequence.id)\n\t\t\t}\n\t\t}\n\t})\n\n\t/**\n\t * Destroy stale containers.\n\t */\n\teach(this.store.containers, container => {\n\t\tif (containerIds.active.indexOf(container.id) === -1) {\n\t\t\tcontainerIds.stale.push(container.id)\n\t\t}\n\t})\n\n\teach(containerIds.stale, staleId => {\n\t\tconst stale = this.store.containers[staleId].node\n\t\tstale.removeEventListener('scroll', this.delegate)\n\t\tstale.removeEventListener('resize', this.delegate)\n\t\tdelete this.store.containers[staleId]\n\t})\n\n\t/**\n\t * Destroy stale sequences.\n\t */\n\teach(this.store.sequences, sequence => {\n\t\tif (sequenceIds.active.indexOf(sequence.id) === -1) {\n\t\t\tsequenceIds.stale.push(sequence.id)\n\t\t}\n\t})\n\n\teach(sequenceIds.stale, staleId => delete this.store.sequences[staleId])\n}\n"
  },
  {
    "path": "src/instance/functions/sequence.js",
    "content": "import animate from './animate'\nimport each from '../../utils/each'\nimport nextUniqueId from '../../utils/next-unique-id'\n\nexport default function sequence(element, pristine = this.pristine) {\n\t/**\n\t * We first check if the element should reset.\n\t */\n\tif (!element.visible && element.revealed && element.config.reset) {\n\t\treturn animate.call(this, element, { reset: true })\n\t}\n\n\tconst seq = this.store.sequences[element.sequence.id]\n\tconst i = element.sequence.index\n\n\tif (seq) {\n\t\tconst visible = new SequenceModel(seq, 'visible', this.store)\n\t\tconst revealed = new SequenceModel(seq, 'revealed', this.store)\n\n\t\tseq.models = { visible, revealed }\n\n\t\t/**\n\t\t * If the sequence has no revealed members,\n\t\t * then we reveal the first visible element\n\t\t * within that sequence.\n\t\t *\n\t\t * The sequence then cues a recursive call\n\t\t * in both directions.\n\t\t */\n\t\tif (!revealed.body.length) {\n\t\t\tconst nextId = seq.members[visible.body[0]]\n\t\t\tconst nextElement = this.store.elements[nextId]\n\n\t\t\tif (nextElement) {\n\t\t\t\tcue.call(this, seq, visible.body[0], -1, pristine)\n\t\t\t\tcue.call(this, seq, visible.body[0], +1, pristine)\n\t\t\t\treturn animate.call(this, nextElement, { reveal: true, pristine })\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * If our element isn’t resetting, we check the\n\t\t * element sequence index against the head, and\n\t\t * then the foot of the sequence.\n\t\t */\n\t\tif (\n\t\t\t!seq.blocked.head &&\n\t\t\ti === [...revealed.head].pop() &&\n\t\t\ti >= [...visible.body].shift()\n\t\t) {\n\t\t\tcue.call(this, seq, i, -1, pristine)\n\t\t\treturn animate.call(this, element, { reveal: true, pristine })\n\t\t}\n\n\t\tif (\n\t\t\t!seq.blocked.foot &&\n\t\t\ti === [...revealed.foot].shift() &&\n\t\t\ti <= [...visible.body].pop()\n\t\t) {\n\t\t\tcue.call(this, seq, i, +1, pristine)\n\t\t\treturn animate.call(this, element, { reveal: true, pristine })\n\t\t}\n\t}\n}\n\nexport function Sequence(interval) {\n\tconst i = Math.abs(interval)\n\tif (!isNaN(i)) {\n\t\tthis.id = nextUniqueId()\n\t\tthis.interval = Math.max(i, 16)\n\t\tthis.members = []\n\t\tthis.models = {}\n\t\tthis.blocked = {\n\t\t\thead: false,\n\t\t\tfoot: false\n\t\t}\n\t} else {\n\t\tthrow new RangeError('Invalid sequence interval.')\n\t}\n}\n\nfunction SequenceModel(seq, prop, store) {\n\tthis.head = []\n\tthis.body = []\n\tthis.foot = []\n\n\teach(seq.members, (id, index) => {\n\t\tconst element = store.elements[id]\n\t\tif (element && element[prop]) {\n\t\t\tthis.body.push(index)\n\t\t}\n\t})\n\n\tif (this.body.length) {\n\t\teach(seq.members, (id, index) => {\n\t\t\tconst element = store.elements[id]\n\t\t\tif (element && !element[prop]) {\n\t\t\t\tif (index < this.body[0]) {\n\t\t\t\t\tthis.head.push(index)\n\t\t\t\t} else {\n\t\t\t\t\tthis.foot.push(index)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunction cue(seq, i, direction, pristine) {\n\tconst blocked = ['head', null, 'foot'][1 + direction]\n\tconst nextId = seq.members[i + direction]\n\tconst nextElement = this.store.elements[nextId]\n\n\tseq.blocked[blocked] = true\n\n\tsetTimeout(() => {\n\t\tseq.blocked[blocked] = false\n\t\tif (nextElement) {\n\t\t\tsequence.call(this, nextElement, pristine)\n\t\t}\n\t}, seq.interval)\n}\n"
  },
  {
    "path": "src/instance/functions/style.js",
    "content": "import {\n\tmultiply,\n\tparse,\n\trotateX,\n\trotateY,\n\trotateZ,\n\tscale,\n\ttranslateX,\n\ttranslateY\n} from 'rematrix'\nimport getPrefixedCssProp from '../../utils/get-prefixed-css-prop'\n\nexport default function style(element) {\n\tconst computed = window.getComputedStyle(element.node)\n\tconst position = computed.position\n\tconst config = element.config\n\n\t/**\n\t * Generate inline styles\n\t */\n\tconst inline = {}\n\tconst inlineStyle = element.node.getAttribute('style') || ''\n\tconst inlineMatch = inlineStyle.match(/[\\w-]+\\s*:\\s*[^;]+\\s*/gi) || []\n\n\tinline.computed = inlineMatch ? inlineMatch.map(m => m.trim()).join('; ') + ';' : ''\n\n\tinline.generated = inlineMatch.some(m => m.match(/visibility\\s?:\\s?visible/i))\n\t\t? inline.computed\n\t\t: [...inlineMatch, 'visibility: visible'].map(m => m.trim()).join('; ') + ';'\n\n\t/**\n\t * Generate opacity styles\n\t */\n\tconst computedOpacity = parseFloat(computed.opacity)\n\tconst configOpacity = !isNaN(parseFloat(config.opacity))\n\t\t? parseFloat(config.opacity)\n\t\t: parseFloat(computed.opacity)\n\n\tconst opacity = {\n\t\tcomputed: computedOpacity !== configOpacity ? `opacity: ${computedOpacity};` : '',\n\t\tgenerated: computedOpacity !== configOpacity ? `opacity: ${configOpacity};` : ''\n\t}\n\n\t/**\n\t * Generate transformation styles\n\t */\n\tconst transformations = []\n\n\tif (parseFloat(config.distance)) {\n\t\tconst axis = config.origin === 'top' || config.origin === 'bottom' ? 'Y' : 'X'\n\n\t\t/**\n\t\t * Let’s make sure our our pixel distances are negative for top and left.\n\t\t * e.g. { origin: 'top', distance: '25px' } starts at `top: -25px` in CSS.\n\t\t */\n\t\tlet distance = config.distance\n\t\tif (config.origin === 'top' || config.origin === 'left') {\n\t\t\tdistance = /^-/.test(distance) ? distance.substr(1) : `-${distance}`\n\t\t}\n\n\t\tconst [value, unit] = distance.match(/(^-?\\d+\\.?\\d?)|(em$|px$|%$)/g)\n\n\t\tswitch (unit) {\n\t\t\tcase 'em':\n\t\t\t\tdistance = parseInt(computed.fontSize) * value\n\t\t\t\tbreak\n\t\t\tcase 'px':\n\t\t\t\tdistance = value\n\t\t\t\tbreak\n\t\t\tcase '%':\n\t\t\t\t/**\n\t\t\t\t * Here we use `getBoundingClientRect` instead of\n\t\t\t\t * the existing data attached to `element.geometry`\n\t\t\t\t * because only the former includes any transformations\n\t\t\t\t * current applied to the element.\n\t\t\t\t *\n\t\t\t\t * If that behavior ends up being unintuitive, this\n\t\t\t\t * logic could instead utilize `element.geometry.height`\n\t\t\t\t * and `element.geoemetry.width` for the distance calculation\n\t\t\t\t */\n\t\t\t\tdistance =\n\t\t\t\t\taxis === 'Y'\n\t\t\t\t\t\t? (element.node.getBoundingClientRect().height * value) / 100\n\t\t\t\t\t\t: (element.node.getBoundingClientRect().width * value) / 100\n\t\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\tthrow new RangeError('Unrecognized or missing distance unit.')\n\t\t}\n\n\t\tif (axis === 'Y') {\n\t\t\ttransformations.push(translateY(distance))\n\t\t} else {\n\t\t\ttransformations.push(translateX(distance))\n\t\t}\n\t}\n\n\tif (config.rotate.x) transformations.push(rotateX(config.rotate.x))\n\tif (config.rotate.y) transformations.push(rotateY(config.rotate.y))\n\tif (config.rotate.z) transformations.push(rotateZ(config.rotate.z))\n\tif (config.scale !== 1) {\n\t\tif (config.scale === 0) {\n\t\t\t/**\n\t\t\t * The CSS Transforms matrix interpolation specification\n\t\t\t * basically disallows transitions of non-invertible\n\t\t\t * matrixes, which means browsers won't transition\n\t\t\t * elements with zero scale.\n\t\t\t *\n\t\t\t * That’s inconvenient for the API and developer\n\t\t\t * experience, so we simply nudge their value\n\t\t\t * slightly above zero; this allows browsers\n\t\t\t * to transition our element as expected.\n\t\t\t *\n\t\t\t * `0.0002` was the smallest number\n\t\t\t * that performed across browsers.\n\t\t\t */\n\t\t\ttransformations.push(scale(0.0002))\n\t\t} else {\n\t\t\ttransformations.push(scale(config.scale))\n\t\t}\n\t}\n\n\tconst transform = {}\n\tif (transformations.length) {\n\t\ttransform.property = getPrefixedCssProp('transform')\n\t\t/**\n\t\t * The default computed transform value should be one of:\n\t\t * undefined || 'none' || 'matrix()' || 'matrix3d()'\n\t\t */\n\t\ttransform.computed = {\n\t\t\traw: computed[transform.property],\n\t\t\tmatrix: parse(computed[transform.property])\n\t\t}\n\n\t\ttransformations.unshift(transform.computed.matrix)\n\t\tconst product = transformations.reduce(multiply)\n\n\t\ttransform.generated = {\n\t\t\tinitial: `${transform.property}: matrix3d(${product.join(', ')});`,\n\t\t\tfinal: `${transform.property}: matrix3d(${transform.computed.matrix.join(', ')});`\n\t\t}\n\t} else {\n\t\ttransform.generated = {\n\t\t\tinitial: '',\n\t\t\tfinal: ''\n\t\t}\n\t}\n\n\t/**\n\t * Generate transition styles\n\t */\n\tlet transition = {}\n\tif (opacity.generated || transform.generated.initial) {\n\t\ttransition.property = getPrefixedCssProp('transition')\n\t\ttransition.computed = computed[transition.property]\n\t\ttransition.fragments = []\n\n\t\tconst { delay, duration, easing } = config\n\n\t\tif (opacity.generated) {\n\t\t\ttransition.fragments.push({\n\t\t\t\tdelayed: `opacity ${duration / 1000}s ${easing} ${delay / 1000}s`,\n\t\t\t\tinstant: `opacity ${duration / 1000}s ${easing} 0s`\n\t\t\t})\n\t\t}\n\n\t\tif (transform.generated.initial) {\n\t\t\ttransition.fragments.push({\n\t\t\t\tdelayed: `${transform.property} ${duration / 1000}s ${easing} ${delay / 1000}s`,\n\t\t\t\tinstant: `${transform.property} ${duration / 1000}s ${easing} 0s`\n\t\t\t})\n\t\t}\n\n\t\t/**\n\t\t * The default computed transition property should be undefined, or one of:\n\t\t * '' || 'none 0s ease 0s' || 'all 0s ease 0s' || 'all 0s 0s cubic-bezier()'\n\t\t */\n\t\tlet hasCustomTransition =\n\t\t\ttransition.computed && !transition.computed.match(/all 0s|none 0s/)\n\n\t\tif (hasCustomTransition) {\n\t\t\ttransition.fragments.unshift({\n\t\t\t\tdelayed: transition.computed,\n\t\t\t\tinstant: transition.computed\n\t\t\t})\n\t\t}\n\n\t\tconst composed = transition.fragments.reduce(\n\t\t\t(composition, fragment, i) => {\n\t\t\t\tcomposition.delayed += i === 0 ? fragment.delayed : `, ${fragment.delayed}`\n\t\t\t\tcomposition.instant += i === 0 ? fragment.instant : `, ${fragment.instant}`\n\t\t\t\treturn composition\n\t\t\t},\n\t\t\t{\n\t\t\t\tdelayed: '',\n\t\t\t\tinstant: ''\n\t\t\t}\n\t\t)\n\n\t\ttransition.generated = {\n\t\t\tdelayed: `${transition.property}: ${composed.delayed};`,\n\t\t\tinstant: `${transition.property}: ${composed.instant};`\n\t\t}\n\t} else {\n\t\ttransition.generated = {\n\t\t\tdelayed: '',\n\t\t\tinstant: ''\n\t\t}\n\t}\n\n\treturn {\n\t\tinline,\n\t\topacity,\n\t\tposition,\n\t\ttransform,\n\t\ttransition\n\t}\n}\n\n/**\n * apply a CSS string to an element using the CSSOM (element.style) rather\n * than setAttribute, which may violate the content security policy.\n *\n * @param {Node}   [el]  Element to receive styles.\n * @param {string} [declaration] Styles to apply.\n */\nexport function applyStyle (el, declaration) {\n\tdeclaration.split(';').forEach(pair => {\n\t\tconst [property, ...value] = pair.split(':')\n\t\tif (property && value) {\n\t\t\tel.style[property.trim()] = value.join(':')\n\t\t}\n\t})\n}\n\n"
  },
  {
    "path": "src/instance/methods/clean.js",
    "content": "import $ from 'tealight'\nimport each from '../../utils/each'\nimport logger from '../../utils/logger'\nimport rinse from '../functions/rinse'\nimport { applyStyle } from '../functions/style'\n\nexport default function clean(target) {\n\tlet dirty\n\ttry {\n\t\teach($(target), node => {\n\t\t\tconst id = node.getAttribute('data-sr-id')\n\t\t\tif (id !== null) {\n\t\t\t\tdirty = true\n\t\t\t\tconst element = this.store.elements[id]\n\t\t\t\tif (element.callbackTimer) {\n\t\t\t\t\twindow.clearTimeout(element.callbackTimer.clock)\n\t\t\t\t}\n\t\t\t\tapplyStyle(element.node, element.styles.inline.generated)\n\t\t\t\tnode.removeAttribute('data-sr-id')\n\t\t\t\tdelete this.store.elements[id]\n\t\t\t}\n\t\t})\n\t} catch (e) {\n\t\treturn logger.call(this, 'Clean failed.', e.message)\n\t}\n\n\tif (dirty) {\n\t\ttry {\n\t\t\trinse.call(this)\n\t\t} catch (e) {\n\t\t\treturn logger.call(this, 'Clean failed.', e.message)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/instance/methods/destroy.js",
    "content": "import each from '../../utils/each'\nimport { applyStyle } from '../functions/style'\n\nexport default function destroy() {\n\t/**\n\t * Remove all generated styles and element ids\n\t */\n\teach(this.store.elements, element => {\n\t\tapplyStyle(element.node, element.styles.inline.generated)\n\t\telement.node.removeAttribute('data-sr-id')\n\t})\n\n\t/**\n\t * Remove all event listeners.\n\t */\n\teach(this.store.containers, container => {\n\t\tconst target =\n\t\t\tcontainer.node === document.documentElement ? window : container.node\n\t\ttarget.removeEventListener('scroll', this.delegate)\n\t\ttarget.removeEventListener('resize', this.delegate)\n\t})\n\n\t/**\n\t * Clear all data from the store\n\t */\n\tthis.store = {\n\t\tcontainers: {},\n\t\telements: {},\n\t\thistory: [],\n\t\tsequences: {}\n\t}\n}\n"
  },
  {
    "path": "src/instance/methods/reveal.js",
    "content": "import tealight from 'tealight'\nimport deepAssign from '../../utils/deep-assign'\nimport each from '../../utils/each'\nimport isMobile from '../../utils/is-mobile'\nimport logger from '../../utils/logger'\nimport nextUniqueId from '../../utils/next-unique-id'\nimport defaults from '../defaults'\nimport initialize from '../functions/initialize'\nimport { Sequence } from '../functions/sequence'\nimport style, { applyStyle } from '../functions/style'\nimport clean from '../methods/clean'\n\nexport default function reveal(target, options = {}, syncing = false) {\n\tconst containerBuffer = []\n\tlet sequence\n\tlet interval = options.interval || defaults.interval\n\n\ttry {\n\t\tif (interval) {\n\t\t\tsequence = new Sequence(interval)\n\t\t}\n\n\t\tconst nodes = tealight(target)\n\t\tif (!nodes.length) {\n\t\t\tthrow new Error('Invalid reveal target.')\n\t\t}\n\n\t\tconst elements = nodes.reduce((elementBuffer, elementNode) => {\n\t\t\tconst element = {}\n\t\t\tconst existingId = elementNode.getAttribute('data-sr-id')\n\n\t\t\tif (existingId) {\n\t\t\t\tdeepAssign(element, this.store.elements[existingId])\n\n\t\t\t\t/**\n\t\t\t\t * In order to prevent previously generated styles\n\t\t\t\t * from throwing off the new styles, the style tag\n\t\t\t\t * has to be reverted to its pre-reveal state.\n\t\t\t\t */\n\t\t\t\tapplyStyle(element.node, element.styles.inline.computed)\n\t\t\t} else {\n\t\t\t\telement.id = nextUniqueId()\n\t\t\t\telement.node = elementNode\n\t\t\t\telement.seen = false\n\t\t\t\telement.revealed = false\n\t\t\t\telement.visible = false\n\t\t\t}\n\n\t\t\tconst config = deepAssign({}, element.config || this.defaults, options)\n\n\t\t\tif ((!config.mobile && isMobile()) || (!config.desktop && !isMobile())) {\n\t\t\t\tif (existingId) {\n\t\t\t\t\tclean.call(this, element)\n\t\t\t\t}\n\t\t\t\treturn elementBuffer // skip elements that are disabled\n\t\t\t}\n\n\t\t\tconst containerNode = tealight(config.container)[0]\n\t\t\tif (!containerNode) {\n\t\t\t\tthrow new Error('Invalid container.')\n\t\t\t}\n\t\t\tif (!containerNode.contains(elementNode)) {\n\t\t\t\treturn elementBuffer // skip elements found outside the container\n\t\t\t}\n\n\t\t\tlet containerId\n\t\t\t{\n\t\t\t\tcontainerId = getContainerId(\n\t\t\t\t\tcontainerNode,\n\t\t\t\t\tcontainerBuffer,\n\t\t\t\t\tthis.store.containers\n\t\t\t\t)\n\t\t\t\tif (containerId === null) {\n\t\t\t\t\tcontainerId = nextUniqueId()\n\t\t\t\t\tcontainerBuffer.push({ id: containerId, node: containerNode })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\telement.config = config\n\t\t\telement.containerId = containerId\n\t\t\telement.styles = style(element)\n\n\t\t\tif (sequence) {\n\t\t\t\telement.sequence = {\n\t\t\t\t\tid: sequence.id,\n\t\t\t\t\tindex: sequence.members.length\n\t\t\t\t}\n\t\t\t\tsequence.members.push(element.id)\n\t\t\t}\n\n\t\t\telementBuffer.push(element)\n\t\t\treturn elementBuffer\n\t\t}, [])\n\n\t\t/**\n\t\t * Modifying the DOM via setAttribute needs to be handled\n\t\t * separately from reading computed styles in the map above\n\t\t * for the browser to batch DOM changes (limiting reflows)\n\t\t */\n\t\teach(elements, element => {\n\t\t\tthis.store.elements[element.id] = element\n\t\t\telement.node.setAttribute('data-sr-id', element.id)\n\t\t})\n\t} catch (e) {\n\t\treturn logger.call(this, 'Reveal failed.', e.message)\n\t}\n\n\t/**\n\t * Now that element set-up is complete...\n\t * Let’s commit any container and sequence data we have to the store.\n\t */\n\teach(containerBuffer, container => {\n\t\tthis.store.containers[container.id] = {\n\t\t\tid: container.id,\n\t\t\tnode: container.node\n\t\t}\n\t})\n\tif (sequence) {\n\t\tthis.store.sequences[sequence.id] = sequence\n\t}\n\n\t/**\n\t * If reveal wasn't invoked by sync, we want to\n\t * make sure to add this call to the history.\n\t */\n\tif (syncing !== true) {\n\t\tthis.store.history.push({ target, options })\n\n\t\t/**\n\t\t * Push initialization to the event queue, giving\n\t\t * multiple reveal calls time to be interpreted.\n\t\t */\n\t\tif (this.initTimeout) {\n\t\t\twindow.clearTimeout(this.initTimeout)\n\t\t}\n\t\tthis.initTimeout = window.setTimeout(initialize.bind(this), 0)\n\t}\n}\n\nfunction getContainerId(node, ...collections) {\n\tlet id = null\n\teach(collections, collection => {\n\t\teach(collection, container => {\n\t\t\tif (id === null && container.node === node) {\n\t\t\t\tid = container.id\n\t\t\t}\n\t\t})\n\t})\n\treturn id\n}\n"
  },
  {
    "path": "src/instance/methods/sync.js",
    "content": "import initialize from '../functions/initialize'\nimport each from '../../utils/each'\nimport reveal from './reveal'\n\n/**\n * Re-runs the reveal method for each record stored in history,\n * for capturing new content asynchronously loaded into the DOM.\n */\nexport default function sync() {\n\teach(this.store.history, record => {\n\t\treveal.call(this, record.target, record.options, true)\n\t})\n\n\tinitialize.call(this)\n}\n"
  },
  {
    "path": "src/instance/mount.js",
    "content": "function failure() {\n\tdocument.documentElement.classList.remove('sr')\n\n\treturn {\n\t\tclean() {},\n\t\tdestroy() {},\n\t\treveal() {},\n\t\tsync() {},\n\t\tget noop() {\n\t\t\treturn true\n\t\t}\n\t}\n}\n\nfunction success() {\n\tdocument.documentElement.classList.add('sr')\n\n\tif (document.body) {\n\t\tdocument.body.style.height = '100%'\n\t} else {\n\t\tdocument.addEventListener('DOMContentLoaded', () => {\n\t\t\tdocument.body.style.height = '100%'\n\t\t})\n\t}\n}\n\nexport default { success, failure }\n"
  },
  {
    "path": "src/polyfills/math-sign.js",
    "content": "export const polyfill = x => (x > 0) - (x < 0) || +x\nexport default Math.sign || polyfill\n"
  },
  {
    "path": "src/utils/deep-assign.js",
    "content": "import isObject from './is-object'\nimport each from './each'\n\nexport default function deepAssign(target, ...sources) {\n\tif (isObject(target)) {\n\t\teach(sources, source => {\n\t\t\teach(source, (data, key) => {\n\t\t\t\tif (isObject(data)) {\n\t\t\t\t\tif (!target[key] || !isObject(target[key])) {\n\t\t\t\t\t\ttarget[key] = {}\n\t\t\t\t\t}\n\t\t\t\t\tdeepAssign(target[key], data)\n\t\t\t\t} else {\n\t\t\t\t\ttarget[key] = data\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\t\treturn target\n\t} else {\n\t\tthrow new TypeError('Target must be an object literal.')\n\t}\n}\n"
  },
  {
    "path": "src/utils/each.js",
    "content": "import isObject from './is-object'\n\nexport default function each(collection, callback) {\n\tif (isObject(collection)) {\n\t\tconst keys = Object.keys(collection)\n\t\treturn keys.forEach(key => callback(collection[key], key, collection))\n\t}\n\tif (collection instanceof Array) {\n\t\treturn collection.forEach((item, i) => callback(item, i, collection))\n\t}\n\tthrow new TypeError('Expected either an array or object literal.')\n}\n"
  },
  {
    "path": "src/utils/get-geometry.js",
    "content": "export default function getGeometry(target, isContainer) {\n\t/**\n\t * We want to ignore padding and scrollbars for container elements.\n\t * More information here: https://goo.gl/vOZpbz\n\t */\n\tconst height = isContainer ? target.node.clientHeight : target.node.offsetHeight\n\tconst width = isContainer ? target.node.clientWidth : target.node.offsetWidth\n\n\tlet offsetTop = 0\n\tlet offsetLeft = 0\n\tlet node = target.node\n\n\tdo {\n\t\tif (!isNaN(node.offsetTop)) {\n\t\t\toffsetTop += node.offsetTop\n\t\t}\n\t\tif (!isNaN(node.offsetLeft)) {\n\t\t\toffsetLeft += node.offsetLeft\n\t\t}\n\t\tnode = node.offsetParent\n\t} while (node)\n\n\treturn {\n\t\tbounds: {\n\t\t\ttop: offsetTop,\n\t\t\tright: offsetLeft + width,\n\t\t\tbottom: offsetTop + height,\n\t\t\tleft: offsetLeft\n\t\t},\n\t\theight,\n\t\twidth\n\t}\n}\n"
  },
  {
    "path": "src/utils/get-prefixed-css-prop.js",
    "content": "const getPrefixedCssProp = (() => {\n\tlet properties = {}\n\tconst style = document.documentElement.style\n\n\tfunction getPrefixedCssProperty(name, source = style) {\n\t\tif (name && typeof name === 'string') {\n\t\t\tif (properties[name]) {\n\t\t\t\treturn properties[name]\n\t\t\t}\n\t\t\tif (typeof source[name] === 'string') {\n\t\t\t\treturn (properties[name] = name)\n\t\t\t}\n\t\t\tif (typeof source[`-webkit-${name}`] === 'string') {\n\t\t\t\treturn (properties[name] = `-webkit-${name}`)\n\t\t\t}\n\t\t\tthrow new RangeError(`Unable to find \"${name}\" style property.`)\n\t\t}\n\t\tthrow new TypeError('Expected a string.')\n\t}\n\n\tgetPrefixedCssProperty.clearCache = () => (properties = {})\n\n\treturn getPrefixedCssProperty\n})()\n\nexport default getPrefixedCssProp\n"
  },
  {
    "path": "src/utils/get-scrolled.js",
    "content": "export default function getScrolled(container) {\n\tlet top, left\n\tif (container.node === document.documentElement) {\n\t\ttop = window.pageYOffset\n\t\tleft = window.pageXOffset\n\t} else {\n\t\ttop = container.node.scrollTop\n\t\tleft = container.node.scrollLeft\n\t}\n\treturn { top, left }\n}\n"
  },
  {
    "path": "src/utils/is-element-visible.js",
    "content": "export default function isElementVisible(element = {}) {\n\tconst container = this.store.containers[element.containerId]\n\tif (!container) return\n\n\tconst viewFactor = Math.max(0, Math.min(1, element.config.viewFactor))\n\tconst viewOffset = element.config.viewOffset\n\n\tconst elementBounds = {\n\t\ttop: element.geometry.bounds.top + element.geometry.height * viewFactor,\n\t\tright: element.geometry.bounds.right - element.geometry.width * viewFactor,\n\t\tbottom: element.geometry.bounds.bottom - element.geometry.height * viewFactor,\n\t\tleft: element.geometry.bounds.left + element.geometry.width * viewFactor\n\t}\n\n\tconst containerBounds = {\n\t\ttop: container.geometry.bounds.top + container.scroll.top + viewOffset.top,\n\t\tright: container.geometry.bounds.right + container.scroll.left - viewOffset.right,\n\t\tbottom:\n\t\t\tcontainer.geometry.bounds.bottom + container.scroll.top - viewOffset.bottom,\n\t\tleft: container.geometry.bounds.left + container.scroll.left + viewOffset.left\n\t}\n\n\treturn (\n\t\t(elementBounds.top < containerBounds.bottom &&\n\t\t\telementBounds.right > containerBounds.left &&\n\t\t\telementBounds.bottom > containerBounds.top &&\n\t\t\telementBounds.left < containerBounds.right) ||\n\t\telement.styles.position === 'fixed'\n\t)\n}\n"
  },
  {
    "path": "src/utils/is-mobile.js",
    "content": "export default function isMobile(agent = navigator.userAgent) {\n\treturn /Android|iPhone|iPad|iPod/i.test(agent)\n}\n"
  },
  {
    "path": "src/utils/is-object.js",
    "content": "export default function isObject(x) {\n\treturn (\n\t\tx !== null &&\n\t\tx instanceof Object &&\n\t\t(x.constructor === Object ||\n\t\t\tObject.prototype.toString.call(x) === '[object Object]')\n\t)\n}\n"
  },
  {
    "path": "src/utils/is-transform-supported.js",
    "content": "export default function isTransformSupported() {\n\tconst style = document.documentElement.style\n\treturn 'transform' in style || 'WebkitTransform' in style\n}\n"
  },
  {
    "path": "src/utils/is-transition-supported.js",
    "content": "export default function isTransitionSupported() {\n\tconst style = document.documentElement.style\n\treturn 'transition' in style || 'WebkitTransition' in style\n}\n"
  },
  {
    "path": "src/utils/logger.js",
    "content": "export default function logger(message, ...details) {\n\tif (this.constructor.debug && console) {\n\t\tlet report = `%cScrollReveal: ${message}`\n\t\tdetails.forEach(detail => (report += `\\n — ${detail}`))\n\t\tconsole.log(report, 'color: #ea654b;') // eslint-disable-line no-console\n\t}\n}\n"
  },
  {
    "path": "src/utils/next-unique-id.js",
    "content": "const nextUniqueId = (() => {\n\tlet uid = 0\n\treturn () => uid++\n})()\n\nexport default nextUniqueId\n"
  },
  {
    "path": "test/instance/constructor.spec.js",
    "content": "import ScrollReveal from '../../src/instance/constructor'\nimport isMobile from '../../src/utils/is-mobile'\nimport { version } from '../../package.json'\n\ndescribe('ScrollReveal', () => {\n\tdescribe('Constructor', () => {\n\t\tit('should return a new instance with `new` keyword', () => {\n\t\t\tconst sr = new ScrollReveal()\n\t\t\texpect(sr).to.exist\n\t\t})\n\n\t\tit('should return a new instance without `new` keyword', () => {\n\t\t\tconst sr = ScrollReveal()\n\t\t\texpect(sr).to.exist\n\t\t})\n\n\t\tit('should add the class `sr` to `<html>` element', () => {\n\t\t\tdocument.documentElement.classList.remove('sr')\n\t\t\tScrollReveal()\n\t\t\tconst result = document.documentElement.classList.contains('sr')\n\t\t\texpect(result).to.be.true\n\t\t})\n\n\t\tit('should add `height: 100%` to `<body>` element', () => {\n\t\t\tdocument.body.style.height = 'auto'\n\t\t\tScrollReveal()\n\t\t\tconst result = document.body.style.height === '100%'\n\t\t\texpect(result).to.be.true\n\t\t})\n\n\t\tit('should return a noop instance when not supported', () => {\n\t\t\tconst stubs = [\n\t\t\t\tsinon.stub(console, 'log'),\n\t\t\t\tsinon.stub(ScrollReveal, 'isSupported')\n\t\t\t]\n\t\t\tconst sr = ScrollReveal()\n\t\t\tstubs.forEach(stub => stub.restore())\n\t\t\texpect(sr.noop).to.be.true\n\t\t})\n\n\t\tit('should return a noop instance when device is disabled', () => {\n\t\t\tisMobile()\n\t\t\t\t? expect(ScrollReveal({ mobile: false }).noop).to.be.true\n\t\t\t\t: expect(ScrollReveal({ desktop: false }).noop).to.be.true\n\n\t\t\tScrollReveal({ desktop: true, mobile: true })\n\t\t})\n\n\t\tit('should return a noop instance when container is invalid', () => {\n\t\t\tconst stub = sinon.stub(console, 'log')\n\t\t\tconst sr = ScrollReveal({ container: null })\n\t\t\tstub.restore()\n\t\t\texpect(sr.noop).to.be.true\n\t\t})\n\n\t\tit('should return a noop instance when passed non-object options', () => {\n\t\t\tconst stub = sinon.stub(console, 'log')\n\t\t\tlet sr\n\t\t\t{\n\t\t\t\tsr = ScrollReveal(null)\n\t\t\t\texpect(sr.noop).to.be.true\n\t\t\t\tsr = ScrollReveal('foo')\n\t\t\t\texpect(sr.noop).to.be.true\n\t\t\t}\n\t\t\tstub.restore()\n\t\t})\n\n\t\tit('should return a singleton', () => {\n\t\t\tconst A = ScrollReveal()\n\t\t\tconst B = ScrollReveal()\n\t\t\texpect(A === B).to.be.true\n\t\t})\n\n\t\tit('should not update the defaults when re-invoked with invalid options', () => {\n\t\t\tScrollReveal({ duration: 1000 })\n\t\t\tScrollReveal(null)\n\t\t\texpect(ScrollReveal().defaults.duration).to.equal(1000)\n\t\t})\n\n\t\tit('should update the defaults when re-invoked with valid options', () => {\n\t\t\tScrollReveal({ duration: 1000 })\n\t\t\tScrollReveal({ duration: 5000 })\n\t\t\texpect(ScrollReveal().defaults.duration).to.equal(5000)\n\t\t})\n\n\t\tit('should have a static `debug` property', () => {\n\t\t\texpect(ScrollReveal.debug).to.exist\n\t\t\texpect(ScrollReveal.debug).to.be.a('boolean')\n\t\t})\n\n\t\tit('should accept boolean value for static `debug` property', () => {\n\t\t\tScrollReveal.debug = true\n\t\t\texpect(ScrollReveal.debug).to.be.true\n\t\t})\n\n\t\tit('should ignore non-boolean values assigned to static `debug` property', () => {\n\t\t\tScrollReveal.debug = null\n\t\t\texpect(ScrollReveal.debug).to.exist\n\t\t\texpect(ScrollReveal.debug).to.be.a('boolean')\n\t\t})\n\t})\n\n\tdescribe('Instance', () => {\n\t\tconst sr = new ScrollReveal()\n\n\t\tit('should have a `clean` method', () => {\n\t\t\texpect(sr.clean).to.exist\n\t\t\texpect(sr.clean).to.be.a('function')\n\t\t})\n\n\t\tit('should have a `destroy` method', () => {\n\t\t\texpect(sr.destroy).to.exist\n\t\t\texpect(sr.destroy).to.be.a('function')\n\t\t})\n\n\t\tit('should have a `reveal` method', () => {\n\t\t\texpect(sr.reveal).to.exist\n\t\t\texpect(sr.reveal).to.be.a('function')\n\t\t})\n\n\t\tit('should have a `sync` method', () => {\n\t\t\texpect(sr.sync).to.exist\n\t\t\texpect(sr.sync).to.be.a('function')\n\t\t})\n\n\t\tit('should have a `delegate` property', () => {\n\t\t\texpect(sr.delegate).to.exist\n\t\t\texpect(sr.delegate).to.be.a('function')\n\t\t})\n\n\t\tit('should have a `version` property', () => {\n\t\t\texpect(sr.version).to.exist\n\t\t\texpect(sr.version).to.be.equal(version)\n\t\t})\n\n\t\tit('should have a `noop` property set to `false`', () => {\n\t\t\texpect(sr.noop).to.exist\n\t\t\texpect(sr.noop).to.be.false\n\t\t})\n\t})\n\n\tdescribe('Non-operational Instance', () => {\n\t\tconst stubs = [\n\t\t\tsinon.stub(console, 'log'),\n\t\t\tsinon.stub(ScrollReveal, 'isSupported')\n\t\t]\n\t\tconst sr = ScrollReveal()\n\t\tstubs.forEach(stub => stub.restore())\n\n\t\tit('should have a `clean` method', () => {\n\t\t\texpect(sr.clean).to.exist\n\t\t\texpect(sr.clean).to.be.a('function')\n\t\t})\n\n\t\tit('should have a `destroy` method', () => {\n\t\t\texpect(sr.destroy).to.exist\n\t\t\texpect(sr.destroy).to.be.a('function')\n\t\t})\n\n\t\tit('should have a `reveal` method', () => {\n\t\t\texpect(sr.reveal).to.exist\n\t\t\texpect(sr.reveal).to.be.a('function')\n\t\t})\n\n\t\tit('should have a `sync` method', () => {\n\t\t\texpect(sr.sync).to.exist\n\t\t\texpect(sr.sync).to.be.a('function')\n\t\t})\n\n\t\tit('should have a `noop` property set to `true`', () => {\n\t\t\texpect(sr.noop).to.exist\n\t\t\texpect(sr.noop).to.be.true\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/karma.conf.js",
    "content": "const rollupPlugins = [\n\trequire('rollup-plugin-json')(),\n\trequire('rollup-plugin-node-resolve')({ jsnext: true, main: true }),\n\trequire('rollup-plugin-buble')()\n]\n\nif (process.env.COVERAGE) {\n\trollupPlugins.push(\n\t\trequire('rollup-plugin-istanbul')({\n\t\t\texclude: [\n\t\t\t\t'../package.json',\n\t\t\t\t'../src/index.js',\n\t\t\t\t'./**/*.spec.js',\n\t\t\t\t'**/node_modules/**'\n\t\t\t],\n\t\t\tinstrumenterConfig: {\n\t\t\t\tembedSource: true\n\t\t\t}\n\t\t})\n\t)\n}\n\nmodule.exports = function(karma) {\n\tkarma.set({\n\t\tframeworks: ['mocha', 'sinon-chai'],\n\n\t\tpreprocessors: {\n\t\t\t'./**/*.spec.js': ['rollup']\n\t\t},\n\n\t\tfiles: [{ pattern: './**/*.spec.js', watched: false }],\n\n\t\trollupPreprocessor: {\n\t\t\tplugins: rollupPlugins,\n\t\t\toutput: {\n\t\t\t\tformat: 'iife',\n\t\t\t\tname: 'ScrollReveal',\n\t\t\t\tsourcemap: 'inline'\n\t\t\t}\n\t\t},\n\n\t\tcolors: true,\n\t\tconcurrency: 10,\n\t\tlogLevel: karma.LOG_ERROR,\n\t\tsingleRun: true,\n\n\t\tbrowserDisconnectTolerance: 1,\n\t\tbrowserDisconnectTimeout: 60 * 1000,\n\t\tbrowserNoActivityTimeout: 60 * 1000,\n\t\t// browserNoActivityTimeout: 60 * 1000 * 10 * 6, // dev tools debugging\n\t\tcaptureTimeout: 4 * 60 * 1000\n\t})\n\n\tif (process.env.TRAVIS) {\n\t\tif (process.env.COVERAGE) {\n\t\t\tkarma.set({\n\t\t\t\tautoWatch: false,\n\t\t\t\tbrowsers: ['ChromeHeadless'],\n\t\t\t\tcoverageReporter: {\n\t\t\t\t\ttype: 'lcovonly',\n\t\t\t\t\tdir: 'coverage/'\n\t\t\t\t},\n\t\t\t\treporters: ['mocha', 'coverage', 'coveralls']\n\t\t\t})\n\t\t} else {\n\t\t\tconst customLaunchers = require('./sauce.conf')\n\t\t\tkarma.set({\n\t\t\t\tautoWatch: false,\n\t\t\t\tbrowsers: Object.keys(customLaunchers),\n\t\t\t\tcustomLaunchers,\n\t\t\t\treporters: ['dots', 'saucelabs'],\n\t\t\t\thostname: 'localsauce',\n\t\t\t\tsauceLabs: {\n\t\t\t\t\ttestName: 'ScrollReveal',\n\t\t\t\t\tbuild: process.env.TRAVIS_BUILD_NUMBER || 'manual',\n\t\t\t\t\ttunnelIdentifier: process.env.TRAVIS_BUILD_NUMBER || 'autoGeneratedTunnelID',\n\t\t\t\t\trecordVideo: true,\n\t\t\t\t\tconnectOptions: {\n\t\t\t\t\t\ttunnelDomains: 'localsauce' // because Android 8 has an SSL error?\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t} else {\n\t\tkarma.set({\n\t\t\tbrowsers: ['ChromeHeadless'],\n\t\t\t// browsers: ['Chrome'], // dev tools debugging\n\t\t\tcoverageReporter: {\n\t\t\t\ttype: 'lcov',\n\t\t\t\tdir: '../.ignore/coverage/'\n\t\t\t},\n\t\t\treporters: ['mocha', 'coverage']\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "test/polyfills/math-sign.spec.js",
    "content": "import { polyfill } from '../../src/polyfills/math-sign'\n\ndescribe('Polyfills', () => {\n\tdescribe('mathSign()', () => {\n\t\tit('should be a function', () => {\n\t\t\texpect(polyfill).to.be.a('function')\n\t\t})\n\n\t\tit('should return -1 when passed values smaller than 0', () => {\n\t\t\texpect(polyfill(-500)).to.equal(-1)\n\t\t})\n\n\t\tit('should return 1 when passed values larger than 0', () => {\n\t\t\texpect(polyfill(500)).to.equal(1)\n\t\t})\n\n\t\tit('should return 1 when passed true', () => {\n\t\t\texpect(polyfill(true)).to.equal(1)\n\t\t})\n\n\t\tit('should return -0 when passed -0', () => {\n\t\t\texpect(polyfill(-0)).to.equal(-0)\n\t\t})\n\n\t\tit('should return 0 when passed 0', () => {\n\t\t\texpect(polyfill(0)).to.equal(0)\n\t\t})\n\n\t\tit('should return 0 when passed falsey values', () => {\n\t\t\texpect(polyfill(false)).to.equal(0)\n\t\t\texpect(polyfill('')).to.equal(0)\n\t\t\texpect(polyfill([])).to.equal(0)\n\t\t\texpect(polyfill(null)).to.equal(0)\n\t\t})\n\n\t\tit('should return NaN when passed non-falsey non-numbers', () => {\n\t\t\texpect(polyfill('foo')).to.be.NaN\n\t\t\texpect(polyfill({})).to.be.NaN\n\t\t\texpect(polyfill([1, 2, 3])).to.be.NaN\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/sauce.conf.js",
    "content": "let launchers = {}\n\nlet mobileLaunchers = [\n\t['iOS', '10.3', 'Safari', 'iPhone 7 Simulator', '1.9.1'],\n\t['iOS', '11.3', 'Safari', 'iPhone 7 Simulator', '1.9.1'],\n\t['iOS', '12.2', 'Safari', 'iPhone 7 Simulator', '1.13.0'],\n\t['iOS', '13.0', 'Safari', 'iPhone 7 Simulator', '1.15.0'],\n\t['Android', '5.1', 'Browser', 'Android Emulator', '1.15.0'],\n\t['Android', '6.0', 'Chrome', 'Android Emulator', '1.15.0'],\n\t['Android', '8.0', 'Chrome', 'Android Emulator', '1.15.0']\n]\n\nfor (let [platform, version, browser, device, appium] of mobileLaunchers) {\n\tlet launcher = `sl_${platform}_${version}_${browser}`\n\t\t.replace(/[^a-z0-9]/gi, '_')\n\t\t.toLowerCase()\n\n\tlaunchers[launcher] = {\n\t\tname: `${browser}, ${platform} ${version}`,\n\t\tplatformName: platform,\n\t\tplatformVersion: version,\n\t\tbrowserName: browser,\n\t\tdeviceName: device,\n\t\tdeviceOrientation: 'portrait',\n\t\tappiumVersion: appium\n\t}\n}\n\nlet desktopLaunchers = [\n\t['Windows 8.1', 'Internet Explorer', '11.0'],\n\t['Windows 8', 'Internet Explorer', '10.0'],\n\t['macOS 10.12', 'Safari', '11.0'],\n\t['OS X 10.11', 'Safari', '10.0'],\n\t['OS X 10.11', 'Safari', '9.0']\n]\n\nfor (let [platform, browser, version] of desktopLaunchers) {\n\tlet launcher = `sl_${platform}_${browser}_${version}`\n\t\t.replace(/[^a-z0-9]/gi, '_')\n\t\t.toLowerCase()\n\n\tlaunchers[launcher] = {\n\t\tname: `${browser} ${version}, ${platform}`,\n\t\tbrowserName: browser,\n\t\tversion,\n\t\tplatform\n\t}\n}\n\nfor (let browser of ['Chrome', 'Firefox', 'MicrosoftEdge']) {\n\tlet pastVersions = 3\n\tdo {\n\t\tpastVersions--\n\t\tlet postfix = pastVersions > 0 ? `-${pastVersions}` : ''\n\t\tlet version = 'latest' + postfix\n\n\t\tlet browserName = browser === 'MicrosoftEdge' ? 'Edge' : browser\n\t\tlet launcher = `sl_win10_${browser}_latest${postfix}`.replace(/-/g, '_').toLowerCase()\n\n\t\tlaunchers[launcher] = {\n\t\t\tname: `${browserName} ${version}, Windows 10`,\n\t\t\tbrowserName: browser,\n\t\t\tversion,\n\t\t\tplatform: 'Windows 10'\n\t\t}\n\t} while (pastVersions)\n}\n\nfor (let launcher in launchers) {\n\tlaunchers[launcher].base = 'SauceLabs'\n}\n\nmodule.exports = launchers\n"
  },
  {
    "path": "test/timeout.spec.js",
    "content": "// describe('suite delay for DOM inspection', function () {\n// \tit('should delay by 10 minutes', function (done) {\n// \t\tdocument.documentElement.style = 'background-color: #eee; height: 100%'\n// \t\tconst time = 1000 * 60 * 10 * 6\n// \t\tthis.timeout(time)\n// \t\tsetTimeout(done, time - 500)\n// \t})\n// })\n"
  },
  {
    "path": "test/utils/deep-assign.spec.js",
    "content": "import deepAssign from '../../src/utils/deep-assign'\n\ndescribe('Utilities', () => {\n\tdescribe('deepAssign()', () => {\n\t\tit('should assign source values to target object', () => {\n\t\t\tconst target = { foo: 'bar', bun: 'baz' }\n\t\t\tconst source = { foo: 'bonk!', bif: 'baff' }\n\t\t\tconst goal = { foo: 'bonk!', bun: 'baz', bif: 'baff' }\n\t\t\tdeepAssign(target, source)\n\t\t\texpect(target).to.deep.equal(goal)\n\t\t})\n\n\t\tit('should assign nested source values to target object', () => {\n\t\t\t// each property tests a\n\t\t\t// different execution path\n\t\t\tconst target = {\n\t\t\t\tfoo: 'initial',\n\t\t\t\tbar: 'initial',\n\t\t\t\tkel: { pow: 'pop' },\n\t\t\t\tzad: null\n\t\t\t}\n\t\t\tconst source = {\n\t\t\t\tfoo: 'bonk!',\n\t\t\t\tbar: { baz: 'baff' },\n\t\t\t\tkel: { pow: 'lol' },\n\t\t\t\tzad: { min: 'max' }\n\t\t\t}\n\t\t\tconst goal = {\n\t\t\t\tfoo: 'bonk!',\n\t\t\t\tbar: { baz: 'baff' },\n\t\t\t\tkel: { pow: 'lol' },\n\t\t\t\tzad: { min: 'max' }\n\t\t\t}\n\t\t\tdeepAssign(target, source)\n\t\t\texpect(target).to.deep.equal(goal)\n\t\t})\n\n\t\tit('should accept multiple sources', () => {\n\t\t\tconst target = { foo: 'bar', bun: 'baz' }\n\t\t\tconst source1 = { foo: 'bonk!', bif: 'baff' }\n\t\t\tconst source2 = { foo: 'pow!' }\n\t\t\tconst goal = { foo: 'pow!', bun: 'baz', bif: 'baff' }\n\t\t\tdeepAssign(target, source1, source2)\n\t\t\texpect(target).to.deep.equal(goal)\n\t\t})\n\n\t\tit('should throw a type error when not passed an object literal', () => {\n\t\t\tlet caught\n\t\t\ttry {\n\t\t\t\tdeepAssign(null, null)\n\t\t\t} catch (error) {\n\t\t\t\tcaught = error\n\t\t\t}\n\t\t\texpect(caught).to.exist\n\t\t\texpect(caught).to.be.an.instanceof(TypeError)\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/utils/each.spec.js",
    "content": "import each from '../../src/utils/each'\n\ndescribe('Utilities', () => {\n\tdescribe('each()', () => {\n\t\tfunction Fixture() {\n\t\t\tthis.foo = 'bar'\n\t\t\tthis.baz = 'bun'\n\t\t}\n\n\t\tdescribe('if passed an object literal...', () => {\n\t\t\tit('should invoke callback for each property', () => {\n\t\t\t\tconst fixture = new Fixture()\n\t\t\t\tconst spy = sinon.spy()\n\t\t\t\teach(fixture, spy)\n\t\t\t\texpect(spy).to.have.been.calledTwice\n\t\t\t})\n\n\t\t\tit('should ignore properties on the prototype chain', () => {\n\t\t\t\tFixture.prototype.biff = 'baff'\n\t\t\t\tconst fixture = new Fixture()\n\t\t\t\tconst spy = sinon.spy()\n\t\t\t\teach(fixture, spy)\n\t\t\t\texpect(spy).to.have.been.calledTwice\n\t\t\t})\n\n\t\t\tit('should pass the value, key and collection to the callback', () => {\n\t\t\t\tconst fixture = new Fixture()\n\t\t\t\tlet _value, _key, _collection\n\t\t\t\teach(fixture, (value, key, collection) => {\n\t\t\t\t\t_value = value\n\t\t\t\t\t_key = key\n\t\t\t\t\t_collection = collection\n\t\t\t\t})\n\t\t\t\texpect(_value).to.equal('bun')\n\t\t\t\texpect(_key).to.equal('baz')\n\t\t\t\texpect(_collection).to.deep.equal(fixture)\n\t\t\t})\n\t\t})\n\n\t\tdescribe('if passed an array...', () => {\n\t\t\tconst fixture = ['apple', 'orange', 'banana']\n\n\t\t\tit('should invoke callback for each value', () => {\n\t\t\t\tconst spy = sinon.spy()\n\t\t\t\teach(fixture, spy)\n\t\t\t\texpect(spy).to.have.been.calledThrice\n\t\t\t})\n\n\t\t\tit('should pass the value, index and collection to the callback', () => {\n\t\t\t\tlet _value, _index, _collection\n\t\t\t\teach(fixture, (value, index, collection) => {\n\t\t\t\t\t_value = value\n\t\t\t\t\t_index = index\n\t\t\t\t\t_collection = collection\n\t\t\t\t})\n\t\t\t\texpect(_value).to.equal('banana')\n\t\t\t\texpect(_index).to.equal(2)\n\t\t\t\texpect(_collection).to.deep.equal(fixture)\n\t\t\t})\n\t\t})\n\n\t\tdescribe('else', () => {\n\t\t\tit('should throw a type error when passed an invalid collection', () => {\n\t\t\t\tlet caught\n\t\t\t\ttry {\n\t\t\t\t\teach(null, () => {})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tcaught = error\n\t\t\t\t}\n\t\t\t\texpect(caught).to.exist\n\t\t\t\texpect(caught).to.be.an.instanceof(TypeError)\n\t\t\t})\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/utils/get-prefixed-css-prop.spec.js",
    "content": "import getPrefixedCssProp from '../../src/utils/get-prefixed-css-prop'\n\ndescribe('Utilities', () => {\n\tdescribe('getPrefixedCssProp()', () => {\n\t\tbeforeEach('clear cache', () => {\n\t\t\tgetPrefixedCssProp.clearCache()\n\t\t})\n\n\t\tit('should return unprefixed properties before prefixed', () => {\n\t\t\tconst source = {\n\t\t\t\ttransform: '',\n\t\t\t\t'-webkit-transform': ''\n\t\t\t}\n\t\t\tconst result = getPrefixedCssProp('transform', source)\n\t\t\texpect(result).to.equal('transform')\n\t\t})\n\n\t\tit('should return prefixed property names', () => {\n\t\t\tconst source = { '-webkit-transform': '' }\n\t\t\tconst result = getPrefixedCssProp('transform', source)\n\t\t\texpect(result).to.equal('-webkit-transform')\n\t\t})\n\n\t\tit('should return property names from cache when available', () => {\n\t\t\tconst source = { '-webkit-transform': '' }\n\t\t\tgetPrefixedCssProp('transform', source)\n\t\t\tconst result = getPrefixedCssProp('transform', {})\n\t\t\texpect(result).to.equal('-webkit-transform')\n\t\t})\n\n\t\tit('should throw a range error when no property is found', () => {\n\t\t\tlet caught\n\t\t\ttry {\n\t\t\t\tgetPrefixedCssProp('transform', {})\n\t\t\t} catch (error) {\n\t\t\t\tcaught = error\n\t\t\t}\n\t\t\texpect(caught).to.exist\n\t\t\texpect(caught).to.be.an.instanceof(RangeError)\n\t\t})\n\n\t\tit('should throw a type error if not passed a string', () => {\n\t\t\tlet caught\n\t\t\ttry {\n\t\t\t\tgetPrefixedCssProp(null)\n\t\t\t} catch (error) {\n\t\t\t\tcaught = error\n\t\t\t}\n\t\t\texpect(caught).to.exist\n\t\t\texpect(caught).to.be.an.instanceof(TypeError)\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/utils/is-mobile.spec.js",
    "content": "import isMobile from '../../src/utils/is-mobile'\n\ndescribe('Utilities', () => {\n\tdescribe('isMobile()', () => {\n\t\tit('should return true when passed a mobile user agent', () => {\n\t\t\tconst android = `Mozilla/5.0 (Linux; U; Android 4.2; en-us;\n\t\t\t\tAndroid SDK built for x86 Build/JOP40C) AppleWebKit/534.30\n\t\t\t\t(KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n\n\t\t\tconst iPhone = `Mozilla/5.0 (iPhone; CPU iPhone OS 10_10_5 like Mac OS X)\n\t\t\t\tAppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12B411 Safari/600.1.4`\n\n\t\t\texpect(isMobile(android)).to.be.true\n\t\t\texpect(isMobile(iPhone)).to.be.true\n\t\t})\n\n\t\tit('should return false when passed a desktop user agent', () => {\n\t\t\tconst chrome = `Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36\n\t\t\t\t(KHTML, like Gecko) Chrome/50.0.2661.75 Safari/537.36`\n\n\t\t\tconst firefox =\n\t\t\t\t'Mozilla/5.0 (X11; Linux i686; rv:45.0) Gecko/20100101 Firefox/45.0'\n\n\t\t\tconst ie10 = `Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1;\n\t\t\t\tWOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E)`\n\n\t\t\texpect(isMobile(chrome)).to.be.false\n\t\t\texpect(isMobile(firefox)).to.be.false\n\t\t\texpect(isMobile(ie10)).to.be.false\n\t\t})\n\n\t\tit('should work when not passed an explicit user agent', () => {\n\t\t\texpect(isMobile()).to.be.a('boolean')\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/utils/is-object.spec.js",
    "content": "import isObject from '../../src/utils/is-object'\n\ndescribe('Utilities', () => {\n\tdescribe('isObject()', () => {\n\t\tit('should return true when passed an object literal', () => {\n\t\t\tconst result = isObject({})\n\t\t\texpect(result).to.be.true\n\t\t})\n\n\t\tit('should return false when passed a function', () => {\n\t\t\tconst result = isObject(() => {})\n\t\t\texpect(result).to.be.false\n\t\t})\n\n\t\tit('should return false when passed an array', () => {\n\t\t\tconst result = isObject([])\n\t\t\texpect(result).to.be.false\n\t\t})\n\n\t\tit('should return false when passed null', () => {\n\t\t\tconst result = isObject(null)\n\t\t\texpect(result).to.be.false\n\t\t})\n\n\t\tit('should return false when passed undefined', () => {\n\t\t\tconst result = isObject(undefined)\n\t\t\texpect(result).to.be.false\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/utils/is-transform-supported.spec.js",
    "content": "import isTransformSupported from '../../src/utils/is-transform-supported'\n\ndescribe('Utilities', () => {\n\tdescribe('isTransformSupported()', () => {\n\t\tit('should return true', () => {\n\t\t\texpect(isTransformSupported()).to.be.true\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/utils/is-transition-supported.spec.js",
    "content": "import isTransitionSupported from '../../src/utils/is-transition-supported'\n\ndescribe('Utilities', () => {\n\tdescribe('isTransitionSupported()', () => {\n\t\tit('should return true', () => {\n\t\t\texpect(isTransitionSupported()).to.be.true\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "test/utils/logger.spec.js",
    "content": "import logger from '../../src/utils/logger'\n\ndescribe('Utilities', () => {\n\tdescribe('logger()', () => {\n\t\tconst mock = { constructor: { debug: true } }\n\n\t\tlet spy\n\t\tlet stub\n\n\t\tbeforeEach('stub console log', () => {\n\t\t\tspy = sinon.spy()\n\t\t\tstub = sinon.stub(console, 'log').callsFake(spy)\n\t\t})\n\n\t\tit('should invoke console.log', () => {\n\t\t\tlogger.call(mock)\n\t\t\texpect(spy).to.have.been.called\n\t\t})\n\n\t\tit('should prepend output with `ScrollReveal: `', () => {\n\t\t\tlogger.call(mock, 'test')\n\t\t\tconst result = '%cScrollReveal: test'\n\t\t\tconst style = 'color: #ea654b;'\n\t\t\texpect(spy).to.have.been.calledWith(result, style)\n\t\t})\n\n\t\tit('should accept multiple arguments as message details', () => {\n\t\t\tlogger.call(mock, 'message', 'detail one', 'detail two')\n\t\t\tconst result = '%cScrollReveal: message\\n — detail one\\n — detail two'\n\t\t\tconst style = 'color: #ea654b;'\n\t\t\texpect(spy).to.have.been.calledWith(result, style)\n\t\t})\n\n\t\tafterEach('restore console log', () => stub.restore())\n\t})\n})\n"
  },
  {
    "path": "test/utils/next-unique-id.spec.js",
    "content": "import nextUniqueId from '../../src/utils/next-unique-id'\n\ndescribe('Utilities', () => {\n\tdescribe('nextUniqueId()', () => {\n\t\tit('should start at 0', () => {\n\t\t\tconst result = nextUniqueId()\n\t\t\texpect(result).to.equal(0)\n\t\t})\n\n\t\tit('should increment by 1', () => {\n\t\t\tconst result = nextUniqueId()\n\t\t\texpect(result).to.equal(1)\n\t\t})\n\n\t\tit('should return a number', () => {\n\t\t\tconst result = nextUniqueId()\n\t\t\texpect(result).to.be.a('number')\n\t\t})\n\t})\n})\n"
  }
]