├── .browserslistrc ├── .editorconfig ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── babel.config.js ├── demo └── demo.gif ├── dist ├── demo.html ├── vue-slider.common.js ├── vue-slider.common.js.map ├── vue-slider.umd.js ├── vue-slider.umd.js.map ├── vue-slider.umd.min.js └── vue-slider.umd.min.js.map ├── package-lock.json ├── package.json ├── postcss.config.js ├── src ├── App.vue ├── assets │ └── sass │ │ ├── app.scss │ │ ├── slider.scss │ │ └── variables.scss ├── components │ └── Slider.vue ├── index.js ├── js │ └── utilities.js └── main.js ├── tests └── unit │ ├── .eslintrc.js │ └── Slider.spec.js └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | '@vue/standard' 9 | ], 10 | rules: { 11 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 13 | }, 14 | parserOptions: { 15 | parser: 'babel-eslint' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Extensions 2 | *.vscode 3 | *.code-workspace 4 | 5 | # Directories 6 | /node_modules 7 | /public -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Jeremy Hamm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue Slider 2 | 3 | > A customizable horizontal slide menu for VueJs 2+ 4 | 5 | ![Demo Image](https://jeremyhamm.github.io/vue-slider/demo/demo.gif) 6 | 7 | *** 8 | 9 | ## Installation 10 | 11 | ##### NPM 12 | ``` 13 | npm i @jeremyhamm/vue-slider 14 | ``` 15 | 16 | #### Browser 17 | ```html 18 | 19 | ``` 20 | 21 | *** 22 | 23 | ## Usage 24 | 25 | #### Mount with global 26 | ```javascript 27 | import Vue from 'vue' 28 | import Slider from '@jeremyhamm/vue-slider' 29 | 30 | Vue.use(Slider) 31 | ``` 32 | 33 | #### Mount with component 34 | ```javascript 35 | 36 | import Slider from '@jeremyhamm/vue-slider' 37 | 38 | export default { 39 | components: { 40 | 'slider': Slider 41 | } 42 | } 43 | ``` 44 | 45 | #### Use in component 46 | ```html 47 | 48 | ``` 49 | 50 | #### Properties 51 | | Name | Type | Default | Options | 52 | | --- |--- | --- | --- | 53 | | width | `Number` | `300` | Menu Width `(px)` | 54 | | format | `String` | `overlay` | `push, full, overlay` | 55 | | direction | `String` | `left` | `left, right` | 56 | | opacity | `Number` | `0` | `0.00 - 1.00` Representing [css opacity](https://developer.mozilla.org/en-US/docs/Web/CSS/opacity) | 57 | | links | `Array` | null | `[{'id': 1, 'text': 'Link 1', 'url': 'https://github.com'}, {'id': 2, 'text': 'Link 2', 'url': 'https://github.com'}]` | 58 | | customStyles | `Object` | `{}` | `{'navMenu': {'background-color': 'black'}, 'navIcon': {'color': 'blue'}}` | 59 | 60 | #### Styles 61 | All menu styles can be updated in `/assets/sass/variables.scss` 62 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /demo/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeremyhamm/vue-slider/072c87baba050af9388c0e5144ed2fb405e63b9f/demo/demo.gif -------------------------------------------------------------------------------- /dist/demo.html: -------------------------------------------------------------------------------- 1 | 2 | vue-slider demo 3 | 4 | 5 | 6 | 7 |
8 | 9 |
10 | 11 | 18 | -------------------------------------------------------------------------------- /dist/vue-slider.common.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | /******/ (function(modules) { // webpackBootstrap 3 | /******/ // The module cache 4 | /******/ var installedModules = {}; 5 | /******/ 6 | /******/ // The require function 7 | /******/ function __webpack_require__(moduleId) { 8 | /******/ 9 | /******/ // Check if module is in cache 10 | /******/ if(installedModules[moduleId]) { 11 | /******/ return installedModules[moduleId].exports; 12 | /******/ } 13 | /******/ // Create a new module (and put it into the cache) 14 | /******/ var module = installedModules[moduleId] = { 15 | /******/ i: moduleId, 16 | /******/ l: false, 17 | /******/ exports: {} 18 | /******/ }; 19 | /******/ 20 | /******/ // Execute the module function 21 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 22 | /******/ 23 | /******/ // Flag the module as loaded 24 | /******/ module.l = true; 25 | /******/ 26 | /******/ // Return the exports of the module 27 | /******/ return module.exports; 28 | /******/ } 29 | /******/ 30 | /******/ 31 | /******/ // expose the modules object (__webpack_modules__) 32 | /******/ __webpack_require__.m = modules; 33 | /******/ 34 | /******/ // expose the module cache 35 | /******/ __webpack_require__.c = installedModules; 36 | /******/ 37 | /******/ // define getter function for harmony exports 38 | /******/ __webpack_require__.d = function(exports, name, getter) { 39 | /******/ if(!__webpack_require__.o(exports, name)) { 40 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 41 | /******/ } 42 | /******/ }; 43 | /******/ 44 | /******/ // define __esModule on exports 45 | /******/ __webpack_require__.r = function(exports) { 46 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 47 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 48 | /******/ } 49 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 50 | /******/ }; 51 | /******/ 52 | /******/ // create a fake namespace object 53 | /******/ // mode & 1: value is a module id, require it 54 | /******/ // mode & 2: merge all properties of value into the ns 55 | /******/ // mode & 4: return value when already ns object 56 | /******/ // mode & 8|1: behave like require 57 | /******/ __webpack_require__.t = function(value, mode) { 58 | /******/ if(mode & 1) value = __webpack_require__(value); 59 | /******/ if(mode & 8) return value; 60 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 61 | /******/ var ns = Object.create(null); 62 | /******/ __webpack_require__.r(ns); 63 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 64 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 65 | /******/ return ns; 66 | /******/ }; 67 | /******/ 68 | /******/ // getDefaultExport function for compatibility with non-harmony modules 69 | /******/ __webpack_require__.n = function(module) { 70 | /******/ var getter = module && module.__esModule ? 71 | /******/ function getDefault() { return module['default']; } : 72 | /******/ function getModuleExports() { return module; }; 73 | /******/ __webpack_require__.d(getter, 'a', getter); 74 | /******/ return getter; 75 | /******/ }; 76 | /******/ 77 | /******/ // Object.prototype.hasOwnProperty.call 78 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 79 | /******/ 80 | /******/ // __webpack_public_path__ 81 | /******/ __webpack_require__.p = ""; 82 | /******/ 83 | /******/ 84 | /******/ // Load entry module and return exports 85 | /******/ return __webpack_require__(__webpack_require__.s = "fb15"); 86 | /******/ }) 87 | /************************************************************************/ 88 | /******/ ({ 89 | 90 | /***/ "0bfb": 91 | /***/ (function(module, exports, __webpack_require__) { 92 | 93 | "use strict"; 94 | 95 | // 21.2.5.3 get RegExp.prototype.flags 96 | var anObject = __webpack_require__("cb7c"); 97 | module.exports = function () { 98 | var that = anObject(this); 99 | var result = ''; 100 | if (that.global) result += 'g'; 101 | if (that.ignoreCase) result += 'i'; 102 | if (that.multiline) result += 'm'; 103 | if (that.unicode) result += 'u'; 104 | if (that.sticky) result += 'y'; 105 | return result; 106 | }; 107 | 108 | 109 | /***/ }), 110 | 111 | /***/ "0d58": 112 | /***/ (function(module, exports, __webpack_require__) { 113 | 114 | // 19.1.2.14 / 15.2.3.14 Object.keys(O) 115 | var $keys = __webpack_require__("ce10"); 116 | var enumBugKeys = __webpack_require__("e11e"); 117 | 118 | module.exports = Object.keys || function keys(O) { 119 | return $keys(O, enumBugKeys); 120 | }; 121 | 122 | 123 | /***/ }), 124 | 125 | /***/ "11e9": 126 | /***/ (function(module, exports, __webpack_require__) { 127 | 128 | var pIE = __webpack_require__("52a7"); 129 | var createDesc = __webpack_require__("4630"); 130 | var toIObject = __webpack_require__("6821"); 131 | var toPrimitive = __webpack_require__("6a99"); 132 | var has = __webpack_require__("69a8"); 133 | var IE8_DOM_DEFINE = __webpack_require__("c69a"); 134 | var gOPD = Object.getOwnPropertyDescriptor; 135 | 136 | exports.f = __webpack_require__("9e1e") ? gOPD : function getOwnPropertyDescriptor(O, P) { 137 | O = toIObject(O); 138 | P = toPrimitive(P, true); 139 | if (IE8_DOM_DEFINE) try { 140 | return gOPD(O, P); 141 | } catch (e) { /* empty */ } 142 | if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]); 143 | }; 144 | 145 | 146 | /***/ }), 147 | 148 | /***/ "1495": 149 | /***/ (function(module, exports, __webpack_require__) { 150 | 151 | var dP = __webpack_require__("86cc"); 152 | var anObject = __webpack_require__("cb7c"); 153 | var getKeys = __webpack_require__("0d58"); 154 | 155 | module.exports = __webpack_require__("9e1e") ? Object.defineProperties : function defineProperties(O, Properties) { 156 | anObject(O); 157 | var keys = getKeys(Properties); 158 | var length = keys.length; 159 | var i = 0; 160 | var P; 161 | while (length > i) dP.f(O, P = keys[i++], Properties[P]); 162 | return O; 163 | }; 164 | 165 | 166 | /***/ }), 167 | 168 | /***/ "230e": 169 | /***/ (function(module, exports, __webpack_require__) { 170 | 171 | var isObject = __webpack_require__("d3f4"); 172 | var document = __webpack_require__("7726").document; 173 | // typeof document.createElement is 'object' in old IE 174 | var is = isObject(document) && isObject(document.createElement); 175 | module.exports = function (it) { 176 | return is ? document.createElement(it) : {}; 177 | }; 178 | 179 | 180 | /***/ }), 181 | 182 | /***/ "2350": 183 | /***/ (function(module, exports) { 184 | 185 | /* 186 | MIT License http://www.opensource.org/licenses/mit-license.php 187 | Author Tobias Koppers @sokra 188 | */ 189 | // css base code, injected by the css-loader 190 | module.exports = function(useSourceMap) { 191 | var list = []; 192 | 193 | // return the list of modules as css string 194 | list.toString = function toString() { 195 | return this.map(function (item) { 196 | var content = cssWithMappingToString(item, useSourceMap); 197 | if(item[2]) { 198 | return "@media " + item[2] + "{" + content + "}"; 199 | } else { 200 | return content; 201 | } 202 | }).join(""); 203 | }; 204 | 205 | // import a list of modules into the list 206 | list.i = function(modules, mediaQuery) { 207 | if(typeof modules === "string") 208 | modules = [[null, modules, ""]]; 209 | var alreadyImportedModules = {}; 210 | for(var i = 0; i < this.length; i++) { 211 | var id = this[i][0]; 212 | if(typeof id === "number") 213 | alreadyImportedModules[id] = true; 214 | } 215 | for(i = 0; i < modules.length; i++) { 216 | var item = modules[i]; 217 | // skip already imported module 218 | // this implementation is not 100% perfect for weird media query combinations 219 | // when a module is imported multiple times with different media queries. 220 | // I hope this will never occur (Hey this way we have smaller bundles) 221 | if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { 222 | if(mediaQuery && !item[2]) { 223 | item[2] = mediaQuery; 224 | } else if(mediaQuery) { 225 | item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; 226 | } 227 | list.push(item); 228 | } 229 | } 230 | }; 231 | return list; 232 | }; 233 | 234 | function cssWithMappingToString(item, useSourceMap) { 235 | var content = item[1] || ''; 236 | var cssMapping = item[3]; 237 | if (!cssMapping) { 238 | return content; 239 | } 240 | 241 | if (useSourceMap && typeof btoa === 'function') { 242 | var sourceMapping = toComment(cssMapping); 243 | var sourceURLs = cssMapping.sources.map(function (source) { 244 | return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */' 245 | }); 246 | 247 | return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); 248 | } 249 | 250 | return [content].join('\n'); 251 | } 252 | 253 | // Adapted from convert-source-map (MIT) 254 | function toComment(sourceMap) { 255 | // eslint-disable-next-line no-undef 256 | var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); 257 | var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64; 258 | 259 | return '/*# ' + data + ' */'; 260 | } 261 | 262 | 263 | /***/ }), 264 | 265 | /***/ "2aba": 266 | /***/ (function(module, exports, __webpack_require__) { 267 | 268 | var global = __webpack_require__("7726"); 269 | var hide = __webpack_require__("32e9"); 270 | var has = __webpack_require__("69a8"); 271 | var SRC = __webpack_require__("ca5a")('src'); 272 | var $toString = __webpack_require__("fa5b"); 273 | var TO_STRING = 'toString'; 274 | var TPL = ('' + $toString).split(TO_STRING); 275 | 276 | __webpack_require__("8378").inspectSource = function (it) { 277 | return $toString.call(it); 278 | }; 279 | 280 | (module.exports = function (O, key, val, safe) { 281 | var isFunction = typeof val == 'function'; 282 | if (isFunction) has(val, 'name') || hide(val, 'name', key); 283 | if (O[key] === val) return; 284 | if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key))); 285 | if (O === global) { 286 | O[key] = val; 287 | } else if (!safe) { 288 | delete O[key]; 289 | hide(O, key, val); 290 | } else if (O[key]) { 291 | O[key] = val; 292 | } else { 293 | hide(O, key, val); 294 | } 295 | // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative 296 | })(Function.prototype, TO_STRING, function toString() { 297 | return typeof this == 'function' && this[SRC] || $toString.call(this); 298 | }); 299 | 300 | 301 | /***/ }), 302 | 303 | /***/ "2aeb": 304 | /***/ (function(module, exports, __webpack_require__) { 305 | 306 | // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) 307 | var anObject = __webpack_require__("cb7c"); 308 | var dPs = __webpack_require__("1495"); 309 | var enumBugKeys = __webpack_require__("e11e"); 310 | var IE_PROTO = __webpack_require__("613b")('IE_PROTO'); 311 | var Empty = function () { /* empty */ }; 312 | var PROTOTYPE = 'prototype'; 313 | 314 | // Create object with fake `null` prototype: use iframe Object with cleared prototype 315 | var createDict = function () { 316 | // Thrash, waste and sodomy: IE GC bug 317 | var iframe = __webpack_require__("230e")('iframe'); 318 | var i = enumBugKeys.length; 319 | var lt = '<'; 320 | var gt = '>'; 321 | var iframeDocument; 322 | iframe.style.display = 'none'; 323 | __webpack_require__("fab2").appendChild(iframe); 324 | iframe.src = 'javascript:'; // eslint-disable-line no-script-url 325 | // createDict = iframe.contentWindow.Object; 326 | // html.removeChild(iframe); 327 | iframeDocument = iframe.contentWindow.document; 328 | iframeDocument.open(); 329 | iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); 330 | iframeDocument.close(); 331 | createDict = iframeDocument.F; 332 | while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]]; 333 | return createDict(); 334 | }; 335 | 336 | module.exports = Object.create || function create(O, Properties) { 337 | var result; 338 | if (O !== null) { 339 | Empty[PROTOTYPE] = anObject(O); 340 | result = new Empty(); 341 | Empty[PROTOTYPE] = null; 342 | // add "__proto__" for Object.getPrototypeOf polyfill 343 | result[IE_PROTO] = O; 344 | } else result = createDict(); 345 | return Properties === undefined ? result : dPs(result, Properties); 346 | }; 347 | 348 | 349 | /***/ }), 350 | 351 | /***/ "2d00": 352 | /***/ (function(module, exports) { 353 | 354 | module.exports = false; 355 | 356 | 357 | /***/ }), 358 | 359 | /***/ "2d95": 360 | /***/ (function(module, exports) { 361 | 362 | var toString = {}.toString; 363 | 364 | module.exports = function (it) { 365 | return toString.call(it).slice(8, -1); 366 | }; 367 | 368 | 369 | /***/ }), 370 | 371 | /***/ "32aa": 372 | /***/ (function(module, exports, __webpack_require__) { 373 | 374 | // style-loader: Adds some css to the DOM by adding a \r\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Slider.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--12-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--0-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Slider.vue?vue&type=script&lang=js&\"","/* globals __VUE_SSR_CONTEXT__ */\n\n// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).\n// This module is a runtime utility for cleaner component module output and will\n// be included in the final webpack user bundle.\n\nexport default function normalizeComponent (\n scriptExports,\n render,\n staticRenderFns,\n functionalTemplate,\n injectStyles,\n scopeId,\n moduleIdentifier, /* server only */\n shadowMode /* vue-cli only */\n) {\n // Vue.extend constructor export interop\n var options = typeof scriptExports === 'function'\n ? scriptExports.options\n : scriptExports\n\n // render functions\n if (render) {\n options.render = render\n options.staticRenderFns = staticRenderFns\n options._compiled = true\n }\n\n // functional template\n if (functionalTemplate) {\n options.functional = true\n }\n\n // scopedId\n if (scopeId) {\n options._scopeId = 'data-v-' + scopeId\n }\n\n var hook\n if (moduleIdentifier) { // server build\n hook = function (context) {\n // 2.3 injection\n context =\n context || // cached call\n (this.$vnode && this.$vnode.ssrContext) || // stateful\n (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional\n // 2.2 with runInNewContext: true\n if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {\n context = __VUE_SSR_CONTEXT__\n }\n // inject component styles\n if (injectStyles) {\n injectStyles.call(this, context)\n }\n // register component module identifier for async chunk inferrence\n if (context && context._registeredComponents) {\n context._registeredComponents.add(moduleIdentifier)\n }\n }\n // used by ssr in case component is cached and beforeCreate\n // never gets called\n options._ssrRegister = hook\n } else if (injectStyles) {\n hook = shadowMode\n ? function () { injectStyles.call(this, this.$root.$options.shadowRoot) }\n : injectStyles\n }\n\n if (hook) {\n if (options.functional) {\n // for template-only hot-reload because in that case the render fn doesn't\n // go through the normalizer\n options._injectStyles = hook\n // register for functioal component in vue file\n var originalRender = options.render\n options.render = function renderWithStyleInjection (h, context) {\n hook.call(context)\n return originalRender(h, context)\n }\n } else {\n // inject component registration as beforeCreate hook\n var existing = options.beforeCreate\n options.beforeCreate = existing\n ? [].concat(existing, hook)\n : [hook]\n }\n }\n\n return {\n exports: scriptExports,\n options: options\n }\n}\n","import { render, staticRenderFns } from \"./Slider.vue?vue&type=template&id=7f183654&scoped=true&\"\nimport script from \"./Slider.vue?vue&type=script&lang=js&\"\nexport * from \"./Slider.vue?vue&type=script&lang=js&\"\nimport style0 from \"./Slider.vue?vue&type=style&index=0&id=7f183654&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"7f183654\",\n null\n \n)\n\nexport default component.exports","import './setPublicPath'\nimport mod from '~entry'\nexport default mod\nexport * from '~entry'\n","module.exports = '\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003' +\n '\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028\\u2029\\uFEFF';\n"],"sourceRoot":""} -------------------------------------------------------------------------------- /dist/vue-slider.umd.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(); 4 | else if(typeof define === 'function' && define.amd) 5 | define([], factory); 6 | else if(typeof exports === 'object') 7 | exports["vue-slider"] = factory(); 8 | else 9 | root["vue-slider"] = factory(); 10 | })((typeof self !== 'undefined' ? self : this), function() { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | /******/ 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | /******/ 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) { 20 | /******/ return installedModules[moduleId].exports; 21 | /******/ } 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ i: moduleId, 25 | /******/ l: false, 26 | /******/ exports: {} 27 | /******/ }; 28 | /******/ 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | /******/ 32 | /******/ // Flag the module as loaded 33 | /******/ module.l = true; 34 | /******/ 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | /******/ 39 | /******/ 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | /******/ 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | /******/ 46 | /******/ // define getter function for harmony exports 47 | /******/ __webpack_require__.d = function(exports, name, getter) { 48 | /******/ if(!__webpack_require__.o(exports, name)) { 49 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 50 | /******/ } 51 | /******/ }; 52 | /******/ 53 | /******/ // define __esModule on exports 54 | /******/ __webpack_require__.r = function(exports) { 55 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 56 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 57 | /******/ } 58 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 59 | /******/ }; 60 | /******/ 61 | /******/ // create a fake namespace object 62 | /******/ // mode & 1: value is a module id, require it 63 | /******/ // mode & 2: merge all properties of value into the ns 64 | /******/ // mode & 4: return value when already ns object 65 | /******/ // mode & 8|1: behave like require 66 | /******/ __webpack_require__.t = function(value, mode) { 67 | /******/ if(mode & 1) value = __webpack_require__(value); 68 | /******/ if(mode & 8) return value; 69 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 70 | /******/ var ns = Object.create(null); 71 | /******/ __webpack_require__.r(ns); 72 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 73 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 74 | /******/ return ns; 75 | /******/ }; 76 | /******/ 77 | /******/ // getDefaultExport function for compatibility with non-harmony modules 78 | /******/ __webpack_require__.n = function(module) { 79 | /******/ var getter = module && module.__esModule ? 80 | /******/ function getDefault() { return module['default']; } : 81 | /******/ function getModuleExports() { return module; }; 82 | /******/ __webpack_require__.d(getter, 'a', getter); 83 | /******/ return getter; 84 | /******/ }; 85 | /******/ 86 | /******/ // Object.prototype.hasOwnProperty.call 87 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 88 | /******/ 89 | /******/ // __webpack_public_path__ 90 | /******/ __webpack_require__.p = ""; 91 | /******/ 92 | /******/ 93 | /******/ // Load entry module and return exports 94 | /******/ return __webpack_require__(__webpack_require__.s = "fb15"); 95 | /******/ }) 96 | /************************************************************************/ 97 | /******/ ({ 98 | 99 | /***/ "0bfb": 100 | /***/ (function(module, exports, __webpack_require__) { 101 | 102 | "use strict"; 103 | 104 | // 21.2.5.3 get RegExp.prototype.flags 105 | var anObject = __webpack_require__("cb7c"); 106 | module.exports = function () { 107 | var that = anObject(this); 108 | var result = ''; 109 | if (that.global) result += 'g'; 110 | if (that.ignoreCase) result += 'i'; 111 | if (that.multiline) result += 'm'; 112 | if (that.unicode) result += 'u'; 113 | if (that.sticky) result += 'y'; 114 | return result; 115 | }; 116 | 117 | 118 | /***/ }), 119 | 120 | /***/ "0d58": 121 | /***/ (function(module, exports, __webpack_require__) { 122 | 123 | // 19.1.2.14 / 15.2.3.14 Object.keys(O) 124 | var $keys = __webpack_require__("ce10"); 125 | var enumBugKeys = __webpack_require__("e11e"); 126 | 127 | module.exports = Object.keys || function keys(O) { 128 | return $keys(O, enumBugKeys); 129 | }; 130 | 131 | 132 | /***/ }), 133 | 134 | /***/ "11e9": 135 | /***/ (function(module, exports, __webpack_require__) { 136 | 137 | var pIE = __webpack_require__("52a7"); 138 | var createDesc = __webpack_require__("4630"); 139 | var toIObject = __webpack_require__("6821"); 140 | var toPrimitive = __webpack_require__("6a99"); 141 | var has = __webpack_require__("69a8"); 142 | var IE8_DOM_DEFINE = __webpack_require__("c69a"); 143 | var gOPD = Object.getOwnPropertyDescriptor; 144 | 145 | exports.f = __webpack_require__("9e1e") ? gOPD : function getOwnPropertyDescriptor(O, P) { 146 | O = toIObject(O); 147 | P = toPrimitive(P, true); 148 | if (IE8_DOM_DEFINE) try { 149 | return gOPD(O, P); 150 | } catch (e) { /* empty */ } 151 | if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]); 152 | }; 153 | 154 | 155 | /***/ }), 156 | 157 | /***/ "1495": 158 | /***/ (function(module, exports, __webpack_require__) { 159 | 160 | var dP = __webpack_require__("86cc"); 161 | var anObject = __webpack_require__("cb7c"); 162 | var getKeys = __webpack_require__("0d58"); 163 | 164 | module.exports = __webpack_require__("9e1e") ? Object.defineProperties : function defineProperties(O, Properties) { 165 | anObject(O); 166 | var keys = getKeys(Properties); 167 | var length = keys.length; 168 | var i = 0; 169 | var P; 170 | while (length > i) dP.f(O, P = keys[i++], Properties[P]); 171 | return O; 172 | }; 173 | 174 | 175 | /***/ }), 176 | 177 | /***/ "230e": 178 | /***/ (function(module, exports, __webpack_require__) { 179 | 180 | var isObject = __webpack_require__("d3f4"); 181 | var document = __webpack_require__("7726").document; 182 | // typeof document.createElement is 'object' in old IE 183 | var is = isObject(document) && isObject(document.createElement); 184 | module.exports = function (it) { 185 | return is ? document.createElement(it) : {}; 186 | }; 187 | 188 | 189 | /***/ }), 190 | 191 | /***/ "2350": 192 | /***/ (function(module, exports) { 193 | 194 | /* 195 | MIT License http://www.opensource.org/licenses/mit-license.php 196 | Author Tobias Koppers @sokra 197 | */ 198 | // css base code, injected by the css-loader 199 | module.exports = function(useSourceMap) { 200 | var list = []; 201 | 202 | // return the list of modules as css string 203 | list.toString = function toString() { 204 | return this.map(function (item) { 205 | var content = cssWithMappingToString(item, useSourceMap); 206 | if(item[2]) { 207 | return "@media " + item[2] + "{" + content + "}"; 208 | } else { 209 | return content; 210 | } 211 | }).join(""); 212 | }; 213 | 214 | // import a list of modules into the list 215 | list.i = function(modules, mediaQuery) { 216 | if(typeof modules === "string") 217 | modules = [[null, modules, ""]]; 218 | var alreadyImportedModules = {}; 219 | for(var i = 0; i < this.length; i++) { 220 | var id = this[i][0]; 221 | if(typeof id === "number") 222 | alreadyImportedModules[id] = true; 223 | } 224 | for(i = 0; i < modules.length; i++) { 225 | var item = modules[i]; 226 | // skip already imported module 227 | // this implementation is not 100% perfect for weird media query combinations 228 | // when a module is imported multiple times with different media queries. 229 | // I hope this will never occur (Hey this way we have smaller bundles) 230 | if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { 231 | if(mediaQuery && !item[2]) { 232 | item[2] = mediaQuery; 233 | } else if(mediaQuery) { 234 | item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; 235 | } 236 | list.push(item); 237 | } 238 | } 239 | }; 240 | return list; 241 | }; 242 | 243 | function cssWithMappingToString(item, useSourceMap) { 244 | var content = item[1] || ''; 245 | var cssMapping = item[3]; 246 | if (!cssMapping) { 247 | return content; 248 | } 249 | 250 | if (useSourceMap && typeof btoa === 'function') { 251 | var sourceMapping = toComment(cssMapping); 252 | var sourceURLs = cssMapping.sources.map(function (source) { 253 | return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */' 254 | }); 255 | 256 | return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); 257 | } 258 | 259 | return [content].join('\n'); 260 | } 261 | 262 | // Adapted from convert-source-map (MIT) 263 | function toComment(sourceMap) { 264 | // eslint-disable-next-line no-undef 265 | var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); 266 | var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64; 267 | 268 | return '/*# ' + data + ' */'; 269 | } 270 | 271 | 272 | /***/ }), 273 | 274 | /***/ "2aba": 275 | /***/ (function(module, exports, __webpack_require__) { 276 | 277 | var global = __webpack_require__("7726"); 278 | var hide = __webpack_require__("32e9"); 279 | var has = __webpack_require__("69a8"); 280 | var SRC = __webpack_require__("ca5a")('src'); 281 | var $toString = __webpack_require__("fa5b"); 282 | var TO_STRING = 'toString'; 283 | var TPL = ('' + $toString).split(TO_STRING); 284 | 285 | __webpack_require__("8378").inspectSource = function (it) { 286 | return $toString.call(it); 287 | }; 288 | 289 | (module.exports = function (O, key, val, safe) { 290 | var isFunction = typeof val == 'function'; 291 | if (isFunction) has(val, 'name') || hide(val, 'name', key); 292 | if (O[key] === val) return; 293 | if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key))); 294 | if (O === global) { 295 | O[key] = val; 296 | } else if (!safe) { 297 | delete O[key]; 298 | hide(O, key, val); 299 | } else if (O[key]) { 300 | O[key] = val; 301 | } else { 302 | hide(O, key, val); 303 | } 304 | // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative 305 | })(Function.prototype, TO_STRING, function toString() { 306 | return typeof this == 'function' && this[SRC] || $toString.call(this); 307 | }); 308 | 309 | 310 | /***/ }), 311 | 312 | /***/ "2aeb": 313 | /***/ (function(module, exports, __webpack_require__) { 314 | 315 | // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) 316 | var anObject = __webpack_require__("cb7c"); 317 | var dPs = __webpack_require__("1495"); 318 | var enumBugKeys = __webpack_require__("e11e"); 319 | var IE_PROTO = __webpack_require__("613b")('IE_PROTO'); 320 | var Empty = function () { /* empty */ }; 321 | var PROTOTYPE = 'prototype'; 322 | 323 | // Create object with fake `null` prototype: use iframe Object with cleared prototype 324 | var createDict = function () { 325 | // Thrash, waste and sodomy: IE GC bug 326 | var iframe = __webpack_require__("230e")('iframe'); 327 | var i = enumBugKeys.length; 328 | var lt = '<'; 329 | var gt = '>'; 330 | var iframeDocument; 331 | iframe.style.display = 'none'; 332 | __webpack_require__("fab2").appendChild(iframe); 333 | iframe.src = 'javascript:'; // eslint-disable-line no-script-url 334 | // createDict = iframe.contentWindow.Object; 335 | // html.removeChild(iframe); 336 | iframeDocument = iframe.contentWindow.document; 337 | iframeDocument.open(); 338 | iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); 339 | iframeDocument.close(); 340 | createDict = iframeDocument.F; 341 | while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]]; 342 | return createDict(); 343 | }; 344 | 345 | module.exports = Object.create || function create(O, Properties) { 346 | var result; 347 | if (O !== null) { 348 | Empty[PROTOTYPE] = anObject(O); 349 | result = new Empty(); 350 | Empty[PROTOTYPE] = null; 351 | // add "__proto__" for Object.getPrototypeOf polyfill 352 | result[IE_PROTO] = O; 353 | } else result = createDict(); 354 | return Properties === undefined ? result : dPs(result, Properties); 355 | }; 356 | 357 | 358 | /***/ }), 359 | 360 | /***/ "2d00": 361 | /***/ (function(module, exports) { 362 | 363 | module.exports = false; 364 | 365 | 366 | /***/ }), 367 | 368 | /***/ "2d95": 369 | /***/ (function(module, exports) { 370 | 371 | var toString = {}.toString; 372 | 373 | module.exports = function (it) { 374 | return toString.call(it).slice(8, -1); 375 | }; 376 | 377 | 378 | /***/ }), 379 | 380 | /***/ "32aa": 381 | /***/ (function(module, exports, __webpack_require__) { 382 | 383 | // style-loader: Adds some css to the DOM by adding a 31 | -------------------------------------------------------------------------------- /src/assets/sass/app.scss: -------------------------------------------------------------------------------- 1 | @import '@/assets/sass/variables.scss'; 2 | @import '@/assets/sass/slider.scss'; -------------------------------------------------------------------------------- /src/assets/sass/slider.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background: $background-color; 3 | transition: background .5s; 4 | } 5 | #app { 6 | transition: margin-left .5s; 7 | transition: margin-right .5s; 8 | padding: 20px; 9 | } 10 | .navMenu { 11 | font-family: $font-family-sans-serif; 12 | height: 100%; 13 | width: 0; 14 | position: fixed; 15 | z-index: 1; 16 | top: 0; 17 | background: $menu-background; 18 | overflow-x: hidden; 19 | padding-top: 60px; 20 | transition: 0.5s; 21 | a { 22 | padding: 8px 8px 8px 32px; 23 | text-decoration: none; 24 | font-size: 25px; 25 | color: $menu-text; 26 | display: block; 27 | transition: 0.3s; 28 | &:hover { 29 | color: $menu-text-hover; 30 | } 31 | } 32 | .closebtn { 33 | position: absolute; 34 | top: 0; 35 | right: 25px; 36 | font-size: 36px; 37 | margin-left: 50px; 38 | } 39 | } 40 | @media screen and (max-height: 450px) { 41 | .navMenu { 42 | padding-top: 15px; 43 | a { 44 | font-size: 18px; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/assets/sass/variables.scss: -------------------------------------------------------------------------------- 1 | 2 | /*** 3 | Typeography and color schema for vue-slider 4 | https://github.com/jeremyhamm/vue-slider 5 | ***/ 6 | 7 | // Typography 8 | @import url('https://fonts.googleapis.com/css?family=Titillium+Web'); 9 | $font-family-sans-serif: "Titillium Web", sans-serif; 10 | 11 | // Background 12 | $background-color: #FFFFFF; 13 | 14 | // Hamburger icon colors 15 | $menu-icon-color: #999999; 16 | 17 | // Menu colors 18 | $menu-background: #3b889A; 19 | $menu-text: #FFFFFF; 20 | $menu-text-hover: #E0E0E0; 21 | 22 | // Export Styles 23 | :export { 24 | background: { 25 | color: $background-color 26 | }; 27 | menu: { 28 | icon-color: $menu-icon-color 29 | }; 30 | } -------------------------------------------------------------------------------- /src/components/Slider.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Slider from '@/components/Slider' 2 | 3 | // Export individual component 4 | export { Slider } 5 | 6 | // What should happen if the user installs the library as a plugin 7 | function install (Vue) { 8 | Vue.component('Slider', Slider) 9 | } 10 | 11 | export default { install: install } 12 | -------------------------------------------------------------------------------- /src/js/utilities.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Utility functions for use in vue-slider 3 | */ 4 | export default { 5 | 6 | /** 7 | * Convert hex value to rgba 8 | * Thanks to https://stackoverflow.com/users/3878400/ajfarkas 9 | * 10 | * @param {String} hex 11 | * @param {String} alpha 12 | */ 13 | hexToRGB (hex, alpha) { 14 | if (hex === '#FFFFFF') { 15 | hex = '#000000' 16 | } 17 | 18 | const r = parseInt(hex.slice(1, 3), 16) 19 | const g = parseInt(hex.slice(3, 5), 16) 20 | const b = parseInt(hex.slice(5, 7), 16) 21 | 22 | if (alpha) { 23 | return `rgba(${r}, ${g}, ${b}, ${alpha})` 24 | } 25 | 26 | return `rgb(${r}, ${g}, ${b})` 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | render: h => h(App) 8 | }).$mount('#app') 9 | -------------------------------------------------------------------------------- /tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | mocha: true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/unit/Slider.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai' 2 | import { shallowMount } from '@vue/test-utils' 3 | import Slider from '@/components/Slider.vue' 4 | 5 | describe('Slider.vue', () => { 6 | it('shows the menu when the menu icon is clicked', () => { 7 | const wrapper = shallowMount(Slider, { 8 | propsData: { 9 | width: 200, 10 | links: [{ 11 | id: 1, 12 | text: 'Link 1', 13 | url: 'https://github.com' 14 | }] 15 | } 16 | }) 17 | // make sure the width is set 18 | expect(wrapper.props().width).to.equal(200) 19 | // check the menu is initially closed 20 | // initial menuWidth width should be 0 21 | expect(wrapper.vm.menuWidth.width).to.equal(0) 22 | // get the nav menu 23 | const navMenu = wrapper.find('[data-test-ref="navMenuLink"]') 24 | // now, click on the menu icon 25 | navMenu.trigger('click') 26 | // check to make sure the menu is shown 27 | expect(wrapper.vm.menuWidth.width).to.equal('200px') 28 | // click on the menu icon again 29 | navMenu.trigger('click') 30 | // check to make sure the menu is closed 31 | expect(wrapper.vm.menuWidth.width).to.equal(0) 32 | }) 33 | 34 | it('has proper user defined styles', () => { 35 | const wrapper = shallowMount(Slider, { 36 | propsData: { 37 | width: 200, 38 | links: [{ 39 | id: 1, 40 | text: 'Link 1', 41 | url: 'https://github.com' 42 | }], 43 | customStyles: { 44 | 'navMenu': { 45 | 'background-color': 'black' 46 | } 47 | } 48 | } 49 | }) 50 | 51 | const expectedUserStyles = { 52 | 'navMenu': { 53 | 'background-color': 'black' 54 | }, 55 | 'navIcon': {} 56 | } 57 | expect(wrapper.vm.userStyles).to.deep.equal(expectedUserStyles) 58 | }) 59 | }) 60 | -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | lintOnSave: process.env.NODE_ENV !== 'production', 3 | css: { 4 | extract: false 5 | } 6 | } 7 | --------------------------------------------------------------------------------