├── .gitignore ├── src ├── index.js └── veeno.js ├── README.md ├── index.html ├── package.json └── dist ├── veeno.min.js ├── veeno.esm.js └── veeno.umd.js /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | 3 | node_modules/ -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // Import vue component 2 | import veeno from './veeno.js'; 3 | 4 | // install function executed by Vue.use() 5 | export function install(Vue) { 6 | if (install.installed) return; 7 | install.installed = true; 8 | Vue.component('veeno', veeno); 9 | } 10 | 11 | // Create module definition for Vue.use() 12 | const plugin = { 13 | install, 14 | }; 15 | 16 | // To auto-install when vue is found 17 | let GlobalVue = null; 18 | if (typeof window !== 'undefined') { 19 | GlobalVue = window.Vue; 20 | } else if (typeof global !== 'undefined') { 21 | GlobalVue = global.Vue; 22 | } 23 | if (GlobalVue) { 24 | GlobalVue.use(plugin); 25 | } 26 | 27 | // To allow use as module (npm/webpack/etc.) export component 28 | export default veeno; 29 | 30 | // It's possible to expose named exports when writing components that can 31 | // also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo'; 32 | // export const RollupDemoDirective = component; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # veeno 2 | 3 | veeno is a range slider component for vue based off of 4 | [noUiSlider](https://github.com/leongersen/noUiSlider) 5 | It supports all noUiSlider features. 6 | 7 | ## Installation 8 | 9 | You can install the package via npm or yarn. 10 | 11 | #### NPM 12 | 13 | ```npm install veeno --save``` 14 | 15 | #### YARN 16 | 17 | ```yarn add veeno``` 18 | 19 | ## Usage 20 | 21 | ```vue 22 | 34 | 35 | 45 | ``` 46 | 47 | ## More 48 | 49 | For visual details, checkout the [homepage](http://veeno.surge.sh/) page 50 | 51 | ## Custom Design 52 | [Shards ui](https://codesandbox.io/s/n462y7lx94) 53 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Veeno | Slider 8 | 9 | 14 | 15 | 16 |
17 |
18 | 22 |
23 |
24 | 30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 43 | 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "veeno", 3 | "version": "0.0.4", 4 | "description": "noUiSlider component for vue 2", 5 | "keywords": [ 6 | "vue", 7 | "slider", 8 | "range", 9 | "vue-slider", 10 | "vue-range-slider", 11 | "vue-component", 12 | "vue-range-component", 13 | "vue-slider-component" 14 | ], 15 | "main": "dist/veeno.umd.js", 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/Lahori-Jawan/veeno" 19 | }, 20 | "author": "Nasir Khan ", 21 | "homepage": "http://veeno.surge.sh/", 22 | "module": "dist/veeno.esm.js", 23 | "unpkg": "dist/veeno.min.js", 24 | "browser": { 25 | "./sfc": "src/veeno.vue" 26 | }, 27 | "scripts": { 28 | "build": "npm run build:unpkg & npm run build:es & npm run build:umd", 29 | "build:umd": "rollup --config build/rollup.config.js --format umd --file dist/veeno.umd.js", 30 | "build:es": "rollup --config build/rollup.config.js --format es --file dist/veeno.esm.js", 31 | "build:unpkg": "rollup --config build/rollup.config.js --format iife --file dist/veeno.min.js" 32 | }, 33 | "dependencies": { 34 | "nouislider": "^11.1.0" 35 | }, 36 | "devDependencies": { 37 | "minimist": "^1.2.0", 38 | "rollup": "^0.57.1", 39 | "rollup-plugin-auto-external": "^1.2.0", 40 | "rollup-plugin-buble": "^0.19.2", 41 | "rollup-plugin-gzip": "^1.4.0", 42 | "rollup-plugin-includepaths": "^0.2.3", 43 | "rollup-plugin-uglify-es": "0.0.1", 44 | "rollup-plugin-vue": "^3.0.0", 45 | "rollup-plugin-uglify": "^4.0.0", 46 | "vue": "^2.5.16", 47 | "vue-template-compiler": "^2.5.16" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /dist/veeno.min.js: -------------------------------------------------------------------------------- 1 | var veeno=function(t,e){"use strict";function n(t){n.installed||(n.installed=!0,t.component("veeno",o))}e=e&&e.hasOwnProperty("default")?e.default:e;var i=["start","slide","update","change","set","end"],o={name:"veeno",props:{inputClass:{type:String,default:"custom-slider-input"},inputName:{type:String,default:"custom-slider-value"},options:{type:Object,default:function(){return{start:[20,80],connect:!0,range:{min:0,max:100}}}},vertical:{type:Boolean,default:!1},handles:{type:[Number,Array],default:null},connect:{type:[Boolean,Array],default:!1},tooltips:{type:[Boolean,Array],default:!1},step:{type:Number,default:0},range:{type:Object,required:!0,validator:function(t){return!Array.isArray(t)&&"object"==typeof t}},pipsy:{type:[Boolean,Object],default:function(){return!1},validator:function(t){return"boolean"==typeof t||!Array.isArray(t)&&"object"==typeof t}},rtl:{type:Boolean,default:!1},set:{type:[Number,Array],default:null,validator:function(t){return"number"==typeof t||Array.isArray(t)}},behaviour:{type:String,default:"tap",validator:function(t){return["drag","tap","fixed","snap","none"].indexOf(-1!==t)}},getset:{type:Function,default:function(){return function(){return""}}}},created:function(){this.optionz=Object.assign({},this.options,this.$props,this.vertical&&(this.options.orientation="vertical"),this.handles&&(this.options.start=this.handles),this.rtl&&(this.options.direction="rtl"),this.pipsy&&!Object.keys(this.pipsy).length?this.options.pips={mode:"range",density:5}:this.options.pips=this.pipsy)},mounted:function(){var t=this,n=this.$el;"vertical"===this.options.orientation&&(n.style.height="100%"),e.create(n,this.optionz),i.forEach(function(e){n.noUiSlider.on(e,function(n,i,o,a,s){t.$emit(e,{values:n,handle:i,unencoded:o,tap:a,positions:s}),"update"===e&&t.$emit("input",n[i])})}),this.getset(n)},render:function(t){var e=t("input",{attrs:{type:"hidden",name:this.name},class:this.inputClass}),n=t("span",s,this.$slots.default);return t("div",a,[e,n])},data:function(){return{optionz:Object,latestHandleValue:null}},watch:{set:function(t){this.$el.noUiSlider.set(t)}}},a={style:{position:"relative"},class:{veeno:!0},attrs:{name:"custom-slider"}},s={style:{position:"absolute",top:"-2.5rem"},class:{"veeno-span":!0}},r={install:n},l=null;return"undefined"!=typeof window?l=window.Vue:"undefined"!=typeof global&&(l=global.Vue),l&&l.use(r),t.install=n,t.default=o,t}({},noUiSlider); 2 | -------------------------------------------------------------------------------- /dist/veeno.esm.js: -------------------------------------------------------------------------------- 1 | function install(t){install.installed||(install.installed=!0,t.component("veeno",veeno))}import noUiSlider from"nouislider";var events=["start","slide","update","change","set","end"],veeno={name:"veeno",props:{inputClass:{type:String,default:"custom-slider-input"},inputName:{type:String,default:"custom-slider-value"},options:{type:Object,default:function(){return{start:[20,80],connect:!0,range:{min:0,max:100}}}},vertical:{type:Boolean,default:!1},handles:{type:[Number,Array],default:null},connect:{type:[Boolean,Array],default:!1},tooltips:{type:[Boolean,Array],default:!1},step:{type:Number,default:0},range:{type:Object,required:!0,validator:function(t){return!Array.isArray(t)&&"object"==typeof t}},pipsy:{type:[Boolean,Object],default:function(){return!1},validator:function(t){return"boolean"==typeof t||!Array.isArray(t)&&"object"==typeof t}},rtl:{type:Boolean,default:!1},set:{type:[Number,Array],default:null,validator:function(t){return"number"==typeof t||Array.isArray(t)}},behaviour:{type:String,default:"tap",validator:function(t){return["drag","tap","fixed","snap","none"].indexOf(-1!==t)}},getset:{type:Function,default:function(){return function(){return""}}}},created:function(){this.optionz=Object.assign({},this.options,this.$props,this.vertical&&(this.options.orientation="vertical"),this.handles&&(this.options.start=this.handles),this.rtl&&(this.options.direction="rtl"),this.pipsy&&!Object.keys(this.pipsy).length?this.options.pips={mode:"range",density:5}:this.options.pips=this.pipsy)},mounted:function(){var t=this,e=this.$el;"vertical"===this.options.orientation&&(e.style.height="100%"),noUiSlider.create(e,this.optionz),events.forEach(function(n){e.noUiSlider.on(n,function(e,i,o,s,a){t.$emit(n,{values:e,handle:i,unencoded:o,tap:s,positions:a}),"update"===n&&t.$emit("input",e[i])})}),this.getset(e)},render:function(t){var e=t("input",{attrs:{type:"hidden",name:this.name},class:this.inputClass}),n=t("span",spanOptions,this.$slots.default);return t("div",divOptions,[e,n])},data:function(){return{optionz:Object,latestHandleValue:null}},watch:{set:function(t){this.$el.noUiSlider.set(t)}}},divOptions={style:{position:"relative"},class:{veeno:!0},attrs:{name:"custom-slider"}},spanOptions={style:{position:"absolute",top:"-2.5rem"},class:{"veeno-span":!0}},plugin={install:install},GlobalVue=null;"undefined"!=typeof window?GlobalVue=window.Vue:"undefined"!=typeof global&&(GlobalVue=global.Vue),GlobalVue&&GlobalVue.use(plugin);export default veeno;export{install}; 2 | -------------------------------------------------------------------------------- /dist/veeno.umd.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("nouislider")):"function"==typeof define&&define.amd?define(["exports","nouislider"],e):e(t.veeno={},t.noUiSlider)}(this,function(t,e){"use strict";function n(t){n.installed||(n.installed=!0,t.component("veeno",o))}e=e&&e.hasOwnProperty("default")?e.default:e;var i=["start","slide","update","change","set","end"],o={name:"veeno",props:{inputClass:{type:String,default:"custom-slider-input"},inputName:{type:String,default:"custom-slider-value"},options:{type:Object,default:function(){return{start:[20,80],connect:!0,range:{min:0,max:100}}}},vertical:{type:Boolean,default:!1},handles:{type:[Number,Array],default:null},connect:{type:[Boolean,Array],default:!1},tooltips:{type:[Boolean,Array],default:!1},step:{type:Number,default:0},range:{type:Object,required:!0,validator:function(t){return!Array.isArray(t)&&"object"==typeof t}},pipsy:{type:[Boolean,Object],default:function(){return!1},validator:function(t){return"boolean"==typeof t||!Array.isArray(t)&&"object"==typeof t}},rtl:{type:Boolean,default:!1},set:{type:[Number,Array],default:null,validator:function(t){return"number"==typeof t||Array.isArray(t)}},behaviour:{type:String,default:"tap",validator:function(t){return["drag","tap","fixed","snap","none"].indexOf(-1!==t)}},getset:{type:Function,default:function(){return function(){return""}}}},created:function(){this.optionz=Object.assign({},this.options,this.$props,this.vertical&&(this.options.orientation="vertical"),this.handles&&(this.options.start=this.handles),this.rtl&&(this.options.direction="rtl"),this.pipsy&&!Object.keys(this.pipsy).length?this.options.pips={mode:"range",density:5}:this.options.pips=this.pipsy)},mounted:function(){var t=this,n=this.$el;"vertical"===this.options.orientation&&(n.style.height="100%"),e.create(n,this.optionz),i.forEach(function(e){n.noUiSlider.on(e,function(n,i,o,s,a){t.$emit(e,{values:n,handle:i,unencoded:o,tap:s,positions:a}),"update"===e&&t.$emit("input",n[i])})}),this.getset(n)},render:function(t){var e=t("input",{attrs:{type:"hidden",name:this.name},class:this.inputClass}),n=t("span",a,this.$slots.default);return t("div",s,[e,n])},data:function(){return{optionz:Object,latestHandleValue:null}},watch:{set:function(t){this.$el.noUiSlider.set(t)}}},s={style:{position:"relative"},class:{veeno:!0},attrs:{name:"custom-slider"}},a={style:{position:"absolute",top:"-2.5rem"},class:{"veeno-span":!0}},r={install:n},l=null;"undefined"!=typeof window?l=window.Vue:"undefined"!=typeof global&&(l=global.Vue),l&&l.use(r),t.install=n,t.default=o,Object.defineProperty(t,"__esModule",{value:!0})}); 2 | -------------------------------------------------------------------------------- /src/veeno.js: -------------------------------------------------------------------------------- 1 | import noUiSlider from 'nouislider' 2 | 3 | let events = ['start', 'slide', 'update', 'change', 'set', 'end'] 4 | 5 | export default { 6 | name: 'veeno', 7 | props: { 8 | inputClass: { 9 | type: String, 10 | default: 'custom-slider-input' 11 | }, 12 | inputName: { 13 | type: String, 14 | default: 'custom-slider-value' 15 | }, 16 | options: { 17 | type: Object, 18 | default: () => ({ 19 | start: [20, 80], 20 | connect: true, 21 | range: { 22 | 'min': 0, 23 | 'max': 100 24 | } 25 | }) 26 | }, 27 | vertical: { 28 | type: Boolean, 29 | default: false 30 | }, 31 | handles: { 32 | type: [Number, Array], 33 | default: null 34 | }, 35 | connect: { 36 | type: [Boolean, Array], 37 | default: false // validate values are boolean 38 | }, 39 | tooltips: { 40 | type: [Boolean, Array], 41 | default: false // validate values are boolean 42 | }, 43 | step: { 44 | type: Number, 45 | default: 0 46 | }, 47 | range: { 48 | type: Object, 49 | required: true, 50 | validator: (value) => (!Array.isArray(value) && typeof value === 'object') 51 | }, 52 | pipsy: { 53 | type: [Boolean, Object], 54 | default: () => false, 55 | validator: (value) => (typeof value === 'boolean' || !Array.isArray(value) && typeof value === 'object') 56 | }, 57 | rtl: { 58 | type: Boolean, 59 | default: false 60 | }, 61 | // test below (set) prop for both types i.e. Number, Array 62 | set: { 63 | type: [Number, Array], 64 | default: null, 65 | validator: (value) => (typeof value === 'number' || Array.isArray(value)) 66 | }, 67 | behaviour: { 68 | type: String, 69 | default: 'tap', 70 | validator: (value) => ['drag', 'tap', 'fixed', 'snap', 'none'].indexOf( value !== -1) 71 | }, 72 | getset: { 73 | type: Function, 74 | default: () => () => '' 75 | } 76 | }, 77 | created () { 78 | this.optionz = Object.assign({}, 79 | this.options, this.$props, 80 | // this.vertical ? this.options.orientation = 'vertical': '', 81 | this.vertical && (this.options.orientation = 'vertical'), 82 | this.handles && (this.options.start = this.handles), 83 | this.rtl && (this.options.direction = 'rtl'), 84 | this.pipsy && !Object.keys(this.pipsy).length ? 85 | this.options.pips = {mode: 'range',density: 5} : this.options.pips = this.pipsy 86 | ) 87 | }, 88 | mounted () { 89 | let slider = this.$el; 90 | this.options.orientation === 'vertical' && (slider.style.height = '100%') 91 | noUiSlider.create(slider, this.optionz) 92 | 93 | events.forEach(event => { 94 | slider.noUiSlider.on(event, (values, handle, unencoded, tap, positions) => { 95 | this.$emit(event, {values, handle, unencoded, tap, positions}) 96 | event === 'update' && (this.$emit('input', values[handle])) 97 | }) 98 | }) 99 | this.getset(slider) 100 | }, 101 | render (createElement) { 102 | let child = createElement('input', 103 | { 104 | attrs: { 105 | 'type': 'hidden', 106 | name:this.name, 107 | }, 108 | class:this.inputClass 109 | }, 110 | ) 111 | let span = createElement('span', spanOptions,this.$slots.default) 112 | 113 | return createElement('div', 114 | divOptions, 115 | [ 116 | child, 117 | span 118 | ]) 119 | }, 120 | data () { 121 | return { 122 | optionz: Object, 123 | latestHandleValue: null 124 | } 125 | }, 126 | watch: { 127 | set (newValue) { 128 | // * reference: https://refreshless.com/nouislider/slider-read-write/ 129 | this.$el.noUiSlider.set(newValue) 130 | } 131 | } 132 | } 133 | 134 | let divOptions = { 135 | style: { 136 | position: 'relative' 137 | }, 138 | class: { 139 | 'veeno': true 140 | }, 141 | attrs: { name:'custom-slider' } 142 | } 143 | 144 | let spanOptions = { 145 | style: { 146 | position: 'absolute', 147 | top: '-2.5rem' 148 | }, 149 | class: { 150 | 'veeno-span': true 151 | } 152 | } --------------------------------------------------------------------------------