[
  {
    "path": ".gitignore",
    "content": "# Dependency directory\n# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git\nnode_modules\nnpm-debug.log\n\n# IntelliJ project files\n.idea\n\npackage-lock.json\n\n.DS_Store\n"
  },
  {
    "path": ".npmignore",
    "content": ".idea\nnode_modules\nnpm-debug.log\nscrollUp.jsx\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"12\"\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "\n# [1.4.0]\n* **Compatibility:** update dependecies to react 18\n\n# [1.3.7]\n* **Internal:** Update node version on test\n\n# [1.3.6]\n\n* **Internal:** Update react dependency and build\n\n# [1.3.5]\n\n* **Internal:** Add typescript declaration file\n\n# [1.3.4]\n\n* **Feature:** Add onShow and onHide react props\n\n# [1.3.3]\n\n* **Bugfix:** Fix peer dependencies to be compliant with semver ranges\n\n# [1.3.2]\n\n* **Compatibility:** update dependecies to react 16\n\n# [1.3.1]\n\n* **Bugfix:** Merge style property instead of override it\n\n# [1.3.0]\n\n* **Internal:** Rewrite source to ES6 syntax\n* **Performance:**: Better performance in handleScroll\n\n# [1.2.3]\n\n* **Compatibility:** Fix deprecated React.PropTypes\n\n# [1.2.2]\n\n* **Compatibility:** Fix deprecated React.createClass\n\n# [1.2.1]\n\n* **Bugfix:** fix require of detect-passive-events\n\n# [1.2.0]\n\n* **Performance:** use of passive listeners to improve scrolling performance\n\n# [1.1.5]\n\n* **Compatibility:** update dependecies to react 15\n\n# [1.1.4]\n\n* **Compatibility:** update for react 15.0\n\n# [1.1.3]\n\n* **Compatibility:** Replace function window.scrollY with window.pageYOffset for better compatibility\n\n# [1.1.2]\n\n* **Bugfix:** Fix stop scrolling if top position reached and add touch events\n* **Bugfix:** Show element after browser refresh, if page is under top position\n\n# [1.1.1]\n\n* **Dependency:** update tween function\n* **Dependency:** update dev dependency\n* **NPM:** Update npmignore\n\n# [1.1.0]\n\n### Other\n\n* **Compatibility:** update for react 0.14\n\n# [1.0.4]\n\n### Bug\n\n* **Dependency:** fix wrong dependencies\n\n# [1.0.3]\n\n### Bug\n\n* **Dependency:** fix wrong dependencies\n\n# [1.0.2]\n\n### Bug\n\n* **Visibility:** set visibility hidden after hide button\n* **Dependency:** Update dependency information\n\n### Other\n\n* **Default value:** change default value of easing\n\n\n# [1.0.1]\n\n### Feature\n\n* **Performance:** animate over requestAnimationFrame\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Miloš Janda\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "# react-scroll-up\n[![npm version](https://badge.fury.io/js/react-scroll-up.svg)](https://badge.fury.io/js/react-scroll-up)\n[![License](https://img.shields.io/npm/l/react-scroll-up.svg)](https://github.com/milosjanda/react-scroll-up/blob/master/LICENSE)\n[![Dependency Status](https://img.shields.io/david/milosjanda/react-scroll-up.svg)]()\n[![peerDependency Status](https://img.shields.io/david/peer/milosjanda/react-scroll-up.svg)]()\n[![Build status](https://travis-ci.org/milosjanda/react-scroll-up.svg?branch=master)](https://travis-ci.org/milosjanda/react-scroll-up)\n[![Downloads](https://img.shields.io/npm/dm/react-scroll-up.svg)]()\n\nReact component to add custom button (it can be something what you want) for scroll to top of page.\n\nLibrary uses [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame),\nif you want better browser compatibility (IE9 and older), you can use something like  [https://gist.github.com/paulirish/1579671].\n\n\n## Install\n\n```npm\nnpm install react-scroll-up\n```\n\n## How to use it\n\n[Live demo](http://milosjanda.github.io/react-scroll-up/)\n\nYou have to define children element, for example `<span>UP</span>`\n\n```jsx\n<ScrollToTop showUnder={160}>\n  <span>UP</span>\n</ScrollToTop>\n```\n\n## Parameters\n\n### showUnder:number in px (required) \n\nWhat position (and below) the button will be displayed.\n\n### topPosition:number in px (optional)\n\ndefault: 0\n\nThe position to which the scrollbar be moved after clicked.\n\n### easing:string (optional)\n\ndefault: easeOutCubic\n\nType of scrolling easing. You can specify some of this type of easing: https://github.com/chenglou/tween-functions\n\nIn graphical representation: http://sole.github.io/tween.js/examples/03_graphs.html\n\n### duration:number in miliseconds (optional)\n\ndefault: 250\n\nTime to reach the `topPosition`\n\n### onShow:function (optional)\n\nCallback function to be called when the button is being displayed.\n\n### onHide:function (optional)\n\nCallback function to be called when the button is being hidden.\n\n### style:object (optional)\n\ndefault:  \n\n```javascript\n{\n  position: 'fixed',\n  bottom: 50,\n  right: 30,\n  cursor: 'pointer',\n  transitionDuration: '0.2s',\n  transitionTimingFunction: 'linear',\n  transitionDelay: '0s'\n}\n```\n\nYou can specify you own style and position of the button.\n\nHide/show button is based on opacity, so this styles `opacity` and `transitionProperty` will be all time overwrite.\n\nIf you can positioned button to left site, you have to reset css property `right: 'auto'`, and similar.\n\n"
  },
  {
    "path": "index.d.ts",
    "content": "declare module 'react-scroll-up' {\n  import React, { ReactNode } from 'react';\n\n  export interface ScrollToTopProps {\n    showUnder: number,\n    topPosition?: number,\n    easing?: 'linear' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' |\n      'easeOutCubic' | 'easeInOutCubic' | 'easeInQuart' | 'easeOutQuart' | 'easeInOutQuart' | 'easeInQuint' |\n      'easeOutQuint' | 'easeInOutQuint' | 'easeInSine' | 'easeOutSine' | 'easeInOutSine' | 'easeInExpo' | 'easeOutExpo' |\n      'easeInOutExpo' | 'easeInCirc' | 'easeOutCirc' | 'easeInOutCirc' | 'easeInElastic' | 'easeOutElastic' |\n      'easeInOutElastic' | 'easeInBack' | 'easeOutBack' | 'easeInOutBack' | 'easeInBounce' | 'easeOutBounce' |\n      'easeInOutBounce',\n    duration?: number,\n    style?: object,\n    onShow?: () => void,\n    onHide?: () => void,\n    children?: ReactNode\n  }\n\n  export default class ScrollToTop extends React.Component<ScrollToTopProps, any> {}\n}\n"
  },
  {
    "path": "index.js",
    "content": "/**\n * @author  Milos Janda\n * @licence MIT\n */\n\n'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n    value: true\n});\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = require('react');\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _propTypes = require('prop-types');\n\nvar _propTypes2 = _interopRequireDefault(_propTypes);\n\nvar _tweenFunctions = require('tween-functions');\n\nvar _tweenFunctions2 = _interopRequireDefault(_tweenFunctions);\n\nvar _detectPassiveEvents = require('detect-passive-events');\n\nvar _objectAssign = require('object-assign');\n\nvar _objectAssign2 = _interopRequireDefault(_objectAssign);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nvar ScrollUp = function (_React$Component) {\n    _inherits(ScrollUp, _React$Component);\n\n    function ScrollUp(props) {\n        _classCallCheck(this, ScrollUp);\n\n        // set default state\n        var _this = _possibleConstructorReturn(this, (ScrollUp.__proto__ || Object.getPrototypeOf(ScrollUp)).call(this, props));\n\n        _this.state = { show: false };\n\n        // default property `data`\n        _this.data = {\n            startValue: 0,\n            currentTime: 0, // store current time of animation\n            startTime: null,\n            rafId: null\n        };\n\n        // bind\n        _this.handleClick = _this.handleClick.bind(_this);\n        _this.handleScroll = _this.handleScroll.bind(_this);\n        _this.scrollStep = _this.scrollStep.bind(_this);\n        _this.stopScrolling = _this.stopScrolling.bind(_this);\n        return _this;\n    }\n\n    _createClass(ScrollUp, [{\n        key: 'shouldComponentUpdate',\n        value: function shouldComponentUpdate(nextProps, nextState) {\n            return nextState.show !== this.state.show;\n        }\n    }, {\n        key: 'componentDidMount',\n        value: function componentDidMount() {\n            this.handleScroll(); // initialize state\n\n            // Add all listeners which can start scroll\n            window.addEventListener('scroll', this.handleScroll);\n            window.addEventListener(\"wheel\", this.stopScrolling, _detectPassiveEvents.supportsPassiveEvents ? { passive: true } : false);\n            window.addEventListener(\"touchstart\", this.stopScrolling, _detectPassiveEvents.supportsPassiveEvents ? { passive: true } : false);\n        }\n    }, {\n        key: 'componentWillUnmount',\n        value: function componentWillUnmount() {\n            // Remove all listeners which was registered\n            window.removeEventListener('scroll', this.handleScroll);\n            window.removeEventListener(\"wheel\", this.stopScrolling, false);\n            window.removeEventListener(\"touchstart\", this.stopScrolling, false);\n        }\n\n        /**\n         * call onShow callback if passed valid props\n         */\n\n    }, {\n        key: 'notifyOnShow',\n        value: function notifyOnShow() {\n            if (this.props.onShow && typeof this.props.onShow === \"function\") {\n                this.props.onShow();\n            }\n        }\n\n        /**\n         * call onHide callback if passed valid props\n         */\n\n    }, {\n        key: 'notifyOnHide',\n        value: function notifyOnHide() {\n            if (this.props.onHide && typeof this.props.onHide === \"function\") {\n                this.props.onHide();\n            }\n        }\n\n        /**\n         * Evaluate show/hide this component, depend on new position\n         */\n\n    }, {\n        key: 'handleScroll',\n        value: function handleScroll() {\n            if (window.pageYOffset > this.props.showUnder) {\n                if (!this.state.show) {\n                    this.setState({ show: true });\n                    this.notifyOnShow();\n                }\n            } else {\n                if (this.state.show) {\n                    this.setState({ show: false });\n                    this.notifyOnHide();\n                }\n            }\n        }\n\n        /**\n         * Handle click on the button\n         */\n\n    }, {\n        key: 'handleClick',\n        value: function handleClick() {\n            this.stopScrolling();\n            this.data.startValue = window.pageYOffset;\n            this.data.currentTime = 0;\n            this.data.startTime = null;\n            this.data.rafId = window.requestAnimationFrame(this.scrollStep);\n        }\n\n        /**\n         * Calculate new position\n         * and scroll screen to new position or stop scrolling\n         * @param timestamp\n         */\n\n    }, {\n        key: 'scrollStep',\n        value: function scrollStep(timestamp) {\n            if (!this.data.startTime) {\n                this.data.startTime = timestamp;\n            }\n\n            this.data.currentTime = timestamp - this.data.startTime;\n\n            var position = _tweenFunctions2.default[this.props.easing](this.data.currentTime, this.data.startValue, this.props.topPosition, this.props.duration);\n\n            if (window.pageYOffset <= this.props.topPosition) {\n                this.stopScrolling();\n            } else {\n                window.scrollTo(window.pageYOffset, position);\n                this.data.rafId = window.requestAnimationFrame(this.scrollStep);\n            }\n        }\n\n        /**\n         * Stop Animation Frame\n         */\n\n    }, {\n        key: 'stopScrolling',\n        value: function stopScrolling() {\n            window.cancelAnimationFrame(this.data.rafId);\n        }\n\n        /**\n         * Render component\n         */\n\n    }, {\n        key: 'render',\n        value: function render() {\n\n            var propStyle = this.props.style;\n            var element = _react2.default.createElement(\n                'div',\n                { style: propStyle, onClick: this.handleClick },\n                this.props.children\n            );\n\n            var style = (0, _objectAssign2.default)({}, ScrollUp.defaultProps.style);\n            style = (0, _objectAssign2.default)(style, propStyle);\n            style.opacity = this.state.show ? 1 : 0;\n            style.visibility = this.state.show ? 'visible' : 'hidden';\n            style.transitionProperty = 'opacity, visibility';\n\n            return _react2.default.cloneElement(element, { style: style });\n        }\n    }]);\n\n    return ScrollUp;\n}(_react2.default.Component);\n\n// Set default props\n\n\nexports.default = ScrollUp;\nScrollUp.defaultProps = {\n    duration: 250,\n    easing: 'easeOutCubic',\n    style: {\n        position: 'fixed',\n        bottom: 50,\n        right: 30,\n        cursor: 'pointer',\n        transitionDuration: '0.2s',\n        transitionTimingFunction: 'linear',\n        transitionDelay: '0s'\n    },\n    topPosition: 0\n};\n\n// Set validation property types\nScrollUp.propTypes = {\n    topPosition: _propTypes2.default.number,\n    showUnder: _propTypes2.default.number.isRequired, // show button under this position,\n    easing: _propTypes2.default.oneOf(['linear', 'easeInQuad', 'easeOutQuad', 'easeInOutQuad', 'easeInCubic', 'easeOutCubic', 'easeInOutCubic', 'easeInQuart', 'easeOutQuart', 'easeInOutQuart', 'easeInQuint', 'easeOutQuint', 'easeInOutQuint', 'easeInSine', 'easeOutSine', 'easeInOutSine', 'easeInExpo', 'easeOutExpo', 'easeInOutExpo', 'easeInCirc', 'easeOutCirc', 'easeInOutCirc', 'easeInElastic', 'easeOutElastic', 'easeInOutElastic', 'easeInBack', 'easeOutBack', 'easeInOutBack', 'easeInBounce', 'easeOutBounce', 'easeInOutBounce']),\n    duration: _propTypes2.default.number, // seconds\n    style: _propTypes2.default.object,\n    onShow: _propTypes2.default.func,\n    onHide: _propTypes2.default.func\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-scroll-up\",\n  \"version\": \"1.4.0\",\n  \"description\": \"React component to render element for scroll to top of page\",\n  \"author\": \"Milos Janda <milos.janda@gmail.com>\",\n  \"scripts\": {\n    \"test\": \"mocha --require babel-core/register test/test.jsx\",\n    \"build\": \"babel scrollUp.jsx --out-file index.js\",\n    \"prepublish\": \"npm run test && npm run build\"\n  },\n  \"main\": \"index.js\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/milosjanda/react-scroll-up.git\"\n  },\n  \"bug\": {\n    \"url\": \"https://github.com/milosjanda/react-scroll-up/issues\"\n  },\n  \"keywords\": [\n    \"scroll\",\n    \"scrollUp\",\n    \"scrollToTop\",\n    \"animation\",\n    \"effects\",\n    \"react\",\n    \"react-component\"\n  ],\n  \"babel\": {\n    \"presets\": [\n      \"es2015\",\n      \"react\"\n    ]\n  },\n  \"dependencies\": {\n    \"detect-passive-events\": \"^2.0.2\",\n    \"object-assign\": \"^4.0.1\",\n    \"prop-types\": \"^15.5.8\",\n    \"tween-functions\": \"^1.1.0\"\n  },\n  \"peerDependencies\": {\n    \"react\": \"0.13 - 18\"\n  },\n  \"devDependencies\": {\n    \"babel-cli\": \"^6.26.0\",\n    \"babel-core\": \"^6.26.3\",\n    \"babel-preset-es2015\": \"6.24.1\",\n    \"babel-preset-react\": \"6.24.1\",\n    \"chai\": \"^4.2.0\",\n    \"chai-enzyme\": \"^1.0.0-beta.1\",\n    \"enzyme\": \"^3.11.0\",\n    \"enzyme-adapter-react-16\": \"^1.15.5\",\n    \"jsdom\": \"^16.4.0\",\n    \"mocha\": \"^8.2.1\",\n    \"raf\": \"^3.4.1\",\n    \"react\": \"^18.0.0\",\n    \"react-dom\": \"^18.0.0\",\n    \"react-test-renderer\": \"^18.0.0\",\n    \"sinon\": \"^9.2.1\"\n  },\n  \"readmeFilename\": \"README.md\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "scrollUp.jsx",
    "content": "/**\n * @author  Milos Janda\n * @licence MIT\n */\n\n'use strict';\n\nimport React from 'react';\nimport PropTypes from 'prop-types';\nimport TweenFunctions from 'tween-functions';\nimport { supportsPassiveEvents } from 'detect-passive-events';\nimport objectAssign from 'object-assign';\n\nexport default class ScrollUp extends React.Component {\n\n    constructor(props) {\n        super(props);\n\n        // set default state\n        this.state = {show: false};\n\n        // default property `data`\n        this.data = {\n            startValue: 0,\n            currentTime: 0, // store current time of animation\n            startTime: null,\n            rafId: null\n        };\n\n        // bind\n        this.handleClick = this.handleClick.bind(this);\n        this.handleScroll = this.handleScroll.bind(this);\n        this.scrollStep = this.scrollStep.bind(this);\n        this.stopScrolling = this.stopScrolling.bind(this);\n    }\n\n    shouldComponentUpdate(nextProps, nextState) {\n        return nextState.show !== this.state.show;\n    }\n\n    componentDidMount() {\n        this.handleScroll(); // initialize state\n\n        // Add all listeners which can start scroll\n        window.addEventListener('scroll', this.handleScroll);\n        window.addEventListener(\"wheel\", this.stopScrolling, supportsPassiveEvents ? { passive: true } : false);\n        window.addEventListener(\"touchstart\", this.stopScrolling, supportsPassiveEvents ? { passive: true } : false);\n    }\n\n    componentWillUnmount() {\n        // Remove all listeners which was registered\n        window.removeEventListener('scroll', this.handleScroll);\n        window.removeEventListener(\"wheel\", this.stopScrolling, false);\n        window.removeEventListener(\"touchstart\", this.stopScrolling, false);\n    }\n\n    /**\n     * call onShow callback if passed valid props\n     */\n    notifyOnShow() {\n        if (this.props.onShow && typeof this.props.onShow === \"function\") {\n            this.props.onShow();\n        }\n    }\n\n    /**\n     * call onHide callback if passed valid props\n     */\n    notifyOnHide() {\n        if (this.props.onHide && typeof this.props.onHide === \"function\") {\n            this.props.onHide();\n        }\n    }\n\n    /**\n     * Evaluate show/hide this component, depend on new position\n     */\n    handleScroll() {\n        if (window.pageYOffset > this.props.showUnder) {\n            if (!this.state.show) {\n                this.setState({show: true});\n                this.notifyOnShow();\n            }\n        } else {\n            if (this.state.show) {\n                this.setState({show: false});\n                this.notifyOnHide();\n            }\n        }\n    }\n\n    /**\n     * Handle click on the button\n     */\n    handleClick() {\n        this.stopScrolling();\n        this.data.startValue = window.pageYOffset;\n        this.data.currentTime = 0;\n        this.data.startTime = null;\n        this.data.rafId = window.requestAnimationFrame(this.scrollStep);\n    }\n\n\n    /**\n     * Calculate new position\n     * and scroll screen to new position or stop scrolling\n     * @param timestamp\n     */\n    scrollStep(timestamp) {\n        if (!this.data.startTime) {\n            this.data.startTime = timestamp;\n        }\n\n        this.data.currentTime = timestamp - this.data.startTime;\n\n        let position = TweenFunctions[this.props.easing](\n            this.data.currentTime,\n            this.data.startValue,\n            this.props.topPosition,\n            this.props.duration\n        );\n\n        if (window.pageYOffset <= this.props.topPosition) {\n            this.stopScrolling();\n        } else {\n            window.scrollTo(window.pageYOffset, position);\n            this.data.rafId = window.requestAnimationFrame(this.scrollStep);\n        }\n    }\n\n    /**\n     * Stop Animation Frame\n     */\n    stopScrolling() {\n        window.cancelAnimationFrame(this.data.rafId);\n    }\n\n    /**\n     * Render component\n     */\n    render() {\n\n        let propStyle = this.props.style;\n        let element =\n            <div style={propStyle} onClick={this.handleClick}>\n                {this.props.children}\n            </div>;\n\n        let style = objectAssign({}, ScrollUp.defaultProps.style);\n        style = objectAssign(style, propStyle);\n        style.opacity = (this.state.show ? 1 : 0);\n        style.visibility = (this.state.show ? 'visible' : 'hidden');\n        style.transitionProperty = 'opacity, visibility';\n\n        return React.cloneElement(element, {style: style});\n    }\n}\n\n\n// Set default props\nScrollUp.defaultProps = {\n    duration: 250,\n    easing: 'easeOutCubic',\n    style: {\n        position: 'fixed',\n        bottom: 50,\n        right: 30,\n        cursor: 'pointer',\n        transitionDuration: '0.2s',\n        transitionTimingFunction: 'linear',\n        transitionDelay: '0s'\n    },\n    topPosition: 0\n};\n\n// Set validation property types\nScrollUp.propTypes = {\n    topPosition: PropTypes.number,\n    showUnder: PropTypes.number.isRequired, // show button under this position,\n    easing: PropTypes.oneOf(['linear', 'easeInQuad', 'easeOutQuad', 'easeInOutQuad', 'easeInCubic',\n        'easeOutCubic', 'easeInOutCubic', 'easeInQuart', 'easeOutQuart', 'easeInOutQuart', 'easeInQuint',\n        'easeOutQuint', 'easeInOutQuint', 'easeInSine', 'easeOutSine', 'easeInOutSine', 'easeInExpo', 'easeOutExpo',\n        'easeInOutExpo', 'easeInCirc', 'easeOutCirc', 'easeInOutCirc', 'easeInElastic', 'easeOutElastic',\n        'easeInOutElastic', 'easeInBack', 'easeOutBack', 'easeInOutBack', 'easeInBounce', 'easeOutBounce',\n        'easeInOutBounce']),\n    duration: PropTypes.number, // seconds\n    style: PropTypes.object,\n    onShow: PropTypes.func,\n    onHide: PropTypes.func\n};\n"
  },
  {
    "path": "test/test.jsx",
    "content": "// JSDom is used to allow the tests to run right from the command line (no browsers needed)\nconst jsdom = require(\"jsdom\");\nconst { JSDOM } = jsdom;\nconst dom = new JSDOM(`<!DOCTYPE html><html lang=\"en\"><body><p>Test</p></body></html>`);\n\n// noinspection JSConstantReassignment\nglobal.window = dom.window;\n// noinspection JSConstantReassignment\nglobal.document = dom.window.document;\n\n// Also apply a requestAnimationFrame polyfill\nrequire('raf').polyfill();\n\nimport React from 'react';\nimport { after, before, beforeEach, describe, it } from \"mocha\";\nimport sinon from 'sinon';\n\nimport { expect } from 'chai';\nimport { shallow } from 'enzyme'; // https://github.com/airbnb/enzyme/issues/465 shallow vs mount vs render\nimport chai from 'chai'; // https://github.com/producthunt/chai-enzyme#setup\nimport chaiEnzyme from 'chai-enzyme';\nimport Enzyme from 'enzyme';\nimport Adapter from 'enzyme-adapter-react-16';\n\nchai.use(chaiEnzyme()); // Note the invocation at the end\n\nimport TestUtils from 'react-dom/test-utils';\nimport ScrollUp from '../scrollUp';\n\nEnzyme.configure({ adapter: new Adapter() });\n\n// describe makes a test group\ndescribe('<ScrollUp/> states', function () {\n    // This will be run before each test to reset the scroll position\n    beforeEach(() => {\n        window.pageYOffset = 0;\n    });\n\n    // and each `it` function describes an individual test\n    it('is hidden when first rendered', function () {\n        let renderedComponent = TestUtils.renderIntoDocument(\n            <ScrollUp showUnder={100}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n\n        expect(renderedComponent.state.show).to.be.false;\n    });\n\n    it('is shown if the page is scrolled past the `showUnder` point', function () {\n        let renderedComponent = TestUtils.renderIntoDocument(\n            <ScrollUp showUnder={100}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n\n        // Set the scroll position to 200 and trigger the event manually\n        window.pageYOffset = 200;\n        renderedComponent.handleScroll();\n\n        expect(renderedComponent.state.show).to.be.true;\n    });\n\n});\n\n\n// describe makes a test group\ndescribe('<ScrollUp/> move 1', function () {\n\n    let scrollToSpy;\n    let renderedComponent;\n\n    before(() => {\n        window.pageYOffset = 0;\n\n        renderedComponent = TestUtils.renderIntoDocument(\n            <ScrollUp showUnder={100}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n\n        // \"stub\" the window.scrollTo function (because we want to see how it's called)\n        scrollToSpy = sinon.stub(global.window, 'scrollTo').callsFake( (x, y) => {\n            window.pageXOffset = x;\n            window.pageYOffset = y;\n            renderedComponent.handleScroll(); // And make sure to trigger the handleScroll for each call\n        });\n\n    });\n\n    after(() => {\n        scrollToSpy.restore();\n    });\n\n    it('scrolls back up to the top when clicked', function (done) {\n\n        // Ensure topPosition is set correctly\n        expect(renderedComponent.props.topPosition).to.equal(0);\n\n        // Set the scroll position to 200 and trigger the event manually\n        window.pageYOffset = 200;\n        renderedComponent.handleScroll();\n\n        // Now activate the click function\n        renderedComponent.handleClick();\n\n        // Give it a bit to scroll back up\n        setTimeout(() => {\n            expect(scrollToSpy.lastCall.args[1]).to.within(-0.1, 0.1);\n            expect(renderedComponent.state.show).to.be.false;\n            done();\n        }, 500);\n    });\n\n});\n\n\n// describe makes a test group\ndescribe('<ScrollUp/> move 2', function () {\n\n    let scrollToSpy;\n    let renderedComponent;\n\n    before(() => {\n        window.pageYOffset = 0;\n\n        renderedComponent = TestUtils.renderIntoDocument(\n            <ScrollUp showUnder={100} topPosition={100}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n\n        // \"stub\" the window.scrollTo function (because we want to see how it's called)\n        scrollToSpy = sinon.stub(global.window, 'scrollTo').callsFake( (x, y) => {\n            window.pageXOffset = x;\n            window.pageYOffset = y;\n            renderedComponent.handleScroll(); // And make sure to trigger the handleScroll for each call\n        });\n    });\n\n    after(() => {\n        scrollToSpy.restore();\n    });\n\n    it('scrolls to `topPosition` when clicked', (done) => {\n        // Ensure topPosition is set correctly\n        expect(renderedComponent.props.topPosition).to.equal(100);\n\n        // Set the scroll position to 200 and trigger the event manually\n        window.pageYOffset = 200;\n        renderedComponent.handleScroll();\n\n        // Now activate the click function\n        renderedComponent.handleClick();\n\n        // Give it a bit to scroll back up\n        setTimeout(() => {\n            expect(scrollToSpy.lastCall.args[1]).to.be.within(95, 105);\n            expect(renderedComponent.state.show).to.be.false;\n            done();\n        }, 500);\n    });\n\n});\n\n\n\n// describe makes a test group\ndescribe('<ScrollUp/> Styles', function () {\n\n    it('check rendered styles - default values - hidden', () => {\n        const wrapper = shallow(\n            <ScrollUp showUnder={100}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n        wrapper.setState({show: false});\n\n        // default styles\n        expect(wrapper).to.have.style(\"position\", 'fixed');\n        expect(wrapper).to.have.style(\"bottom\", '50px');\n        expect(wrapper).to.have.style(\"right\", '30px');\n        expect(wrapper).to.have.style(\"cursor\", 'pointer');\n        expect(wrapper).to.have.style(\"transition-duration\", '0.2s');\n        expect(wrapper).to.have.style(\"transition-timing-function\", 'linear');\n        expect(wrapper).to.have.style(\"transition-delay\", '0s');\n        expect(wrapper).to.have.style(\"opacity\" , '0');\n        expect(wrapper).to.have.style(\"visibility\", 'hidden');\n        expect(wrapper).to.have.style(\"transition-property\",  'opacity, visibility');\n    });\n\n\n    it('check rendered styles - default values - visible', () => {\n        const wrapper = shallow(\n            <ScrollUp showUnder={100}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n\n        wrapper.setState({show: true});\n\n        // default styles\n        expect(wrapper).to.have.style(\"position\", 'fixed');\n        expect(wrapper).to.have.style(\"bottom\", '50px');\n        expect(wrapper).to.have.style(\"right\", '30px');\n        expect(wrapper).to.have.style(\"cursor\", 'pointer');\n        expect(wrapper).to.have.style(\"transition-duration\", '0.2s');\n        expect(wrapper).to.have.style(\"transition-timing-function\", 'linear');\n        expect(wrapper).to.have.style(\"transition-delay\", '0s');\n        expect(wrapper).to.have.style(\"opacity\" , '1');\n        expect(wrapper).to.have.style(\"visibility\", 'visible');\n        expect(wrapper).to.have.style(\"transition-property\",  'opacity, visibility');\n    });\n\n\n    it('check rendered styles - custom values', () => {\n        const wrapper = shallow(\n            <ScrollUp showUnder={100}\n                      style={{\n                          zIndex: 3,\n                          right: 20,\n                          opacity: 0,\n                          visibility: 'hidden',\n                          transitionProperty: 'opacity'}}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n\n        // to check override opacity\n        wrapper.setState({show: true});\n\n        // default styles\n        expect(wrapper).to.have.style(\"position\", 'fixed');\n        expect(wrapper).to.have.style(\"bottom\", '50px');\n        expect(wrapper).to.have.style(\"cursor\", 'pointer');\n        expect(wrapper).to.have.style(\"transition-duration\", '0.2s');\n        expect(wrapper).to.have.style(\"transition-timing-function\", 'linear');\n        expect(wrapper).to.have.style(\"transition-delay\", '0s');\n\n        // overrides by props, but have to still value respective state\n        expect(wrapper).to.have.style(\"opacity\" , '1');\n        expect(wrapper).to.have.style(\"visibility\", 'visible');\n        expect(wrapper).to.have.style(\"transition-property\",  'opacity, visibility');\n\n        // overrides default values\n        expect(wrapper).to.have.style(\"right\", '20px');\n\n        // props styles\n        expect(wrapper).to.have.style(\"z-index\", '3');\n    });\n\n});\n\n\n// describe makes a test group\ndescribe('<ScrollUp/> children', function () {\n\n    it('check if children is rendered ', () => {\n        window.pageYOffset = 500;\n\n        const wrapper = shallow(\n            <ScrollUp showUnder={100}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n\n        expect(wrapper.find('span')).to.have.text('UP');\n    });\n\n});\n\n// describe makes a test group\ndescribe('<ScrollUp/> onShow onHide props', function () {\n    // This will be run before each test to reset the scroll position\n    beforeEach(() => {\n        window.pageYOffset = 0;\n    });\n\n    it('check onShow callback is working properly', function () {\n        let calledOnShow = false;\n\n        let renderedComponent = TestUtils.renderIntoDocument(\n            <ScrollUp showUnder={100} onShow={() => { calledOnShow = true }}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n\n        // is hidden when first rendered\n        expect(renderedComponent.state.show).to.be.false;\n\n        // Set the scroll position to 200 and trigger the event manually\n        window.pageYOffset = 200;\n        renderedComponent.handleScroll();\n\n        expect(renderedComponent.state.show).to.be.true; // button is now displayed\n        expect(calledOnShow).to.be.true; // and callback was called\n    });\n\n    it('check onHide callback is working properly', function () {\n        let calledOnHide = false;\n\n        let renderedComponent = TestUtils.renderIntoDocument(\n            <ScrollUp showUnder={100} onHide={() => { calledOnHide = true }}>\n                <span>UP</span>\n            </ScrollUp>\n        );\n\n        // is hidden when first rendered\n        expect(renderedComponent.state.show).to.be.false;\n\n        // Set the scroll position to 200 and trigger the event manually\n        window.pageYOffset = 200;\n        renderedComponent.handleScroll();\n        expect(renderedComponent.state.show).to.be.true; // button is now displayed\n        expect(calledOnHide).to.be.false; // and callback was not yet called\n\n        // Set the scroll position to 50 and trigger the event manually\n        window.pageYOffset = 50;\n        renderedComponent.handleScroll();\n        expect(renderedComponent.state.show).to.be.false; // button is now hidden\n        expect(calledOnHide).to.be.true; // and callback was called\n    });\n});"
  }
]