[
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\n    [\n      \"@babel/env\",\n      {\n        \"modules\": false\n      }\n    ]\n  ],\n  \"plugins\": [\n    \"@babel/plugin-transform-runtime\"\n  ]\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"extends\": [\"eslint:recommended\"],\n  \"parserOptions\": {\n    \"sourceType\": \"module\"\n  },\n  \"env\": {\n    \"browser\": true,\n    \"es6\": true\n  },\n  \"globals\": {\n    \"Vue\": \"readonly\"\n  }\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "\n# Created by https://www.gitignore.io/api/node,sass,macos,sublimetext,visualstudiocode\n\n### macOS ###\n# General\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n### Node ###\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# TypeScript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# parcel-bundler cache (https://parceljs.org/)\n.cache\n\n# next.js build output\n.next\n\n# nuxt.js build output\n.nuxt\n\n# vuepress build output\n.vuepress/dist\n\n# Serverless directories\n.serverless\n\n### Sass ###\n.sass-cache/\n*.css.map\n*.sass.map\n*.scss.map\n\n### SublimeText ###\n# Cache files for Sublime Text\n*.tmlanguage.cache\n*.tmPreferences.cache\n*.stTheme.cache\n\n# Workspace files are user-specific\n*.sublime-workspace\n\n# Project files should be checked into the repository, unless a significant\n# proportion of contributors will probably not be using Sublime Text\n# *.sublime-project\n\n# SFTP configuration file\nsftp-config.json\n\n# Package control specific files\nPackage Control.last-run\nPackage Control.ca-list\nPackage Control.ca-bundle\nPackage Control.system-ca-bundle\nPackage Control.cache/\nPackage Control.ca-certs/\nPackage Control.merged-ca-bundle\nPackage Control.user-ca-bundle\noscrypto-ca-bundle.crt\nbh_unicode_properties.cache\n\n# Sublime-github package stores a github token in this file\n# https://packagecontrol.io/packages/sublime-github\nGitHub.sublime-settings\n\n### VisualStudioCode ###\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n\n# End of https://www.gitignore.io/api/node,sass,macos,sublimetext,visualstudiocode\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"trailingComma\": \"es5\",\n  \"tabWidth\": 2,\n  \"semi\": true,\n  \"singleQuote\": true,\n  \"printWidth\": 100\n}\n"
  },
  {
    "path": ".webpack/webpack.config.dev.js",
    "content": "const path = require('path');\nconst VueLoaderPlugin = require('vue-loader/lib/plugin');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\n\nmodule.exports = {\n  mode: 'development',\n  entry: path.resolve(__dirname, '../src/sandbox/sandbox.js'),\n  output: {\n    path: path.resolve(__dirname, '../dist'),\n  },\n  devtool: 'inline-source-map',\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        exclude: /node_modules/,\n        use: ['babel-loader'],\n      },\n      {\n        test: /\\.vue$/,\n        loader: 'vue-loader',\n      },\n      {\n        test: /\\.css$/,\n        use: ['vue-style-loader', 'css-loader'],\n      },\n      {\n        test: /\\.scss$/,\n        use: ['style-loader', 'css-loader', 'sass-loader'],\n      },\n    ],\n  },\n  plugins: [\n    new VueLoaderPlugin(),\n    new HtmlWebpackPlugin({\n      template: 'src/sandbox/index.html',\n    }),\n  ],\n  devServer: {\n    contentBase: path.join(__dirname, '../dist'),\n  },\n};\n"
  },
  {
    "path": ".webpack/webpack.config.prod.js",
    "content": "const path = require('path');\nconst VueLoaderPlugin = require('vue-loader/lib/plugin');\n\nmodule.exports = {\n  mode: 'production',\n  entry: path.resolve(__dirname, '../src/index.js'),\n  output: {\n    filename: 'vue-scrollactive.min.js',\n    globalObject: \"typeof self !== 'undefined' ? self : this\",\n    path: path.resolve(__dirname, '../dist'),\n    publicPath: '/dist/',\n    library: {\n      root: 'vueScrollactive',\n      amd: 'vue-scrollactive',\n      commonjs: 'vue-scrollactive',\n    },\n    libraryTarget: 'umd',\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        exclude: /node_modules/,\n        use: ['babel-loader'],\n      },\n      {\n        test: /\\.vue$/,\n        use: ['vue-loader'],\n      },\n    ],\n  },\n  plugins: [new VueLoaderPlugin()],\n};\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2017 Mauricio Dziedzinski\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# vue-scrollactive\n\nThis component makes it simple to highlight a menu item with an 'active' class as you scroll.\n\n- Highlights items with a class as you scroll\n- Scrolls to item's section on click\n- Configurable easing scroll effect\n- Emits events for full control\n\nMake sure to check the [demo](https://eddiemf.github.io/vue-scrollactive/dist) where you can play around with every option.\n\n## Installation\n\nInstall using `yarn`\n\n```bash\nyarn add vue-scrollactive\n```\n\nor `npm`\n\n```bash\nnpm install --save vue-scrollactive\n```\n\nthen install the plugin\n\n```js\nimport VueScrollactive from 'vue-scrollactive';\n\nVue.use(VueScrollactive);\n```\n\nOr if you wish to include it in a `script` tag, just download the source code from the latest release [here](https://github.com/eddiemf/vue-scrollactive/releases/latest) and include the `vue-scrollactive.min.js` file located in the `dist` folder in your page as a script:\n\n```html\n<script src=\"dist/vue-scrollactive.min.js\"></script>\n```\n\nIf you're not running any transpiler like babel, you'll most likely need to install a Promise polyfill such as [this](https://github.com/taylorhakes/promise-polyfill) to support older browsers since this library depends on promises to work.\n\n## Usage\n\nThe primary way to use the plugin is to wrap your menu in a `<scrollactive>` tag (which will be your nav) and add a `.scrollactive-item` class in your `<a>` tags as I show in the example below:\n\n```html\n<scrollactive class=\"my-nav\">\n  <a href=\"#home\" class=\"scrollactive-item\">Home</a>\n  <a href=\"#about-us\" class=\"scrollactive-item\">About Us</a>\n  <a href=\"#portfolio\" class=\"scrollactive-item\">Portfolio</a>\n  <a href=\"#contact\" class=\"scrollactive-item\">Contact</a>\n</scrollactive>\n```\n\nYou can follow whatever structure you wish, just make sure to set the `.scrollactive-item` class in the items you want to highlight and set its `href` with a valid element ID that you would like to track while scrolling.\n\nThe secondary way to use it is almost the same as the primary but instead of relying on `href` to find your sections you'll need to set a data attribute `data-section-selector` on your elements with the section selector you wish to have.\n\n```html\n<scrollactive class=\"my-nav\">\n  <span data-section-selector=\"#home\" class=\"scrollactive-item\">Home</span>\n  <span data-section-selector=\".about-us\" class=\"scrollactive-item\">About Us</span>\n  <span data-section-selector=\".portfolio div span\" class=\"scrollactive-item\">Portfolio</span>\n  <span data-section-selector=\"#contact\" class=\"scrollactive-item\">Contact</span>\n</scrollactive>\n```\n\nAs you can see this gives you more freedom to choose different tags and you can use whatever CSS selector you find necessary, but it's important to notice that `data-section-selector` takes precedence over `href`, so if you have a tag `<a href=\"#section-1\" data-section-selector=\"#another-section\">` it will completely ignore the `#section-1` and use `#another-section` instead.\n\n## Events\n\nScrollactive will emit an `itemchanged(event, currentItem, lastActiveItem)` event when an active menu item is changed to another. You can catch that event doing as the example below:\n\n```html\n<scrollactive class=\"my-nav\" v-on:itemchanged=\"onItemChanged\">\n  <a href=\"#home\" class=\"scrollactive-item\">Home</a>\n  <a href=\"#about-us\" class=\"scrollactive-item\">About Us</a>\n  <a href=\"#portfolio\" class=\"scrollactive-item\">Portfolio</a>\n  <a href=\"#contact\" class=\"scrollactive-item\">Contact</a>\n</scrollactive>\n```\n\n```javascript\n// ...\nmethods: {\n  onItemChanged(event, currentItem, lastActiveItem) {\n    // here you have access to everything you need regarding that event\n  },\n},\n// ...\n```\n\n## Configuration\n\nAll options should be passed as a prop in the `<scrollactive>` component as you can see in the example below:\n\n```html\n<scrollactive active-class=\"active\" :offset=\"80\" :duration=\"800\" bezier-easing-value=\".5,0,.35,1\">\n</scrollactive>\n```\n\nRemember that all options are optional and you can check the default values below:\n\n### Options\n\n```javascript\n/**\n * Active class that will be applied to the active item.\n */\nactiveClass: {\n  type: String,\n  default: 'is-active',\n},\n\n/**\n * Amount of space between top of screen and the section to highlight. (Usually your fixed\n * header's height).\n */\noffset: {\n  type: Number,\n  default: 20,\n},\n\n/**\n * Amount of space between the top of the screen and the section to highlight when clicking a\n * scrollactive item to scroll. It will use the value of the `offset` prop if none is provided\n * here. Useful when you want to use the `offset` prop to make an item be active as soon as\n * it shows on the screen but still scroll to the top of the section when clicking the item.\n */\nscrollOffset: {\n  type: Number,\n  default: null,\n},\n\n/**\n * The selector string of the scroll container element you'd like to use. It defaults to the\n * window object (most common), but you might want to change in case you're using an element\n * as container with overflow.\n */\nscrollContainerSelector: {\n  type: String,\n  default: '',\n},\n\n/**\n * Enables/disables the scrolling when clicking in a menu item.\n * Disable if you'd like to handle the scrolling by your own.\n */\nclickToScroll: {\n  type: Boolean,\n  default: true,\n},\n\n/**\n * The duration of the scroll animation when clicking to scroll is activated.\n */\nduration: {\n  type: Number,\n  default: 600,\n},\n\n/**\n * Defines if the plugin should track the section change when clicking an item to scroll to\n * its section. If set to true, it will always keep track and change the active class to the\n * current section while scrolling, if false, the active class will be immediately applied to\n * the clicked menu item, ignoring the passed sections until the scrolling is over.\n */\nalwaysTrack: {\n  type: Boolean,\n  default: false,\n},\n\n/**\n * Your custom easing value for the click to scroll functionality.\n * It must be a string with 4 values separated by commas in a cubic bezier format.\n */\nbezierEasingValue: {\n  type: String,\n  default: '.5,0,.35,1',\n},\n\n/**\n * Decides if the URL should be modified with the section id when clicking a scrollactive\n * item.\n */\nmodifyUrl: {\n  type: Boolean,\n  default: true,\n},\n\n/**\n * If true the active class will only be applied when a section matches exactly one of the\n * scrollactive items, meaning it will be highlighted when scrolling exactly inside the\n * section. If false (default) it will always highlight the last item which was matched\n * in a section, even if it is already outside that section (and not inside another that's\n * being tracked).\n */\nexact: {\n  type: Boolean,\n  default: false,\n},\n\n/**\n * If true the active class will be applied to the first scrollactive-item before you scroll\n * past it (even if you didn't reach it yet).\n */\nhighlightFirstItem: {\n  type: Boolean,\n  default: false,\n},\n\n/**\n * Changes the scrollactive container component html tag.\n */\ntag: {\n  type: String,\n  default: 'nav',\n},\n\n/**\n * If true the screen will scroll down to the element in the URL when the component is mounted.\n */\nscrollOnStart: {\n  type: Boolean,\n  default: true,\n},\n```\n\n## Contributing\n\nClone the repository and install the dependencies running `yarn`. After the dependencies are installed you should be good to run `yarn start` which will load up a server with the sandbox for you to play around.\n"
  },
  {
    "path": "dist/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Scrollactive!</title>\n    <link\n      rel=\"stylesheet\"\n      href=\"https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.2/css/bulma.min.css\"\n    />\n  </head>\n  <body>\n    <div id=\"app\">\n      <header id=\"site-header\" class=\"nav is-fixed\">\n        <div class=\"container\">\n          <scrollactive\n            ref=\"scrollactive\"\n            :offset=\"offset\"\n            :always-track=\"alwaysTrack\"\n            :duration=\"duration\"\n            :click-to-scroll=\"clickToScroll\"\n            :bezier-easing-value=\"easing\"\n            ><ul class=\"nav-center\">\n              <li><a href=\"#section-1\" class=\"scrollactive-item nav-item\">Section 1</a></li>\n              <li><a href=\"#section-2\" class=\"scrollactive-item nav-item\">Section 2</a></li>\n              <li><a href=\"#section-3\" class=\"scrollactive-item nav-item\">Section 3</a></li>\n              <li><a href=\"#section-4\" class=\"scrollactive-item nav-item\">Section 4</a></li>\n            </ul></scrollactive\n          >\n        </div>\n      </header>\n      <div class=\"buttons\">\n        <button @click=\"addNewElement()\">Add new element</button>\n        <button @click=\"removeElement()\">Remove last element</button>\n        <button\n          @click=\"alwaysTrack = !alwaysTrack\"\n          v-text=\"'Always track ' + (alwaysTrack ? 'on' : 'off')\"\n        ></button>\n        <button\n          @click=\"clickToScroll = !clickToScroll\"\n          v-text=\"'Click to scroll ' + (clickToScroll ? 'on' : 'off')\"\n        ></button>\n        <label for=\"duration\">Duration</label>\n        <input type=\"number\" v-model=\"duration\" id=\"duration\" /> <label for=\"offset\">Offset</label>\n        <input type=\"number\" v-model=\"offset\" id=\"offset\" />\n        <label for=\"easing\">Easing (cubic-bezier format)</label>\n        <input v-model=\"easing\" id=\"easing\" />\n      </div>\n      <main>\n        <section id=\"section-1\" class=\"section hero is-primary is-fullheight\">\n          <div class=\"container\"><h1 class=\"heading title is-1\">Section 1</h1></div>\n        </section>\n        <section id=\"section-2\" class=\"section hero is-info is-fullheight\">\n          <div class=\"container\"><h1 class=\"heading title is-1\">Section 2</h1></div>\n        </section>\n        <section id=\"section-3\" class=\"section hero is-danger is-fullheight\">\n          <div class=\"container\"><h1 class=\"heading title is-1\">Section 3</h1></div>\n        </section>\n        <section id=\"section-4\" class=\"section hero is-success is-fullheight\">\n          <div class=\"container\"><h1 class=\"heading title is-1\">Section 4</h1></div>\n        </section>\n      </main>\n    </div>\n    <script src=\"https://unpkg.com/vue\"></script>\n    <script src=\"main.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "dist/main.js",
    "content": "!(function (e) {\n  var t = {};\n  function n(o) {\n    if (t[o]) return t[o].exports;\n    var r = (t[o] = { i: o, l: !1, exports: {} });\n    return e[o].call(r.exports, r, r.exports, n), (r.l = !0), r.exports;\n  }\n  (n.m = e),\n    (n.c = t),\n    (n.d = function (e, t, o) {\n      n.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: o });\n    }),\n    (n.r = function (e) {\n      'undefined' != typeof Symbol &&\n        Symbol.toStringTag &&\n        Object.defineProperty(e, Symbol.toStringTag, { value: 'Module' }),\n        Object.defineProperty(e, '__esModule', { value: !0 });\n    }),\n    (n.t = function (e, t) {\n      if ((1 & t && (e = n(e)), 8 & t)) return e;\n      if (4 & t && 'object' == typeof e && e && e.__esModule) return e;\n      var o = Object.create(null);\n      if (\n        (n.r(o),\n        Object.defineProperty(o, 'default', { enumerable: !0, value: e }),\n        2 & t && 'string' != typeof e)\n      )\n        for (var r in e)\n          n.d(\n            o,\n            r,\n            function (t) {\n              return e[t];\n            }.bind(null, r)\n          );\n      return o;\n    }),\n    (n.n = function (e) {\n      var t =\n        e && e.__esModule\n          ? function () {\n              return e.default;\n            }\n          : function () {\n              return e;\n            };\n      return n.d(t, 'a', t), t;\n    }),\n    (n.o = function (e, t) {\n      return Object.prototype.hasOwnProperty.call(e, t);\n    }),\n    (n.p = ''),\n    n((n.s = 7));\n})([\n  function (e, t, n) {\n    'use strict';\n    var o,\n      r = function () {\n        return void 0 === o && (o = Boolean(window && document && document.all && !window.atob)), o;\n      },\n      i = (function () {\n        var e = {};\n        return function (t) {\n          if (void 0 === e[t]) {\n            var n = document.querySelector(t);\n            if (window.HTMLIFrameElement && n instanceof window.HTMLIFrameElement)\n              try {\n                n = n.contentDocument.head;\n              } catch (e) {\n                n = null;\n              }\n            e[t] = n;\n          }\n          return e[t];\n        };\n      })(),\n      a = [];\n    function s(e) {\n      for (var t = -1, n = 0; n < a.length; n++)\n        if (a[n].identifier === e) {\n          t = n;\n          break;\n        }\n      return t;\n    }\n    function l(e, t) {\n      for (var n = {}, o = [], r = 0; r < e.length; r++) {\n        var i = e[r],\n          l = t.base ? i[0] + t.base : i[0],\n          c = n[l] || 0,\n          u = ''.concat(l, ' ').concat(c);\n        n[l] = c + 1;\n        var f = s(u),\n          d = { css: i[1], media: i[2], sourceMap: i[3] };\n        -1 !== f\n          ? (a[f].references++, a[f].updater(d))\n          : a.push({ identifier: u, updater: v(d, t), references: 1 }),\n          o.push(u);\n      }\n      return o;\n    }\n    function c(e) {\n      var t = document.createElement('style'),\n        o = e.attributes || {};\n      if (void 0 === o.nonce) {\n        var r = n.nc;\n        r && (o.nonce = r);\n      }\n      if (\n        (Object.keys(o).forEach(function (e) {\n          t.setAttribute(e, o[e]);\n        }),\n        'function' == typeof e.insert)\n      )\n        e.insert(t);\n      else {\n        var a = i(e.insert || 'head');\n        if (!a)\n          throw new Error(\n            \"Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.\"\n          );\n        a.appendChild(t);\n      }\n      return t;\n    }\n    var u,\n      f =\n        ((u = []),\n        function (e, t) {\n          return (u[e] = t), u.filter(Boolean).join('\\n');\n        });\n    function d(e, t, n, o) {\n      var r = n ? '' : o.media ? '@media '.concat(o.media, ' {').concat(o.css, '}') : o.css;\n      if (e.styleSheet) e.styleSheet.cssText = f(t, r);\n      else {\n        var i = document.createTextNode(r),\n          a = e.childNodes;\n        a[t] && e.removeChild(a[t]), a.length ? e.insertBefore(i, a[t]) : e.appendChild(i);\n      }\n    }\n    function m(e, t, n) {\n      var o = n.css,\n        r = n.media,\n        i = n.sourceMap;\n      if (\n        (r ? e.setAttribute('media', r) : e.removeAttribute('media'),\n        i &&\n          btoa &&\n          (o += '\\n/*# sourceMappingURL=data:application/json;base64,'.concat(\n            btoa(unescape(encodeURIComponent(JSON.stringify(i)))),\n            ' */'\n          )),\n        e.styleSheet)\n      )\n        e.styleSheet.cssText = o;\n      else {\n        for (; e.firstChild; ) e.removeChild(e.firstChild);\n        e.appendChild(document.createTextNode(o));\n      }\n    }\n    var p = null,\n      h = 0;\n    function v(e, t) {\n      var n, o, r;\n      if (t.singleton) {\n        var i = h++;\n        (n = p || (p = c(t))), (o = d.bind(null, n, i, !1)), (r = d.bind(null, n, i, !0));\n      } else\n        (n = c(t)),\n          (o = m.bind(null, n, t)),\n          (r = function () {\n            !(function (e) {\n              if (null === e.parentNode) return !1;\n              e.parentNode.removeChild(e);\n            })(n);\n          });\n      return (\n        o(e),\n        function (t) {\n          if (t) {\n            if (t.css === e.css && t.media === e.media && t.sourceMap === e.sourceMap) return;\n            o((e = t));\n          } else r();\n        }\n      );\n    }\n    e.exports = function (e, t) {\n      (t = t || {}).singleton || 'boolean' == typeof t.singleton || (t.singleton = r());\n      var n = l((e = e || []), t);\n      return function (e) {\n        if (((e = e || []), '[object Array]' === Object.prototype.toString.call(e))) {\n          for (var o = 0; o < n.length; o++) {\n            var r = s(n[o]);\n            a[r].references--;\n          }\n          for (var i = l(e, t), c = 0; c < n.length; c++) {\n            var u = s(n[c]);\n            0 === a[u].references && (a[u].updater(), a.splice(u, 1));\n          }\n          n = i;\n        }\n      };\n    };\n  },\n  function (e, t, n) {\n    'use strict';\n    e.exports = function (e) {\n      var t = [];\n      return (\n        (t.toString = function () {\n          return this.map(function (t) {\n            var n = (function (e, t) {\n              var n = e[1] || '',\n                o = e[3];\n              if (!o) return n;\n              if (t && 'function' == typeof btoa) {\n                var r =\n                    ((a = o),\n                    (s = btoa(unescape(encodeURIComponent(JSON.stringify(a))))),\n                    (l = 'sourceMappingURL=data:application/json;charset=utf-8;base64,'.concat(s)),\n                    '/*# '.concat(l, ' */')),\n                  i = o.sources.map(function (e) {\n                    return '/*# sourceURL='.concat(o.sourceRoot || '').concat(e, ' */');\n                  });\n                return [n].concat(i).concat([r]).join('\\n');\n              }\n              var a, s, l;\n              return [n].join('\\n');\n            })(t, e);\n            return t[2] ? '@media '.concat(t[2], ' {').concat(n, '}') : n;\n          }).join('');\n        }),\n        (t.i = function (e, n, o) {\n          'string' == typeof e && (e = [[null, e, '']]);\n          var r = {};\n          if (o)\n            for (var i = 0; i < this.length; i++) {\n              var a = this[i][0];\n              null != a && (r[a] = !0);\n            }\n          for (var s = 0; s < e.length; s++) {\n            var l = [].concat(e[s]);\n            (o && r[l[0]]) ||\n              (n && (l[2] ? (l[2] = ''.concat(n, ' and ').concat(l[2])) : (l[2] = n)), t.push(l));\n          }\n        }),\n        t\n      );\n    };\n  },\n  function (e, t) {\n    var n = 'function' == typeof Float32Array;\n    function o(e, t) {\n      return 1 - 3 * t + 3 * e;\n    }\n    function r(e, t) {\n      return 3 * t - 6 * e;\n    }\n    function i(e) {\n      return 3 * e;\n    }\n    function a(e, t, n) {\n      return ((o(t, n) * e + r(t, n)) * e + i(t)) * e;\n    }\n    function s(e, t, n) {\n      return 3 * o(t, n) * e * e + 2 * r(t, n) * e + i(t);\n    }\n    function l(e) {\n      return e;\n    }\n    e.exports = function (e, t, o, r) {\n      if (!(0 <= e && e <= 1 && 0 <= o && o <= 1))\n        throw new Error('bezier x values must be in [0, 1] range');\n      if (e === t && o === r) return l;\n      for (var i = n ? new Float32Array(11) : new Array(11), c = 0; c < 11; ++c)\n        i[c] = a(0.1 * c, e, o);\n      function u(t) {\n        for (var n = 0, r = 1; 10 !== r && i[r] <= t; ++r) n += 0.1;\n        --r;\n        var l = n + 0.1 * ((t - i[r]) / (i[r + 1] - i[r])),\n          c = s(l, e, o);\n        return c >= 0.001\n          ? (function (e, t, n, o) {\n              for (var r = 0; r < 4; ++r) {\n                var i = s(t, n, o);\n                if (0 === i) return t;\n                t -= (a(t, n, o) - e) / i;\n              }\n              return t;\n            })(t, l, e, o)\n          : 0 === c\n          ? l\n          : (function (e, t, n, o, r) {\n              var i,\n                s,\n                l = 0;\n              do {\n                (i = a((s = t + (n - t) / 2), o, r) - e) > 0 ? (n = s) : (t = s);\n              } while (Math.abs(i) > 1e-7 && ++l < 10);\n              return s;\n            })(t, n, n + 0.1, e, o);\n      }\n      return function (e) {\n        return 0 === e ? 0 : 1 === e ? 1 : a(u(e), t, r);\n      };\n    };\n  },\n  function (e, t, n) {\n    var o = n(0),\n      r = n(4);\n    'string' == typeof (r = r.__esModule ? r.default : r) && (r = [[e.i, r, '']]);\n    var i = { insert: 'head', singleton: !1 };\n    o(r, i);\n    e.exports = r.locals || {};\n  },\n  function (e, t, n) {\n    (t = n(1)(!1)).push([\n      e.i,\n      '/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:0.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,html [type=\"button\"],[type=\"reset\"],[type=\"submit\"]{-webkit-appearance:button}button::-moz-focus-inner,[type=\"button\"]::-moz-focus-inner,[type=\"reset\"]::-moz-focus-inner,[type=\"submit\"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=\"button\"]:-moz-focusring,[type=\"reset\"]:-moz-focusring,[type=\"submit\"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=\"checkbox\"],[type=\"radio\"]{box-sizing:border-box;padding:0}[type=\"number\"]::-webkit-inner-spin-button,[type=\"number\"]::-webkit-outer-spin-button{height:auto}[type=\"search\"]{-webkit-appearance:textfield;outline-offset:-2px}[type=\"search\"]::-webkit-search-cancel-button,[type=\"search\"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}\\n',\n      '',\n    ]),\n      (e.exports = t);\n  },\n  function (e, t, n) {\n    var o = n(0),\n      r = n(6);\n    'string' == typeof (r = r.__esModule ? r.default : r) && (r = [[e.i, r, '']]);\n    var i = { insert: 'head', singleton: !1 };\n    o(r, i);\n    e.exports = r.locals || {};\n  },\n  function (e, t, n) {\n    (t = n(1)(!1)).push([\n      e.i,\n      '.nav.is-fixed{position:fixed;left:0;right:0}.nav.is-fixed .is-active{color:#00d1b2}.section{padding-top:100px}.buttons{position:fixed;z-index:10;top:100px;right:100px;padding:15px 30px;border-radius:10px;background-color:#7a7a7a;background-color:#fff}.buttons label{display:block}.buttons input,.buttons button{display:block;width:100%;height:42px;padding:10px 20px;margin-top:15px;margin-bottom:15px;border:0;border:2px solid #00d1b2;border-radius:10px;font-weight:600;outline:0;transition:all 0.1s}.buttons button{background-color:#00d1b2;cursor:pointer;color:#fff}.buttons button:hover{background-color:#fff;color:#00d1b2}\\n',\n      '',\n    ]),\n      (e.exports = t);\n  },\n  function (e, t, n) {\n    'use strict';\n    n.r(t);\n    var o = function () {\n      var e = this.$createElement;\n      return (this._self._c || e)(\n        this.tag,\n        { ref: 'scrollactive-nav-wrapper', tag: 'component', staticClass: 'scrollactive-nav' },\n        [this._t('default')],\n        2\n      );\n    };\n    o._withStripped = !0;\n    var r = n(2),\n      i = n.n(r);\n    function a(e) {\n      return (\n        (function (e) {\n          if (Array.isArray(e)) return s(e);\n        })(e) ||\n        (function (e) {\n          if ('undefined' != typeof Symbol && Symbol.iterator in Object(e)) return Array.from(e);\n        })(e) ||\n        (function (e, t) {\n          if (!e) return;\n          if ('string' == typeof e) return s(e, t);\n          var n = Object.prototype.toString.call(e).slice(8, -1);\n          'Object' === n && e.constructor && (n = e.constructor.name);\n          if ('Map' === n || 'Set' === n) return Array.from(e);\n          if ('Arguments' === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))\n            return s(e, t);\n        })(e) ||\n        (function () {\n          throw new TypeError(\n            'Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.'\n          );\n        })()\n      );\n    }\n    function s(e, t) {\n      (null == t || t > e.length) && (t = e.length);\n      for (var n = 0, o = new Array(t); n < t; n++) o[n] = e[n];\n      return o;\n    }\n    var l = (function (e, t, n, o, r, i, a, s) {\n      var l,\n        c = 'function' == typeof e ? e.options : e;\n      if (\n        (t && ((c.render = t), (c.staticRenderFns = n), (c._compiled = !0)),\n        o && (c.functional = !0),\n        i && (c._scopeId = 'data-v-' + i),\n        a\n          ? ((l = function (e) {\n              (e =\n                e ||\n                (this.$vnode && this.$vnode.ssrContext) ||\n                (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext)) ||\n                'undefined' == typeof __VUE_SSR_CONTEXT__ ||\n                (e = __VUE_SSR_CONTEXT__),\n                r && r.call(this, e),\n                e && e._registeredComponents && e._registeredComponents.add(a);\n            }),\n            (c._ssrRegister = l))\n          : r &&\n            (l = s\n              ? function () {\n                  r.call(this, (c.functional ? this.parent : this).$root.$options.shadowRoot);\n                }\n              : r),\n        l)\n      )\n        if (c.functional) {\n          c._injectStyles = l;\n          var u = c.render;\n          c.render = function (e, t) {\n            return l.call(t), u(e, t);\n          };\n        } else {\n          var f = c.beforeCreate;\n          c.beforeCreate = f ? [].concat(f, l) : [l];\n        }\n      return { exports: e, options: c };\n    })(\n      {\n        props: {\n          activeClass: { type: String, default: 'is-active' },\n          offset: { type: Number, default: 20 },\n          scrollOffset: { type: Number, default: null },\n          scrollContainerSelector: { type: String, default: '' },\n          clickToScroll: { type: Boolean, default: !0 },\n          duration: { type: Number, default: 600 },\n          alwaysTrack: { type: Boolean, default: !1 },\n          bezierEasingValue: { type: String, default: '.5,0,.35,1' },\n          modifyUrl: { type: Boolean, default: !0 },\n          exact: { type: Boolean, default: !1 },\n          highlightFirstItem: { type: Boolean, default: !1 },\n          tag: { type: String, default: 'nav' },\n          scrollOnStart: { type: Boolean, default: !0 },\n        },\n        data: function () {\n          return {\n            observer: null,\n            items: [],\n            currentItem: null,\n            lastActiveItem: null,\n            scrollAnimationFrame: null,\n            bezierEasing: i.a,\n          };\n        },\n        computed: {\n          cubicBezierArray: function () {\n            return this.bezierEasingValue.split(',');\n          },\n          scrollContainer: function () {\n            var e = window;\n            return (\n              this.scrollContainerSelector &&\n                (e = document.querySelector(this.scrollContainerSelector) || window),\n              e\n            );\n          },\n        },\n        mounted: function () {\n          var e = window.MutationObserver || window.WebKitMutationObserver;\n          this.observer ||\n            ((this.observer = new e(this.initScrollactiveItems)),\n            this.observer.observe(this.$refs['scrollactive-nav-wrapper'], {\n              childList: !0,\n              subtree: !0,\n            })),\n            this.initScrollactiveItems(),\n            this.removeActiveClass(),\n            (this.currentItem = this.getItemInsideWindow()),\n            this.currentItem && this.currentItem.classList.add(this.activeClass),\n            this.scrollOnStart && this.scrollToHashElement(),\n            this.scrollContainer.addEventListener('scroll', this.onScroll);\n        },\n        updated: function () {\n          this.initScrollactiveItems();\n        },\n        beforeDestroy: function () {\n          this.scrollContainer.removeEventListener('scroll', this.onScroll),\n            window.cancelAnimationFrame(this.scrollAnimationFrame);\n        },\n        methods: {\n          onScroll: function (e) {\n            (this.currentItem = this.getItemInsideWindow()),\n              this.currentItem !== this.lastActiveItem &&\n                (this.removeActiveClass(),\n                this.$emit('itemchanged', e, this.currentItem, this.lastActiveItem),\n                (this.lastActiveItem = this.currentItem)),\n              this.currentItem && this.currentItem.classList.add(this.activeClass);\n          },\n          getItemInsideWindow: function () {\n            var e,\n              t = this;\n            return (\n              [].forEach.call(this.items, function (n) {\n                var o = n === t.items[0],\n                  r = document.getElementById(decodeURI(n.hash.substr(1)));\n                if (r) {\n                  var i = t.scrollContainer.scrollTop || window.pageYOffset,\n                    a = i >= t.getOffsetTop(r) - t.offset,\n                    s = i < t.getOffsetTop(r) - t.offset + r.offsetHeight;\n                  o && t.highlightFirstItem && s && (e = n),\n                    t.exact && a && s && (e = n),\n                    !t.exact && a && (e = n);\n                }\n              }),\n              e\n            );\n          },\n          initScrollactiveItems: function () {\n            var e = this;\n            (this.items = this.$el.querySelectorAll('.scrollactive-item')),\n              this.clickToScroll\n                ? [].forEach.call(this.items, function (t) {\n                    t.addEventListener('click', e.handleClick);\n                  })\n                : [].forEach.call(this.items, function (t) {\n                    t.removeEventListener('click', e.handleClick);\n                  });\n          },\n          setScrollactiveItems: function () {\n            this.initScrollactiveItems();\n          },\n          handleClick: function (e) {\n            var t = this;\n            e.preventDefault();\n            var n = e.currentTarget.hash,\n              o = document.getElementById(decodeURI(n.substr(1)));\n            o\n              ? (this.alwaysTrack ||\n                  (this.scrollContainer.removeEventListener('scroll', this.onScroll),\n                  window.cancelAnimationFrame(this.scrollAnimationFrame),\n                  this.removeActiveClass(),\n                  e.currentTarget.classList.add(this.activeClass)),\n                this.scrollTo(o).then(function () {\n                  if (!t.alwaysTrack) {\n                    t.scrollContainer.addEventListener('scroll', t.onScroll);\n                    (t.currentItem = [].find.call(t.items, function (e) {\n                      return decodeURI(e.hash.substr(1)) === o.id;\n                    })),\n                      t.currentItem !== t.lastActiveItem &&\n                        (t.$emit('itemchanged', null, t.currentItem, t.lastActiveItem),\n                        (t.lastActiveItem = t.currentItem));\n                  }\n                  t.modifyUrl && t.pushHashToUrl(n);\n                }))\n              : console.warn(\n                  \"[vue-scrollactive] Element '\".concat(\n                    n,\n                    \"' was not found. Make sure it is set in the DOM.\"\n                  )\n                );\n          },\n          scrollTo: function (e) {\n            var t = this;\n            return new Promise(function (n) {\n              var o = t.getOffsetTop(e),\n                r = t.scrollContainer.scrollTop || window.pageYOffset,\n                i = o - r,\n                s = t.bezierEasing.apply(t, a(t.cubicBezierArray)),\n                l = null;\n              window.requestAnimationFrame(function e(o) {\n                l || (l = o);\n                var a = o - l,\n                  c = a / t.duration;\n                a >= t.duration && (a = t.duration), c >= 1 && (c = 1);\n                var u = t.scrollOffset || t.offset,\n                  f = r + s(c) * (i - u);\n                t.scrollContainer.scrollTo(0, f),\n                  a < t.duration ? (t.scrollAnimationFrame = window.requestAnimationFrame(e)) : n();\n              });\n            });\n          },\n          getOffsetTop: function (e) {\n            for (var t = 0, n = e; n; ) (t += n.offsetTop), (n = n.offsetParent);\n            return this.scrollContainer.offsetTop && (t -= this.scrollContainer.offsetTop), t;\n          },\n          removeActiveClass: function () {\n            var e = this;\n            [].forEach.call(this.items, function (t) {\n              t.classList.remove(e.activeClass);\n            });\n          },\n          scrollToHashElement: function () {\n            var e = this,\n              t = window.location.hash;\n            if (t) {\n              var n = document.querySelector(decodeURI(t));\n              n &&\n                ((window.location.hash = ''),\n                setTimeout(function () {\n                  var o = n.offsetTop - e.offset;\n                  e.scrollContainer.scrollTo(0, o), e.pushHashToUrl(t);\n                }, 0));\n            }\n          },\n          pushHashToUrl: function (e) {\n            window.history.pushState\n              ? window.history.pushState(null, null, e)\n              : (window.location.hash = e);\n          },\n        },\n      },\n      o,\n      [],\n      !1,\n      null,\n      null,\n      null\n    );\n    l.options.__file = 'src/scrollactive.vue';\n    var c = l.exports,\n      u = {\n        install: function (e) {\n          u.install.installed || e.component('scrollactive', c);\n        },\n      };\n    'undefined' != typeof window && window.Vue && u.install(window.Vue);\n    var f = u;\n    n(3), n(5);\n    Vue.use(f);\n    var d = new Vue({\n      el: '#app',\n      data: {\n        elements: [],\n        alwaysTrack: !1,\n        duration: 600,\n        clickToScroll: !0,\n        offset: 52,\n        easing: '.5,0,.35,1',\n      },\n      computed: {\n        numberOfElements: function () {\n          return this.elements.length;\n        },\n      },\n      mounted: function () {\n        this.elements = this.$el.querySelectorAll('.scrollactive-item');\n      },\n      methods: {\n        addNewElement: function () {\n          var e = this.numberOfElements + 1,\n            t = this.numberOfElements % 2 == 0 ? 'is-primary' : 'is-danger',\n            n = document.createElement('div');\n          (n.innerHTML = '<a href=\"#section-'\n            .concat(e, '\" class=\"scrollactive-item nav-item\">Section ')\n            .concat(e, '</a>')),\n            document.querySelector('.nav-center').appendChild(n.firstChild);\n          var o = document.createElement('div');\n          (o.innerHTML = '<section id=\"section-'\n            .concat(e, '\" class=\"section hero ')\n            .concat(\n              t,\n              ' is-fullheight\">\\n      <div class=\"container\">\\n      <h1 class=\"heading title is-1\">Section '\n            )\n            .concat(e, '</h1>\\n      </div>\\n      </section>\\n      ')),\n            document.querySelector('main').appendChild(o.firstChild),\n            (this.elements = this.$el.querySelectorAll('.scrollactive-item'));\n        },\n        removeElement: function () {\n          if (this.numberOfElements >= 1) {\n            var e = [].map\n              .call(this.elements, function (e) {\n                return e.hash;\n              })\n              .slice(-1);\n            document.querySelector('.nav-center a[href=\"'.concat(e, '\"]')).remove(),\n              document.querySelector('main').removeChild(document.querySelector(e)),\n              (this.elements = this.$el.querySelectorAll('.scrollactive-item'));\n          }\n        },\n      },\n    });\n    t.default = d;\n  },\n]);\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"vue-scrollactive\",\n  \"version\": \"0.9.3\",\n  \"title\": \"Vue Scrollactive\",\n  \"description\": \"Lightweight and simple to use vue component that highlights menu items as you scroll the page, also scrolling to target section when clicked.\",\n  \"main\": \"dist/vue-scrollactive.min.js\",\n  \"scripts\": {\n    \"start\": \"webpack-dev-server\",\n    \"sandbox\": \"webpack\",\n    \"prod\": \"TARGET=production webpack\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/eddiemf/vue-scrollactive.git\"\n  },\n  \"keywords\": [\n    \"vue\",\n    \"vue-plugin\",\n    \"vue-component\",\n    \"scrollspy\",\n    \"scroll\",\n    \"active\",\n    \"active-class\",\n    \"menu-item\",\n    \"highlight-menu-item\"\n  ],\n  \"author\": {\n    \"name\": \"Mauricio Farias Dziedzinski\",\n    \"email\": \"d.mauriciofarias@gmail.com\"\n  },\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/eddiemf/vue-scrollactive/issues\"\n  },\n  \"homepage\": \"https://github.com/eddiemf/vue-scrollactive#readme\",\n  \"dependencies\": {\n    \"bezier-easing\": \"^2.0.3\"\n  },\n  \"devDependencies\": {\n    \"@babel/cli\": \"^7.8.4\",\n    \"@babel/core\": \"^7.9.6\",\n    \"@babel/plugin-transform-runtime\": \"^7.9.6\",\n    \"@babel/preset-env\": \"^7.9.6\",\n    \"babel-loader\": \"^8.1.0\",\n    \"css-loader\": \"^3.5.3\",\n    \"eslint\": \"^7.0.0\",\n    \"html-webpack-plugin\": \"^4.3.0\",\n    \"husky\": \"^4.2.5\",\n    \"node-sass\": \"^4.14.1\",\n    \"prettier\": \"^2.0.5\",\n    \"pretty-quick\": \"^2.0.1\",\n    \"sass-loader\": \"^8.0.2\",\n    \"style-loader\": \"^1.2.1\",\n    \"vue-loader\": \"^15.9.2\",\n    \"vue-style-loader\": \"^4.1.2\",\n    \"vue-template-compiler\": \"^2.6.11\",\n    \"webpack\": \"^4.43.0\",\n    \"webpack-cli\": \"^3.3.11\",\n    \"webpack-dev-server\": \"^3.11.0\"\n  },\n  \"husky\": {\n    \"hooks\": {\n      \"pre-commit\": \"pretty-quick --staged\"\n    }\n  }\n}\n"
  },
  {
    "path": "src/ScrollContainer.js",
    "content": "export class ScrollContainer {\n  constructor(containerSelector) {\n    let container = window;\n\n    if (containerSelector) {\n      container = document.querySelector(containerSelector) || window;\n    }\n\n    this.container = container;\n  }\n\n  addScrollListener(callback) {\n    this.scrollListenerCallback = callback;\n    this.container.addEventListener('scroll', callback);\n  }\n\n  removeScrollListener() {\n    this.container.removeEventListener('scroll', this.scrollListenerCallback);\n  }\n\n  getDistanceFromTop() {\n    return this.container.scrollTop || this.container.pageYOffset;\n  }\n\n  scrollTo(x, y) {\n    return this.container.scrollTo(x, y);\n  }\n\n  getOffsetTop() {\n    return this.container.offsetTop;\n  }\n}\n"
  },
  {
    "path": "src/index.js",
    "content": "import Scrollactive from './scrollactive.vue';\n\nconst Plugin = {};\n\nPlugin.install = (Vue) => {\n  if (Plugin.install.installed) return;\n\n  Vue.component('scrollactive', Scrollactive);\n};\n\nif (typeof window !== 'undefined' && window.Vue) {\n  Plugin.install(window.Vue);\n}\n\nexport default Plugin;\n"
  },
  {
    "path": "src/sandbox/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Scrollactive!</title>\n    <link\n      rel=\"stylesheet\"\n      href=\"https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.2/css/bulma.min.css\"\n    />\n  </head>\n  <body>\n    <div id=\"app\">\n      <header id=\"site-header\" class=\"nav is-fixed\">\n        <div class=\"container\">\n          <scrollactive\n            ref=\"scrollactive\"\n            :offset=\"offset\"\n            :always-track=\"alwaysTrack\"\n            :duration=\"duration\"\n            :click-to-scroll=\"clickToScroll\"\n            :bezier-easing-value=\"easing\"\n          >\n            <ul class=\"nav-center\">\n              <li>\n                <a href=\"#section-1\" class=\"scrollactive-item nav-item\">Section 1</a>\n              </li>\n              <li>\n                <a href=\"#section-2\" class=\"scrollactive-item nav-item\">Section 2</a>\n              </li>\n              <li>\n                <a href=\"#section-3\" class=\"scrollactive-item nav-item\">Section 3</a>\n              </li>\n              <li>\n                <a href=\"#section-4\" class=\"scrollactive-item nav-item\">Section 4</a>\n              </li>\n            </ul>\n          </scrollactive>\n        </div>\n      </header>\n\n      <div class=\"buttons\">\n        <button @click=\"addNewElement()\">Add new element</button>\n        <button @click=\"removeElement()\">Remove last element</button>\n        <button\n          @click=\"alwaysTrack = !alwaysTrack\"\n          v-text=\"'Always track ' + (alwaysTrack ? 'on' : 'off')\"\n        ></button>\n        <button\n          @click=\"clickToScroll = !clickToScroll\"\n          v-text=\"'Click to scroll ' + (clickToScroll ? 'on' : 'off')\"\n        ></button>\n        <label for=\"duration\">Duration</label>\n        <input type=\"number\" v-model=\"duration\" id=\"duration\" />\n        <label for=\"offset\">Offset</label>\n        <input type=\"number\" v-model=\"offset\" id=\"offset\" />\n        <label for=\"easing\">Easing (cubic-bezier format)</label>\n        <input type=\"text\" v-model=\"easing\" id=\"easing\" />\n      </div>\n\n      <main>\n        <section id=\"section-1\" class=\"section hero is-primary is-fullheight\">\n          <div class=\"container\">\n            <h1 class=\"heading title is-1\">Section 1</h1>\n          </div>\n        </section>\n\n        <section id=\"section-2\" class=\"section hero is-info is-fullheight\">\n          <div class=\"container\">\n            <h1 class=\"heading title is-1\">Section 2</h1>\n          </div>\n        </section>\n\n        <section id=\"section-3\" class=\"section hero is-danger is-fullheight\">\n          <div class=\"container\">\n            <h1 class=\"heading title is-1\">Section 3</h1>\n          </div>\n        </section>\n\n        <section id=\"section-4\" class=\"section hero is-success is-fullheight\">\n          <div class=\"container\">\n            <h1 class=\"heading title is-1\">Section 4</h1>\n          </div>\n        </section>\n      </main>\n    </div>\n\n    <script src=\"https://unpkg.com/vue\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "src/sandbox/normalize.scss",
    "content": "/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n   ========================================================================== */\n\n/**\n * 1. Correct the line height in all browsers.\n * 2. Prevent adjustments of font size after orientation changes in\n *    IE on Windows Phone and in iOS.\n */\n\nhtml {\n  line-height: 1.15; /* 1 */\n  -ms-text-size-adjust: 100%; /* 2 */\n  -webkit-text-size-adjust: 100%; /* 2 */\n}\n\n/* Sections\n   ========================================================================== */\n\n/**\n * Remove the margin in all browsers (opinionated).\n */\n\nbody {\n  margin: 0;\n}\n\n/**\n * Add the correct display in IE 9-.\n */\n\narticle,\naside,\nfooter,\nheader,\nnav,\nsection {\n  display: block;\n}\n\n/**\n * Correct the font size and margin on `h1` elements within `section` and\n * `article` contexts in Chrome, Firefox, and Safari.\n */\n\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n/* Grouping content\n   ========================================================================== */\n\n/**\n * Add the correct display in IE 9-.\n * 1. Add the correct display in IE.\n */\n\nfigcaption,\nfigure,\nmain {\n  /* 1 */\n  display: block;\n}\n\n/**\n * Add the correct margin in IE 8.\n */\n\nfigure {\n  margin: 1em 40px;\n}\n\n/**\n * 1. Add the correct box sizing in Firefox.\n * 2. Show the overflow in Edge and IE.\n */\n\nhr {\n  box-sizing: content-box; /* 1 */\n  height: 0; /* 1 */\n  overflow: visible; /* 2 */\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\npre {\n  font-family: monospace, monospace; /* 1 */\n  font-size: 1em; /* 2 */\n}\n\n/* Text-level semantics\n   ========================================================================== */\n\n/**\n * 1. Remove the gray background on active links in IE 10.\n * 2. Remove gaps in links underline in iOS 8+ and Safari 8+.\n */\n\na {\n  background-color: transparent; /* 1 */\n  -webkit-text-decoration-skip: objects; /* 2 */\n}\n\n/**\n * 1. Remove the bottom border in Chrome 57- and Firefox 39-.\n * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n */\n\nabbr[title] {\n  border-bottom: none; /* 1 */\n  text-decoration: underline; /* 2 */\n  text-decoration: underline dotted; /* 2 */\n}\n\n/**\n * Prevent the duplicate application of `bolder` by the next rule in Safari 6.\n */\n\nb,\nstrong {\n  font-weight: inherit;\n}\n\n/**\n * Add the correct font weight in Chrome, Edge, and Safari.\n */\n\nb,\nstrong {\n  font-weight: bolder;\n}\n\n/**\n * 1. Correct the inheritance and scaling of font size in all browsers.\n * 2. Correct the odd `em` font sizing in all browsers.\n */\n\ncode,\nkbd,\nsamp {\n  font-family: monospace, monospace; /* 1 */\n  font-size: 1em; /* 2 */\n}\n\n/**\n * Add the correct font style in Android 4.3-.\n */\n\ndfn {\n  font-style: italic;\n}\n\n/**\n * Add the correct background and color in IE 9-.\n */\n\nmark {\n  background-color: #ff0;\n  color: #000;\n}\n\n/**\n * Add the correct font size in all browsers.\n */\n\nsmall {\n  font-size: 80%;\n}\n\n/**\n * Prevent `sub` and `sup` elements from affecting the line height in\n * all browsers.\n */\n\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nsup {\n  top: -0.5em;\n}\n\n/* Embedded content\n   ========================================================================== */\n\n/**\n * Add the correct display in IE 9-.\n */\n\naudio,\nvideo {\n  display: inline-block;\n}\n\n/**\n * Add the correct display in iOS 4-7.\n */\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n/**\n * Remove the border on images inside links in IE 10-.\n */\n\nimg {\n  border-style: none;\n}\n\n/**\n * Hide the overflow in IE.\n */\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\n/* Forms\n   ========================================================================== */\n\n/**\n * 1. Change the font styles in all browsers (opinionated).\n * 2. Remove the margin in Firefox and Safari.\n */\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  font-family: sans-serif; /* 1 */\n  font-size: 100%; /* 1 */\n  line-height: 1.15; /* 1 */\n  margin: 0; /* 2 */\n}\n\n/**\n * Show the overflow in IE.\n * 1. Show the overflow in Edge.\n */\n\nbutton,\ninput {\n  /* 1 */\n  overflow: visible;\n}\n\n/**\n * Remove the inheritance of text transform in Edge, Firefox, and IE.\n * 1. Remove the inheritance of text transform in Firefox.\n */\n\nbutton,\nselect {\n  /* 1 */\n  text-transform: none;\n}\n\n/**\n * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n *    controls in Android 4.\n * 2. Correct the inability to style clickable types in iOS and Safari.\n */\n\nbutton,\nhtml [type=\"button\"], /* 1 */\n[type=\"reset\"],\n[type=\"submit\"] {\n  -webkit-appearance: button; /* 2 */\n}\n\n/**\n * Remove the inner border and padding in Firefox.\n */\n\nbutton::-moz-focus-inner,\n[type='button']::-moz-focus-inner,\n[type='reset']::-moz-focus-inner,\n[type='submit']::-moz-focus-inner {\n  border-style: none;\n  padding: 0;\n}\n\n/**\n * Restore the focus styles unset by the previous rule.\n */\n\nbutton:-moz-focusring,\n[type='button']:-moz-focusring,\n[type='reset']:-moz-focusring,\n[type='submit']:-moz-focusring {\n  outline: 1px dotted ButtonText;\n}\n\n/**\n * Correct the padding in Firefox.\n */\n\nfieldset {\n  padding: 0.35em 0.75em 0.625em;\n}\n\n/**\n * 1. Correct the text wrapping in Edge and IE.\n * 2. Correct the color inheritance from `fieldset` elements in IE.\n * 3. Remove the padding so developers are not caught out when they zero out\n *    `fieldset` elements in all browsers.\n */\n\nlegend {\n  box-sizing: border-box; /* 1 */\n  color: inherit; /* 2 */\n  display: table; /* 1 */\n  max-width: 100%; /* 1 */\n  padding: 0; /* 3 */\n  white-space: normal; /* 1 */\n}\n\n/**\n * 1. Add the correct display in IE 9-.\n * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.\n */\n\nprogress {\n  display: inline-block; /* 1 */\n  vertical-align: baseline; /* 2 */\n}\n\n/**\n * Remove the default vertical scrollbar in IE.\n */\n\ntextarea {\n  overflow: auto;\n}\n\n/**\n * 1. Add the correct box sizing in IE 10-.\n * 2. Remove the padding in IE 10-.\n */\n\n[type='checkbox'],\n[type='radio'] {\n  box-sizing: border-box; /* 1 */\n  padding: 0; /* 2 */\n}\n\n/**\n * Correct the cursor style of increment and decrement buttons in Chrome.\n */\n\n[type='number']::-webkit-inner-spin-button,\n[type='number']::-webkit-outer-spin-button {\n  height: auto;\n}\n\n/**\n * 1. Correct the odd appearance in Chrome and Safari.\n * 2. Correct the outline style in Safari.\n */\n\n[type='search'] {\n  -webkit-appearance: textfield; /* 1 */\n  outline-offset: -2px; /* 2 */\n}\n\n/**\n * Remove the inner padding and cancel buttons in Chrome and Safari on macOS.\n */\n\n[type='search']::-webkit-search-cancel-button,\n[type='search']::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\n/**\n * 1. Correct the inability to style clickable types in iOS and Safari.\n * 2. Change font properties to `inherit` in Safari.\n */\n\n::-webkit-file-upload-button {\n  -webkit-appearance: button; /* 1 */\n  font: inherit; /* 2 */\n}\n\n/* Interactive\n   ========================================================================== */\n\n/*\n * Add the correct display in IE 9-.\n * 1. Add the correct display in Edge, IE, and Firefox.\n */\n\ndetails, /* 1 */\nmenu {\n  display: block;\n}\n\n/*\n * Add the correct display in all browsers.\n */\n\nsummary {\n  display: list-item;\n}\n\n/* Scripting\n   ========================================================================== */\n\n/**\n * Add the correct display in IE 9-.\n */\n\ncanvas {\n  display: inline-block;\n}\n\n/**\n * Add the correct display in IE.\n */\n\ntemplate {\n  display: none;\n}\n\n/* Hidden\n   ========================================================================== */\n\n/**\n * Add the correct display in IE 10-.\n */\n\n[hidden] {\n  display: none;\n}\n"
  },
  {
    "path": "src/sandbox/sandbox.js",
    "content": "import Scrollactive from '../index';\nimport './normalize.scss';\nimport './sandbox.scss';\n\nVue.use(Scrollactive);\n\nconst app = new Vue({\n  el: '#app',\n  data: {\n    elements: [],\n    alwaysTrack: false,\n    duration: 600,\n    clickToScroll: true,\n    offset: 52,\n    easing: '.5,0,.35,1',\n  },\n  computed: {\n    numberOfElements() {\n      return this.elements.length;\n    },\n  },\n  mounted() {\n    this.elements = this.$el.querySelectorAll('.scrollactive-item');\n  },\n  methods: {\n    addNewElement() {\n      const sectionNumber = this.numberOfElements + 1;\n      const colorClass = this.numberOfElements % 2 === 0 ? 'is-primary' : 'is-danger';\n      const menuItem = document.createElement('div');\n      menuItem.innerHTML = `<a href=\"#section-${sectionNumber}\" class=\"scrollactive-item nav-item\">Section ${sectionNumber}</a>`;\n      document.querySelector('.nav-center').appendChild(menuItem.firstChild);\n\n      const section = document.createElement('div');\n      section.innerHTML = `<section id=\"section-${sectionNumber}\" class=\"section hero ${colorClass} is-fullheight\">\n      <div class=\"container\">\n      <h1 class=\"heading title is-1\">Section ${sectionNumber}</h1>\n      </div>\n      </section>\n      `;\n      document.querySelector('main').appendChild(section.firstChild);\n      this.elements = this.$el.querySelectorAll('.scrollactive-item');\n    },\n    removeElement() {\n      if (this.numberOfElements >= 1) {\n        const elementsIds = [].map.call(this.elements, (el) => el.hash);\n        const lastElementId = elementsIds.slice(-1);\n\n        document.querySelector(`.nav-center a[href=\"${lastElementId}\"]`).remove();\n        document.querySelector('main').removeChild(document.querySelector(lastElementId));\n\n        this.elements = this.$el.querySelectorAll('.scrollactive-item');\n      }\n    },\n  },\n});\n\nexport default app;\n"
  },
  {
    "path": "src/sandbox/sandbox.scss",
    "content": ".nav.is-fixed {\n  position: fixed;\n  left: 0;\n  right: 0;\n\n  .is-active {\n    color: #00d1b2;\n  }\n}\n\n.section {\n  padding-top: 100px;\n}\n\n.buttons {\n  position: fixed;\n  z-index: 10;\n  top: 100px;\n  right: 100px;\n  padding: 15px 30px;\n  border-radius: 10px;\n  background-color: #7a7a7a;\n  background-color: #fff;\n\n  label {\n    display: block;\n  }\n\n  input,\n  button {\n    display: block;\n    width: 100%;\n    height: 42px;\n    padding: 10px 20px;\n    margin-top: 15px;\n    margin-bottom: 15px;\n    border: 0;\n    border: 2px solid #00d1b2;\n    border-radius: 10px;\n    font-weight: 600;\n    outline: 0;\n    transition: all 0.1s;\n  }\n\n  button {\n    background-color: #00d1b2;\n    cursor: pointer;\n    color: #fff;\n\n    &:hover {\n      background-color: #fff;\n      color: #00d1b2;\n    }\n  }\n}\n"
  },
  {
    "path": "src/scrollactive.vue",
    "content": "<script>\nimport bezierEasing from 'bezier-easing';\nimport { ScrollContainer } from './ScrollContainer';\nimport {\n  forEach,\n  find,\n  getIdFromHash,\n  pushHashToUrl,\n  getSectionSelector,\n  getSectionIdFromElement,\n} from './utils';\n\nexport default {\n  props: {\n    /**\n     * Active class that will be applied to the active item.\n     */\n    activeClass: {\n      type: String,\n      default: 'is-active',\n    },\n\n    /**\n     * Amount of space between top of screen and the section to highlight. (Usually your fixed\n     * header's height).\n     */\n    offset: {\n      type: Number,\n      default: 20,\n    },\n\n    /**\n     * Amount of space between the top of the screen and the section to highlight when clicking a\n     * scrollactive item to scroll. It will use the value of the `offset` prop if none is provided\n     * here. Useful when you want to use the `offset` prop to make an item be active as soon as\n     * it shows on the screen but still scroll to the top of the section when clicking the item.\n     */\n    scrollOffset: {\n      type: Number,\n      default: null,\n    },\n\n    /**\n     * The selector string of the scroll container element you'd like to use. It defaults to the\n     * window object (most common), but you might want to change in case you're using an element\n     * as container with overflow.\n     */\n    scrollContainerSelector: {\n      type: String,\n      default: '',\n    },\n\n    /**\n     * Enables/disables the scrolling when clicking in a menu item.\n     * Disable if you'd like to handle the scrolling by your own.\n     */\n    clickToScroll: {\n      type: Boolean,\n      default: true,\n    },\n\n    /**\n     * The duration of the scroll animation when clicking to scroll is activated.\n     */\n    duration: {\n      type: Number,\n      default: 600,\n    },\n\n    /**\n     * Defines if the plugin should track the section change when clicking an item to scroll to\n     * its section. If set to true, it will always keep track and change the active class to the\n     * current section while scrolling, if false, the active class will be immediately applied to\n     * the clicked menu item, ignoring the passed sections until the scrolling is over.\n     */\n    alwaysTrack: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     * Your custom easing value for the click to scroll functionality.\n     * It must be a string with 4 values separated by commas in a cubic bezier format.\n     */\n    bezierEasingValue: {\n      type: String,\n      default: '.5,0,.35,1',\n    },\n\n    /**\n     * Decides if the URL should be modified with the section id when clicking a scrollactive\n     * item.\n     */\n    modifyUrl: {\n      type: Boolean,\n      default: true,\n    },\n\n    /**\n     * If true the active class will only be applied when a section matches exactly one of the\n     * scrollactive items, meaning it will be highlighted when scrolling exactly inside the\n     * section. If false (default) it will always highlight the last item which was matched\n     * in a section, even if it is already outside that section (and not inside another that's\n     * being tracked).\n     */\n    exact: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     * If true the active class will be applied to the first scrollactive-item before you scroll\n     * past it (even if you didn't reach it yet).\n     */\n    highlightFirstItem: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     * Changes the scrollactive container component html tag.\n     */\n    tag: {\n      type: String,\n      default: 'nav',\n    },\n\n    /**\n     * If true the screen will scroll down to the element in the URL when the component is mounted.\n     */\n    scrollOnStart: {\n      type: Boolean,\n      default: true,\n    },\n  },\n\n  data() {\n    return {\n      observer: null,\n      items: [],\n      currentItem: null,\n      lastActiveItem: null,\n      scrollAnimationFrame: null,\n      bezierEasing,\n    };\n  },\n\n  computed: {\n    /**\n     * Computes the bezier easing string value into an array.\n     */\n    cubicBezierArray() {\n      return this.bezierEasingValue.split(',');\n    },\n\n    scrollContainer() {\n      return new ScrollContainer(this.scrollContainerSelector);\n    },\n  },\n\n  mounted() {\n    this.resetOnDOMChange();\n    this.initScrollactiveItems();\n    this.removeActiveClass();\n    this.currentItem = this.getItemInsideWindow();\n\n    if (this.currentItem) this.currentItem.classList.add(this.activeClass);\n\n    if (this.scrollOnStart) this.scrollToHashElement();\n\n    this.scrollContainer.addScrollListener(this.onScroll);\n  },\n\n  updated() {\n    this.initScrollactiveItems();\n  },\n\n  beforeDestroy() {\n    this.scrollContainer.removeScrollListener();\n    window.cancelAnimationFrame(this.scrollAnimationFrame);\n  },\n\n  methods: {\n    /**\n     * Makes sure the component is recalculated whenever the DOM tree changes inside of the\n     * scrollactive wrapper.\n     */\n    resetOnDOMChange() {\n      const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;\n\n      if (!this.observer) {\n        this.observer = new MutationObserver(this.initScrollactiveItems);\n        // Calls this.initScrollactiveItems() whenever the DOM tree is changed inside of the wrapper\n        this.observer.observe(this.$refs['scrollactive-nav-wrapper'], {\n          childList: true,\n          subtree: true,\n        });\n      }\n    },\n\n    /**\n     * Sets the list of menu items, adding or removing the click listener depending on the\n     * clickToScroll prop.\n     */\n    initScrollactiveItems() {\n      const elements = this.$el.querySelectorAll('.scrollactive-item');\n      const items = [];\n\n      forEach(elements, (menuElement) => {\n        const section = document.querySelector(getSectionSelector(menuElement));\n        if (!section) return;\n\n        items.push({ section, menuElement });\n      });\n\n      this.items = items;\n\n      if (this.clickToScroll) {\n        forEach(elements, (element) => element.addEventListener('click', this.onMenuItemClick));\n      } else {\n        forEach(elements, (element) => element.removeEventListener('click', this.onMenuItemClick));\n      }\n    },\n\n    /**\n     * Will be called when scrolling event is triggered to handle the addition of the active class\n     * in the current section item and fire the change event.\n     */\n    onScroll(event) {\n      this.currentItem = this.getItemInsideWindow();\n      const sectionHasChanged = this.currentItem !== this.lastActiveItem;\n\n      if (sectionHasChanged) {\n        this.removeActiveClass();\n        this.$emit('itemchanged', event, this.currentItem, this.lastActiveItem);\n        this.lastActiveItem = this.currentItem;\n      }\n\n      // Check first because item might be null if not inside any section\n      if (this.currentItem) this.currentItem.classList.add(this.activeClass);\n    },\n\n    /**\n     * Gets the scrollactive item that corresponds to the current section inside the window\n     */\n    getItemInsideWindow() {\n      let currentItem;\n\n      forEach(this.items, ({ menuElement, section }, index) => {\n        const isFirstItem = index === 0;\n        const distanceFromTop = this.scrollContainer.getDistanceFromTop();\n        const targetOffsetTop = this.getOffsetTop(section) - this.offset;\n        const isScreenPastSectionStart = distanceFromTop >= targetOffsetTop;\n        const isScreenBeforeSectionEnd = distanceFromTop < targetOffsetTop + section.offsetHeight;\n        const isScreenInsideSection = isScreenPastSectionStart && isScreenBeforeSectionEnd;\n\n        if (isFirstItem && this.highlightFirstItem) {\n          if (isScreenBeforeSectionEnd) currentItem = menuElement;\n        }\n\n        if (this.exact && isScreenInsideSection) currentItem = menuElement;\n        if (!this.exact && isScreenPastSectionStart) currentItem = menuElement;\n      });\n\n      return currentItem;\n    },\n\n    /**\n     * Handles the scrolling when clicking a menu item.\n     */\n    async onMenuItemClick(event) {\n      event.preventDefault();\n\n      const menuItem = event.target;\n      const sectionSelector = getSectionSelector(menuItem);\n      const section = document.querySelector(sectionSelector);\n\n      if (!section) {\n        console.warn(\n          `[vue-scrollactive] Element '${sectionSelector}' was not found. Make sure it is set in the DOM.`\n        );\n\n        return;\n      }\n\n      /**\n       *  Temporarily removes the scroll listener and the request animation frame so the active\n       *  class will only be applied to the clicked element, and not all elements while the window\n       *  is scrolling.\n       */\n      if (!this.alwaysTrack) {\n        this.scrollContainer.removeScrollListener();\n        window.cancelAnimationFrame(this.scrollAnimationFrame);\n\n        this.removeActiveClass();\n        menuItem.classList.add(this.activeClass);\n      }\n\n      await this.scrollTo(section);\n\n      if (!this.alwaysTrack) {\n        this.scrollContainer.addScrollListener(this.onScroll);\n        this.currentItem = menuItem;\n\n        if (this.currentItem !== this.lastActiveItem) {\n          this.$emit('itemchanged', event, this.currentItem, this.lastActiveItem);\n          this.lastActiveItem = this.currentItem;\n        }\n      }\n\n      if (this.modifyUrl) {\n        pushHashToUrl(getSectionIdFromElement(menuItem));\n      }\n    },\n\n    /**\n     * Scrolls the page to the given target element.\n     */\n    scrollTo(target) {\n      return new Promise((resolve) => {\n        const targetDistanceFromTop = this.getOffsetTop(target);\n        const startingY = this.scrollContainer.getDistanceFromTop();\n        const distanceFromTarget = targetDistanceFromTop - startingY;\n        const easing = this.bezierEasing(...this.cubicBezierArray);\n        let startingTime = null;\n\n        const step = (currentTime) => {\n          if (!startingTime) startingTime = currentTime;\n\n          let progress = currentTime - startingTime;\n          let progressPercentage = progress / this.duration;\n\n          if (progress >= this.duration) progress = this.duration;\n          if (progressPercentage >= 1) progressPercentage = 1;\n\n          const offset = this.scrollOffset || this.offset;\n          const perTick = startingY + easing(progressPercentage) * (distanceFromTarget - offset);\n\n          this.scrollContainer.scrollTo(0, perTick);\n\n          if (progress < this.duration) {\n            this.scrollAnimationFrame = window.requestAnimationFrame(step);\n          } else {\n            resolve();\n          }\n        };\n\n        window.requestAnimationFrame(step);\n      });\n    },\n\n    /**\n     * Gets the top offset position of an element in the document.\n     */\n    getOffsetTop(element) {\n      let yPosition = 0;\n      let nextElement = element;\n\n      while (nextElement) {\n        yPosition += nextElement.offsetTop;\n        nextElement = nextElement.offsetParent;\n      }\n\n      if (this.scrollContainer.getOffsetTop()) {\n        yPosition -= this.scrollContainer.getOffsetTop();\n      }\n\n      return yPosition;\n    },\n\n    /**\n     * Removes the active class from all scrollactive items.\n     */\n    removeActiveClass() {\n      // Must be called with 'call' to prevent bugs on some devices\n      forEach(this.items, ({ menuElement }) => {\n        menuElement.classList.remove(this.activeClass);\n      });\n    },\n\n    /**\n     * Scrolls the page to the element passed as a hash in URL, preventing weird native scroll\n     * jumps while maintaining the hash in the URL.\n     */\n    scrollToHashElement() {\n      const { hash } = window.location;\n      if (!hash) return;\n\n      const hashElement = document.getElementById(getIdFromHash(hash));\n      if (!hashElement) return;\n\n      window.location.hash = ''; // Clears the hash to prevent scroll from jumping\n\n      setTimeout(() => {\n        const yPos = hashElement.offsetTop - this.offset;\n\n        this.scrollContainer.scrollTo(0, yPos);\n        // Sets the hash back with pushState so it won't jump to the element ignoring the offset\n        pushHashToUrl(hash);\n      }, 0);\n    },\n  },\n};\n</script>\n\n<template>\n  <component :is=\"tag\" ref=\"scrollactive-nav-wrapper\" class=\"scrollactive-nav\">\n    <slot />\n  </component>\n</template>\n"
  },
  {
    "path": "src/utils/find.js",
    "content": "// Must be called with 'call' to prevent bugs on some devices\nexport const find = (list, callback) => [].find.call(list, callback);\n"
  },
  {
    "path": "src/utils/forEach.js",
    "content": "// Must be called with 'call' to prevent bugs on some devices\nexport const forEach = (list, callback) => [].forEach.call(list, callback);\n"
  },
  {
    "path": "src/utils/getIdFromHash.js",
    "content": "// Decoded in case there are special characters\nexport const getIdFromHash = (hash) => decodeURI(hash.substr(1));\n"
  },
  {
    "path": "src/utils/getSectionIdFromElement.js",
    "content": "export const getSectionIdFromElement = (element) => {\n  if (element.dataset.sectionSelector && element.dataset.sectionSelector.substr(0, 1) === '#') {\n    return element.dataset.sectionSelector;\n  }\n\n  return element.hash;\n};\n"
  },
  {
    "path": "src/utils/getSectionSelector.js",
    "content": "import { getIdFromHash } from './getIdFromHash';\n\nexport const getSectionSelector = (element) => {\n  if (element.dataset.sectionSelector) return element.dataset.sectionSelector;\n  if (element.hash) return `#${getIdFromHash(element.hash)}`;\n\n  return '';\n};\n"
  },
  {
    "path": "src/utils/index.js",
    "content": "export { forEach } from './forEach';\nexport { find } from './find';\nexport { getIdFromHash } from './getIdFromHash';\nexport { pushHashToUrl } from './pushHashToUrl';\nexport { getSectionSelector } from './getSectionSelector';\nexport { getSectionIdFromElement } from './getSectionIdFromElement';\n"
  },
  {
    "path": "src/utils/pushHashToUrl.js",
    "content": "/**\n * Pushes the given hash to the URL using primarily pushState if available to prevent the\n * scroll from jumping to the hash element. Uses window.location.hash as a fallback.\n *\n * @param {String} hash The hash value to be pushed\n */\nexport const pushHashToUrl = (hash) => {\n  if (window.history.pushState) {\n    window.history.pushState(null, null, hash);\n\n    return;\n  }\n\n  window.location.hash = hash;\n};\n"
  },
  {
    "path": "webpack.config.js",
    "content": "const TARGET = process.env.TARGET;\n\nif (TARGET === 'production') {\n  module.exports = require('./.webpack/webpack.config.prod');\n} else {\n  module.exports = require('./.webpack/webpack.config.dev');\n}\n"
  }
]