├── .gitignore ├── demos ├── grid │ ├── grid.gif │ ├── grid.css │ ├── grid.js │ └── index.html ├── bounded │ ├── bounded.css │ ├── bounded.js │ └── index.html ├── boundedcustom │ ├── boundedcustom.css │ ├── index.html │ └── boundedcustom.js ├── __common │ ├── common.js │ └── common.css ├── basic │ ├── basic.js │ └── index.html └── handle │ ├── handle.js │ └── index.html ├── Gruntfile.coffee ├── Gruntfile.js ├── bower.json ├── LICENSE.md ├── package.json ├── dist └── draggable.min.js ├── README.md ├── src └── draggable.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /demos/grid/grid.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcherny/draggable/HEAD/demos/grid/grid.gif -------------------------------------------------------------------------------- /demos/bounded/bounded.css: -------------------------------------------------------------------------------- 1 | #container { 2 | bottom: 35%; 3 | left: 50px; 4 | right: 50px; 5 | top: 50px; 6 | } -------------------------------------------------------------------------------- /demos/boundedcustom/boundedcustom.css: -------------------------------------------------------------------------------- 1 | .ball { 2 | margin: -50px 0 0 -50px; 3 | position: absolute; 4 | left: 50%; 5 | top: 50%; 6 | z-index: 1; 7 | } 8 | 9 | #drag-bound-indicator { 10 | background: #ddd; 11 | border-radius: 150px; 12 | height: 300px; 13 | margin: -150px 0 0 -150px; 14 | position: absolute; 15 | left: 50%; 16 | top: 50%; 17 | width: 300px; 18 | z-index: 0; 19 | } -------------------------------------------------------------------------------- /demos/grid/grid.css: -------------------------------------------------------------------------------- 1 | #container { 2 | background: #eee url(grid.gif) 0 0; 3 | background-size: 10px; 4 | } 5 | 6 | /* form */ 7 | 8 | label { 9 | display: block; 10 | font-size: 16px; 11 | line-height: 24px; 12 | padding: 10px 10px 0; 13 | text-align: left; 14 | } 15 | 16 | input { 17 | float: right; 18 | } 19 | 20 | input[type="number"] { 21 | padding: 5px; 22 | } 23 | 24 | input[type="checkbox"] { 25 | position: relative; 26 | top: -1px 27 | } -------------------------------------------------------------------------------- /demos/bounded/bounded.js: -------------------------------------------------------------------------------- 1 | var container = document.getElementById('container'), 2 | element = document.getElementsByClassName('ball')[0], 3 | labelX = document.getElementsByClassName('coords-x')[0], 4 | labelY = document.getElementsByClassName('coords-y')[0]; 5 | 6 | // options 7 | var options = { 8 | limit: container, 9 | setCursor: true, 10 | onDrag: function (element, x, y) { 11 | labelX.innerHTML = x; 12 | labelY.innerHTML = y; 13 | } 14 | }; 15 | 16 | // initialize drag 17 | new Draggable(element, options); -------------------------------------------------------------------------------- /Gruntfile.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (grunt) -> 2 | 3 | grunt.config.init 4 | 5 | uglify: 6 | options: 7 | mangle: 8 | toplevel: true 9 | compress: 10 | dead_code: true 11 | unused: true 12 | join_vars: true 13 | comments: false 14 | standard: 15 | files: 16 | 'dist/draggable.min.js': [ 17 | 'src/draggable.js' 18 | ] 19 | #wrap: true 20 | 21 | grunt.loadNpmTasks 'grunt-contrib-concat' 22 | grunt.loadNpmTasks 'grunt-contrib-uglify' 23 | 24 | grunt.registerTask 'default', ['uglify'] -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | grunt.config.init({ 4 | concat: { 5 | dist: { 6 | src: [ 7 | 'src/lib/polyfills.js', 8 | 'src/lib/dom.js', 9 | 'src/lib/util.js', 10 | 'src/lib/template.js', 11 | 'src/microbox.js' 12 | ], 13 | dest: 'dist/microbox.min.js' 14 | } 15 | }, 16 | wrap: true 17 | }); 18 | 19 | grunt.loadNpmTasks('grunt-contrib-concat'); 20 | 21 | //grunt.loadNpmTasks('grunt-contrib-uglify'); 22 | 23 | grunt.registerTask('default', ['concat']); 24 | 25 | }; -------------------------------------------------------------------------------- /demos/__common/common.js: -------------------------------------------------------------------------------- 1 | // IE8 polyfill 2 | HTMLDocument.prototype.getElementsByClassName = 3 | Element.prototype.getElementsByClassName = 4 | function getElementsByClassName (className) { 5 | for (var res = [], els = this.getElementsByTagName('*'), n = els.length; n--;) { 6 | if (els[n].className.indexOf(className) > -1) { 7 | res.push(els[n]); 8 | } 9 | } 10 | return res; 11 | } 12 | 13 | // prevent selection because it's annoying when dragging 14 | document.onselectstart = function(){ return false; }; 15 | document.body.setAttribute('unselectable', 'on', 0); -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "draggable", 3 | "version": "4.1.1", 4 | "homepage": "http://bcherny.github.io/draggable/demos", 5 | "authors": [ 6 | "Boris Cherny " 7 | ], 8 | "description": "High performance, fully cross browser, full featured drag and drop in a tiny (2k gzipped), dependency-free package", 9 | "main": "dist/draggable.min.js", 10 | "keywords": [ 11 | "drag", 12 | "drop", 13 | "drag", 14 | "and", 15 | "drop", 16 | "dragndrop", 17 | "move" 18 | ], 19 | "license": "MIT", 20 | "ignore": [ 21 | "node_modules", 22 | "bower_components" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /demos/basic/basic.js: -------------------------------------------------------------------------------- 1 | // find our elements 2 | var elements = document.getElementsByClassName('ball'), 3 | labelsX = document.getElementsByClassName('coords-x'), 4 | labelsY = document.getElementsByClassName('coords-y'); 5 | 6 | // loop over the 3 balls... 7 | for (var n = elements.length; n--;) { 8 | 9 | // ... augment our default options with individual `onDrag` handlers 10 | var opts = { 11 | onDrag: onDragFactory(n), 12 | setCursor: true 13 | }; 14 | 15 | // ... and initialize drag for each 16 | window.d = new Draggable(elements[n], opts); 17 | 18 | } 19 | 20 | // bind `n` to its value at iteration time 21 | function onDragFactory (n) { 22 | 23 | return function (element, x, y) { 24 | labelsX[n].innerHTML = x; 25 | labelsY[n].innerHTML = y; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /demos/handle/handle.js: -------------------------------------------------------------------------------- 1 | // find our elements 2 | var elements = document.getElementsByClassName('ball'), 3 | handles = document.querySelectorAll('.ball p'), 4 | labelsX = document.getElementsByClassName('coords-x'), 5 | labelsY = document.getElementsByClassName('coords-y'); 6 | 7 | // loop over the 3 balls... 8 | for (var n = elements.length; n--;) { 9 | 10 | // ... augment our default options with individual `onDrag` handlers 11 | var opts = { 12 | onDrag: onDragFactory(n), 13 | setCursor: true, 14 | handle: elements[n].getElementsByTagName('p')[0] 15 | }; 16 | 17 | // ... and initialize drag for each 18 | new Draggable(elements[n], opts); 19 | 20 | } 21 | 22 | // bind `n` to its value at iteration time 23 | function onDragFactory (n) { 24 | 25 | return function (element, x, y) { 26 | labelsX[n].innerHTML = x; 27 | labelsY[n].innerHTML = y; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2013-2015 Boris Cherny 2 | 3 | Permission 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE 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. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "draggable", 3 | "version": "4.2.0", 4 | "description": "High performance, fully cross browser, full featured drag and drop in a tiny (2k gzipped), dependency-free package", 5 | "homepage": "http://bcherny.github.io/draggable/demos", 6 | "author": "Boris Cherny ", 7 | "main": "dist/draggable.min.js", 8 | "contributors": [ 9 | { 10 | "name": "Boris Cherny", 11 | "email": "boris@performancejs.com" 12 | } 13 | ], 14 | "scripts": { 15 | "build": "grunt" 16 | }, 17 | "devDependencies": { 18 | "grunt": "^1.0.2", 19 | "grunt-cli": "^1.2.0", 20 | "grunt-contrib-concat": "^1.0.1", 21 | "grunt-contrib-uglify": "^3.3.0" 22 | }, 23 | "license": "MIT", 24 | "readmeFilename": "README.md", 25 | "dependencies": {}, 26 | "repository": { 27 | "type": "git", 28 | "url": "https://github.com/bcherny/draggable.git" 29 | }, 30 | "keywords": [ 31 | "drag", 32 | "drop", 33 | "drag and drop", 34 | "dragndrop", 35 | "move" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /demos/grid/grid.js: -------------------------------------------------------------------------------- 1 | var container = document.getElementById('container'), 2 | element = document.getElementsByClassName('ball')[0], 3 | labelX = document.getElementsByClassName('coords-x')[0], 4 | labelY = document.getElementsByClassName('coords-y')[0], 5 | inputGrid = document.getElementById('input-grid'), 6 | inputSmooth = document.getElementById('input-smooth'); 7 | 8 | // options 9 | var options = { 10 | grid: 10, 11 | setCursor: true, 12 | onDrag: update, 13 | onDragEnd: update 14 | }; 15 | 16 | // initialize drag 17 | var drag = new Draggable(element, options); 18 | 19 | function update (element, x, y) { 20 | labelX.innerHTML = x; 21 | labelY.innerHTML = y; 22 | } 23 | 24 | // form events 25 | inputGrid.addEventListener('change', function() { 26 | 27 | var grid = +inputGrid.value; 28 | 29 | // resize visual grid 30 | container.style.backgroundSize = grid; 31 | 32 | // update grid size in drag instance 33 | drag.setOption('grid', grid); 34 | 35 | }, false); 36 | 37 | inputSmooth.addEventListener('change', function() { 38 | 39 | drag.setOption('smoothDrag', inputSmooth.checked); 40 | 41 | }, false); -------------------------------------------------------------------------------- /demos/bounded/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | bounded demo | draggable.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 |
23 |
24 |
25 | 26 |
27 |
28 |
29 | 30 | 31 |
32 |
33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /demos/boundedcustom/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | bounded custom demo | draggable.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 | 31 | 32 |
33 |
34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /demos/boundedcustom/boundedcustom.js: -------------------------------------------------------------------------------- 1 | var element = document.getElementsByClassName('ball')[0], 2 | labelX = document.getElementsByClassName('coords-x')[0], 3 | labelY = document.getElementsByClassName('coords-y')[0]; 4 | 5 | // options 6 | var options = { 7 | limit: limit, 8 | setCursor: true, 9 | onDrag: function (element, x, y) { 10 | labelX.innerHTML = x; 11 | labelY.innerHTML = y; 12 | } 13 | }; 14 | 15 | // initialize drag 16 | new Draggable(element, options); 17 | 18 | // our custom limit function 19 | function limit ( 20 | x, // current X coordinate 21 | y, // current Y coordinate 22 | x0, // original X coordinate (where drag was started) 23 | y0 // original Y coordinate (where drag was started) 24 | ) { 25 | 26 | var radius = 100, 27 | dx = x - x0, 28 | dy = y - y0, 29 | distance = Math.sqrt(dx*dx + dy*dy), 30 | outOfRange = distance > radius; 31 | 32 | // only allow dragging within a circle of radius 100. 33 | // if our point is outside of the circle, compute the 34 | // point on the circle's edge closest to our point. 35 | // see http://math.stackexchange.com/a/127615/93158 36 | 37 | if (outOfRange) { 38 | 39 | x = ( x0 + radius * (x - x0) / distance ).toPrecision(4); 40 | y = ( y0 + radius * (y - y0) / distance ).toPrecision(4); 41 | 42 | } 43 | 44 | return { 45 | x: x, 46 | y: y 47 | }; 48 | 49 | } -------------------------------------------------------------------------------- /demos/grid/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | grid demo | draggable.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 21 |
22 |
23 |
24 |
25 |
26 | 30 | 34 |
35 |
36 | 37 | 38 |
39 |
40 |
41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /demos/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | basic demo | draggable.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 |
22 |
1
23 |
2
24 |
3
25 |
26 |
27 |
28 |

1

29 | 30 | 31 |
32 |
33 |

2

34 | 35 | 36 |
37 |
38 |

3

39 | 40 | 41 |
42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /demos/handle/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | handle element demo | draggable.js 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 |
22 |

23 |

24 |

25 |
26 |
27 |
28 |

1

29 | 30 | 31 |
32 |
33 |

2

34 | 35 | 36 |
37 |
38 |

3

39 | 40 | 41 |
42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /demos/__common/common.css: -------------------------------------------------------------------------------- 1 | /* general */ 2 | 3 | * {border:0;margin:0;outline:0;padding:0} 4 | 5 | body { 6 | font: 13px "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 7 | text-align: center; 8 | } 9 | 10 | /* navigation */ 11 | 12 | #nav { 13 | background: #ddd; 14 | height: 36px; 15 | position: absolute; 16 | left: 0; 17 | right: 0; 18 | top: 0; 19 | } 20 | 21 | #nav li { 22 | display: inline; 23 | list-style: none; 24 | margin-right: -4px; 25 | } 26 | 27 | #nav:before { 28 | color: #888; 29 | content: "Choose a demo:"; 30 | font-style: italic; 31 | padding-right: 10px; 32 | } 33 | 34 | #nav a { 35 | color: #666; 36 | display: inline-block; 37 | line-height: 36px; 38 | padding: 0 20px; 39 | text-decoration: none; 40 | } 41 | 42 | #nav a:hover { 43 | background: #DA8EB2; 44 | color: #fff; 45 | } 46 | 47 | #nav a.cur { 48 | background: #C0427E; 49 | color: #fff; 50 | font-weight: bold; 51 | } 52 | 53 | /* balls */ 54 | 55 | .ball { 56 | border-radius: 50px; 57 | color: rgba(255, 255, 255, .5); 58 | display: inline-block; 59 | font: bold 40px/100px Arial; 60 | height: 100px; 61 | width: 100px; 62 | } 63 | 64 | .ball p { 65 | display: block; 66 | background: white; 67 | border-radius: 50%; 68 | cursor: move; 69 | width: 30px; 70 | height: 30px; 71 | line-height: 39px; 72 | position: absolute; 73 | top: 50%; 74 | left: 50%; 75 | font-size: 22px; 76 | margin: -15px 0 0 -15px; 77 | } 78 | 79 | .ball.has-handle { 80 | cursor: default !important; 81 | } 82 | 83 | .red { background: red } 84 | .green { background: green } 85 | .blue { background: blue } 86 | 87 | /* layout */ 88 | 89 | #container { 90 | background: #eee; 91 | position: fixed; 92 | bottom: 0; 93 | left: 0; 94 | right: 0; 95 | top: 36px; 96 | } 97 | 98 | #info { 99 | background: #333; 100 | color: #777; 101 | font: bold 20px/40px Arial; 102 | height: 100px; 103 | position: fixed; 104 | bottom: 0; 105 | left: 0; 106 | right: 0; 107 | } 108 | 109 | .column { 110 | float: left; 111 | height: 100%; 112 | position: relative; 113 | width: 33.33333333%; 114 | } 115 | 116 | .column:after { 117 | background: #111; 118 | content: ""; 119 | position: absolute; 120 | bottom: 0; 121 | right: 0; 122 | top: 0; 123 | width: 1px; 124 | } 125 | 126 | .coords-x:before, 127 | .coords-y:before { 128 | color: #111; 129 | padding-right: 5px; 130 | position: relative; 131 | top: -1px; 132 | } 133 | 134 | .coords-x:before { content: "x" } 135 | .coords-y:before { content: "y" } 136 | 137 | h1 { 138 | font-size: 40px; 139 | line-height: 60px; 140 | } 141 | 142 | /* mobile */ 143 | @media only screen and (min-device-width : 320px) and (max-device-width : 480px) { 144 | 145 | #info { 146 | font: bold 16px/32px Arial; 147 | } 148 | 149 | } -------------------------------------------------------------------------------- /dist/draggable.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define([],e):t.Draggable=e()}(this,function(){"use strict";var t={grid:0,filterTarget:null,limit:{x:null,y:null},threshold:0,setCursor:!1,setPosition:!0,smoothDrag:!0,useGPU:!0,onDrag:u,onDragStart:u,onDragEnd:u},e={transform:function(){for(var t=" -o- -ms- -moz- -webkit-".split(" "),e=document.body.style,n=t.length;n--;){var o=t[n]+"transform";if(o in e)return o}}()},n={assign:function(){for(var t=arguments[0],e=arguments.length,n=1;ne[1]&&(t=e[1]):t=+e,t},addEvent:"attachEvent"in Element.prototype?function(t,e,n){t.attachEvent("on"+e,n)}:function(t,e,n){t.addEventListener(e,n,!1)},removeEvent:"attachEvent"in Element.prototype?function(t,e,n){t.detachEvent("on"+e,n)}:function(t,e,n){t.removeEventListener(e,n)}};function o(e,o){var i=this,r=n.bind(i.start,i),s=n.bind(i.drag,i),u=n.bind(i.stop,i);if(!a(e))throw new TypeError("Draggable expects argument 0 to be an Element");o=n.assign({},t,o),n.assign(i,{element:e,handle:o.handle&&a(o.handle)?o.handle:e,handlers:{start:{mousedown:r,touchstart:r},move:{mousemove:s,mouseup:u,touchmove:s,touchend:u}},options:o}),i.initialize()}function i(t){return parseInt(t,10)}function r(t){return"currentStyle"in t?t.currentStyle:getComputedStyle(t)}function s(t){return null!=t}function a(t){return t instanceof Element||"undefined"!=typeof HTMLDocument&&t instanceof HTMLDocument}function u(){}return n.assign(o.prototype,{setOption:function(t,e){var n=this;return n.options[t]=e,n.initialize(),n},get:function(){var t=this.dragEvent;return{x:t.x,y:t.y}},set:function(t,e){var n=this.dragEvent;return n.original={x:n.x,y:n.y},this.move(t,e),this},dragEvent:{started:!1,x:0,y:0},initialize:function(){var t,o=this,i=o.element,s=(o.handle,i.style),a=r(i),u=o.options,f=e.transform,l=o._dimensions={height:i.offsetHeight,left:i.offsetLeft,top:i.offsetTop,width:i.offsetWidth};u.useGPU&&f&&("none"===(t=a[f])&&(t=""),s[f]=t+" translate3d(0,0,0)"),u.setPosition&&(s.display="block",s.left=l.left+"px",s.top=l.top+"px",s.width=l.width+"px",s.height=l.height+"px",s.bottom=s.right="auto",s.margin=0,s.position="absolute"),u.setCursor&&(s.cursor="move"),o.setLimit(u.limit),n.assign(o.dragEvent,{x:l.left,y:l.top}),n.on(o.handle,o.handlers.start)},start:function(t){var e=this,o=e.getCursor(t),i=e.element;e.useTarget(t.target||t.srcElement)&&(t.preventDefault&&!t.target.getAttribute("contenteditable")?t.preventDefault():t.target.getAttribute("contenteditable")||(t.returnValue=!1),e.dragEvent.oldZindex=i.style.zIndex,i.style.zIndex=1e4,e.setCursor(o),e.setPosition(),e.setZoom(),n.on(document,e.handlers.move))},drag:function(t){var e=this,n=e.dragEvent,o=e.element,i=e._cursor,r=e._dimensions,s=e.options,a=r.zoom,u=e.getCursor(t),f=s.threshold,l=(u.x-i.x)/a+r.left,d=(u.y-i.y)/a+r.top;!n.started&&f&&Math.abs(i.x-u.x) 14 | ``` 15 | 16 | **JavaScript** 17 | 18 | *Using browser globals:* 19 | ```js 20 | var element = document.getElementById('id'); 21 | var options = { 22 | grid: 10, 23 | onDrag: function(){ ... } 24 | }; 25 | new Draggable (element, options); 26 | ``` 27 | 28 | *Using AMD/CommonJS:* 29 | ```js 30 | var Draggable = require ('Draggable'); 31 | var element = document.getElementById('id'); 32 | new Draggable (element); 33 | ``` 34 | 35 | ## Dependencies 36 | 37 | None! 38 | 39 | ## Options 40 | 41 | | Option | Type | Default | Description | 42 | |-------------------|---------------------|---------|-----------------------------------------------------------------------| 43 | | **grid** | `Number` | `0` | grid size for snapping on drag | 44 | | **handle** | `Element` | `null` | the handle of the draggable; if null, the whole element is the handle | 45 | | **filterTarget** | `Function(target)` | `null` | prevent drag when target passes this test | 46 | | **limit** | `Element`, `Function(x, y, x0, y0)`, or `Object` | `{ x: null, y: null }` | limit x/y drag bounds | 47 | | **threshold** | `Number` | `0` | threshold before drag begins (in px) | 48 | | **setCursor** | `Boolean` (truthy) | `false` | change cursor to `move`? | 49 | | **setPosition** | `Boolean` (truthy) | `true` | change draggable position to `absolute`? | 50 | | **smoothDrag** | `Boolean` (truthy) | `true` | snap to grid only when dropped, not during drag | 51 | | **useGPU** | `Boolean` (truthy) | `true` | move graphics calculation/composition to the GPU? (modern browsers only, graceful degradation) | 52 | 53 | ## Events 54 | 55 | | Event | Arguments | 56 | |-----------------|-------------------------| 57 | | **onDrag** | `element, x, y, event` | 58 | | **onDragStart** | `element, x, y, event` | 59 | | **onDragEnd** | `element, x, y, event` | 60 | 61 | ## Instance methods 62 | 63 | | Method | Arguments | Returns | Description 64 | |---------------|-----------------------------------------|-----------------------|-------------------------------------------| 65 | | **get** | --- | `{Object}` {x, y} | Get the current coordinates | 66 | | **set** | `{Number}` x, `{Number}` y | instance | Move to the specified coordinates | 67 | | **setOption** | `{String}` property, `{Mixed}` value | instance | Set an option in the live instance | 68 | | **destroy** | --- | --- | Unbind the instance's DOM event listeners | 69 | 70 | ## Notes 71 | 72 | Options.limit accepts arguments in several forms: 73 | 74 | ```js 75 | // no limit 76 | limit: null 77 | 78 | // limit x, but leave y unbounded 79 | limit: { 80 | x: [1,10], 81 | y: null 82 | } 83 | 84 | // limit both axes 85 | limit: { 86 | x: [1,10], 87 | y: [1,500] 88 | } 89 | 90 | // bound x, set y to a constant 91 | limit: { 92 | x: [1,10], 93 | y: 5 94 | } 95 | 96 | // bound with an element 97 | limit: document.getElementById('id') 98 | 99 | // bound with a custom function 100 | limit: function ( 101 | x, // current X coordinate 102 | y, // current Y coordinate 103 | x0, // original X coordinate (where drag was started) 104 | y0 // original Y coordinate (where drag was started) 105 | ) { 106 | 107 | var radius = 100, 108 | dx = x - x0, 109 | dy = y - y0, 110 | distance = Math.sqrt(dx*dx + dy*dy), 111 | 112 | // only allow dragging within a circle of radius 100 113 | outOfRange = distance > radius; 114 | 115 | 116 | // if our point is outside of the circle, compute the 117 | // point on the circle's edge closest to our point 118 | if (outOfRange) { 119 | 120 | x = x0 + radius * (x - x0) / distance; 121 | y = y0 + radius * (y - y0) / distance; 122 | 123 | } 124 | 125 | return { 126 | x: x, 127 | y: y 128 | }; 129 | 130 | } 131 | ``` 132 | 133 | ## Tested on 134 | 135 | - Chrome 29 on OSX 136 | - Chrome 28 on Windows 137 | - Firefox 23 on OSX 138 | - Firefox 21 on Windows 139 | - Opera 16 on OSX 140 | - Safari 6 on OSX 141 | - Safari 6 on iPhone4/iOS6 142 | - Safari 6 on iPhone5/iOS6 143 | - Safari 6 on iPad2/iOS6 144 | - Safari 6 on iPad3/iOS6 145 | - Internet Explorer 8-10 on Windows 146 | 147 | ## To do 148 | 149 | - Improve performance on old iOS 150 | - Unit tests 151 | -------------------------------------------------------------------------------- /src/draggable.js: -------------------------------------------------------------------------------- 1 | (function (root, factory) { 2 | if (typeof exports === 'object') { 3 | module.exports = factory(); 4 | } else if (typeof define === 'function' && define.amd) { 5 | define([], factory); 6 | } else { 7 | root.Draggable = factory(); 8 | } 9 | }(this, function () { 10 | 11 | 'use strict'; 12 | 13 | var defaults = { 14 | 15 | // settings 16 | grid: 0, // grid cell size for snapping to on drag 17 | filterTarget: null, // disallow drag when target passes this test 18 | limit: { // limit the drag bounds 19 | x: null, // [minimum position, maximum position] || position 20 | y: null // [minimum position, maximum position] || position 21 | }, 22 | threshold: 0, // threshold to move before drag begins (in px) 23 | 24 | // flags 25 | setCursor: false, // change cursor to reflect draggable? 26 | setPosition: true, // change draggable position to absolute? 27 | smoothDrag: true, // snap to grid when dropped, but not during 28 | useGPU: true, // move graphics calculation/composition to the GPU 29 | 30 | // event hooks 31 | onDrag: noop, // function(element, X, Y, event) 32 | onDragStart: noop, // function(element, X, Y, event) 33 | onDragEnd: noop // function(element, X, Y, event) 34 | 35 | }; 36 | 37 | var env = { 38 | 39 | // CSS vendor-prefixed transform property 40 | transform: (function(){ 41 | 42 | var prefixes = ' -o- -ms- -moz- -webkit-'.split(' '); 43 | var style = document.body.style; 44 | 45 | for (var n = prefixes.length; n--;) { 46 | var property = prefixes[n] + 'transform'; 47 | if (property in style) { 48 | return property; 49 | } 50 | } 51 | 52 | })() 53 | 54 | }; 55 | 56 | var util = { 57 | 58 | assign: function () { 59 | 60 | var obj = arguments[0]; 61 | var count = arguments.length; 62 | 63 | for ( var n = 1; n < count; n++ ) { 64 | var argument = arguments[n]; 65 | for ( var key in argument ) { 66 | obj[key] = argument[key]; 67 | } 68 | } 69 | 70 | return obj; 71 | 72 | }, 73 | 74 | bind: function (fn, context) { 75 | return function() { 76 | fn.apply(context, arguments); 77 | } 78 | }, 79 | 80 | on: function (element, e, fn) { 81 | if (e && fn) { 82 | util.addEvent (element, e, fn); 83 | } else if (e) { 84 | for (var ee in e) { 85 | util.addEvent (element, ee, e[ee]); 86 | } 87 | } 88 | }, 89 | 90 | off: function (element, e, fn) { 91 | if (e && fn) { 92 | util.removeEvent (element, e, fn); 93 | } else if (e) { 94 | for (var ee in e) { 95 | util.removeEvent (element, ee, e[ee]); 96 | } 97 | } 98 | }, 99 | 100 | // Example: 101 | // 102 | // util.limit(x, limit.x) 103 | limit: function (n, limit) { 104 | // {Array} limit.x 105 | if (isArray(limit)) { 106 | limit = [+limit[0], +limit[1]]; 107 | if (n < limit[0]) n = limit[0]; 108 | else if (n > limit[1]) n = limit[1]; 109 | // {Number} limit.x 110 | } else { 111 | n = +limit; 112 | } 113 | 114 | return n; 115 | }, 116 | 117 | addEvent: ('attachEvent' in Element.prototype) 118 | ? function (element, e, fn) { element.attachEvent('on'+e, fn) } 119 | : function (element, e, fn) { element.addEventListener(e, fn, false) }, 120 | 121 | removeEvent: ('attachEvent' in Element.prototype) 122 | ? function (element, e, fn) { element.detachEvent('on'+e, fn) } 123 | : function (element, e, fn) { element.removeEventListener(e, fn) } 124 | 125 | }; 126 | 127 | /* 128 | usage: 129 | 130 | new Draggable (element, options) 131 | - or - 132 | new Draggable (element) 133 | */ 134 | 135 | function Draggable (element, options) { 136 | 137 | var me = this, 138 | start = util.bind(me.start, me), 139 | drag = util.bind(me.drag, me), 140 | stop = util.bind(me.stop, me); 141 | 142 | // sanity check 143 | if (!isElement(element)) { 144 | throw new TypeError('Draggable expects argument 0 to be an Element'); 145 | } 146 | 147 | options = util.assign({}, defaults, options); 148 | 149 | // set instance properties 150 | util.assign(me, { 151 | 152 | // DOM element 153 | element: element, 154 | handle: (options.handle && isElement(options.handle)) 155 | ? options.handle 156 | : element, 157 | 158 | // DOM event handlers 159 | handlers: { 160 | start: { 161 | mousedown: start, 162 | touchstart: start 163 | }, 164 | move: { 165 | mousemove: drag, 166 | mouseup: stop, 167 | touchmove: drag, 168 | touchend: stop 169 | } 170 | }, 171 | 172 | // options 173 | options: options 174 | 175 | }); 176 | 177 | // initialize 178 | me.initialize(); 179 | 180 | } 181 | 182 | util.assign (Draggable.prototype, { 183 | 184 | // public 185 | 186 | setOption: function (property, value) { 187 | 188 | var me = this; 189 | 190 | me.options[property] = value; 191 | me.initialize(); 192 | 193 | return me; 194 | 195 | }, 196 | 197 | get: function() { 198 | 199 | var dragEvent = this.dragEvent; 200 | 201 | return { 202 | x: dragEvent.x, 203 | y: dragEvent.y 204 | }; 205 | 206 | }, 207 | 208 | set: function (x, y) { 209 | 210 | var me = this, 211 | dragEvent = me.dragEvent; 212 | 213 | dragEvent.original = { 214 | x: dragEvent.x, 215 | y: dragEvent.y 216 | }; 217 | 218 | me.move(x, y); 219 | 220 | return me; 221 | 222 | }, 223 | 224 | // internal 225 | 226 | dragEvent: { 227 | started: false, 228 | x: 0, 229 | y: 0 230 | }, 231 | 232 | initialize: function() { 233 | 234 | var me = this, 235 | element = me.element, 236 | handle = me.handle, 237 | style = element.style, 238 | compStyle = getStyle(element), 239 | options = me.options, 240 | transform = env.transform, 241 | oldTransform; 242 | 243 | // cache element dimensions (for performance) 244 | 245 | var _dimensions = me._dimensions = { 246 | height: element.offsetHeight, 247 | left: element.offsetLeft, 248 | top: element.offsetTop, 249 | width: element.offsetWidth 250 | }; 251 | 252 | // shift compositing over to the GPU if the browser supports it (for performance) 253 | 254 | if (options.useGPU && transform) { 255 | 256 | // concatenate to any existing transform 257 | // so we don't accidentally override it 258 | oldTransform = compStyle[transform]; 259 | 260 | if (oldTransform === 'none') { 261 | oldTransform = ''; 262 | } 263 | 264 | style[transform] = oldTransform + ' translate3d(0,0,0)'; 265 | } 266 | 267 | // optional styling 268 | 269 | if (options.setPosition) { 270 | style.display = 'block'; 271 | style.left = _dimensions.left + 'px'; 272 | style.top = _dimensions.top + 'px'; 273 | style.width = _dimensions.width + 'px'; 274 | style.height = _dimensions.height + 'px'; 275 | style.bottom = style.right = 'auto'; 276 | style.margin = 0; 277 | style.position = 'absolute'; 278 | } 279 | 280 | if (options.setCursor) { 281 | style.cursor = 'move'; 282 | } 283 | 284 | // set limit 285 | me.setLimit(options.limit); 286 | 287 | // set position in model 288 | util.assign(me.dragEvent, { 289 | x: _dimensions.left, 290 | y: _dimensions.top 291 | }); 292 | 293 | // attach mousedown event 294 | util.on(me.handle, me.handlers.start); 295 | 296 | }, 297 | 298 | start: function (e) { 299 | 300 | var me = this; 301 | var cursor = me.getCursor(e); 302 | var element = me.element; 303 | 304 | // filter the target? 305 | if (!me.useTarget(e.target || e.srcElement)) { 306 | return; 307 | } 308 | 309 | // prevent browsers from visually dragging the element's outline 310 | if (e.preventDefault && !e.target.getAttribute('contenteditable')) { 311 | e.preventDefault(); 312 | } else if (!e.target.getAttribute('contenteditable')) { 313 | e.returnValue = false; // IE10 314 | } 315 | 316 | // set a high z-index, just in case 317 | me.dragEvent.oldZindex = element.style.zIndex; 318 | element.style.zIndex = 10000; 319 | 320 | // set initial position 321 | me.setCursor(cursor); 322 | me.setPosition(); 323 | me.setZoom(); 324 | 325 | // add event listeners 326 | util.on(document, me.handlers.move); 327 | 328 | }, 329 | 330 | drag: function (e) { 331 | 332 | var me = this, 333 | dragEvent = me.dragEvent, 334 | element = me.element, 335 | initialCursor = me._cursor, 336 | initialPosition = me._dimensions, 337 | options = me.options, 338 | zoom = initialPosition.zoom, 339 | cursor = me.getCursor(e), 340 | threshold = options.threshold, 341 | x = (cursor.x - initialCursor.x)/zoom + initialPosition.left, 342 | y = (cursor.y - initialCursor.y)/zoom + initialPosition.top; 343 | 344 | // check threshold 345 | if (!dragEvent.started && threshold && 346 | (Math.abs(initialCursor.x - cursor.x) < threshold) && 347 | (Math.abs(initialCursor.y - cursor.y) < threshold) 348 | ) { 349 | return; 350 | } 351 | 352 | // save original position? 353 | if (!dragEvent.original) { 354 | dragEvent.original = { x: x, y: y }; 355 | } 356 | 357 | // trigger start event? 358 | if (!dragEvent.started) { 359 | options.onDragStart(element, x, y, e); 360 | dragEvent.started = true; 361 | } 362 | 363 | // move the element 364 | if (me.move(x, y)) { 365 | 366 | // trigger drag event 367 | options.onDrag(element, dragEvent.x, dragEvent.y, e); 368 | } 369 | 370 | }, 371 | 372 | move: function (x, y) { 373 | 374 | var me = this, 375 | dragEvent = me.dragEvent, 376 | options = me.options, 377 | grid = options.grid, 378 | style = me.element.style, 379 | pos = me.limit(x, y, dragEvent.original.x, dragEvent.original.y); 380 | 381 | // snap to grid? 382 | if (!options.smoothDrag && grid) { 383 | pos = me.round (pos, grid); 384 | } 385 | 386 | // move it 387 | if (pos.x !== dragEvent.x || pos.y !== dragEvent.y) { 388 | 389 | dragEvent.x = pos.x; 390 | dragEvent.y = pos.y; 391 | style.left = pos.x + 'px'; 392 | style.top = pos.y + 'px'; 393 | 394 | return true; 395 | } 396 | 397 | return false; 398 | 399 | }, 400 | 401 | stop: function (e) { 402 | 403 | var me = this, 404 | dragEvent = me.dragEvent, 405 | element = me.element, 406 | options = me.options, 407 | grid = options.grid, 408 | pos; 409 | 410 | // remove event listeners 411 | util.off(document, me.handlers.move); 412 | 413 | // resent element's z-index 414 | element.style.zIndex = dragEvent.oldZindex; 415 | 416 | // snap to grid? 417 | if (options.smoothDrag && grid) { 418 | pos = me.round({ x: dragEvent.x, y: dragEvent.y }, grid); 419 | me.move(pos.x, pos.y); 420 | util.assign(me.dragEvent, pos); 421 | } 422 | 423 | // trigger dragend event 424 | if (me.dragEvent.started) { 425 | options.onDragEnd(element, dragEvent.x, dragEvent.y, e); 426 | } 427 | 428 | // clear temp vars 429 | me.reset(); 430 | 431 | }, 432 | 433 | reset: function() { 434 | 435 | this.dragEvent.started = false; 436 | 437 | }, 438 | 439 | round: function (pos) { 440 | 441 | var grid = this.options.grid; 442 | 443 | return { 444 | x: grid * Math.round(pos.x/grid), 445 | y: grid * Math.round(pos.y/grid) 446 | }; 447 | 448 | }, 449 | 450 | getCursor: function (e) { 451 | 452 | return { 453 | x: (e.targetTouches ? e.targetTouches[0] : e).clientX, 454 | y: (e.targetTouches ? e.targetTouches[0] : e).clientY 455 | }; 456 | 457 | }, 458 | 459 | setCursor: function (xy) { 460 | 461 | this._cursor = xy; 462 | 463 | }, 464 | 465 | setLimit: function (limit) { 466 | 467 | var me = this, 468 | _true = function (x, y) { 469 | return { x:x, y:y }; 470 | }; 471 | 472 | // limit is a function 473 | if (isFunction(limit)) { 474 | 475 | me.limit = limit; 476 | 477 | } 478 | 479 | // limit is an element 480 | else if (isElement(limit)) { 481 | 482 | var draggableSize = me._dimensions, 483 | height = limit.scrollHeight - draggableSize.height, 484 | width = limit.scrollWidth - draggableSize.width; 485 | 486 | me.limit = function (x, y) { 487 | return { 488 | x: util.limit(x, [0, width]), 489 | y: util.limit(y, [0, height]) 490 | } 491 | }; 492 | 493 | } 494 | 495 | // limit is defined 496 | else if (limit) { 497 | 498 | var defined = { 499 | x: isDefined(limit.x), 500 | y: isDefined(limit.y) 501 | }; 502 | var _x, _y; 503 | 504 | // {Undefined} limit.x, {Undefined} limit.y 505 | if (!defined.x && !defined.y) { 506 | 507 | me.limit = _true; 508 | 509 | } else { 510 | 511 | me.limit = function (x, y) { 512 | return { 513 | x: defined.x ? util.limit(x, limit.x) : x, 514 | y: defined.y ? util.limit(y, limit.y) : y 515 | }; 516 | }; 517 | 518 | } 519 | } 520 | 521 | // limit is `null` or `undefined` 522 | else { 523 | 524 | me.limit = _true; 525 | 526 | } 527 | 528 | }, 529 | 530 | setPosition: function() { 531 | 532 | var me = this, 533 | element = me.element, 534 | style = element.style; 535 | 536 | util.assign(me._dimensions, { 537 | left: parse(style.left) || element.offsetLeft, 538 | top: parse(style.top) || element.offsetTop 539 | }); 540 | 541 | }, 542 | 543 | setZoom: function() { 544 | 545 | var me = this; 546 | var element = me.element; 547 | var zoom = 1; 548 | 549 | while (element = element.offsetParent) { 550 | 551 | var z = getStyle(element).zoom; 552 | 553 | if (z && z !== 'normal') { 554 | zoom = z; 555 | break; 556 | } 557 | 558 | } 559 | 560 | me._dimensions.zoom = zoom; 561 | 562 | }, 563 | 564 | useTarget: function (element) { 565 | 566 | var filterTarget = this.options.filterTarget; 567 | 568 | if (filterTarget instanceof Function) { 569 | return filterTarget(element); 570 | } 571 | 572 | return true; 573 | 574 | }, 575 | 576 | destroy: function () { 577 | 578 | util.off(this.handle, this.handlers.start); 579 | util.off(document, this.handlers.move); 580 | 581 | } 582 | 583 | }); 584 | 585 | // helpers 586 | 587 | function parse (string) { 588 | return parseInt(string, 10); 589 | } 590 | 591 | function getStyle (element) { 592 | return 'currentStyle' in element ? element.currentStyle : getComputedStyle(element); 593 | } 594 | 595 | function isArray (thing) { 596 | return thing instanceof Array; // HTMLElement 597 | } 598 | 599 | function isDefined (thing) { 600 | return thing !== void 0 && thing !== null; 601 | } 602 | 603 | function isElement (thing) { 604 | return thing instanceof Element || typeof HTMLDocument !== 'undefined' && thing instanceof HTMLDocument; 605 | } 606 | 607 | function isFunction (thing) { 608 | return thing instanceof Function; 609 | } 610 | 611 | function noop (){}; 612 | 613 | return Draggable; 614 | 615 | })); 616 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | abbrev@1: 6 | version "1.1.1" 7 | resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" 8 | 9 | ansi-regex@^2.0.0: 10 | version "2.1.1" 11 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 12 | 13 | ansi-styles@^2.2.1: 14 | version "2.2.1" 15 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 16 | 17 | argparse@^1.0.2: 18 | version "1.0.10" 19 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 20 | dependencies: 21 | sprintf-js "~1.0.2" 22 | 23 | array-find-index@^1.0.1: 24 | version "1.0.2" 25 | resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" 26 | 27 | async@~1.5.2: 28 | version "1.5.2" 29 | resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 30 | 31 | balanced-match@^1.0.0: 32 | version "1.0.0" 33 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 34 | 35 | brace-expansion@^1.1.7: 36 | version "1.1.11" 37 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 38 | dependencies: 39 | balanced-match "^1.0.0" 40 | concat-map "0.0.1" 41 | 42 | browserify-zlib@^0.1.4: 43 | version "0.1.4" 44 | resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" 45 | dependencies: 46 | pako "~0.2.0" 47 | 48 | builtin-modules@^1.0.0: 49 | version "1.1.1" 50 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" 51 | 52 | camelcase-keys@^2.0.0: 53 | version "2.1.0" 54 | resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" 55 | dependencies: 56 | camelcase "^2.0.0" 57 | map-obj "^1.0.0" 58 | 59 | camelcase@^2.0.0: 60 | version "2.1.1" 61 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" 62 | 63 | chalk@^1.0.0, chalk@~1.1.1: 64 | version "1.1.3" 65 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 66 | dependencies: 67 | ansi-styles "^2.2.1" 68 | escape-string-regexp "^1.0.2" 69 | has-ansi "^2.0.0" 70 | strip-ansi "^3.0.0" 71 | supports-color "^2.0.0" 72 | 73 | coffeescript@~1.10.0: 74 | version "1.10.0" 75 | resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.10.0.tgz#e7aa8301917ef621b35d8a39f348dcdd1db7e33e" 76 | 77 | colors@~1.1.2: 78 | version "1.1.2" 79 | resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" 80 | 81 | commander@~2.14.1: 82 | version "2.14.1" 83 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" 84 | 85 | concat-map@0.0.1: 86 | version "0.0.1" 87 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 88 | 89 | concat-stream@^1.4.1: 90 | version "1.6.0" 91 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" 92 | dependencies: 93 | inherits "^2.0.3" 94 | readable-stream "^2.2.2" 95 | typedarray "^0.0.6" 96 | 97 | core-util-is@~1.0.0: 98 | version "1.0.2" 99 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 100 | 101 | currently-unhandled@^0.4.1: 102 | version "0.4.1" 103 | resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" 104 | dependencies: 105 | array-find-index "^1.0.1" 106 | 107 | dateformat@~1.0.12: 108 | version "1.0.12" 109 | resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" 110 | dependencies: 111 | get-stdin "^4.0.1" 112 | meow "^3.3.0" 113 | 114 | decamelize@^1.1.2: 115 | version "1.2.0" 116 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 117 | 118 | error-ex@^1.2.0: 119 | version "1.3.1" 120 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" 121 | dependencies: 122 | is-arrayish "^0.2.1" 123 | 124 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 125 | version "1.0.5" 126 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 127 | 128 | esprima@^2.6.0: 129 | version "2.7.3" 130 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" 131 | 132 | eventemitter2@~0.4.13: 133 | version "0.4.14" 134 | resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-0.4.14.tgz#8f61b75cde012b2e9eb284d4545583b5643b61ab" 135 | 136 | exit@~0.1.1: 137 | version "0.1.2" 138 | resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" 139 | 140 | figures@^1.0.1: 141 | version "1.7.0" 142 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" 143 | dependencies: 144 | escape-string-regexp "^1.0.5" 145 | object-assign "^4.1.0" 146 | 147 | find-up@^1.0.0: 148 | version "1.1.2" 149 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" 150 | dependencies: 151 | path-exists "^2.0.0" 152 | pinkie-promise "^2.0.0" 153 | 154 | findup-sync@~0.3.0: 155 | version "0.3.0" 156 | resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16" 157 | dependencies: 158 | glob "~5.0.0" 159 | 160 | fs.realpath@^1.0.0: 161 | version "1.0.0" 162 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 163 | 164 | get-stdin@^4.0.1: 165 | version "4.0.1" 166 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" 167 | 168 | getobject@~0.1.0: 169 | version "0.1.0" 170 | resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c" 171 | 172 | glob@~5.0.0: 173 | version "5.0.15" 174 | resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" 175 | dependencies: 176 | inflight "^1.0.4" 177 | inherits "2" 178 | minimatch "2 || 3" 179 | once "^1.3.0" 180 | path-is-absolute "^1.0.0" 181 | 182 | glob@~7.0.0: 183 | version "7.0.6" 184 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" 185 | dependencies: 186 | fs.realpath "^1.0.0" 187 | inflight "^1.0.4" 188 | inherits "2" 189 | minimatch "^3.0.2" 190 | once "^1.3.0" 191 | path-is-absolute "^1.0.0" 192 | 193 | graceful-fs@^4.1.2: 194 | version "4.1.11" 195 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 196 | 197 | grunt-cli@^1.2.0, grunt-cli@~1.2.0: 198 | version "1.2.0" 199 | resolved "https://registry.yarnpkg.com/grunt-cli/-/grunt-cli-1.2.0.tgz#562b119ebb069ddb464ace2845501be97b35b6a8" 200 | dependencies: 201 | findup-sync "~0.3.0" 202 | grunt-known-options "~1.1.0" 203 | nopt "~3.0.6" 204 | resolve "~1.1.0" 205 | 206 | grunt-contrib-concat@^1.0.1: 207 | version "1.0.1" 208 | resolved "https://registry.yarnpkg.com/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz#61509863084e871d7e86de48c015259ed97745bd" 209 | dependencies: 210 | chalk "^1.0.0" 211 | source-map "^0.5.3" 212 | 213 | grunt-contrib-uglify@^3.3.0: 214 | version "3.3.0" 215 | resolved "https://registry.yarnpkg.com/grunt-contrib-uglify/-/grunt-contrib-uglify-3.3.0.tgz#dcc29bee1dd4768698930e46fb8bff8e8d37fb08" 216 | dependencies: 217 | chalk "^1.0.0" 218 | maxmin "^1.1.0" 219 | uglify-js "~3.3.0" 220 | uri-path "^1.0.0" 221 | 222 | grunt-known-options@~1.1.0: 223 | version "1.1.0" 224 | resolved "https://registry.yarnpkg.com/grunt-known-options/-/grunt-known-options-1.1.0.tgz#a4274eeb32fa765da5a7a3b1712617ce3b144149" 225 | 226 | grunt-legacy-log-utils@~1.0.0: 227 | version "1.0.0" 228 | resolved "https://registry.yarnpkg.com/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz#a7b8e2d0fb35b5a50f4af986fc112749ebc96f3d" 229 | dependencies: 230 | chalk "~1.1.1" 231 | lodash "~4.3.0" 232 | 233 | grunt-legacy-log@~1.0.0: 234 | version "1.0.0" 235 | resolved "https://registry.yarnpkg.com/grunt-legacy-log/-/grunt-legacy-log-1.0.0.tgz#fb86f1809847bc07dc47843f9ecd6cacb62df2d5" 236 | dependencies: 237 | colors "~1.1.2" 238 | grunt-legacy-log-utils "~1.0.0" 239 | hooker "~0.2.3" 240 | lodash "~3.10.1" 241 | underscore.string "~3.2.3" 242 | 243 | grunt-legacy-util@~1.0.0: 244 | version "1.0.0" 245 | resolved "https://registry.yarnpkg.com/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz#386aa78dc6ed50986c2b18957265b1b48abb9b86" 246 | dependencies: 247 | async "~1.5.2" 248 | exit "~0.1.1" 249 | getobject "~0.1.0" 250 | hooker "~0.2.3" 251 | lodash "~4.3.0" 252 | underscore.string "~3.2.3" 253 | which "~1.2.1" 254 | 255 | grunt@^1.0.2: 256 | version "1.0.2" 257 | resolved "https://registry.yarnpkg.com/grunt/-/grunt-1.0.2.tgz#4e6a5e695b70472fd5304f5fa9e34236836a73bc" 258 | dependencies: 259 | coffeescript "~1.10.0" 260 | dateformat "~1.0.12" 261 | eventemitter2 "~0.4.13" 262 | exit "~0.1.1" 263 | findup-sync "~0.3.0" 264 | glob "~7.0.0" 265 | grunt-cli "~1.2.0" 266 | grunt-known-options "~1.1.0" 267 | grunt-legacy-log "~1.0.0" 268 | grunt-legacy-util "~1.0.0" 269 | iconv-lite "~0.4.13" 270 | js-yaml "~3.5.2" 271 | minimatch "~3.0.2" 272 | nopt "~3.0.6" 273 | path-is-absolute "~1.0.0" 274 | rimraf "~2.2.8" 275 | 276 | gzip-size@^1.0.0: 277 | version "1.0.0" 278 | resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-1.0.0.tgz#66cf8b101047227b95bace6ea1da0c177ed5c22f" 279 | dependencies: 280 | browserify-zlib "^0.1.4" 281 | concat-stream "^1.4.1" 282 | 283 | has-ansi@^2.0.0: 284 | version "2.0.0" 285 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 286 | dependencies: 287 | ansi-regex "^2.0.0" 288 | 289 | hooker@~0.2.3: 290 | version "0.2.3" 291 | resolved "https://registry.yarnpkg.com/hooker/-/hooker-0.2.3.tgz#b834f723cc4a242aa65963459df6d984c5d3d959" 292 | 293 | hosted-git-info@^2.1.4: 294 | version "2.5.0" 295 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" 296 | 297 | iconv-lite@~0.4.13: 298 | version "0.4.19" 299 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" 300 | 301 | indent-string@^2.1.0: 302 | version "2.1.0" 303 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" 304 | dependencies: 305 | repeating "^2.0.0" 306 | 307 | inflight@^1.0.4: 308 | version "1.0.6" 309 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 310 | dependencies: 311 | once "^1.3.0" 312 | wrappy "1" 313 | 314 | inherits@2, inherits@^2.0.3, inherits@~2.0.3: 315 | version "2.0.3" 316 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 317 | 318 | is-arrayish@^0.2.1: 319 | version "0.2.1" 320 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 321 | 322 | is-builtin-module@^1.0.0: 323 | version "1.0.0" 324 | resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" 325 | dependencies: 326 | builtin-modules "^1.0.0" 327 | 328 | is-finite@^1.0.0: 329 | version "1.0.2" 330 | resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" 331 | dependencies: 332 | number-is-nan "^1.0.0" 333 | 334 | is-utf8@^0.2.0: 335 | version "0.2.1" 336 | resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" 337 | 338 | isarray@~1.0.0: 339 | version "1.0.0" 340 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 341 | 342 | isexe@^2.0.0: 343 | version "2.0.0" 344 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 345 | 346 | js-yaml@~3.5.2: 347 | version "3.5.5" 348 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.5.5.tgz#0377c38017cabc7322b0d1fbcd25a491641f2fbe" 349 | dependencies: 350 | argparse "^1.0.2" 351 | esprima "^2.6.0" 352 | 353 | load-json-file@^1.0.0: 354 | version "1.1.0" 355 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" 356 | dependencies: 357 | graceful-fs "^4.1.2" 358 | parse-json "^2.2.0" 359 | pify "^2.0.0" 360 | pinkie-promise "^2.0.0" 361 | strip-bom "^2.0.0" 362 | 363 | lodash@~3.10.1: 364 | version "3.10.1" 365 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" 366 | 367 | lodash@~4.3.0: 368 | version "4.3.0" 369 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.3.0.tgz#efd9c4a6ec53f3b05412429915c3e4824e4d25a4" 370 | 371 | loud-rejection@^1.0.0: 372 | version "1.6.0" 373 | resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" 374 | dependencies: 375 | currently-unhandled "^0.4.1" 376 | signal-exit "^3.0.0" 377 | 378 | map-obj@^1.0.0, map-obj@^1.0.1: 379 | version "1.0.1" 380 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" 381 | 382 | maxmin@^1.1.0: 383 | version "1.1.0" 384 | resolved "https://registry.yarnpkg.com/maxmin/-/maxmin-1.1.0.tgz#71365e84a99dd8f8b3f7d5fde2f00d1e7f73be61" 385 | dependencies: 386 | chalk "^1.0.0" 387 | figures "^1.0.1" 388 | gzip-size "^1.0.0" 389 | pretty-bytes "^1.0.0" 390 | 391 | meow@^3.1.0, meow@^3.3.0: 392 | version "3.7.0" 393 | resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" 394 | dependencies: 395 | camelcase-keys "^2.0.0" 396 | decamelize "^1.1.2" 397 | loud-rejection "^1.0.0" 398 | map-obj "^1.0.1" 399 | minimist "^1.1.3" 400 | normalize-package-data "^2.3.4" 401 | object-assign "^4.0.1" 402 | read-pkg-up "^1.0.1" 403 | redent "^1.0.0" 404 | trim-newlines "^1.0.0" 405 | 406 | "minimatch@2 || 3", minimatch@^3.0.2, minimatch@~3.0.2: 407 | version "3.0.4" 408 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 409 | dependencies: 410 | brace-expansion "^1.1.7" 411 | 412 | minimist@^1.1.3: 413 | version "1.2.0" 414 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" 415 | 416 | nopt@~3.0.6: 417 | version "3.0.6" 418 | resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" 419 | dependencies: 420 | abbrev "1" 421 | 422 | normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: 423 | version "2.4.0" 424 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" 425 | dependencies: 426 | hosted-git-info "^2.1.4" 427 | is-builtin-module "^1.0.0" 428 | semver "2 || 3 || 4 || 5" 429 | validate-npm-package-license "^3.0.1" 430 | 431 | number-is-nan@^1.0.0: 432 | version "1.0.1" 433 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 434 | 435 | object-assign@^4.0.1, object-assign@^4.1.0: 436 | version "4.1.1" 437 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 438 | 439 | once@^1.3.0: 440 | version "1.4.0" 441 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 442 | dependencies: 443 | wrappy "1" 444 | 445 | pako@~0.2.0: 446 | version "0.2.9" 447 | resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" 448 | 449 | parse-json@^2.2.0: 450 | version "2.2.0" 451 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" 452 | dependencies: 453 | error-ex "^1.2.0" 454 | 455 | path-exists@^2.0.0: 456 | version "2.1.0" 457 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" 458 | dependencies: 459 | pinkie-promise "^2.0.0" 460 | 461 | path-is-absolute@^1.0.0, path-is-absolute@~1.0.0: 462 | version "1.0.1" 463 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 464 | 465 | path-type@^1.0.0: 466 | version "1.1.0" 467 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" 468 | dependencies: 469 | graceful-fs "^4.1.2" 470 | pify "^2.0.0" 471 | pinkie-promise "^2.0.0" 472 | 473 | pify@^2.0.0: 474 | version "2.3.0" 475 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 476 | 477 | pinkie-promise@^2.0.0: 478 | version "2.0.1" 479 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 480 | dependencies: 481 | pinkie "^2.0.0" 482 | 483 | pinkie@^2.0.0: 484 | version "2.0.4" 485 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 486 | 487 | pretty-bytes@^1.0.0: 488 | version "1.0.4" 489 | resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84" 490 | dependencies: 491 | get-stdin "^4.0.1" 492 | meow "^3.1.0" 493 | 494 | process-nextick-args@~2.0.0: 495 | version "2.0.0" 496 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" 497 | 498 | read-pkg-up@^1.0.1: 499 | version "1.0.1" 500 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" 501 | dependencies: 502 | find-up "^1.0.0" 503 | read-pkg "^1.0.0" 504 | 505 | read-pkg@^1.0.0: 506 | version "1.1.0" 507 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" 508 | dependencies: 509 | load-json-file "^1.0.0" 510 | normalize-package-data "^2.3.2" 511 | path-type "^1.0.0" 512 | 513 | readable-stream@^2.2.2: 514 | version "2.3.4" 515 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.4.tgz#c946c3f47fa7d8eabc0b6150f4a12f69a4574071" 516 | dependencies: 517 | core-util-is "~1.0.0" 518 | inherits "~2.0.3" 519 | isarray "~1.0.0" 520 | process-nextick-args "~2.0.0" 521 | safe-buffer "~5.1.1" 522 | string_decoder "~1.0.3" 523 | util-deprecate "~1.0.1" 524 | 525 | redent@^1.0.0: 526 | version "1.0.0" 527 | resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" 528 | dependencies: 529 | indent-string "^2.1.0" 530 | strip-indent "^1.0.1" 531 | 532 | repeating@^2.0.0: 533 | version "2.0.1" 534 | resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" 535 | dependencies: 536 | is-finite "^1.0.0" 537 | 538 | resolve@~1.1.0: 539 | version "1.1.7" 540 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" 541 | 542 | rimraf@~2.2.8: 543 | version "2.2.8" 544 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" 545 | 546 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 547 | version "5.1.1" 548 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" 549 | 550 | "semver@2 || 3 || 4 || 5": 551 | version "5.5.0" 552 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" 553 | 554 | signal-exit@^3.0.0: 555 | version "3.0.2" 556 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 557 | 558 | source-map@^0.5.3: 559 | version "0.5.7" 560 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 561 | 562 | source-map@~0.6.1: 563 | version "0.6.1" 564 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 565 | 566 | spdx-correct@^3.0.0: 567 | version "3.0.0" 568 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" 569 | dependencies: 570 | spdx-expression-parse "^3.0.0" 571 | spdx-license-ids "^3.0.0" 572 | 573 | spdx-exceptions@^2.1.0: 574 | version "2.1.0" 575 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" 576 | 577 | spdx-expression-parse@^3.0.0: 578 | version "3.0.0" 579 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" 580 | dependencies: 581 | spdx-exceptions "^2.1.0" 582 | spdx-license-ids "^3.0.0" 583 | 584 | spdx-license-ids@^3.0.0: 585 | version "3.0.0" 586 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" 587 | 588 | sprintf-js@~1.0.2: 589 | version "1.0.3" 590 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 591 | 592 | string_decoder@~1.0.3: 593 | version "1.0.3" 594 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" 595 | dependencies: 596 | safe-buffer "~5.1.0" 597 | 598 | strip-ansi@^3.0.0: 599 | version "3.0.1" 600 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 601 | dependencies: 602 | ansi-regex "^2.0.0" 603 | 604 | strip-bom@^2.0.0: 605 | version "2.0.0" 606 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" 607 | dependencies: 608 | is-utf8 "^0.2.0" 609 | 610 | strip-indent@^1.0.1: 611 | version "1.0.1" 612 | resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" 613 | dependencies: 614 | get-stdin "^4.0.1" 615 | 616 | supports-color@^2.0.0: 617 | version "2.0.0" 618 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 619 | 620 | trim-newlines@^1.0.0: 621 | version "1.0.0" 622 | resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" 623 | 624 | typedarray@^0.0.6: 625 | version "0.0.6" 626 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 627 | 628 | uglify-js@~3.3.0: 629 | version "3.3.12" 630 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.3.12.tgz#efd87c16a1f4c674a8a5ede571001ef634dcc883" 631 | dependencies: 632 | commander "~2.14.1" 633 | source-map "~0.6.1" 634 | 635 | underscore.string@~3.2.3: 636 | version "3.2.3" 637 | resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.2.3.tgz#806992633665d5e5fcb4db1fb3a862eb68e9e6da" 638 | 639 | uri-path@^1.0.0: 640 | version "1.0.0" 641 | resolved "https://registry.yarnpkg.com/uri-path/-/uri-path-1.0.0.tgz#9747f018358933c31de0fccfd82d138e67262e32" 642 | 643 | util-deprecate@~1.0.1: 644 | version "1.0.2" 645 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 646 | 647 | validate-npm-package-license@^3.0.1: 648 | version "3.0.3" 649 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" 650 | dependencies: 651 | spdx-correct "^3.0.0" 652 | spdx-expression-parse "^3.0.0" 653 | 654 | which@~1.2.1: 655 | version "1.2.14" 656 | resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" 657 | dependencies: 658 | isexe "^2.0.0" 659 | 660 | wrappy@1: 661 | version "1.0.2" 662 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 663 | --------------------------------------------------------------------------------