├── .gitignore
├── .jsdoc.json
├── .travis.yml
├── LICENSE
├── README.md
├── dist
├── ranger.cjs.js
├── ranger.esm.js
└── ranger.umd.js
├── examples
├── es6
│ ├── .babelrc
│ ├── package.json
│ ├── src
│ │ ├── index.html
│ │ ├── index.js
│ │ └── js
│ │ │ ├── App.js
│ │ │ ├── config.js
│ │ │ ├── core
│ │ │ ├── BaseApp.js
│ │ │ ├── graphics
│ │ │ │ ├── Circle.js
│ │ │ │ └── Rect.js
│ │ │ └── sceneGraph
│ │ │ │ ├── Node.js
│ │ │ │ └── Renderer.js
│ │ │ ├── examples
│ │ │ ├── BaseExample.js
│ │ │ ├── Color.js
│ │ │ ├── CustomCurve.js
│ │ │ ├── Divide.js
│ │ │ ├── MapPosition.js
│ │ │ ├── ParticleTiming.js
│ │ │ ├── RandomPosition.js
│ │ │ └── Wrap.js
│ │ │ ├── factories
│ │ │ ├── circleFactory.js
│ │ │ └── rectFactory.js
│ │ │ └── lib
│ │ │ └── guify.min.js
│ └── webpack.config.js
└── umd
│ └── index.html
├── package-lock.json
├── package.json
├── rollup.config.js
├── src
├── Range.js
├── main.cjs.js
├── main.es.js
├── main.umd.js
└── ranger.js
└── test
└── test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | docs
4 |
--------------------------------------------------------------------------------
/.jsdoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "tags": {
3 | "allowUnknownTags": true,
4 | "dictionaries": ["jsdoc"]
5 | },
6 | "source": {
7 | "include": ["src/ranger.js", "src/Range.js", "README.md"],
8 | "excludePattern": "(node_modules/|docs)"
9 | },
10 | "plugins": [
11 | "plugins/markdown"
12 | ],
13 | "templates": {
14 | "cleverLinks": false,
15 | "monospaceLinks": true,
16 | "useLongnameInNav": false,
17 | "showInheritedInNav": true
18 | },
19 | "opts": {
20 | "destination": "./docs/",
21 | "encoding": "utf8",
22 | "private": true,
23 | "recurse": true,
24 | "template": "./node_modules/minami"
25 | }
26 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '9'
4 | - '8'
5 | - '6'
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 [these people](https://github.com/rollup/rollup-starter-lib/graphs/contributors)
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.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ranger
2 |
3 | Ranger.js is a small, standalone library for working with ranges of numbers in Javascript.
4 |
5 | Ranger provides all the utility methods you'd expect, including `clamp`, `wrap`, `map`, and `random`.
6 | These methods are available statically, as well as through a `Range` object that can be instantiated for repeated use.
7 |
8 | Ranger's main feature is the ability to provide a 'curve' function to certain methods, which will affect how numbers are distributed.
9 |
10 | ``` js
11 | import ranger from '@zadvorsky/ranger';
12 |
13 | // this will return a float between 20 and 40
14 | // when called repeatedly, the distribution of numbers will be approximately linear.
15 | ranger.random(20, 40);
16 |
17 | // just an arbitrary easing function
18 | function expoEaseOut(x) {
19 | return 1.0 - Math.pow(2.0, -10.0 * x);
20 | }
21 |
22 | // this will also return a float between 20 and 40
23 | // but the distribution will be heavily skewed towards the higher end of the range
24 | ranger.random(20, 40, expoEaseOut);
25 | ```
26 |
27 | The curve can be any function that takes a float between 0.0 and 1.0, and returns a transformed float.
28 | Easing functions are a good example of this, but there are many [others](https://pbs.twimg.com/media/DRJY_inVoAA5t7A.jpg:large).
29 |
30 | Curves can be applied to `random`, `randomInt`, `map`, `divide`, among others.
31 |
32 | Being able to apply easing any value in your application is a powerful way to give yourself more control over the visual output.
33 |
34 | Ranger does not ship with any curves itself, but there are plenty of sources for them.
35 | * [https://gist.github.com/gre/1650294](https://gist.github.com/gre/1650294)
36 | * [https://github.com/danro/easing-js](https://github.com/danro/easing-js)
37 | * [https://github.com/component/ease](https://github.com/component/ease)
38 |
39 | If you are using GSAP, you can access its easing functions directly like this:
40 | ``` js
41 | ranger.random(20, 40, Expo.easeOut.getRatio);
42 | ```
43 | ## Usage
44 |
45 | For the browser version, include `dist/ranger.umd.js` in a script tag. A global `ranger` namespace will then be available.
46 | ``` js
47 | var value1 = ranger.random(20, 40);
48 |
49 | var range = new ranger.Range(20, 40);
50 | var value2 = range.random();
51 | ```
52 |
53 | For usage with NPM, run `npm install --save @zadvorsky/ranger`.
54 | ``` js
55 | // with ES6 imports
56 | import ranger, { Range } from '@zadvorsky/ranger';
57 |
58 | // or CommonJS
59 | const ranger = require('@zadvorsky/ranger');
60 | const { Range } = require('@zadvorsky/ranger');
61 |
62 | // creates a range {min: 0, max: 100}
63 | const range1 = new Range(0, 100);
64 |
65 | range1.random(); // returns a float between range.min and range.max
66 | range1.contains(101) // returns false
67 |
68 | // Range has chainable transformation methods
69 | // this line creates a range of {min: -10, max: 10}
70 | const range2 = range.clone().set(-1, 1).scale(10);
71 |
72 | // maps a value from range 2 to range 1
73 | range2.map(-5, range1); // returns 25
74 |
75 | // static method
76 | ranger.map(-5, range2, range1) // same as above
77 |
78 | // crates a range with expoEaseOut as the default curve.
79 | const range3 = new Range(0, 100, expoEaseOut);
80 | ```
81 |
82 | ## Documentation
83 |
84 | Documentation can be found [here](http://ranger-docs.surge.sh/).
85 |
86 | Examples can be found [here](http://ranger-examples.surge.sh/).
87 |
88 | ## Build
89 |
90 | To build locally, run
91 | ``` sh
92 | npm install
93 | npm run dev
94 | ```
95 | This project uses Rollup to bundle the library.
96 |
97 | ## Build examples
98 |
99 | To build the es6 example application, run
100 | ``` sh
101 | cd examples/es6
102 | npm install
103 | npm run start
104 | ```
105 |
106 | The example application uses WebPack 4. It has a bunch of boilerplate code, and uses GSAP for animations.
107 |
108 | The actual example code can be found in `examples/es6/src/js/examples`.
109 |
110 | ## License
111 |
112 | [MIT](LICENSE).
113 |
--------------------------------------------------------------------------------
/dist/ranger.cjs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * @namespace
5 | */
6 | const ranger = {
7 |
8 | /**
9 | * Default curve, which is just a pass-through function.
10 | *
11 | * @param {number} x
12 | * @returns {number}
13 | */
14 | LINEAR: x => x,
15 |
16 | // measurements
17 |
18 | /**
19 | * Calculates the length of a range, or just (max - min). Used internally.
20 | * No validation is performed to check if the range is valid (max >= min).
21 | *
22 | * @param {number} min - Min value of the range.
23 | * @param {number} max - Max value of the range.
24 | * @returns {number} Length of the range.
25 | */
26 | length(min, max) {
27 | return max - min;
28 | },
29 |
30 | /**
31 | * A range is valid if max >= min.
32 | *
33 | * @param {number} min - Min value of the range.
34 | * @param {number} max - Max value of the range.
35 | * @returns {boolean}
36 | */
37 | isValid(min, max) {
38 | return max >= min;
39 | },
40 |
41 | /**
42 | * Returns the position of a value in the range, as a float 0.0 and 1.0.
43 | * The supplied value is not clamped. If it's out of bounds, the returned position will be proportionally out of bounds.
44 | *
45 | * @param {number} x - The value to check.
46 | * @param {number} min - Min value of the range.
47 | * @param {number} max - Max value of the range.
48 | * @param {function} [curve] - The curve function to apply.
49 | * @returns {number} - Position of the supplied value.
50 | */
51 | getPosition(x, min, max, curve = ranger.LINEAR) {
52 | return curve((x - min) / ranger.length(min, max));
53 | },
54 |
55 | /**
56 | * Returns the value at a given position in the rage.
57 | * The returned value is not clamped.
58 | *
59 | * @param {number} x - The position to check. Should be between 0.0 and 1.0.
60 | * @param {number} min - Min value of the range.
61 | * @param {number} max - Max value of the range.
62 | * @param {function} [curve] - The curve function to apply.
63 | * @returns {*} - Value at the supplied position.
64 | */
65 | getValue(x, min, max, curve = ranger.LINEAR) {
66 | return min + curve(x) * ranger.length(min, max);
67 | },
68 |
69 | // mapping
70 |
71 | /**
72 | * Maps a value from one range to a value from another range at the same position.
73 | * The source range is sampled linearly.
74 | * None of the values are clamped.
75 | *
76 | * @param {number} x - The value to map. Should be contained in sourceRange.
77 | * @param {Range} sourceRange - The range to map from.
78 | * @param {Range} targetRange - The range to map to.
79 | * @param {function} [curve] - The curve function to apply to the targetRange.
80 | * @returns {Number} - The mapped value, between targetRange.min and targetRange.max.
81 | */
82 | map(x, sourceRange, targetRange, curve = ranger.LINEAR) {
83 | return ranger.getValue(sourceRange.getPosition(x, ranger.LINEAR), targetRange.min, targetRange.max, curve);
84 | },
85 |
86 | /**
87 | * Same as map, but the source and target ranges should be provided as numbers.
88 | *
89 | * @see map
90 | *
91 | * @param {number} x - The value to map. Should be contained in the source range.
92 | * @param {number} sourceMin - Min value for the source range.
93 | * @param {number} sourceMax - Max value for the source range.
94 | * @param {number} targetMin - Min value for the target range.
95 | * @param {number} targetMax - Max value for the target range.
96 | * @param {function} [curve] - The curve function to apply to the target range.
97 | * @returns {number} - The mapped value, between targetMin and targetMax.
98 | */
99 | mapFloat(x, sourceMin, sourceMax, targetMin, targetMax, curve = ranger.LINEAR) {
100 | return ranger.getValue(ranger.getPosition(x, sourceMin, sourceMax, ranger.LINEAR), targetMin, targetMax, curve);
101 | },
102 |
103 | // random
104 |
105 | /**
106 | * Returns a random float between min and max.
107 | *
108 | * @param {number} min - Min value of the range.
109 | * @param {number} max - Max value of the range.
110 | * @param {function} [curve] - The curve function to apply.
111 | * @returns {number}
112 | */
113 | random(min, max, curve = ranger.LINEAR) {
114 | return min + curve(Math.random()) * ranger.length(min, max);
115 | },
116 |
117 | /**
118 | * Returns a random int between min and max.
119 | * The returned value is floored, so it will never equal max.
120 | *
121 | * @param {number} min - Min value of the range.
122 | * @param {number} max - Max value of the range.
123 | * @param {function} [curve] - The curve function to apply.
124 | * @returns {number}
125 | */
126 | randomInt(min, max, curve = ranger.LINEAR) {
127 | return ranger.random(min, max, curve) | 0;
128 | },
129 |
130 | // common operations
131 |
132 | /**
133 | * Returns min if x < min.
134 | * Returns max if x > max.
135 | * Returns x otherwise.
136 | *
137 | * @param {number} x - The value to check.
138 | * @param {number} min - Min value of the range.
139 | * @param {number} max - Max value of the range.
140 | * @returns {number} - The clamped value.
141 | */
142 | clamp(x, min, max) {
143 | return x < min ? min : x > max ? max : x;
144 | },
145 |
146 | /**
147 | * Wraps a value around the range.
148 | * This is similar to the modulo operator, but for arbitrary ranges.
149 | *
150 | * @param {number} x - The value to wrap.
151 | * @param {number} min - Min value of the range.
152 | * @param {number} max - Max value of the range.
153 | * @returns {number} - The wrapped value.
154 | */
155 | wrap(x, min, max) {
156 | const l = ranger.length(min, max);
157 |
158 | return (((x - min) % l) + l) % l + min;
159 | },
160 |
161 | /**
162 | * Checks if a value is inside the range.
163 | *
164 | * @param {number} x - The value to check.
165 | * @param {number} min - Min value of the range.
166 | * @param {number} max - Max value of the range.
167 | * @returns {boolean}
168 | */
169 | contains(x, min, max) {
170 | return x >= min && x <= max;
171 | },
172 |
173 | /**
174 | * Checks if the source range is contained in the target range.
175 | *
176 | * @param {Range} sourceRange - The range to check.
177 | * @param {Range} targetRange - The range the sourceRange will be compared to.
178 | * @returns {boolean}
179 | */
180 | containsRange(sourceRange, targetRange) {
181 | return ranger.contains(sourceRange.min, targetRange.min, targetRange.max) && ranger.contains(sourceRange.max, targetRange.min, targetRange.max);
182 | },
183 | };
184 |
185 | /**
186 | * Creates a new Range instance with a min, max, and curve for repeated use.
187 | * No validation is performed to check if min is less or equal to max.
188 | *
189 | * @class
190 | * @constructor
191 | */
192 | class Range {
193 | /**
194 | * Creates a new Range instance with a min, max, and curve for repeated use.
195 | * No validation is performed to check if min is less or equal to max.
196 | *
197 | * @param {number} min - Min value for this range.
198 | * @param {number} max - Max value for this range.
199 | * @param {function} [curve] - The curve function to apply by default.
200 | */
201 | constructor(min = 0, max = 0, curve = ranger.LINEAR) {
202 | /**
203 | * Min value for this range
204 | * @type {number}
205 | */
206 | this.min = min;
207 | /**
208 | * Max value for this range
209 | * @type {number}
210 | */
211 | this.max = max;
212 | /**
213 | * The curve used by this range.
214 | * This should be a function that takes a number (0.0 to 1.0), and returns a transformed number.
215 | * @type {Function}
216 | */
217 | this.curve = curve;
218 | }
219 |
220 | /**
221 | * Sets this range min and max based on a size and a center.
222 | * Min will be set to size * -0.5 + center.
223 | * Max will be set to size * 0.5 + center.
224 | *
225 | * @param {Number} size - The total size of the range.
226 | * @param {Number} [center=0] - The center of the range. Defaults to 0.
227 | * @param {function} [curve] - The curve function to apply by default.
228 | * @returns {Range}
229 | */
230 | fromSizeAndCenter(size, center = 0, curve = this.curve) {
231 | this.min = size * -0.5 + center;
232 | this.max = size * 0.5 + center;
233 | this.curve = curve;
234 |
235 | return this;
236 | }
237 |
238 | /**
239 | * Sets the min, max, and curve for this range.
240 | *
241 | * @param {number} min - Min value for this range.
242 | * @param {number} max - Max value for this range.
243 | * @param {function} [curve] - The curve function to apply by default.
244 | * @returns {Range}
245 | */
246 | set(min = this.min, max = this.max, curve = this.curve) {
247 | this.min = min;
248 | this.max = max;
249 | this.curve = curve;
250 |
251 | return this;
252 | }
253 |
254 | /**
255 | * Sets the min value for this range. This method mostly exists for chaining.
256 | *
257 | * @param {number} min - Min value for this range.
258 | * @returns {Range}
259 | */
260 | setMin(min) {
261 | this.min = min;
262 |
263 | return this;
264 | }
265 |
266 | /**
267 | * Sets the max value for this range. This method mostly exists for chaining.
268 | *
269 | * @param {number} max - Max value for this range.
270 | * @returns {Range}
271 | */
272 | setMax(max) {
273 | this.max = max;
274 |
275 | return this;
276 | }
277 |
278 | /**
279 | * Sets the default curve for this range. This method mostly exists for chaining.
280 | *
281 | * @param {function} curve - The curve function to apply by default.
282 | * @returns {Range}
283 | */
284 | setCurve(curve) {
285 | this.curve = curve;
286 |
287 | return this;
288 | }
289 |
290 | /**
291 | * Multiplies this range's min and max with the given scalar.
292 | * Values below 1.0 will make the range smaller.
293 | * Values over 1.0 will make it bigger.
294 | *
295 | * @param {number} s - The scalar to use.
296 | * @returns {Range}
297 | */
298 | scale(s) {
299 | this.min *= s;
300 | this.max *= s;
301 |
302 | return this;
303 | }
304 |
305 | /**
306 | * Expands this range by a given delta.
307 | * The delta is subtracted from this.min, and added to this.max.
308 | *
309 | * @param {Number} d - The delta to expand this range by.
310 | * @returns {Range}
311 | */
312 | expand(d) {
313 | this.min -= d;
314 | this.max += d;
315 |
316 | return this;
317 | }
318 |
319 | /**
320 | * Contracts this range by a given delta.
321 | * The delta is added to this.min, and subtracted from this.max.
322 | *
323 | * @param {number} d - The delta to contract this range by.
324 | * @returns {Range}
325 | */
326 | contract(d) {
327 | this.min += d;
328 | this.max -= d;
329 |
330 | return this;
331 | }
332 |
333 | /**
334 | * Shifts this range by a given delta.
335 | * The delta is added to this.min and this.max.
336 | *
337 | * @param {number} d - The delta to shift this range by.
338 | * @returns {Range}
339 | */
340 | shift(d) {
341 | this.min += d;
342 | this.max += d;
343 |
344 | return this;
345 | }
346 |
347 | /**
348 | * Copies another range's min, max, and curve into this one.
349 | * The curve is passed by reference.
350 | *
351 | * @param {Range} range - The range to copy from.
352 | * @returns {Range}
353 | */
354 | copy(range) {
355 | this.min = range.min;
356 | this.max = range.max;
357 | this.curve = range.curve;
358 |
359 | return this;
360 | }
361 |
362 | /**
363 | * Creates a shallow copy of this range.
364 | *
365 | * @returns {Range}
366 | */
367 | clone() {
368 | return new Range(this.min, this.max, this.curve);
369 | }
370 |
371 | /**
372 | * Checks if this range is empty.
373 | * A range is empty if its min === max.
374 | *
375 | * @returns {boolean}
376 | */
377 | isEmpty() {
378 | return this.min === this.max;
379 | }
380 |
381 | /**
382 | * Sets this range's min and max to 0.
383 | *
384 | * @returns {Range}
385 | */
386 | makeEmpty() {
387 | this.min = 0;
388 | this.max = 0;
389 |
390 | return this;
391 | }
392 |
393 | /**
394 | * @see ranger.length
395 | * @returns {number}
396 | */
397 | length() {
398 | return ranger.length(this.min, this.max);
399 | }
400 |
401 | /**
402 | * @see ranger.getPosition
403 | *
404 | * @param {number} x - The value to check.
405 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
406 | * @returns {number}
407 | */
408 | getPosition(x, curve = this.curve) {
409 | return ranger.getPosition(x, this.min, this.max, curve)
410 | }
411 |
412 | /**
413 | * @see ranger.getValue
414 | *
415 | * @param {number} x - The position to check. Should be between 0.0 and 1.0.
416 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
417 | * @returns {number}
418 | */
419 | getValue(x, curve = this.curve) {
420 | return ranger.getValue(x, this.min, this.max, curve);
421 | }
422 |
423 | /**
424 | * @see ranger.map
425 | *
426 | * @param {number} x - The value to map. Should be contained in sourceRange.
427 | * @param {Range} range - The range to map from.
428 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
429 | * @returns {Number}
430 | */
431 | map(x, range, curve = this.curve) {
432 | return ranger.map(x, range, this, curve);
433 | }
434 |
435 | /**
436 | * @see ranger.mapFloat
437 | *
438 | * @param {number} x - The value to map. Should be contained in the source range.
439 | * @param {number} min - Min value for the source range.
440 | * @param {number} max - Max value for the source range.
441 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
442 | * @returns {number}
443 | */
444 | mapFloat(x, min, max, curve = this.curve) {
445 | return ranger.mapFloat(x, min, max, this.min, this.max, curve);
446 | }
447 |
448 | /**
449 | * @see ranger.random
450 | *
451 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
452 | * @returns {number}
453 | */
454 | random(curve = this.curve) {
455 | return ranger.random(this.min, this.max, curve);
456 | }
457 |
458 | /**
459 | * @see ranger.randomInt
460 | *
461 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
462 | * @returns {number}
463 | */
464 | randomInt(curve = this.curve) {
465 | return ranger.randomInt(this.min, this.max, curve);
466 | }
467 |
468 | /**
469 | * Creates an array of values spread inside this range.
470 | * Values are inclusive, ie values[0] === this.min, and values[values.length - 1] === this.max.
471 | *
472 | * @param {number} count - Number of values (slices) to create. Should be >= 2.
473 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
474 | * @returns {number[]}
475 | */
476 | slice(count, curve = this.curve) {
477 | if (count < 2) return [this.min, this.max];
478 |
479 | const values = [];
480 |
481 | for (let i = 0; i < count; i++) {
482 | values[i] = this.getValue(i / (count - 1), curve);
483 | }
484 |
485 | return values;
486 | }
487 |
488 | /**
489 | * Divides this range into a number of smaller ranges.
490 | * Each range will copy this range's curve.
491 | *
492 | * todo: add support for margin and padding.
493 | *
494 | * @param {number} count - The number of sub-ranges to create.
495 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
496 | * @returns {Range[]}
497 | */
498 | divide(count, curve = this.curve) {
499 | if (count <= 1) return [this.clone()];
500 |
501 | const ranges = [];
502 |
503 | for (let i = 0; i < count; i++) {
504 | const min = this.getValue(i / count);
505 | const max = this.getValue((i + 1) / count);
506 |
507 | ranges[i] = new Range(min, max, this.curve);
508 | }
509 |
510 | return ranges;
511 | }
512 |
513 | /**
514 | * @see ranger.clamp
515 | *
516 | * @param {number} x - The value to check.
517 | * @returns {number}
518 | */
519 | clamp(x) {
520 | return ranger.clamp(x, this.min, this.max);
521 | }
522 |
523 | /**
524 | * @see ranger.wrap
525 | *
526 | * @param {number} x - The value to wrap.
527 | * @returns {number}
528 | */
529 | wrap(x) {
530 | return ranger.wrap(x, this.min, this.max);
531 | }
532 |
533 | /**
534 | * @see ranger.contains
535 | *
536 | * @param {number} x - The value to check.
537 | * @returns {boolean}
538 | */
539 | contains(x) {
540 | return ranger.contains(x, this.min, this.max);
541 | }
542 |
543 | /**
544 | * @see ranger.containsRange
545 | *
546 | * @param {Range} range - The range to check.
547 | * @returns {boolean}
548 | */
549 | containsRange(range) {
550 | return ranger.containsRange(range, this);
551 | }
552 | }
553 |
554 | ranger.Range = Range;
555 |
556 | module.exports = ranger;
557 |
--------------------------------------------------------------------------------
/dist/ranger.esm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @namespace
3 | */
4 | const ranger = {
5 |
6 | /**
7 | * Default curve, which is just a pass-through function.
8 | *
9 | * @param {number} x
10 | * @returns {number}
11 | */
12 | LINEAR: x => x,
13 |
14 | // measurements
15 |
16 | /**
17 | * Calculates the length of a range, or just (max - min). Used internally.
18 | * No validation is performed to check if the range is valid (max >= min).
19 | *
20 | * @param {number} min - Min value of the range.
21 | * @param {number} max - Max value of the range.
22 | * @returns {number} Length of the range.
23 | */
24 | length(min, max) {
25 | return max - min;
26 | },
27 |
28 | /**
29 | * A range is valid if max >= min.
30 | *
31 | * @param {number} min - Min value of the range.
32 | * @param {number} max - Max value of the range.
33 | * @returns {boolean}
34 | */
35 | isValid(min, max) {
36 | return max >= min;
37 | },
38 |
39 | /**
40 | * Returns the position of a value in the range, as a float 0.0 and 1.0.
41 | * The supplied value is not clamped. If it's out of bounds, the returned position will be proportionally out of bounds.
42 | *
43 | * @param {number} x - The value to check.
44 | * @param {number} min - Min value of the range.
45 | * @param {number} max - Max value of the range.
46 | * @param {function} [curve] - The curve function to apply.
47 | * @returns {number} - Position of the supplied value.
48 | */
49 | getPosition(x, min, max, curve = ranger.LINEAR) {
50 | return curve((x - min) / ranger.length(min, max));
51 | },
52 |
53 | /**
54 | * Returns the value at a given position in the rage.
55 | * The returned value is not clamped.
56 | *
57 | * @param {number} x - The position to check. Should be between 0.0 and 1.0.
58 | * @param {number} min - Min value of the range.
59 | * @param {number} max - Max value of the range.
60 | * @param {function} [curve] - The curve function to apply.
61 | * @returns {*} - Value at the supplied position.
62 | */
63 | getValue(x, min, max, curve = ranger.LINEAR) {
64 | return min + curve(x) * ranger.length(min, max);
65 | },
66 |
67 | // mapping
68 |
69 | /**
70 | * Maps a value from one range to a value from another range at the same position.
71 | * The source range is sampled linearly.
72 | * None of the values are clamped.
73 | *
74 | * @param {number} x - The value to map. Should be contained in sourceRange.
75 | * @param {Range} sourceRange - The range to map from.
76 | * @param {Range} targetRange - The range to map to.
77 | * @param {function} [curve] - The curve function to apply to the targetRange.
78 | * @returns {Number} - The mapped value, between targetRange.min and targetRange.max.
79 | */
80 | map(x, sourceRange, targetRange, curve = ranger.LINEAR) {
81 | return ranger.getValue(sourceRange.getPosition(x, ranger.LINEAR), targetRange.min, targetRange.max, curve);
82 | },
83 |
84 | /**
85 | * Same as map, but the source and target ranges should be provided as numbers.
86 | *
87 | * @see map
88 | *
89 | * @param {number} x - The value to map. Should be contained in the source range.
90 | * @param {number} sourceMin - Min value for the source range.
91 | * @param {number} sourceMax - Max value for the source range.
92 | * @param {number} targetMin - Min value for the target range.
93 | * @param {number} targetMax - Max value for the target range.
94 | * @param {function} [curve] - The curve function to apply to the target range.
95 | * @returns {number} - The mapped value, between targetMin and targetMax.
96 | */
97 | mapFloat(x, sourceMin, sourceMax, targetMin, targetMax, curve = ranger.LINEAR) {
98 | return ranger.getValue(ranger.getPosition(x, sourceMin, sourceMax, ranger.LINEAR), targetMin, targetMax, curve);
99 | },
100 |
101 | // random
102 |
103 | /**
104 | * Returns a random float between min and max.
105 | *
106 | * @param {number} min - Min value of the range.
107 | * @param {number} max - Max value of the range.
108 | * @param {function} [curve] - The curve function to apply.
109 | * @returns {number}
110 | */
111 | random(min, max, curve = ranger.LINEAR) {
112 | return min + curve(Math.random()) * ranger.length(min, max);
113 | },
114 |
115 | /**
116 | * Returns a random int between min and max.
117 | * The returned value is floored, so it will never equal max.
118 | *
119 | * @param {number} min - Min value of the range.
120 | * @param {number} max - Max value of the range.
121 | * @param {function} [curve] - The curve function to apply.
122 | * @returns {number}
123 | */
124 | randomInt(min, max, curve = ranger.LINEAR) {
125 | return ranger.random(min, max, curve) | 0;
126 | },
127 |
128 | // common operations
129 |
130 | /**
131 | * Returns min if x < min.
132 | * Returns max if x > max.
133 | * Returns x otherwise.
134 | *
135 | * @param {number} x - The value to check.
136 | * @param {number} min - Min value of the range.
137 | * @param {number} max - Max value of the range.
138 | * @returns {number} - The clamped value.
139 | */
140 | clamp(x, min, max) {
141 | return x < min ? min : x > max ? max : x;
142 | },
143 |
144 | /**
145 | * Wraps a value around the range.
146 | * This is similar to the modulo operator, but for arbitrary ranges.
147 | *
148 | * @param {number} x - The value to wrap.
149 | * @param {number} min - Min value of the range.
150 | * @param {number} max - Max value of the range.
151 | * @returns {number} - The wrapped value.
152 | */
153 | wrap(x, min, max) {
154 | const l = ranger.length(min, max);
155 |
156 | return (((x - min) % l) + l) % l + min;
157 | },
158 |
159 | /**
160 | * Checks if a value is inside the range.
161 | *
162 | * @param {number} x - The value to check.
163 | * @param {number} min - Min value of the range.
164 | * @param {number} max - Max value of the range.
165 | * @returns {boolean}
166 | */
167 | contains(x, min, max) {
168 | return x >= min && x <= max;
169 | },
170 |
171 | /**
172 | * Checks if the source range is contained in the target range.
173 | *
174 | * @param {Range} sourceRange - The range to check.
175 | * @param {Range} targetRange - The range the sourceRange will be compared to.
176 | * @returns {boolean}
177 | */
178 | containsRange(sourceRange, targetRange) {
179 | return ranger.contains(sourceRange.min, targetRange.min, targetRange.max) && ranger.contains(sourceRange.max, targetRange.min, targetRange.max);
180 | },
181 | };
182 |
183 | /**
184 | * Creates a new Range instance with a min, max, and curve for repeated use.
185 | * No validation is performed to check if min is less or equal to max.
186 | *
187 | * @class
188 | * @constructor
189 | */
190 | class Range {
191 | /**
192 | * Creates a new Range instance with a min, max, and curve for repeated use.
193 | * No validation is performed to check if min is less or equal to max.
194 | *
195 | * @param {number} min - Min value for this range.
196 | * @param {number} max - Max value for this range.
197 | * @param {function} [curve] - The curve function to apply by default.
198 | */
199 | constructor(min = 0, max = 0, curve = ranger.LINEAR) {
200 | /**
201 | * Min value for this range
202 | * @type {number}
203 | */
204 | this.min = min;
205 | /**
206 | * Max value for this range
207 | * @type {number}
208 | */
209 | this.max = max;
210 | /**
211 | * The curve used by this range.
212 | * This should be a function that takes a number (0.0 to 1.0), and returns a transformed number.
213 | * @type {Function}
214 | */
215 | this.curve = curve;
216 | }
217 |
218 | /**
219 | * Sets this range min and max based on a size and a center.
220 | * Min will be set to size * -0.5 + center.
221 | * Max will be set to size * 0.5 + center.
222 | *
223 | * @param {Number} size - The total size of the range.
224 | * @param {Number} [center=0] - The center of the range. Defaults to 0.
225 | * @param {function} [curve] - The curve function to apply by default.
226 | * @returns {Range}
227 | */
228 | fromSizeAndCenter(size, center = 0, curve = this.curve) {
229 | this.min = size * -0.5 + center;
230 | this.max = size * 0.5 + center;
231 | this.curve = curve;
232 |
233 | return this;
234 | }
235 |
236 | /**
237 | * Sets the min, max, and curve for this range.
238 | *
239 | * @param {number} min - Min value for this range.
240 | * @param {number} max - Max value for this range.
241 | * @param {function} [curve] - The curve function to apply by default.
242 | * @returns {Range}
243 | */
244 | set(min = this.min, max = this.max, curve = this.curve) {
245 | this.min = min;
246 | this.max = max;
247 | this.curve = curve;
248 |
249 | return this;
250 | }
251 |
252 | /**
253 | * Sets the min value for this range. This method mostly exists for chaining.
254 | *
255 | * @param {number} min - Min value for this range.
256 | * @returns {Range}
257 | */
258 | setMin(min) {
259 | this.min = min;
260 |
261 | return this;
262 | }
263 |
264 | /**
265 | * Sets the max value for this range. This method mostly exists for chaining.
266 | *
267 | * @param {number} max - Max value for this range.
268 | * @returns {Range}
269 | */
270 | setMax(max) {
271 | this.max = max;
272 |
273 | return this;
274 | }
275 |
276 | /**
277 | * Sets the default curve for this range. This method mostly exists for chaining.
278 | *
279 | * @param {function} curve - The curve function to apply by default.
280 | * @returns {Range}
281 | */
282 | setCurve(curve) {
283 | this.curve = curve;
284 |
285 | return this;
286 | }
287 |
288 | /**
289 | * Multiplies this range's min and max with the given scalar.
290 | * Values below 1.0 will make the range smaller.
291 | * Values over 1.0 will make it bigger.
292 | *
293 | * @param {number} s - The scalar to use.
294 | * @returns {Range}
295 | */
296 | scale(s) {
297 | this.min *= s;
298 | this.max *= s;
299 |
300 | return this;
301 | }
302 |
303 | /**
304 | * Expands this range by a given delta.
305 | * The delta is subtracted from this.min, and added to this.max.
306 | *
307 | * @param {Number} d - The delta to expand this range by.
308 | * @returns {Range}
309 | */
310 | expand(d) {
311 | this.min -= d;
312 | this.max += d;
313 |
314 | return this;
315 | }
316 |
317 | /**
318 | * Contracts this range by a given delta.
319 | * The delta is added to this.min, and subtracted from this.max.
320 | *
321 | * @param {number} d - The delta to contract this range by.
322 | * @returns {Range}
323 | */
324 | contract(d) {
325 | this.min += d;
326 | this.max -= d;
327 |
328 | return this;
329 | }
330 |
331 | /**
332 | * Shifts this range by a given delta.
333 | * The delta is added to this.min and this.max.
334 | *
335 | * @param {number} d - The delta to shift this range by.
336 | * @returns {Range}
337 | */
338 | shift(d) {
339 | this.min += d;
340 | this.max += d;
341 |
342 | return this;
343 | }
344 |
345 | /**
346 | * Copies another range's min, max, and curve into this one.
347 | * The curve is passed by reference.
348 | *
349 | * @param {Range} range - The range to copy from.
350 | * @returns {Range}
351 | */
352 | copy(range) {
353 | this.min = range.min;
354 | this.max = range.max;
355 | this.curve = range.curve;
356 |
357 | return this;
358 | }
359 |
360 | /**
361 | * Creates a shallow copy of this range.
362 | *
363 | * @returns {Range}
364 | */
365 | clone() {
366 | return new Range(this.min, this.max, this.curve);
367 | }
368 |
369 | /**
370 | * Checks if this range is empty.
371 | * A range is empty if its min === max.
372 | *
373 | * @returns {boolean}
374 | */
375 | isEmpty() {
376 | return this.min === this.max;
377 | }
378 |
379 | /**
380 | * Sets this range's min and max to 0.
381 | *
382 | * @returns {Range}
383 | */
384 | makeEmpty() {
385 | this.min = 0;
386 | this.max = 0;
387 |
388 | return this;
389 | }
390 |
391 | /**
392 | * @see ranger.length
393 | * @returns {number}
394 | */
395 | length() {
396 | return ranger.length(this.min, this.max);
397 | }
398 |
399 | /**
400 | * @see ranger.getPosition
401 | *
402 | * @param {number} x - The value to check.
403 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
404 | * @returns {number}
405 | */
406 | getPosition(x, curve = this.curve) {
407 | return ranger.getPosition(x, this.min, this.max, curve)
408 | }
409 |
410 | /**
411 | * @see ranger.getValue
412 | *
413 | * @param {number} x - The position to check. Should be between 0.0 and 1.0.
414 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
415 | * @returns {number}
416 | */
417 | getValue(x, curve = this.curve) {
418 | return ranger.getValue(x, this.min, this.max, curve);
419 | }
420 |
421 | /**
422 | * @see ranger.map
423 | *
424 | * @param {number} x - The value to map. Should be contained in sourceRange.
425 | * @param {Range} range - The range to map from.
426 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
427 | * @returns {Number}
428 | */
429 | map(x, range, curve = this.curve) {
430 | return ranger.map(x, range, this, curve);
431 | }
432 |
433 | /**
434 | * @see ranger.mapFloat
435 | *
436 | * @param {number} x - The value to map. Should be contained in the source range.
437 | * @param {number} min - Min value for the source range.
438 | * @param {number} max - Max value for the source range.
439 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
440 | * @returns {number}
441 | */
442 | mapFloat(x, min, max, curve = this.curve) {
443 | return ranger.mapFloat(x, min, max, this.min, this.max, curve);
444 | }
445 |
446 | /**
447 | * @see ranger.random
448 | *
449 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
450 | * @returns {number}
451 | */
452 | random(curve = this.curve) {
453 | return ranger.random(this.min, this.max, curve);
454 | }
455 |
456 | /**
457 | * @see ranger.randomInt
458 | *
459 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
460 | * @returns {number}
461 | */
462 | randomInt(curve = this.curve) {
463 | return ranger.randomInt(this.min, this.max, curve);
464 | }
465 |
466 | /**
467 | * Creates an array of values spread inside this range.
468 | * Values are inclusive, ie values[0] === this.min, and values[values.length - 1] === this.max.
469 | *
470 | * @param {number} count - Number of values (slices) to create. Should be >= 2.
471 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
472 | * @returns {number[]}
473 | */
474 | slice(count, curve = this.curve) {
475 | if (count < 2) return [this.min, this.max];
476 |
477 | const values = [];
478 |
479 | for (let i = 0; i < count; i++) {
480 | values[i] = this.getValue(i / (count - 1), curve);
481 | }
482 |
483 | return values;
484 | }
485 |
486 | /**
487 | * Divides this range into a number of smaller ranges.
488 | * Each range will copy this range's curve.
489 | *
490 | * todo: add support for margin and padding.
491 | *
492 | * @param {number} count - The number of sub-ranges to create.
493 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
494 | * @returns {Range[]}
495 | */
496 | divide(count, curve = this.curve) {
497 | if (count <= 1) return [this.clone()];
498 |
499 | const ranges = [];
500 |
501 | for (let i = 0; i < count; i++) {
502 | const min = this.getValue(i / count);
503 | const max = this.getValue((i + 1) / count);
504 |
505 | ranges[i] = new Range(min, max, this.curve);
506 | }
507 |
508 | return ranges;
509 | }
510 |
511 | /**
512 | * @see ranger.clamp
513 | *
514 | * @param {number} x - The value to check.
515 | * @returns {number}
516 | */
517 | clamp(x) {
518 | return ranger.clamp(x, this.min, this.max);
519 | }
520 |
521 | /**
522 | * @see ranger.wrap
523 | *
524 | * @param {number} x - The value to wrap.
525 | * @returns {number}
526 | */
527 | wrap(x) {
528 | return ranger.wrap(x, this.min, this.max);
529 | }
530 |
531 | /**
532 | * @see ranger.contains
533 | *
534 | * @param {number} x - The value to check.
535 | * @returns {boolean}
536 | */
537 | contains(x) {
538 | return ranger.contains(x, this.min, this.max);
539 | }
540 |
541 | /**
542 | * @see ranger.containsRange
543 | *
544 | * @param {Range} range - The range to check.
545 | * @returns {boolean}
546 | */
547 | containsRange(range) {
548 | return ranger.containsRange(range, this);
549 | }
550 | }
551 |
552 | export default ranger;
553 | export { Range };
554 |
--------------------------------------------------------------------------------
/dist/ranger.umd.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3 | typeof define === 'function' && define.amd ? define(factory) :
4 | (global.ranger = factory());
5 | }(this, (function () { 'use strict';
6 |
7 | /**
8 | * @namespace
9 | */
10 | var ranger = {
11 |
12 | /**
13 | * Default curve, which is just a pass-through function.
14 | *
15 | * @param {number} x
16 | * @returns {number}
17 | */
18 | LINEAR: function LINEAR(x) {
19 | return x;
20 | },
21 |
22 | // measurements
23 |
24 | /**
25 | * Calculates the length of a range, or just (max - min). Used internally.
26 | * No validation is performed to check if the range is valid (max >= min).
27 | *
28 | * @param {number} min - Min value of the range.
29 | * @param {number} max - Max value of the range.
30 | * @returns {number} Length of the range.
31 | */
32 | length: function length(min, max) {
33 | return max - min;
34 | },
35 |
36 |
37 | /**
38 | * A range is valid if max >= min.
39 | *
40 | * @param {number} min - Min value of the range.
41 | * @param {number} max - Max value of the range.
42 | * @returns {boolean}
43 | */
44 | isValid: function isValid(min, max) {
45 | return max >= min;
46 | },
47 |
48 |
49 | /**
50 | * Returns the position of a value in the range, as a float 0.0 and 1.0.
51 | * The supplied value is not clamped. If it's out of bounds, the returned position will be proportionally out of bounds.
52 | *
53 | * @param {number} x - The value to check.
54 | * @param {number} min - Min value of the range.
55 | * @param {number} max - Max value of the range.
56 | * @param {function} [curve] - The curve function to apply.
57 | * @returns {number} - Position of the supplied value.
58 | */
59 | getPosition: function getPosition(x, min, max) {
60 | var curve = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ranger.LINEAR;
61 |
62 | return curve((x - min) / ranger.length(min, max));
63 | },
64 |
65 |
66 | /**
67 | * Returns the value at a given position in the rage.
68 | * The returned value is not clamped.
69 | *
70 | * @param {number} x - The position to check. Should be between 0.0 and 1.0.
71 | * @param {number} min - Min value of the range.
72 | * @param {number} max - Max value of the range.
73 | * @param {function} [curve] - The curve function to apply.
74 | * @returns {*} - Value at the supplied position.
75 | */
76 | getValue: function getValue(x, min, max) {
77 | var curve = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ranger.LINEAR;
78 |
79 | return min + curve(x) * ranger.length(min, max);
80 | },
81 |
82 |
83 | // mapping
84 |
85 | /**
86 | * Maps a value from one range to a value from another range at the same position.
87 | * The source range is sampled linearly.
88 | * None of the values are clamped.
89 | *
90 | * @param {number} x - The value to map. Should be contained in sourceRange.
91 | * @param {Range} sourceRange - The range to map from.
92 | * @param {Range} targetRange - The range to map to.
93 | * @param {function} [curve] - The curve function to apply to the targetRange.
94 | * @returns {Number} - The mapped value, between targetRange.min and targetRange.max.
95 | */
96 | map: function map(x, sourceRange, targetRange) {
97 | var curve = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ranger.LINEAR;
98 |
99 | return ranger.getValue(sourceRange.getPosition(x, ranger.LINEAR), targetRange.min, targetRange.max, curve);
100 | },
101 |
102 |
103 | /**
104 | * Same as map, but the source and target ranges should be provided as numbers.
105 | *
106 | * @see map
107 | *
108 | * @param {number} x - The value to map. Should be contained in the source range.
109 | * @param {number} sourceMin - Min value for the source range.
110 | * @param {number} sourceMax - Max value for the source range.
111 | * @param {number} targetMin - Min value for the target range.
112 | * @param {number} targetMax - Max value for the target range.
113 | * @param {function} [curve] - The curve function to apply to the target range.
114 | * @returns {number} - The mapped value, between targetMin and targetMax.
115 | */
116 | mapFloat: function mapFloat(x, sourceMin, sourceMax, targetMin, targetMax) {
117 | var curve = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : ranger.LINEAR;
118 |
119 | return ranger.getValue(ranger.getPosition(x, sourceMin, sourceMax, ranger.LINEAR), targetMin, targetMax, curve);
120 | },
121 |
122 |
123 | // random
124 |
125 | /**
126 | * Returns a random float between min and max.
127 | *
128 | * @param {number} min - Min value of the range.
129 | * @param {number} max - Max value of the range.
130 | * @param {function} [curve] - The curve function to apply.
131 | * @returns {number}
132 | */
133 | random: function random(min, max) {
134 | var curve = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ranger.LINEAR;
135 |
136 | return min + curve(Math.random()) * ranger.length(min, max);
137 | },
138 |
139 |
140 | /**
141 | * Returns a random int between min and max.
142 | * The returned value is floored, so it will never equal max.
143 | *
144 | * @param {number} min - Min value of the range.
145 | * @param {number} max - Max value of the range.
146 | * @param {function} [curve] - The curve function to apply.
147 | * @returns {number}
148 | */
149 | randomInt: function randomInt(min, max) {
150 | var curve = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ranger.LINEAR;
151 |
152 | return ranger.random(min, max, curve) | 0;
153 | },
154 |
155 |
156 | // common operations
157 |
158 | /**
159 | * Returns min if x < min.
160 | * Returns max if x > max.
161 | * Returns x otherwise.
162 | *
163 | * @param {number} x - The value to check.
164 | * @param {number} min - Min value of the range.
165 | * @param {number} max - Max value of the range.
166 | * @returns {number} - The clamped value.
167 | */
168 | clamp: function clamp(x, min, max) {
169 | return x < min ? min : x > max ? max : x;
170 | },
171 |
172 |
173 | /**
174 | * Wraps a value around the range.
175 | * This is similar to the modulo operator, but for arbitrary ranges.
176 | *
177 | * @param {number} x - The value to wrap.
178 | * @param {number} min - Min value of the range.
179 | * @param {number} max - Max value of the range.
180 | * @returns {number} - The wrapped value.
181 | */
182 | wrap: function wrap(x, min, max) {
183 | var l = ranger.length(min, max);
184 |
185 | return ((x - min) % l + l) % l + min;
186 | },
187 |
188 |
189 | /**
190 | * Checks if a value is inside the range.
191 | *
192 | * @param {number} x - The value to check.
193 | * @param {number} min - Min value of the range.
194 | * @param {number} max - Max value of the range.
195 | * @returns {boolean}
196 | */
197 | contains: function contains(x, min, max) {
198 | return x >= min && x <= max;
199 | },
200 |
201 |
202 | /**
203 | * Checks if the source range is contained in the target range.
204 | *
205 | * @param {Range} sourceRange - The range to check.
206 | * @param {Range} targetRange - The range the sourceRange will be compared to.
207 | * @returns {boolean}
208 | */
209 | containsRange: function containsRange(sourceRange, targetRange) {
210 | return ranger.contains(sourceRange.min, targetRange.min, targetRange.max) && ranger.contains(sourceRange.max, targetRange.min, targetRange.max);
211 | }
212 | };
213 |
214 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
215 |
216 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
217 |
218 | /**
219 | * Creates a new Range instance with a min, max, and curve for repeated use.
220 | * No validation is performed to check if min is less or equal to max.
221 | *
222 | * @class
223 | * @constructor
224 | */
225 |
226 | var Range = function () {
227 | /**
228 | * Creates a new Range instance with a min, max, and curve for repeated use.
229 | * No validation is performed to check if min is less or equal to max.
230 | *
231 | * @param {number} min - Min value for this range.
232 | * @param {number} max - Max value for this range.
233 | * @param {function} [curve] - The curve function to apply by default.
234 | */
235 | function Range() {
236 | var min = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
237 | var max = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
238 | var curve = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ranger.LINEAR;
239 |
240 | _classCallCheck(this, Range);
241 |
242 | /**
243 | * Min value for this range
244 | * @type {number}
245 | */
246 | this.min = min;
247 | /**
248 | * Max value for this range
249 | * @type {number}
250 | */
251 | this.max = max;
252 | /**
253 | * The curve used by this range.
254 | * This should be a function that takes a number (0.0 to 1.0), and returns a transformed number.
255 | * @type {Function}
256 | */
257 | this.curve = curve;
258 | }
259 |
260 | /**
261 | * Sets this range min and max based on a size and a center.
262 | * Min will be set to size * -0.5 + center.
263 | * Max will be set to size * 0.5 + center.
264 | *
265 | * @param {Number} size - The total size of the range.
266 | * @param {Number} [center=0] - The center of the range. Defaults to 0.
267 | * @param {function} [curve] - The curve function to apply by default.
268 | * @returns {Range}
269 | */
270 |
271 |
272 | _createClass(Range, [{
273 | key: 'fromSizeAndCenter',
274 | value: function fromSizeAndCenter(size) {
275 | var center = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
276 | var curve = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.curve;
277 |
278 | this.min = size * -0.5 + center;
279 | this.max = size * 0.5 + center;
280 | this.curve = curve;
281 |
282 | return this;
283 | }
284 |
285 | /**
286 | * Sets the min, max, and curve for this range.
287 | *
288 | * @param {number} min - Min value for this range.
289 | * @param {number} max - Max value for this range.
290 | * @param {function} [curve] - The curve function to apply by default.
291 | * @returns {Range}
292 | */
293 |
294 | }, {
295 | key: 'set',
296 | value: function set() {
297 | var min = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.min;
298 | var max = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.max;
299 | var curve = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.curve;
300 |
301 | this.min = min;
302 | this.max = max;
303 | this.curve = curve;
304 |
305 | return this;
306 | }
307 |
308 | /**
309 | * Sets the min value for this range. This method mostly exists for chaining.
310 | *
311 | * @param {number} min - Min value for this range.
312 | * @returns {Range}
313 | */
314 |
315 | }, {
316 | key: 'setMin',
317 | value: function setMin(min) {
318 | this.min = min;
319 |
320 | return this;
321 | }
322 |
323 | /**
324 | * Sets the max value for this range. This method mostly exists for chaining.
325 | *
326 | * @param {number} max - Max value for this range.
327 | * @returns {Range}
328 | */
329 |
330 | }, {
331 | key: 'setMax',
332 | value: function setMax(max) {
333 | this.max = max;
334 |
335 | return this;
336 | }
337 |
338 | /**
339 | * Sets the default curve for this range. This method mostly exists for chaining.
340 | *
341 | * @param {function} curve - The curve function to apply by default.
342 | * @returns {Range}
343 | */
344 |
345 | }, {
346 | key: 'setCurve',
347 | value: function setCurve(curve) {
348 | this.curve = curve;
349 |
350 | return this;
351 | }
352 |
353 | /**
354 | * Multiplies this range's min and max with the given scalar.
355 | * Values below 1.0 will make the range smaller.
356 | * Values over 1.0 will make it bigger.
357 | *
358 | * @param {number} s - The scalar to use.
359 | * @returns {Range}
360 | */
361 |
362 | }, {
363 | key: 'scale',
364 | value: function scale(s) {
365 | this.min *= s;
366 | this.max *= s;
367 |
368 | return this;
369 | }
370 |
371 | /**
372 | * Expands this range by a given delta.
373 | * The delta is subtracted from this.min, and added to this.max.
374 | *
375 | * @param {Number} d - The delta to expand this range by.
376 | * @returns {Range}
377 | */
378 |
379 | }, {
380 | key: 'expand',
381 | value: function expand(d) {
382 | this.min -= d;
383 | this.max += d;
384 |
385 | return this;
386 | }
387 |
388 | /**
389 | * Contracts this range by a given delta.
390 | * The delta is added to this.min, and subtracted from this.max.
391 | *
392 | * @param {number} d - The delta to contract this range by.
393 | * @returns {Range}
394 | */
395 |
396 | }, {
397 | key: 'contract',
398 | value: function contract(d) {
399 | this.min += d;
400 | this.max -= d;
401 |
402 | return this;
403 | }
404 |
405 | /**
406 | * Shifts this range by a given delta.
407 | * The delta is added to this.min and this.max.
408 | *
409 | * @param {number} d - The delta to shift this range by.
410 | * @returns {Range}
411 | */
412 |
413 | }, {
414 | key: 'shift',
415 | value: function shift(d) {
416 | this.min += d;
417 | this.max += d;
418 |
419 | return this;
420 | }
421 |
422 | /**
423 | * Copies another range's min, max, and curve into this one.
424 | * The curve is passed by reference.
425 | *
426 | * @param {Range} range - The range to copy from.
427 | * @returns {Range}
428 | */
429 |
430 | }, {
431 | key: 'copy',
432 | value: function copy(range) {
433 | this.min = range.min;
434 | this.max = range.max;
435 | this.curve = range.curve;
436 |
437 | return this;
438 | }
439 |
440 | /**
441 | * Creates a shallow copy of this range.
442 | *
443 | * @returns {Range}
444 | */
445 |
446 | }, {
447 | key: 'clone',
448 | value: function clone() {
449 | return new Range(this.min, this.max, this.curve);
450 | }
451 |
452 | /**
453 | * Checks if this range is empty.
454 | * A range is empty if its min === max.
455 | *
456 | * @returns {boolean}
457 | */
458 |
459 | }, {
460 | key: 'isEmpty',
461 | value: function isEmpty() {
462 | return this.min === this.max;
463 | }
464 |
465 | /**
466 | * Sets this range's min and max to 0.
467 | *
468 | * @returns {Range}
469 | */
470 |
471 | }, {
472 | key: 'makeEmpty',
473 | value: function makeEmpty() {
474 | this.min = 0;
475 | this.max = 0;
476 |
477 | return this;
478 | }
479 |
480 | /**
481 | * @see ranger.length
482 | * @returns {number}
483 | */
484 |
485 | }, {
486 | key: 'length',
487 | value: function length() {
488 | return ranger.length(this.min, this.max);
489 | }
490 |
491 | /**
492 | * @see ranger.getPosition
493 | *
494 | * @param {number} x - The value to check.
495 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
496 | * @returns {number}
497 | */
498 |
499 | }, {
500 | key: 'getPosition',
501 | value: function getPosition(x) {
502 | var curve = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.curve;
503 |
504 | return ranger.getPosition(x, this.min, this.max, curve);
505 | }
506 |
507 | /**
508 | * @see ranger.getValue
509 | *
510 | * @param {number} x - The position to check. Should be between 0.0 and 1.0.
511 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
512 | * @returns {number}
513 | */
514 |
515 | }, {
516 | key: 'getValue',
517 | value: function getValue(x) {
518 | var curve = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.curve;
519 |
520 | return ranger.getValue(x, this.min, this.max, curve);
521 | }
522 |
523 | /**
524 | * @see ranger.map
525 | *
526 | * @param {number} x - The value to map. Should be contained in sourceRange.
527 | * @param {Range} range - The range to map from.
528 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
529 | * @returns {Number}
530 | */
531 |
532 | }, {
533 | key: 'map',
534 | value: function map(x, range) {
535 | var curve = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.curve;
536 |
537 | return ranger.map(x, range, this, curve);
538 | }
539 |
540 | /**
541 | * @see ranger.mapFloat
542 | *
543 | * @param {number} x - The value to map. Should be contained in the source range.
544 | * @param {number} min - Min value for the source range.
545 | * @param {number} max - Max value for the source range.
546 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
547 | * @returns {number}
548 | */
549 |
550 | }, {
551 | key: 'mapFloat',
552 | value: function mapFloat(x, min, max) {
553 | var curve = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : this.curve;
554 |
555 | return ranger.mapFloat(x, min, max, this.min, this.max, curve);
556 | }
557 |
558 | /**
559 | * @see ranger.random
560 | *
561 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
562 | * @returns {number}
563 | */
564 |
565 | }, {
566 | key: 'random',
567 | value: function random() {
568 | var curve = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.curve;
569 |
570 | return ranger.random(this.min, this.max, curve);
571 | }
572 |
573 | /**
574 | * @see ranger.randomInt
575 | *
576 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
577 | * @returns {number}
578 | */
579 |
580 | }, {
581 | key: 'randomInt',
582 | value: function randomInt() {
583 | var curve = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.curve;
584 |
585 | return ranger.randomInt(this.min, this.max, curve);
586 | }
587 |
588 | /**
589 | * Creates an array of values spread inside this range.
590 | * Values are inclusive, ie values[0] === this.min, and values[values.length - 1] === this.max.
591 | *
592 | * @param {number} count - Number of values (slices) to create. Should be >= 2.
593 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
594 | * @returns {number[]}
595 | */
596 |
597 | }, {
598 | key: 'slice',
599 | value: function slice(count) {
600 | var curve = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.curve;
601 |
602 | if (count < 2) return [this.min, this.max];
603 |
604 | var values = [];
605 |
606 | for (var i = 0; i < count; i++) {
607 | values[i] = this.getValue(i / (count - 1), curve);
608 | }
609 |
610 | return values;
611 | }
612 |
613 | /**
614 | * Divides this range into a number of smaller ranges.
615 | * Each range will copy this range's curve.
616 | *
617 | * todo: add support for margin and padding.
618 | *
619 | * @param {number} count - The number of sub-ranges to create.
620 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
621 | * @returns {Range[]}
622 | */
623 |
624 | }, {
625 | key: 'divide',
626 | value: function divide(count) {
627 | var curve = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.curve;
628 |
629 | if (count <= 1) return [this.clone()];
630 |
631 | var ranges = [];
632 |
633 | for (var i = 0; i < count; i++) {
634 | var min = this.getValue(i / count);
635 | var max = this.getValue((i + 1) / count);
636 |
637 | ranges[i] = new Range(min, max, this.curve);
638 | }
639 |
640 | return ranges;
641 | }
642 |
643 | /**
644 | * @see ranger.clamp
645 | *
646 | * @param {number} x - The value to check.
647 | * @returns {number}
648 | */
649 |
650 | }, {
651 | key: 'clamp',
652 | value: function clamp(x) {
653 | return ranger.clamp(x, this.min, this.max);
654 | }
655 |
656 | /**
657 | * @see ranger.wrap
658 | *
659 | * @param {number} x - The value to wrap.
660 | * @returns {number}
661 | */
662 |
663 | }, {
664 | key: 'wrap',
665 | value: function wrap(x) {
666 | return ranger.wrap(x, this.min, this.max);
667 | }
668 |
669 | /**
670 | * @see ranger.contains
671 | *
672 | * @param {number} x - The value to check.
673 | * @returns {boolean}
674 | */
675 |
676 | }, {
677 | key: 'contains',
678 | value: function contains(x) {
679 | return ranger.contains(x, this.min, this.max);
680 | }
681 |
682 | /**
683 | * @see ranger.containsRange
684 | *
685 | * @param {Range} range - The range to check.
686 | * @returns {boolean}
687 | */
688 |
689 | }, {
690 | key: 'containsRange',
691 | value: function containsRange(range) {
692 | return ranger.containsRange(range, this);
693 | }
694 | }]);
695 |
696 | return Range;
697 | }();
698 |
699 | ranger.Range = Range;
700 |
701 | return ranger;
702 |
703 | })));
704 |
--------------------------------------------------------------------------------
/examples/es6/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env"],
3 | "plugins": [
4 | "transform-es2015-destructuring",
5 | "transform-es2015-parameters",
6 | "transform-object-rest-spread",
7 | "transform-es2015-arrow-functions",
8 | "transform-class-properties"
9 | ]
10 | }
--------------------------------------------------------------------------------
/examples/es6/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ranger_particles_example",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --mode development --open",
8 | "build": "webpack --mode production"
9 | },
10 | "author": "Szenia Zadvornykh",
11 | "license": "MIT",
12 | "devDependencies": {
13 | "babel-core": "^6.26.0",
14 | "babel-loader": "^7.1.4",
15 | "babel-preset-env": "^1.6.1",
16 | "html-webpack-plugin": "^3.1.0",
17 | "webpack": "^4.2.0",
18 | "webpack-cli": "^2.0.13",
19 | "webpack-dev-server": "^3.1.1"
20 | },
21 | "dependencies": {
22 | "gsap": "^1.20.4",
23 | "guify": "^0.10.1"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/es6/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Ranger.js examples
7 |
40 |
41 |
42 |
43 | It's a thing!
44 |
45 |
--------------------------------------------------------------------------------
/examples/es6/src/index.js:
--------------------------------------------------------------------------------
1 | import App from './js/App';
2 |
3 | new App();
4 |
--------------------------------------------------------------------------------
/examples/es6/src/js/App.js:
--------------------------------------------------------------------------------
1 | import { TweenMax } from 'gsap';
2 | import guify from './lib/guify.min';
3 | import ranger, { Range } from '../../../../dist/ranger.esm';
4 | import BaseApp from './core/BaseApp';
5 | import RandomPosition from "./examples/RandomPosition";
6 | import MapPosition from "./examples/MapPosition";
7 | import Divide from "./examples/Divide";
8 | import Color from "./examples/Color";
9 | import ParticleTiming from "./examples/ParticleTiming";
10 | import Wrap from "./examples/Wrap";
11 |
12 | export default class App extends BaseApp {
13 |
14 | static exampleMap = {
15 | 'Random Position': RandomPosition,
16 | 'Map Position': MapPosition,
17 | 'Divide': Divide,
18 | 'Particle Timing': ParticleTiming,
19 | 'Color': Color,
20 | 'Wrap': Wrap
21 | };
22 |
23 | static exampleKeys = Object.keys(App.exampleMap);
24 |
25 | state = {
26 | exampleKey: App.exampleKeys[0]
27 | };
28 |
29 | constructor() {
30 | super({
31 | canvas: document.querySelector('#canvas')
32 | });
33 |
34 | this.elDiscription = document.querySelector('#description');
35 |
36 | this.initGUI();
37 | this.setExample();
38 | }
39 |
40 | initGUI() {
41 | this.gui = new guify({
42 | title: 'Ranger.js',
43 | barMode: 'none'
44 | });
45 |
46 | this.gui.Register({
47 | type: 'title',
48 | label: 'Examples'
49 | });
50 |
51 | App.exampleKeys.forEach(key => {
52 | this.gui.Register({
53 | type: 'button',
54 | label: key,
55 | action: () => {
56 | this.state.exampleKey = key;
57 | this.setExample();
58 | }
59 | })
60 | });
61 |
62 | this.gui.Register({
63 | type: 'title',
64 | label: 'Options'
65 | });
66 |
67 | // options inserted by the example itself
68 | }
69 |
70 | update() {
71 | if (this.example) {
72 | this.example.update();
73 | }
74 | }
75 |
76 | setExample() {
77 | if (this.example) {
78 | this.example.destroy();
79 | }
80 |
81 | this.example = new App.exampleMap[this.state.exampleKey]({
82 | gui: this.gui,
83 | size: this.renderer.size
84 | });
85 | this.example.create();
86 | this.setRootNode(this.example);
87 |
88 | this.elDiscription.innerHTML = this.example.description;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/examples/es6/src/js/config.js:
--------------------------------------------------------------------------------
1 | export const curves = [
2 | 'none',
3 | 'Quad.easeIn',
4 | 'Quad.easeOut',
5 | 'Quad.easeInOut',
6 | 'Cubic.easeIn',
7 | 'Cubic.easeOut',
8 | 'Cubic.easeInOut',
9 | 'Quart.easeIn',
10 | 'Quart.easeOut',
11 | 'Quart.easeInOut',
12 | 'Expo.easeIn',
13 | 'Expo.easeOut',
14 | 'Expo.easeInOut'
15 | ];
--------------------------------------------------------------------------------
/examples/es6/src/js/core/BaseApp.js:
--------------------------------------------------------------------------------
1 | import Renderer from "./sceneGraph/Renderer";
2 |
3 | export default class BaseApp {
4 |
5 | _rafId = null;
6 | rootNode = null;
7 |
8 | constructor({canvas, autoUpdate = true, autoResize = true}) {
9 | this.renderer = new Renderer({
10 | canvas,
11 | pixelRatio: window.devicePixelRatio
12 | });
13 |
14 | // update handling
15 | if (autoUpdate) {
16 | this._rafId = window.requestAnimationFrame(this.tick);
17 | }
18 |
19 | // resize handling
20 | if (autoResize) {
21 | window.addEventListener('resize', this.resize);
22 | }
23 | }
24 |
25 | destroy = () => {
26 | window.cancelAnimationFrame(this._rafId);
27 | window.removeEventListener('resize', this.resize);
28 | };
29 |
30 | setRootNode(node) {
31 | this.rootNode = node;
32 | }
33 |
34 | tick = () => {
35 | this.update();
36 | this.render();
37 |
38 | this._rafId = window.requestAnimationFrame(this.tick);
39 | };
40 |
41 | // abstract
42 | update() {};
43 |
44 | render() {
45 | if (this.rootNode) {
46 | this.renderer.render(this.rootNode);
47 | }
48 | };
49 |
50 | resize = () => {
51 | this.renderer.resize();
52 | };
53 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/core/graphics/Circle.js:
--------------------------------------------------------------------------------
1 | export default class Circle {
2 | constructor({cx = 0, cy = 0, radius = 0, fill = null, stroke = null}) {
3 | this.cx = cx;
4 | this.cy = cy;
5 | this.radius = radius;
6 | this.fill = fill;
7 | this.stroke = stroke;
8 |
9 | this.updatePath();
10 | }
11 |
12 | destroy() {
13 | this.path = null;
14 | }
15 |
16 | updatePath() {
17 | this.path = new Path2D();
18 | this.path.arc(this.cx, this.cy, this.radius, 0, Math.PI * 2);
19 | }
20 |
21 | render(ctx) {
22 | if (this.fill !== null) {
23 | ctx.fillStyle = this.fill;
24 | ctx.fill(this.path);
25 | }
26 |
27 | if (this.stroke !== null) {
28 | ctx.strokeStyle = this.stroke;
29 | ctx.stroke(this.path);
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/core/graphics/Rect.js:
--------------------------------------------------------------------------------
1 | export default class Rect {
2 | constructor({x = 0, y = 0, width = 0, height = 0, fill = null, stroke = null}) {
3 | this.x = x;
4 | this.y = y;
5 | this.width = width;
6 | this.height = height;
7 | this.fill = fill;
8 | this.stroke = stroke;
9 |
10 | this.updatePath();
11 | }
12 |
13 | destroy() {
14 | this.path = null;
15 | }
16 |
17 | updatePath() {
18 | this.path = new Path2D();
19 | this.path.rect(this.x, this.y, this.width, this.height);
20 | }
21 |
22 | render(ctx) {
23 | if (this.fill !== null) {
24 | ctx.fillStyle = this.fill;
25 | ctx.fill(this.path);
26 | }
27 |
28 | if (this.stroke !== null) {
29 | ctx.strokeStyle = this.stroke;
30 | ctx.stroke(this.path);
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/core/sceneGraph/Node.js:
--------------------------------------------------------------------------------
1 | export default class Node {
2 |
3 | x = 0;
4 | y = 0;
5 |
6 | constructor(graphics) {
7 | this.children = [];
8 | this.graphics = graphics;
9 | }
10 |
11 | destroy() {
12 | if (this.graphics) {
13 | this.graphics.destroy();
14 | }
15 |
16 | this.children.forEach(child => {
17 | child.destroy();
18 | });
19 |
20 | this.children.length = 0;
21 | }
22 |
23 | add(child) {
24 | this.children.push(child);
25 | }
26 |
27 | remove(child) {
28 | const i = this.children.indexOf(child);
29 |
30 | if (i !== -1) {
31 | this.children.splice(i, 1);
32 | }
33 | }
34 |
35 | removeAll() {
36 | this.children.length = 0;
37 | }
38 |
39 | render(ctx) {
40 | ctx.save();
41 |
42 | ctx.translate(this.x, this.y);
43 |
44 | if (this.graphics) {
45 | this.graphics.render(ctx);
46 | }
47 |
48 | for (let i = 0; i < this.children.length; i++) {
49 | this.children[i].render(ctx);
50 | }
51 |
52 | ctx.restore();
53 | }
54 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/core/sceneGraph/Renderer.js:
--------------------------------------------------------------------------------
1 | export default class Renderer {
2 |
3 | size = {width: 0, height: 0};
4 |
5 | constructor({canvas, pixelRatio = 1}) {
6 | this.canvas = canvas;
7 | this.ctx = canvas.getContext('2d');
8 | this.pixelRatio = pixelRatio;
9 |
10 | this.resize();
11 | }
12 |
13 | render(node) {
14 | this.ctx.save();
15 |
16 | this.ctx.scale(this.pixelRatio, this.pixelRatio);
17 | this.ctx.clearRect(0, 0, this.size.width, this.size.height);
18 |
19 | node.render(this.ctx);
20 |
21 | this.ctx.restore();
22 | }
23 |
24 | resize() {
25 | this.size.width = this.canvas.clientWidth;
26 | this.size.height = this.canvas.clientHeight;
27 |
28 | this.canvas.width = this.size.width * this.pixelRatio;
29 | this.canvas.height = this.size.height * this.pixelRatio;
30 | }
31 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/examples/BaseExample.js:
--------------------------------------------------------------------------------
1 | import Node from "../core/sceneGraph/Node";
2 | import { curves } from "../config";
3 | import ranger from "../../../../../dist/ranger.esm";
4 |
5 | export default class BaseExample extends Node {
6 | constructor({size, gui}) {
7 | super();
8 |
9 | this.size = size;
10 | this.gui = gui;
11 | this.options = [];
12 | }
13 |
14 | create() {
15 | this.createOptions();
16 | this.createGraphics();
17 | }
18 |
19 | createOptions() {}
20 |
21 | createCurveSelector(key, label) {
22 | const gui = this.gui.Register({
23 | type: 'select',
24 | label,
25 | options: curves,
26 | onChange: value => {
27 | if (value === 'none') {
28 | this.state[key] = ranger.LINEAR;
29 | } else {
30 | // GSAP easing functions are stored as 'Name.function'
31 | const parts = value.split('.');
32 | this.state[key] = x => window[parts[0]][parts[1]].getRatio(x);
33 | }
34 |
35 | this.updateGraphics();
36 | }
37 | });
38 |
39 | this.options.push(gui);
40 | }
41 |
42 | createRangeInput(key, label, min, max, step) {
43 | const gui = this.gui.Register({
44 | type: 'range',
45 | label,
46 | min,
47 | max,
48 | step,
49 | object: this.state,
50 | property: key,
51 | onChange: value => {
52 | this.state[key] = value;
53 | this.updateGraphics();
54 | }
55 | });
56 |
57 | this.options.push(gui);
58 | }
59 |
60 | updateGraphics() {
61 | this.removeAll();
62 | this.createGraphics();
63 | }
64 |
65 | createGraphics() {}
66 |
67 | update() {
68 |
69 | }
70 |
71 | destroy() {
72 | this.options.forEach(option => {
73 | this.gui.Remove(option);
74 | });
75 | }
76 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/examples/Color.js:
--------------------------------------------------------------------------------
1 | import circleFactory from '../factories/circleFactory';
2 | import ranger, { Range } from "../../../../../dist/ranger.esm";
3 | import BaseExample from "./BaseExample";
4 |
5 | export default class Color extends BaseExample {
6 |
7 | description = 'HSL color model controlled by 3 ranges.';
8 |
9 | state = {
10 | hCurve: undefined,
11 | sCurve: undefined,
12 | lCurve: undefined,
13 | };
14 |
15 | createOptions() {
16 | this.createCurveSelector('hCurve', 'h curve');
17 | this.createCurveSelector('sCurve', 's curve');
18 | this.createCurveSelector('lCurve', 'l curve');
19 | }
20 |
21 | createGraphics() {
22 | const steps = 32;
23 | const circleRadius = this.size.width / steps * 0.5;
24 | // create a range between 0 and canvas width for x positions
25 | const xRange = new Range(0, this.size.width);
26 | // create a range between 0 and canvas height for y positions
27 | const yRange = new Range(0, this.size.height);
28 | // create an array of positions spread over the ranges
29 | // this array is inclusive, so the xPositions[0] === 0, and xPositions[steps - 1] === this.size.width
30 | const xPositions = xRange.slice(steps);
31 | const yPositions = yRange.slice(steps);
32 |
33 | for(let i = 0; i < steps; i++) {
34 | for (let j = 0; j < steps; j++) {
35 | // hsl color model:
36 | // hue: 0 - 255
37 | // saturation: 0 - 100 (%)
38 | // lightness: 0 - 100 (%)
39 |
40 | // create a color based on grid position and component ranges
41 | const h = ranger.randomInt(0, 256, this.state.hCurve);
42 | const s = ranger.mapFloat(i, 0, steps, 0, 100, this.state.sCurve);
43 | const l = ranger.mapFloat(j, 0, steps, 0, 100, this.state.lCurve);
44 | const color = `hsl(${h}, ${s}%, ${l}%)`;
45 |
46 | const circle = circleFactory.create({
47 | x: xPositions[i],
48 | y: yPositions[j],
49 | radius: circleRadius,
50 | color
51 | });
52 |
53 | this.add(circle);
54 | }
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/examples/CustomCurve.js:
--------------------------------------------------------------------------------
1 | import ranger, { Range } from "../../../../../dist/ranger.esm";
2 | import BaseExample from "./BaseExample";
3 | import rectFactory from "../factories/rectFactory";
4 | import circleFactory from "../factories/circleFactory";
5 |
6 | const customCurve = (x, e) => {
7 | return Math.pow(Math.cos(Math.PI * x * 0.5), e);
8 | };
9 |
10 | export default class CustomCurve extends BaseExample {
11 |
12 | description = '[wip] The radius curve uses a curve that is ~0 at 0, 1.0 at 0.5, and ~0 at 1.0.';
13 |
14 | state = {
15 | curveExponent: 0.5
16 | };
17 |
18 | createOptions() {
19 | this.createRangeInput('curveExponent', 'curve exponent', 0.1, 10, 0.1);
20 | }
21 |
22 | createGraphics() {
23 | // create a range between 0 and canvas width for x positions
24 | const xRange = new Range(0, this.size.width).contract(10);
25 | // create a range between 0 and canvas height for y positions
26 | const yRange = new Range(0, this.size.height).contract(10);
27 |
28 | const rRange = new Range(0, 24, x => customCurve(x * 2 - 1, this.state.curveExponent));
29 |
30 | const count = 12;
31 |
32 | for (let i = 0; i < count; i++) {
33 | const x = xRange.mapFloat(i, 0, count - 1);
34 | const y = yRange.mapFloat(i, 0, count - 1);
35 | const radius = rRange.getValue(i / (count - 1));
36 |
37 | const circle = circleFactory.create({
38 | x,
39 | y,
40 | radius
41 | });
42 |
43 | this.add(circle);
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/examples/Divide.js:
--------------------------------------------------------------------------------
1 | import ranger, { Range } from "../../../../../dist/ranger.esm";
2 | import BaseExample from "./BaseExample";
3 | import rectFactory from "../factories/rectFactory";
4 |
5 | export default class Divide extends BaseExample {
6 |
7 | description = 'The canvas is divided into sub-ranges based on a curve for width and a curve for height.';
8 |
9 | state = {
10 | xCurve: undefined,
11 | yCurve: undefined,
12 | xSteps: 16,
13 | ySteps: 16
14 | };
15 |
16 | createOptions() {
17 | this.createCurveSelector('xCurve', 'x curve');
18 | this.createCurveSelector('yCurve', 'y curve');
19 | this.createRangeInput('xSteps', 'x steps', 2, 32, 1);
20 | this.createRangeInput('ySteps', 'y steps', 2, 32, 1);
21 | }
22 |
23 | createGraphics() {
24 | // create a range between 0 and canvas width for x positions
25 | const xRange = new Range(0, this.size.width, this.state.xCurve);
26 | // create a range between 0 and canvas height for y positions
27 | const yRange = new Range(0, this.size.height, this.state.yCurve);
28 | // divide the ranges into sub-ranges (which are also Range instances)
29 | const xRanges = xRange.divide(this.state.xSteps);
30 | const yRanges = yRange.divide(this.state.ySteps);
31 |
32 | for(let i = 0; i < xRanges.length; i++) {
33 | for (let j = 0; j < yRanges.length; j++) {
34 | // min for x and y ranges gives us the position for each rect
35 | const x = xRanges[i].min;
36 | const y = yRanges[j].min;
37 | // length of each range gives us the size
38 | const width = xRanges[i].length(); // range.max - range.min
39 | const height = yRanges[j].length();
40 |
41 | const rect = rectFactory.create({x, y, width, height});
42 |
43 | this.add(rect);
44 | }
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/examples/MapPosition.js:
--------------------------------------------------------------------------------
1 | import circleFactory from '../factories/circleFactory';
2 | import ranger, { Range } from "../../../../../dist/ranger.esm";
3 | import BaseExample from "./BaseExample";
4 |
5 | export default class MapPosition extends BaseExample {
6 |
7 | description = 'X and Y positions are mapped to two ranges. Change the curves to see how it affects the distribution';
8 |
9 | state = {
10 | xCurve: undefined,
11 | yCurve: undefined,
12 | };
13 |
14 | createOptions() {
15 | this.createCurveSelector('xCurve', 'x curve');
16 | this.createCurveSelector('yCurve', 'y curve');
17 | }
18 |
19 | createGraphics() {
20 | // create a range between 0 and canvas width for x positions
21 | const xRange = new Range(0, this.size.width, this.state.xCurve);
22 | // create a range between 0 and canvas height for y positions
23 | const yRange = new Range(0, this.size.height, this.state.yCurve);
24 | const columns = 100;
25 | const rows = 100;
26 |
27 | // we can create a range for column indices
28 | const columnRange = new Range(0, columns - 1);
29 |
30 | for (let i = 0; i < rows; i++) {
31 | for (let j = 0; j < columns; j++) {
32 | const circle = circleFactory.create({
33 | // mapFloat maps a value from this range to [min, max]
34 | x: xRange.mapFloat(i, 0, rows - 1),
35 | // map maps a value from this range to another range instance
36 | y: yRange.map(j, columnRange),
37 | radius: 1
38 | });
39 |
40 | this.add(circle);
41 | }
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/examples/ParticleTiming.js:
--------------------------------------------------------------------------------
1 | import circleFactory from '../factories/circleFactory';
2 | import ranger, { Range } from "../../../../../dist/ranger.esm";
3 | import BaseExample from "./BaseExample";
4 |
5 | export default class ParticleTiming extends BaseExample {
6 |
7 | description = 'Particle animation duration and start time (delay) are both set using a curve. Change the curve to see how the animation is affected.';
8 |
9 | state = {
10 | delayCurve: undefined,
11 | durationCurve: undefined,
12 | };
13 |
14 | createOptions() {
15 | this.createCurveSelector('delayCurve', 'delay curve');
16 | this.createCurveSelector('durationCurve', 'duration curve');
17 | }
18 |
19 | createGraphics() {
20 | if (this.animation) {
21 | this.animation.kill();
22 | }
23 |
24 | this.animation = new TimelineMax({repeat: -1});
25 |
26 | const radius = 4;
27 | const count = 640;
28 | const centerX = this.size.width * 0.5;
29 | const centerY = this.size.height * 0.5;
30 | const angleRange = new Range(0, Math.PI * 2);
31 | // just outside of the screen
32 | const distance = this.size.width * 0.707 + radius;
33 |
34 | for (let i = 0; i < count; i++) {
35 | const circle = circleFactory.create({
36 | x: centerX,
37 | y: centerY,
38 | radius: 4,
39 | });
40 |
41 | // get an angle and distance based on i, spread equally around PI * 2.
42 | const angle = angleRange.getValue(i / (count - 1));
43 | const tx = centerX + Math.cos(angle) * distance;
44 | const ty = centerY + Math.sin(angle) * distance;
45 |
46 | // get a delay and duration based on the selected curve. Min and max values are arbitrary.
47 | const duration = ranger.random(0.5, 2.0, this.state.durationCurve);
48 | // const delay = ranger.random(0.0, 1.0, this.state.delayCurve);
49 | // const duration = ranger.mapFloat(i, 0, count - 1, 0.5, 2.0, this.state.durationCurve);
50 | const delay = ranger.mapFloat(i, 0, count - 1, 0.0, 1.0, this.state.delayCurve);
51 |
52 | this.animation.to(circle, duration, {
53 | x: tx,
54 | y: ty,
55 | }, delay);
56 |
57 | this.add(circle);
58 | }
59 | }
60 |
61 | destroy() {
62 | super.destroy();
63 |
64 | if (this.animation) {
65 | this.animation.kill();
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/examples/RandomPosition.js:
--------------------------------------------------------------------------------
1 | import circleFactory from '../factories/circleFactory';
2 | import ranger, { Range } from "../../../../../";
3 | import BaseExample from "./BaseExample";
4 |
5 | export default class RandomPosition extends BaseExample {
6 |
7 | description = 'Circle positions and radii are randomized using ranges. Change the curve to see how it affects the distribution.';
8 |
9 | state = {
10 | xCurve: undefined,
11 | yCurve: undefined,
12 | radiusCurve: undefined
13 | };
14 |
15 | createOptions() {
16 | this.createCurveSelector('xCurve', 'x curve');
17 | this.createCurveSelector('yCurve', 'y curve');
18 | this.createCurveSelector('radiusCurve', 'radius curve');
19 | }
20 |
21 | createGraphics() {
22 | // create a range between 0 and canvas width for x positions
23 | const xRange = new Range(0, this.size.width, this.state.xCurve);
24 | // create a range between 0 and canvas height for y positions
25 | const yRange = new Range(0, this.size.height, this.state.yCurve);
26 | // create a rang for radii
27 | // ranges with an xxOut curve will produce more larger circles
28 | // ranges with an xxIn curve will produce more smaller circles
29 | const radiusRange = new Range(1, 10, this.state.radiusCurve);
30 |
31 | for (let i = 0; i < 1000; i++) {
32 | const circle = circleFactory.create({
33 | x: xRange.random(),
34 | y: yRange.random(),
35 | radius: radiusRange.random(),
36 | });
37 |
38 | this.add(circle);
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/examples/Wrap.js:
--------------------------------------------------------------------------------
1 | import circleFactory from '../factories/circleFactory';
2 | import ranger, { Range } from "../../../../../dist/ranger.esm";
3 | import BaseExample from "./BaseExample";
4 |
5 | export default class Wrap extends BaseExample {
6 |
7 | description = 'Circle positions are wrapped around the canvas using ranges.';
8 |
9 | state = {
10 | speedXCurve: undefined,
11 | speedYCurve: undefined,
12 | };
13 |
14 | createOptions() {
15 | this.createCurveSelector('speedXCurve', 'speed x curve');
16 | this.createCurveSelector('speedXCurve', 'speed y curve');
17 | }
18 |
19 | createGraphics() {
20 | // create a range between 0 and canvas width for x positions
21 | const xRange = new Range(0, this.size.width, this.state.xCurve);
22 | // create a range between 0 and canvas height for y positions
23 | const yRange = new Range(0, this.size.height, this.state.yCurve);
24 |
25 | // fromSizeAndCenter creates a range of {min: size * -0.5 + center, max: size * 0.5 + center}
26 | // center is 0 by default
27 | // the two lines below create identical ranges
28 | const speedXRange = new Range().fromSizeAndCenter(8, 0, this.state.speedXCurve);
29 | const speedYRange = new Range().fromSizeAndCenter(8).setCurve(this.state.speedYCurve);
30 |
31 | const circleRadius = 12;
32 | const circleCount = 16;
33 |
34 | // wrap the position as soon as the circle is fully outside of the canvas
35 | this.wrapXRange = new Range(-circleRadius, this.size.width + circleRadius);
36 | this.wrapYRange = new Range(-circleRadius, this.size.height + circleRadius);
37 |
38 | for (let i = 0; i < circleCount; i++) {
39 | const circle = circleFactory.create({
40 | x: xRange.random(),
41 | y: yRange.random(),
42 | radius: circleRadius,
43 | color: `hsl(${ranger.mapFloat(i, 0, circleCount - 1, 0, 255)}, 100%, 50%)`
44 | });
45 |
46 | circle.speedX = speedXRange.random();
47 | circle.speedY = speedYRange.random();
48 |
49 | this.add(circle);
50 | }
51 | }
52 |
53 | update() {
54 | this.children.forEach(child => {
55 | child.x = this.wrapXRange.wrap(child.x + child.speedX);
56 | child.y = this.wrapYRange.wrap(child.y + child.speedY);
57 | });
58 | }
59 | }
--------------------------------------------------------------------------------
/examples/es6/src/js/factories/circleFactory.js:
--------------------------------------------------------------------------------
1 | import Circle from "../core/graphics/Circle";
2 | import Node from "../core/sceneGraph/Node";
3 |
4 | const circleFactory = {
5 | create({x = 0, y = 0, radius = 1, color = '#000'}) {
6 | const c = new Node(new Circle({
7 | radius: radius,
8 | fill: color
9 | }));
10 |
11 | c.x = x;
12 | c.y = y;
13 |
14 | return c;
15 | }
16 | };
17 |
18 | export default circleFactory;
--------------------------------------------------------------------------------
/examples/es6/src/js/factories/rectFactory.js:
--------------------------------------------------------------------------------
1 | import Node from "../core/sceneGraph/Node";
2 | import Rect from "../core/graphics/Rect";
3 |
4 | const rectFactory = {
5 | create({x = 0, y = 0, width = 0, height= 0, color = '#000'}) {
6 | const c = new Node(new Rect({
7 | width,
8 | height,
9 | stroke: color
10 | }));
11 |
12 | c.x = x;
13 | c.y = y;
14 |
15 | return c;
16 | }
17 | };
18 |
19 | export default rectFactory;
--------------------------------------------------------------------------------
/examples/es6/src/js/lib/guify.min.js:
--------------------------------------------------------------------------------
1 | !function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define("guify",[],n):"object"==typeof exports?exports.guify=n():e.guify=n()}(this,function(){return function(e){function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}var t={};return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:o})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n(n.s=14)}([function(e,n,t){function o(e,n,t){var o=c[n];if(void 0===o&&(o=i(n)),o){if(void 0===t)return e.style[o];e.style[o]=l(o,t)}}function r(e,n){for(var t in n)n.hasOwnProperty(t)&&o(e,t,n[t])}function i(e){var n=u(e),t=s(n);return c[n]=c[e]=c[t]=t,t}function a(){2===arguments.length?"string"==typeof arguments[1]?arguments[0].style.cssText=arguments[1]:r(arguments[0],arguments[1]):o(arguments[0],arguments[1],arguments[2])}var s=t(16),u=t(17),c={float:"cssFloat"},l=t(20);e.exports=a,e.exports.set=a,e.exports.get=function(e,n){return Array.isArray(n)?n.reduce(function(n,t){return n[t]=o(e,t||""),n},{}):o(e,n||"")}},function(e,n,t){"use strict";function o(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.theme=void 0;var r=function(){function e(e,n){for(var t=0;t+~#:)]*)(?![^{]*})/.source,r=/(@\S*keyframes\s*)([^{\s]*)/.source,i=/(?!(?:[^*\/]|\*[^\/]|\/[^*])*\*+\/)/.source,a=new RegExp(o+i,"g"),s=new RegExp(r+i,"g");e.exports={classRegex:a,keyframesRegex:s,ignoreComments:i}},function(e,n,t){"use strict";e.exports={light:{name:"Light",colors:{menuBarBackground:"rgb(227, 227, 227)",menuBarText:"rgb(36, 36, 36)",panelBackground:"rgb(227, 227, 227)",componentBackground:"rgb(204, 204, 204)",componentBackgroundHover:"rgb(190, 190, 190)",componentForeground:"rgb(105, 105, 105)",componentActive:"rgb(36, 36, 36)",textPrimary:"rgb(36, 36, 36)",textSecondary:"rgb(87, 87, 87)",textHover:"rgb(204, 204, 204)",textActive:"rgb(204, 204, 204)"}},dark:{name:"Dark",colors:{menuBarBackground:"rgb(35, 35, 35)",menuBarText:"rgb(235, 235, 235)",panelBackground:"rgb(35, 35, 35)",componentBackground:"rgb(54, 54, 54)",componentBackgroundHover:"rgb(76, 76, 76)",componentForeground:"rgb(112, 112, 112)",componentActive:"rgb(202, 202, 202)",textPrimary:"rgb(235, 235, 235)",textSecondary:"rgb(181, 181, 181)",textHover:"rgb(235, 235, 235)",textActive:"rgb(54, 54, 54)"}},yorha:{name:"YoRHa",colors:{menuBarBackground:"#CCC8B1",menuBarText:"#454138",panelBackground:"#CCC8B1",componentBackground:"#BAB5A1",componentBackgroundHover:"#877F6E",componentForeground:"#454138",componentActive:"#978F7E",textPrimary:"#454138",textSecondary:"#454138",textHover:"#CCC8B1",textActive:"#CCC8B1"},font:{fontFamily:"helvetica, sans-serif",fontSize:"14px",fontWeight:"100"}}}},function(e,n,t){"use strict";e.exports=" css "},function(e,n,t){"use strict";e.exports=t(43)},function(e,n){function t(e,n){if(n=n||{},void 0===e)throw new Error(a);var t=!0===n.prepend?"prepend":"append",s=void 0!==n.container?n.container:document.querySelector("head"),u=r.indexOf(s);-1===u&&(u=r.push(s)-1,i[u]={});var c;return void 0!==i[u]&&void 0!==i[u][t]?c=i[u][t]:(c=i[u][t]=o(),"prepend"===t?s.insertBefore(c,s.childNodes[0]):s.appendChild(c)),65279===e.charCodeAt(0)&&(e=e.substr(1,e.length)),c.styleSheet?c.styleSheet.cssText+=e:c.textContent+=e,c}function o(){var e=document.createElement("style");return e.setAttribute("type","text/css"),e}var r=[],i=[],a="insert-css: You need to provide a CSS string. Usage: insertCss(cssString[, options]).";e.exports=t,e.exports.insertCss=t},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o=t(0),r=function(e){return e&&e.__esModule?e:{default:e}}(o);n.default=function(e,n,t,o,i){var a=e.appendChild(document.createElement("input"));a.type="text",a.value=n;var s={position:"absolute",backgroundColor:t.colors.componentBackground,paddingLeft:"1%",height:t.sizing.componentHeight,width:o,display:"inline-block",overflow:"hidden",border:"none","font-family":"'Hack', monospace","font-size":"11px",color:t.colors.textSecondary,userSelect:"text",cursor:"text",lineHeight:t.sizing.componentHeight,wordBreak:"break-all","box-sizing":"border-box","-moz-box-sizing":"border-box","-webkit-box-sizing":"border-box"};return i||(s.right=0),(0,r.default)(a,s),a},e.exports=n.default},function(e,n,t){var o;!function(r){function i(e,n){if(e=e||"",n=n||{},e instanceof i)return e;if(!(this instanceof i))return new i(e,n);var t=a(e);this._originalInput=e,this._r=t.r,this._g=t.g,this._b=t.b,this._a=t.a,this._roundA=D(100*this._a)/100,this._format=n.format||t.format,this._gradientType=n.gradientType,this._r<1&&(this._r=D(this._r)),this._g<1&&(this._g=D(this._g)),this._b<1&&(this._b=D(this._b)),this._ok=t.ok,this._tc_id=I++}function a(e){var n={r:0,g:0,b:0},t=1,o=null,r=null,i=null,a=!1,u=!1;return"string"==typeof e&&(e=U(e)),"object"==typeof e&&(F(e.r)&&F(e.g)&&F(e.b)?(n=s(e.r,e.g,e.b),a=!0,u="%"===String(e.r).substr(-1)?"prgb":"rgb"):F(e.h)&&F(e.s)&&F(e.v)?(o=T(e.s),r=T(e.v),n=f(e.h,o,r),a=!0,u="hsv"):F(e.h)&&F(e.s)&&F(e.l)&&(o=T(e.s),i=T(e.l),n=c(e.h,o,i),a=!0,u="hsl"),e.hasOwnProperty("a")&&(t=e.a)),t=O(t),{ok:a,format:e.format||u,r:W(255,G(n.r,0)),g:W(255,G(n.g,0)),b:W(255,G(n.b,0)),a:t}}function s(e,n,t){return{r:255*M(e,255),g:255*M(n,255),b:255*M(t,255)}}function u(e,n,t){e=M(e,255),n=M(n,255),t=M(t,255);var o,r,i=G(e,n,t),a=W(e,n,t),s=(i+a)/2;if(i==a)o=r=0;else{var u=i-a;switch(r=s>.5?u/(2-i-a):u/(i+a),i){case e:o=(n-t)/u+(n1&&(t-=1),t<1/6?e+6*(n-e)*t:t<.5?n:t<2/3?e+(n-e)*(2/3-t)*6:e}var r,i,a;if(e=M(e,360),n=M(n,100),t=M(t,100),0===n)r=i=a=t;else{var s=t<.5?t*(1+n):t+n-t*n,u=2*t-s;r=o(u,s,e+1/3),i=o(u,s,e),a=o(u,s,e-1/3)}return{r:255*r,g:255*i,b:255*a}}function l(e,n,t){e=M(e,255),n=M(n,255),t=M(t,255);var o,r,i=G(e,n,t),a=W(e,n,t),s=i,u=i-a;if(r=0===i?0:u/i,i==a)o=0;else{switch(i){case e:o=(n-t)/u+(n>1)+720)%360;--n;)o.h=(o.h+r)%360,a.push(i(o));return a}function C(e,n){n=n||6;for(var t=i(e).toHsv(),o=t.h,r=t.s,a=t.v,s=[],u=1/n;n--;)s.push(i({h:o,s:r,v:a})),a=(a+u)%1;return s}function O(e){return e=parseFloat(e),(isNaN(e)||e<0||e>1)&&(e=1),e}function M(e,n){A(e)&&(e="100%");var t=L(e);return e=W(n,G(0,parseFloat(e))),t&&(e=parseInt(e*n,10)/100),r.abs(e-n)<1e-6?1:e%n/parseFloat(n)}function H(e){return W(1,G(0,e))}function E(e){return parseInt(e,16)}function A(e){return"string"==typeof e&&-1!=e.indexOf(".")&&1===parseFloat(e)}function L(e){return"string"==typeof e&&-1!=e.indexOf("%")}function P(e){return 1==e.length?"0"+e:""+e}function T(e){return e<=1&&(e=100*e+"%"),e}function B(e){return r.round(255*parseFloat(e)).toString(16)}function R(e){return E(e)/255}function F(e){return!!X.CSS_UNIT.exec(e)}function U(e){e=e.replace(N,"").replace(V,"").toLowerCase();var n=!1;if(Y[e])e=Y[e],n=!0;else if("transparent"==e)return{r:0,g:0,b:0,a:0,format:"name"};var t;return(t=X.rgb.exec(e))?{r:t[1],g:t[2],b:t[3]}:(t=X.rgba.exec(e))?{r:t[1],g:t[2],b:t[3],a:t[4]}:(t=X.hsl.exec(e))?{h:t[1],s:t[2],l:t[3]}:(t=X.hsla.exec(e))?{h:t[1],s:t[2],l:t[3],a:t[4]}:(t=X.hsv.exec(e))?{h:t[1],s:t[2],v:t[3]}:(t=X.hsva.exec(e))?{h:t[1],s:t[2],v:t[3],a:t[4]}:(t=X.hex8.exec(e))?{r:E(t[1]),g:E(t[2]),b:E(t[3]),a:R(t[4]),format:n?"name":"hex8"}:(t=X.hex6.exec(e))?{r:E(t[1]),g:E(t[2]),b:E(t[3]),format:n?"name":"hex"}:(t=X.hex4.exec(e))?{r:E(t[1]+""+t[1]),g:E(t[2]+""+t[2]),b:E(t[3]+""+t[3]),a:R(t[4]+""+t[4]),format:n?"name":"hex8"}:!!(t=X.hex3.exec(e))&&{r:E(t[1]+""+t[1]),g:E(t[2]+""+t[2]),b:E(t[3]+""+t[3]),format:n?"name":"hex"}}function $(e){var n,t;return e=e||{level:"AA",size:"small"},n=(e.level||"AA").toUpperCase(),t=(e.size||"small").toLowerCase(),"AA"!==n&&"AAA"!==n&&(n="AA"),"small"!==t&&"large"!==t&&(t="small"),{level:n,size:t}}var N=/^\s+/,V=/\s+$/,I=0,D=r.round,W=r.min,G=r.max,q=r.random;i.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var e=this.toRgb();return(299*e.r+587*e.g+114*e.b)/1e3},getLuminance:function(){var e,n,t,o,i,a,s=this.toRgb();return e=s.r/255,n=s.g/255,t=s.b/255,o=e<=.03928?e/12.92:r.pow((e+.055)/1.055,2.4),i=n<=.03928?n/12.92:r.pow((n+.055)/1.055,2.4),a=t<=.03928?t/12.92:r.pow((t+.055)/1.055,2.4),.2126*o+.7152*i+.0722*a},setAlpha:function(e){return this._a=O(e),this._roundA=D(100*this._a)/100,this},toHsv:function(){var e=l(this._r,this._g,this._b);return{h:360*e.h,s:e.s,v:e.v,a:this._a}},toHsvString:function(){var e=l(this._r,this._g,this._b),n=D(360*e.h),t=D(100*e.s),o=D(100*e.v);return 1==this._a?"hsv("+n+", "+t+"%, "+o+"%)":"hsva("+n+", "+t+"%, "+o+"%, "+this._roundA+")"},toHsl:function(){var e=u(this._r,this._g,this._b);return{h:360*e.h,s:e.s,l:e.l,a:this._a}},toHslString:function(){var e=u(this._r,this._g,this._b),n=D(360*e.h),t=D(100*e.s),o=D(100*e.l);return 1==this._a?"hsl("+n+", "+t+"%, "+o+"%)":"hsla("+n+", "+t+"%, "+o+"%, "+this._roundA+")"},toHex:function(e){return p(this._r,this._g,this._b,e)},toHexString:function(e){return"#"+this.toHex(e)},toHex8:function(e){return h(this._r,this._g,this._b,this._a,e)},toHex8String:function(e){return"#"+this.toHex8(e)},toRgb:function(){return{r:D(this._r),g:D(this._g),b:D(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+D(this._r)+", "+D(this._g)+", "+D(this._b)+")":"rgba("+D(this._r)+", "+D(this._g)+", "+D(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:D(100*M(this._r,255))+"%",g:D(100*M(this._g,255))+"%",b:D(100*M(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+D(100*M(this._r,255))+"%, "+D(100*M(this._g,255))+"%, "+D(100*M(this._b,255))+"%)":"rgba("+D(100*M(this._r,255))+"%, "+D(100*M(this._g,255))+"%, "+D(100*M(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(Z[p(this._r,this._g,this._b,!0)]||!1)},toFilter:function(e){var n="#"+d(this._r,this._g,this._b,this._a),t=n,o=this._gradientType?"GradientType = 1, ":"";if(e){var r=i(e);t="#"+d(r._r,r._g,r._b,r._a)}return"progid:DXImageTransform.Microsoft.gradient("+o+"startColorstr="+n+",endColorstr="+t+")"},toString:function(e){var n=!!e;e=e||this._format;var t=!1,o=this._a<1&&this._a>=0;return n||!o||"hex"!==e&&"hex6"!==e&&"hex3"!==e&&"hex4"!==e&&"hex8"!==e&&"name"!==e?("rgb"===e&&(t=this.toRgbString()),"prgb"===e&&(t=this.toPercentageRgbString()),"hex"!==e&&"hex6"!==e||(t=this.toHexString()),"hex3"===e&&(t=this.toHexString(!0)),"hex4"===e&&(t=this.toHex8String(!0)),"hex8"===e&&(t=this.toHex8String()),"name"===e&&(t=this.toName()),"hsl"===e&&(t=this.toHslString()),"hsv"===e&&(t=this.toHsvString()),t||this.toHexString()):"name"===e&&0===this._a?this.toName():this.toRgbString()},clone:function(){return i(this.toString())},_applyModification:function(e,n){var t=e.apply(null,[this].concat([].slice.call(n)));return this._r=t._r,this._g=t._g,this._b=t._b,this.setAlpha(t._a),this},lighten:function(){return this._applyModification(y,arguments)},brighten:function(){return this._applyModification(v,arguments)},darken:function(){return this._applyModification(x,arguments)},desaturate:function(){return this._applyModification(g,arguments)},saturate:function(){return this._applyModification(b,arguments)},greyscale:function(){return this._applyModification(m,arguments)},spin:function(){return this._applyModification(k,arguments)},_applyCombination:function(e,n){return e.apply(null,[this].concat([].slice.call(n)))},analogous:function(){return this._applyCombination(j,arguments)},complement:function(){return this._applyCombination(w,arguments)},monochromatic:function(){return this._applyCombination(C,arguments)},splitcomplement:function(){return this._applyCombination(S,arguments)},triad:function(){return this._applyCombination(_,arguments)},tetrad:function(){return this._applyCombination(z,arguments)}},i.fromRatio=function(e,n){if("object"==typeof e){var t={};for(var o in e)e.hasOwnProperty(o)&&(t[o]="a"===o?e[o]:T(e[o]));e=t}return i(e,n)},i.equals=function(e,n){return!(!e||!n)&&i(e).toRgbString()==i(n).toRgbString()},i.random=function(){return i.fromRatio({r:q(),g:q(),b:q()})},i.mix=function(e,n,t){t=0===t?0:t||50;var o=i(e).toRgb(),r=i(n).toRgb(),a=t/100;return i({r:(r.r-o.r)*a+o.r,g:(r.g-o.g)*a+o.g,b:(r.b-o.b)*a+o.b,a:(r.a-o.a)*a+o.a})},i.readability=function(e,n){var t=i(e),o=i(n);return(r.max(t.getLuminance(),o.getLuminance())+.05)/(r.min(t.getLuminance(),o.getLuminance())+.05)},i.isReadable=function(e,n,t){var o,r,a=i.readability(e,n);switch(r=!1,o=$(t),o.level+o.size){case"AAsmall":case"AAAlarge":r=a>=4.5;break;case"AAlarge":r=a>=3;break;case"AAAsmall":r=a>=7}return r},i.mostReadable=function(e,n,t){var o,r,a,s,u=null,c=0;t=t||{},r=t.includeFallbackColors,a=t.level,s=t.size;for(var l=0;lc&&(c=o,u=i(n[l]));return i.isReadable(e,u,{level:a,size:s})||!r?u:(t.includeFallbackColors=!1,i.mostReadable(e,["#fff","#000"],t))};var Y=i.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},Z=i.hexNames=function(e){var n={};for(var t in e)e.hasOwnProperty(t)&&(n[e[t]]=t);return n}(Y),X=function(){var e="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)",n="[\\s|\\(]+("+e+")[,|\\s]+("+e+")[,|\\s]+("+e+")\\s*\\)?",t="[\\s|\\(]+("+e+")[,|\\s]+("+e+")[,|\\s]+("+e+")[,|\\s]+("+e+")\\s*\\)?";return{CSS_UNIT:new RegExp(e),rgb:new RegExp("rgb"+n),rgba:new RegExp("rgba"+t),hsl:new RegExp("hsl"+n),hsla:new RegExp("hsla"+t),hsv:new RegExp("hsv"+n),hsva:new RegExp("hsva"+t),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();void 0!==e&&e.exports?e.exports=i:void 0!==(o=function(){return i}.call(n,t,n,e))&&(e.exports=o)}(Math)},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o=t(15),r=function(e){return e&&e.__esModule?e:{default:e}}(o);n.default=r.default,e.exports=n.default},function(e,n,t){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var i=function(){function e(e,n){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:{};if(!Array.isArray(e)){var o=Object.assign(e,t);return this._Register(o)}e.forEach(function(e){var o=Object.assign(e,t);n._Register(o)})}},{key:"Remove",value:function(e){e.Remove(),this.loadedComponents=this.loadedComponents.filter(function(n){return n!==e})}},{key:"_Register",value:function(e){if(e.object&&e.property&&void 0===e.object[e.property])throw new Error("Object "+e.object+" has no property '"+e.property+"'");e.object&&e.property&&(e.initial=e.object[e.property]);var n=this.panel.panel;if(e.folder){var t=this.loadedComponents.find(function(n){return"folder"===n.opts.type&&n.opts.label===e.folder});if(!t)throw new Error("No folder exists with the name "+e.folder);n=t.folderContainer}var o=this.componentManager.Create(n,e);return e.object&&e.property&&(o.binding={object:e.object,property:e.property}),o.on&&(o.on("initialized",function(n){e.onInitialize&&e.onInitialize(n)}),o.on("input",function(n){e.object&&e.property&&(e.object[e.property]=n),e.onChange&&e.onChange(n)})),this.loadedComponents.push(o),o}},{key:"Toast",value:function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:5e3,t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;this.toaster.CreateToast(e,n,t)}}]),e}();n.default=y,e.exports=n.default},function(e,n){var t=null,o=["Webkit","Moz","O","ms"];e.exports=function(e){t||(t=document.createElement("div"));var n=t.style;if(e in n)return e;for(var r=e.charAt(0).toUpperCase()+e.slice(1),i=o.length;i>=0;i--){var a=o[i]+r;if(a in n)return a}return!1}},function(e,n,t){function o(e){return r(e).replace(/\s(\w)/g,function(e,n){return n.toUpperCase()})}var r=t(18);e.exports=o},function(e,n,t){function o(e){return r(e).replace(/[\W_]+(.|$)/g,function(e,n){return n?" "+n:""}).trim()}var r=t(19);e.exports=o},function(e,n){function t(e){return i.test(e)?e.toLowerCase():a.test(e)?(o(e)||e).toLowerCase():s.test(e)?r(e).toLowerCase():e.toLowerCase()}function o(e){return e.replace(u,function(e,n){return n?" "+n:""})}function r(e){return e.replace(c,function(e,n,t){return n+" "+t.toLowerCase().split("").join(" ")})}e.exports=t;var i=/\s/,a=/(_|-|\.|:)/,s=/([a-z][A-Z]|[A-Z][a-z])/,u=/[\W_]+(.|$)/g,c=/(.)([A-Z]+)/g},function(e,n){var t={animationIterationCount:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridRow:!0,gridColumn:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,stopOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0};e.exports=function(e,n){return"number"!=typeof n||t[e]?n:n+"px"}},function(e,n,t){"use strict";var o=String.prototype.valueOf,r=function(e){try{return o.call(e),!0}catch(e){return!1}},i=Object.prototype.toString,a="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;e.exports=function(e){return"string"==typeof e||"object"==typeof e&&(a?r(e):"[object String]"===i.call(e))}},function(e,n,t){"use strict";function o(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.ComponentManager=void 0;var r=function(){function e(e,n){for(var t=0;t>>((3&n)<<3)&255;return r}}},function(e,n){function t(e,n){var t=n||0,r=o;return r[e[t++]]+r[e[t++]]+r[e[t++]]+r[e[t++]]+"-"+r[e[t++]]+r[e[t++]]+"-"+r[e[t++]]+r[e[t++]]+"-"+r[e[t++]]+r[e[t++]]+"-"+r[e[t++]]+r[e[t++]]+r[e[t++]]+r[e[t++]]+r[e[t++]]+r[e[t++]]}for(var o=[],r=0;r<256;++r)o[r]=(r+256).toString(16).substr(1);e.exports=t},function(e,n,t){"use strict";function o(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=t(0),i=function(e){return e&&e.__esModule?e:{default:e}}(r),a=function e(n,r,a){o(this,e),this.opts=r,this.container=t(2)(n,r.label,a),(0,i.default)(this.container,{});var s=this.container.appendChild(document.createElement("div"));(0,i.default)(s,{"box-sizing":"border-box",width:"100%",display:"inline-block",height:a.sizing.componentHeight,verticalAlign:"top"});var u=s.appendChild(document.createElement("div"));u.innerHTML="■ "+r.label+" ■",(0,i.default)(u,{display:"inline-block",verticalAlign:"sub",height:a.sizing.componentHeight,"line-height":a.sizing.componentHeight,"padding-left":"5px","padding-right":"5px","background-color":a.colors.textPrimary,color:a.colors.panelBackground})};n.default=a,e.exports=n.default},function(e,n,t){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}function i(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}function a(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,n){for(var t=0;t0;)n="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[e%62]+n,e=Math.floor(e/62);return n}},function(e,n,t){"use strict";e.exports=function(e){for(var n=5381,t=e.length;t;)n=33*n^e.charCodeAt(--t);return n>>>0}},function(e,n,t){function o(e){var n=Object.keys(e.keyframes).reduce(function(n,t){return n[e.keyframes[t]]=t,n},{}),t=Object.keys(n);if(t.length){var o="((?:animation|animation-name)\\s*:[^};]*)("+t.join("|")+")([;\\s])"+r,i=new RegExp(o,"g");return{css:e.css.replace(i,function(e,t,o,r){return t+n[o]+r}),keyframes:e.keyframes,classes:e.classes}}return e}var r=t(7).ignoreComments;e.exports=o},function(e,n,t){"use strict";function o(e){return{css:e,keyframes:r(e,s),classes:r(e,a)}}function r(e,n){for(var t,o={};null!==(t=n.exec(e));){var r=t[2];o[r]=r}return o}var i=t(7),a=i.classRegex,s=i.keyframesRegex;e.exports=o},function(e,n,t){"use strict";var o=t(9);e.exports=function(e){return e[o]}},function(e,n,t){"use strict";e.exports=t(10)},function(e,n,t){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}function i(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}function a(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}Object.defineProperty(n,"__esModule",{value:!0});var s=t(4),u=o(s),c=t(0),l=(o(c),t(46)),f=function(e){function n(e,o,a,s){r(this,n);var u=i(this,(n.__proto__||Object.getPrototypeOf(n)).call(this));u.opts=o,u.container=t(2)(e,o.label,a),t(5)(u.container,"",a);var c=u.container.appendChild(document.createElement("button"));return c.className=l["guify-button"],c.textContent=o.label,c.addEventListener("click",o.action),c.addEventListener("mouseup",function(){c.blur()}),u}return a(n,e),n}(u.default);n.default=f,e.exports=n.default},function(e,n,t){"use strict";var o=function(e,n){return Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(n)}}))}(["\n\n.guify-button {\n box-sizing: border-box !important;\n color: ",";\n background-color: ",";\n\n position: absolute;\n text-align: center;\n height: ",";\n line-height: ",";\n padding-top: 0px;\n padding-bottom: 0px;\n width: calc(100% - ",");\n border: none;\n cursor: pointer;\n right: 0;\n font-family: inherit;\n}\n\n\n.guify-button:focus {\n outline:none;\n}\n.guify-button::-moz-focus-inner {\n border:0;\n}\n\n.guify-button:hover,\n.guify-button:focus {\n color: ",";\n background-color: ",";\n}\n\n.guify-button:active {\n color: "," !important;\n background-color: "," !important;\n}\n\n"],["\n\n.guify-button {\n box-sizing: border-box !important;\n color: ",";\n background-color: ",";\n\n position: absolute;\n text-align: center;\n height: ",";\n line-height: ",";\n padding-top: 0px;\n padding-bottom: 0px;\n width: calc(100% - ",");\n border: none;\n cursor: pointer;\n right: 0;\n font-family: inherit;\n}\n\n\n.guify-button:focus {\n outline:none;\n}\n.guify-button::-moz-focus-inner {\n border:0;\n}\n\n.guify-button:hover,\n.guify-button:focus {\n color: ",";\n background-color: ",";\n}\n\n.guify-button:active {\n color: "," !important;\n background-color: "," !important;\n}\n\n"]),r=t(1),i=t(3);e.exports=i(o,r.theme.colors.textSecondary,r.theme.colors.componentBackground,r.theme.sizing.componentHeight,r.theme.sizing.componentHeight,r.theme.sizing.labelWidth,r.theme.colors.textHover,r.theme.colors.componentForeground,r.theme.colors.textActive,r.theme.colors.componentActive)},function(e,n,t){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}function i(e,n){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!n||"object"!=typeof n&&"function"!=typeof n?e:n}function a(e,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);e.prototype=Object.create(n&&n.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(e,n):e.__proto__=n)}Object.defineProperty(n,"__esModule",{value:!0});var s=function(){function e(e,n){for(var t=0;t','','',"",'"].join(""),this.$saturation=this.$el.querySelector(".Scp-saturation"),this.$hue=this.$el.querySelector(".Scp-hue"),this.$sbSelector=this.$el.querySelector(".Scp-sbSelector"),this.$hSelector=this.$el.querySelector(".Scp-hSelector"),this.$saturation.addEventListener("mousedown",this._onSaturationMouseDown),this.$saturation.addEventListener("touchstart",this._onSaturationMouseDown),this.$hue.addEventListener("mousedown",this._onHueMouseDown),this.$hue.addEventListener("touchstart",this._onHueMouseDown),e.el&&this.appendTo(e.el),e.background&&this.setBackgroundColor(e.background),e.widthUnits&&(this.widthUnits=e.widthUnits),e.heightUnits&&(this.heightUnits=e.heightUnits),this.setSize(e.width||175,e.height||150),this.setColor(e.color),this}function o(e,n,t){return Math.min(Math.max(e,n),t)}function r(e){return e=0===e.type.indexOf("touch")?e.touches[0]:e,{x:e.clientX,y:e.clientY}}function i(e){return e="#"+("00000"+(0|e).toString(16)).substr(-6)}var a=t(54),s=t(55),u=t(13),c=t(58);a(n.prototype),n.prototype.appendTo=function(e){return e.appendChild(this.$el),this},n.prototype.remove=function(){this._onSaturationMouseUp(),this._onHueMouseUp(),this.$saturation.removeEventListener("mousedown",this._onSaturationMouseDown),this.$saturation.removeEventListener("touchstart",this._onSaturationMouseDown),this.$hue.removeEventListener("mousedown",this._onHueMouseDown),this.$hue.removeEventListener("touchstart",this._onHueMouseDown),this.off(),this.$el.parentNode&&this.$el.parentNode.removeChild(this.$el)},n.prototype.setColor=function(e){s(e)?(this.inputIsNumber=!0,e=i(e)):this.inputIsNumber=!1,this.color=u(e);var n=this.color.toHsv();return isNaN(n.h)||(this.hue=n.h),this._moveSelectorTo(this.saturationWidth*n.s,(1-n.v)*this.hueHeight),this._moveHueTo((1-this.hue/360)*this.hueHeight),this._updateHue(),this},n.prototype.setSize=function(e,n){return this.width=e,this.height=n,this.$el.style.width=this.width+this.widthUnits,this.$el.style.height=this.height+this.heightUnits,this.saturationWidth=this.width-25,this.$saturation.style.width=this.saturationWidth+"px",this.hueHeight=this.height,this.maxHue=this.hueHeight-2,this},n.prototype.setBackgroundColor=function(e){return s(e)&&(e=i(e)),this.$el.style.padding="5px",this.$el.style.background=u(e).toHexString(),this},n.prototype.setNoBackground=function(){this.$el.style.padding="0px",this.$el.style.background="none"},n.prototype.onChange=function(e){return this.on("update",e),this.emit("update",this.getHexString()),this},n.prototype.getColor=function(){return this.inputIsNumber?this.getHexNumber():this.color.toString()},n.prototype.getHexString=function(){return this.color.toHexString().toUpperCase()},n.prototype.getHexNumber=function(){return parseInt(this.color.toHex(),16)},n.prototype.getRGB=function(){return this.color.toRgb()},n.prototype.getHSV=function(){return this.color.toHsv()},n.prototype.isDark=function(){return this.color.isDark()},n.prototype.isLight=function(){return this.color.isLight()},n.prototype._moveSelectorTo=function(e,n){this.position.x=o(e,0,this.saturationWidth),this.position.y=o(n,0,this.hueHeight),c(this.$sbSelector,{x:this.position.x,y:this.position.y})},n.prototype._updateColorFromPosition=function(){this.color=u({h:this.hue,s:this.position.x/this.saturationWidth,v:1-this.position.y/this.hueHeight}),this._updateColor()},n.prototype._moveHueTo=function(e){this.huePosition=o(e,0,this.maxHue),c(this.$hSelector,{y:this.huePosition})},n.prototype._updateHueFromPosition=function(){var e=this.color.toHsv();this.hue=360*(1-this.huePosition/this.maxHue),this.color=u({h:this.hue,s:e.s,v:e.v}),this._updateHue()},n.prototype._updateHue=function(){var e=u({h:this.hue,s:1,v:1});this.$saturation.style.background="linear-gradient(to right, #fff, "+e.toHexString()+")",this._updateColor()},n.prototype._updateColor=function(){this.$sbSelector.style.background=this.color.toHexString(),this.$sbSelector.style.borderColor=this.color.isDark()?"#fff":"#000",this.emit("update",this.color.toHexString())},n.prototype._onSaturationMouseDown=function(e){var n=this.$saturation.getBoundingClientRect(),t=r(e).x,o=r(e).y;this._moveSelectorTo(t-n.left,o-n.top),this._updateColorFromPosition(),window.addEventListener("mouseup",this._onSaturationMouseUp),window.addEventListener("touchend",this._onSaturationMouseUp),window.addEventListener("mousemove",this._onSaturationMouseMove),window.addEventListener("touchmove",this._onSaturationMouseMove),e.preventDefault()},n.prototype._onSaturationMouseMove=function(e){var n=this.$saturation.getBoundingClientRect(),t=r(e).x,o=r(e).y;this._moveSelectorTo(t-n.left,o-n.top),this._updateColorFromPosition()},n.prototype._onSaturationMouseUp=function(){window.removeEventListener("mouseup",this._onSaturationMouseUp),window.removeEventListener("touchend",this._onSaturationMouseUp),window.removeEventListener("mousemove",this._onSaturationMouseMove),window.removeEventListener("touchmove",this._onSaturationMouseMove)},n.prototype._onHueMouseDown=function(e){var n=this.$hue.getBoundingClientRect(),t=r(e).y;this._moveHueTo(t-n.top),this._updateHueFromPosition(),window.addEventListener("mouseup",this._onHueMouseUp),window.addEventListener("touchend",this._onHueMouseUp),window.addEventListener("mousemove",this._onHueMouseMove),window.addEventListener("touchmove",this._onHueMouseMove),e.preventDefault()},n.prototype._onHueMouseMove=function(e){var n=this.$hue.getBoundingClientRect(),t=r(e).y;this._moveHueTo(t-n.top),this._updateHueFromPosition()},n.prototype._onHueMouseUp=function(){window.removeEventListener("mouseup",this._onHueMouseUp),window.removeEventListener("touchend",this._onHueMouseUp),window.removeEventListener("mousemove",this._onHueMouseMove),window.removeEventListener("touchmove",this._onHueMouseMove)},void 0!==e&&e.exports&&(e.exports=n)}()},function(e,n,t){function o(e){if(e)return r(e)}function r(e){for(var n in o.prototype)e[n]=o.prototype[n];return e}e.exports=o,o.prototype.on=o.prototype.addEventListener=function(e,n){return this._callbacks=this._callbacks||{},(this._callbacks["$"+e]=this._callbacks["$"+e]||[]).push(n),this},o.prototype.once=function(e,n){function t(){this.off(e,t),n.apply(this,arguments)}return t.fn=n,this.on(e,t),this},o.prototype.off=o.prototype.removeListener=o.prototype.removeAllListeners=o.prototype.removeEventListener=function(e,n){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var t=this._callbacks["$"+e];if(!t)return this;if(1==arguments.length)return delete this._callbacks["$"+e],this;for(var o,r=0;r
3 | *
4 | * Copyright (c) 2014-2015, Jon Schlinkert.
5 | * Licensed under the MIT License.
6 | */
7 | var o=t(56);e.exports=function(e){var n=o(e);if("string"===n){if(!e.trim())return!1}else if("number"!==n)return!1;return e-e+1>=0}},function(e,n,t){var o=t(57),r=Object.prototype.toString;e.exports=function(e){if(void 0===e)return"undefined";if(null===e)return"null";if(!0===e||!1===e||e instanceof Boolean)return"boolean";if("string"==typeof e||e instanceof String)return"string";if("number"==typeof e||e instanceof Number)return"number";if("function"==typeof e||e instanceof Function)return"function";if(void 0!==Array.isArray&&Array.isArray(e))return"array";if(e instanceof RegExp)return"regexp";if(e instanceof Date)return"date";var n=r.call(e);return"[object RegExp]"===n?"regexp":"[object Date]"===n?"date":"[object Arguments]"===n?"arguments":"[object Error]"===n?"error":o(e)?"buffer":"[object Set]"===n?"set":"[object WeakSet]"===n?"weakset":"[object Map]"===n?"map":"[object WeakMap]"===n?"weakmap":"[object Symbol]"===n?"symbol":"[object Int8Array]"===n?"int8array":"[object Uint8Array]"===n?"uint8array":"[object Uint8ClampedArray]"===n?"uint8clampedarray":"[object Int16Array]"===n?"int16array":"[object Uint16Array]"===n?"uint16array":"[object Int32Array]"===n?"int32array":"[object Uint32Array]"===n?"uint32array":"[object Float32Array]"===n?"float32array":"[object Float64Array]"===n?"float64array":"object"}},function(e,n){function t(e){return!!e.constructor&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}function o(e){return"function"==typeof e.readFloatLE&&"function"==typeof e.slice&&t(e.slice(0,0))}/*!
8 | * Determine if an object is a Buffer
9 | *
10 | * @author Feross Aboukhadijeh
11 | * @license MIT
12 | */
13 | e.exports=function(e){return null!=e&&(t(e)||o(e)||!!e._isBuffer)}},function(e,n,t){"use strict";function o(e,n){var t,o,r,i=[];s(n);for(t in n)h.call(n,t)&&(o=n[t],h.call(f.transform,t)?(r=f.transform[t],l(o)&&(o=o.join(r.separator)),i.push(t+"("+p(o,r.defaultUnit,r.separator)+")")):h.call(f,t)?(r=f[t],l(o)&&(o=o.join(r.separator)),e.style[c(t)]=p(o,r.defaultUnit,r.separator)):console.warn("dom-transform: this property (`"+t+"`) is not supported."));e.style[d]=i.join(" ")}function r(e,n){var t=e.style;if("string"==typeof n)return h.call(f.transform,n)?t[d]:t[c(n)];n||(n=u());var o={};return n.forEach(function(e){o[e]=t[c(e)]}),o}function i(e,n){var t=e.style;if("string"==typeof n)return void(t[c(n)]=null);n||(n=u()),n.forEach(function(e){t[c(e)]=null})}function a(){return d.length>0}function s(e){var n;for(n in e)h.call(g,n)&&(e[g[n]]=e[n],delete e[n])}function u(){return Object.keys(f).map(function(e){return e})}var c=t(59),l=t(60),f=t(61),p=t(62),h=Object.prototype.hasOwnProperty,d=c("transform"),g={x:"translateX",y:"translateY",z:"translateZ",origin:"transformOrigin"};n=e.exports=o,n.get=r,n.reset=i,n.isSupported=a},function(e,n){function t(e){if(e=e.replace(/-([a-z])/g,function(e,n){return n.toUpperCase()}),void 0!==i[e])return e;for(var n=e.charAt(0).toUpperCase()+e.slice(1),t=a.length;t--;){var o=a[t]+n;if(void 0!==i[o])return o}return e}function o(e){return e in u?u[e]:u[e]=t(e)}function r(e){return e=t(e),s.test(e)&&(e="-"+e.replace(s,"-$1"),s.lastIndex=0),e.toLowerCase()}var i="undefined"!=typeof document?document.createElement("p").style:{},a=["O","ms","Moz","Webkit"],s=/([A-Z])/g,u={};e.exports=o,e.exports.dash=r},function(e,n){var t=Array.isArray,o=Object.prototype.toString;e.exports=t||function(e){return!!e&&"[object Array]"==o.call(e)}},function(e,n,t){"use strict";e.exports={transform:{translate:{defaultUnit:"px"},translate3d:{defaultUnit:"px"},translateX:{defaultUnit:"px"},translateY:{defaultUnit:"px"},translateZ:{defaultUnit:"px"},scale:{defaultUnit:""},scale3d:{defaultUnit:""},scaleX:{defaultUnit:""},scaleY:{defaultUnit:""},scaleZ:{defaultUnit:""},rotate:{defaultUnit:"deg"},rotate3d:{defaultUnit:""},rotateX:{defaultUnit:"deg"},rotateY:{defaultUnit:"deg"},rotateZ:{defaultUnit:"deg"},skew:{defaultUnit:"deg"},skewX:{defaultUnit:"deg"},skewY:{defaultUnit:"deg"},perspective:{defaultUnit:"px"},matrix:{defaultUnit:""},matrix3d:{defaultUnit:""}},transformOrigin:{defaultUnit:"px",separator:" "}}},function(e,n,t){"use strict";var o=t(63),r=/^-?\d+(\.\d+)?$/;e.exports=function(e,n,t){if(t=t||",","number"==typeof e)return""+e+n;var i=new RegExp(t,"g");return e.split(i.test(e)?t:" ").map(function(e){return e=o(e),r.test(e)&&(e+=n),e}).join(t)}},function(e,n){function t(e){return e.replace(/^\s*|\s*$/g,"")}n=e.exports=t,n.left=function(e){return e.replace(/^\s*/,"")},n.right=function(e){return e.replace(/\s*$/,"")}},function(e,n,t){"use strict";function o(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function e(e,n){for(var t=0;t\n \n \n '}}]),e}()},function(e,n,t){"use strict";var o=function(e,n){return Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(n)}}))}(["\n\n.guify-panel-container {\n position: absolute;\n background: ",";\n}\n\n.guify-panel {\n padding: 14px;\n /* Last component will have a margin, so reduce padding to account for this */\n padding-bottom: calc(14px - ",");\n\n /* all: initial; */\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n cursor: default;\n text-align: left;\n box-sizing: border-box;\n}\n\n.guify-panel.guify-panel-hidden {\n height: 0px;\n display: none;\n}\n\n.guify-panel * {\n box-sizing: initial;\n -webkit-box-sizing: initial;\n -moz-box-sizing: initial;\n}\n\n.guify-panel input {\n font-family: 'Hack';\n font-size: 11px;\n display: inline;\n}\n\n.guify-panel a {\n color: inherit;\n text-decoration: none;\n}\n\n.guify-panel-toggle-button {\n position: absolute;\n top: 0;\n margin: 0;\n padding: 0;\n width: 15px;\n height: 15px;\n line-height: 15px;\n text-align: center;\n border: none;\n cursor: pointer;\n font-family: inherit;\n color: ",";\n background-color: ",";\n\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n\n}\n\n/* Open/Close button styling */\n.guify-panel-toggle-button svg {\n fill-opacity: 0;\n stroke-width: 3;\n stroke: ",";\n}\n\n/* Remove browser default outlines since we're providing our own */\n.guify-panel-toggle-button:focus {\n outline:none;\n}\n.guify-panel-toggle-button::-moz-focus-inner {\n border: 0;\n}\n\n.guify-panel-toggle-button:hover,\n.guify-panel-toggle-button:focus {\n color: ",";\n background-color: ",";\n}\n\n.guify-panel-toggle-button:active {\n color: ",";\n background-color: ",";\n}\n\n"],["\n\n.guify-panel-container {\n position: absolute;\n background: ",";\n}\n\n.guify-panel {\n padding: 14px;\n /* Last component will have a margin, so reduce padding to account for this */\n padding-bottom: calc(14px - ",");\n\n /* all: initial; */\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n cursor: default;\n text-align: left;\n box-sizing: border-box;\n}\n\n.guify-panel.guify-panel-hidden {\n height: 0px;\n display: none;\n}\n\n.guify-panel * {\n box-sizing: initial;\n -webkit-box-sizing: initial;\n -moz-box-sizing: initial;\n}\n\n.guify-panel input {\n font-family: 'Hack';\n font-size: 11px;\n display: inline;\n}\n\n.guify-panel a {\n color: inherit;\n text-decoration: none;\n}\n\n.guify-panel-toggle-button {\n position: absolute;\n top: 0;\n margin: 0;\n padding: 0;\n width: 15px;\n height: 15px;\n line-height: 15px;\n text-align: center;\n border: none;\n cursor: pointer;\n font-family: inherit;\n color: ",";\n background-color: ",";\n\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n\n}\n\n/* Open/Close button styling */\n.guify-panel-toggle-button svg {\n fill-opacity: 0;\n stroke-width: 3;\n stroke: ",";\n}\n\n/* Remove browser default outlines since we're providing our own */\n.guify-panel-toggle-button:focus {\n outline:none;\n}\n.guify-panel-toggle-button::-moz-focus-inner {\n border: 0;\n}\n\n.guify-panel-toggle-button:hover,\n.guify-panel-toggle-button:focus {\n color: ",";\n background-color: ",";\n}\n\n.guify-panel-toggle-button:active {\n color: ",";\n background-color: ",";\n}\n\n"]),r=t(1),i=t(3);e.exports=i(o,r.theme.colors.panelBackground,r.theme.sizing.componentSpacing,r.theme.colors.textPrimary,r.theme.colors.componentBackground,r.theme.colors.componentForeground,r.theme.colors.textHover,r.theme.colors.componentForeground,r.theme.colors.textActive,r.theme.colors.componentActive)},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.default=function(e,n,t){var o=e.appendChild(document.createElement("div"));return o.innerHTML=n,(0,r.default)(o,{width:"100%",textAlign:"center",color:t.colors.textSecondary,height:"20px",marginBottom:"4px"}),o};var o=t(0),r=function(e){return e&&e.__esModule?e:{default:e}}(o);e.exports=n.default},function(e,n,t){"use strict";function o(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0}),n.ToastArea=void 0;var r=function(){function e(e,n){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:5e3,t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;console.log("[Toast] "+e);var o=this.element.appendChild(document.createElement("div"));o.classList.add(this.styles["guify-toast-notification"]),o.setAttribute("aria-live","polite"),o.innerHTML=e,(0,a.default)(o,{});var r=o.appendChild(document.createElement("button"));r.innerHTML="✖",r.classList.add(this.styles["guify-toast-close-button"]);var i=void 0,s=function(){o.blur(),(0,a.default)(o,{opacity:"0"}),clearTimeout(i),i=setTimeout(function(){o&&o.parentNode.removeChild(o)},t)};i=setTimeout(s,n),r.onclick=s}}]),e}()},function(e,n,t){"use strict";var o=function(e,n){return Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(n)}}))}(["\n\n.guify-toast-notification {\n box-sizing: border-box;\n color: theme.colors.text1;\n position: relative;\n width: 100%;\n /* height: 20px; */\n padding: 8px;\n padding-left: 20px;\n padding-right: 20px;\n text-align: center;\n font-family: 'Hack', monospace;\n font-size: 11px;\n}\n\n.guify-toast-area .guify-toast-notification:nth-child(odd) {\n color: ",";\n background-color: ",";\n}\n\n.guify-toast-area .guify-toast-notification:nth-child(even) {\n color: ",";\n background-color: ",";\n}\n\n.guify-toast-close-button {\n color: ",";\n background: transparent;\n position: absolute;\n textAlign: center;\n margin-top: auto;\n margin-bottom: auto;\n border: none;\n cursor: pointer;\n top: 0;\n bottom: 0;\n right: 8px;\n}\n\n"],["\n\n.guify-toast-notification {\n box-sizing: border-box;\n color: theme.colors.text1;\n position: relative;\n width: 100%;\n /* height: 20px; */\n padding: 8px;\n padding-left: 20px;\n padding-right: 20px;\n text-align: center;\n font-family: 'Hack', monospace;\n font-size: 11px;\n}\n\n.guify-toast-area .guify-toast-notification:nth-child(odd) {\n color: ",";\n background-color: ",";\n}\n\n.guify-toast-area .guify-toast-notification:nth-child(even) {\n color: ",";\n background-color: ",";\n}\n\n.guify-toast-close-button {\n color: ",";\n background: transparent;\n position: absolute;\n textAlign: center;\n margin-top: auto;\n margin-bottom: auto;\n border: none;\n cursor: pointer;\n top: 0;\n bottom: 0;\n right: 8px;\n}\n\n"]),r=t(1),i=t(3);e.exports=i(o,r.theme.colors.textPrimary,r.theme.colors.panelBackground,r.theme.colors.textPrimary,r.theme.colors.menuBarBackground,r.theme.colors.textPrimary)},function(e,n,t){"use strict";var o=function(e,n){return Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(n)}}))}(["\n\n.guify-container {\n position: relative;\n left: 0;\n width: 100%;\n font-size: 11px;\n z-index: 9999;\n}\n\n"],["\n\n.guify-container {\n position: relative;\n left: 0;\n width: 100%;\n font-size: 11px;\n z-index: 9999;\n}\n\n"]),r=(t(1),t(3));e.exports=r(o)}])});
--------------------------------------------------------------------------------
/examples/es6/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebPackPlugin = require("html-webpack-plugin");
2 |
3 | module.exports = {
4 | module: {
5 | rules: [
6 | {
7 | test: /\.js$/,
8 | exclude: /node_modules/,
9 | use: {
10 | loader: "babel-loader"
11 | }
12 | }
13 | ]
14 | },
15 | plugins: [
16 | new HtmlWebPackPlugin({
17 | template: "./src/index.html",
18 | filename: "./index.html"
19 | })
20 | ]
21 | };
--------------------------------------------------------------------------------
/examples/umd/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Ranger.js examples
7 |
12 |
13 |
14 |
15 |
24 | See console for amazing test output.
25 |
26 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rollup-starter-lib",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "arr-diff": {
8 | "version": "2.0.0",
9 | "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
10 | "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
11 | "dev": true,
12 | "requires": {
13 | "arr-flatten": "1.1.0"
14 | }
15 | },
16 | "arr-flatten": {
17 | "version": "1.1.0",
18 | "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
19 | "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
20 | "dev": true
21 | },
22 | "array-unique": {
23 | "version": "0.2.1",
24 | "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
25 | "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
26 | "dev": true
27 | },
28 | "braces": {
29 | "version": "1.8.5",
30 | "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
31 | "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
32 | "dev": true,
33 | "requires": {
34 | "expand-range": "1.8.2",
35 | "preserve": "0.2.0",
36 | "repeat-element": "1.1.2"
37 | }
38 | },
39 | "builtin-modules": {
40 | "version": "2.0.0",
41 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-2.0.0.tgz",
42 | "integrity": "sha512-3U5kUA5VPsRUA3nofm/BXX7GVHKfxz0hOBAPxXrIvHzlDRkQVqEn6yi8QJegxl4LzOHLdvb7XF5dVawa/VVYBg==",
43 | "dev": true
44 | },
45 | "estree-walker": {
46 | "version": "0.5.1",
47 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.1.tgz",
48 | "integrity": "sha512-7HgCgz1axW7w5aOvgOQkoR1RMBkllygJrssU3BvymKQ95lxXYv6Pon17fBRDm9qhkvXZGijOULoSF9ShOk/ZLg==",
49 | "dev": true
50 | },
51 | "expand-brackets": {
52 | "version": "0.1.5",
53 | "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
54 | "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
55 | "dev": true,
56 | "requires": {
57 | "is-posix-bracket": "0.1.1"
58 | }
59 | },
60 | "expand-range": {
61 | "version": "1.8.2",
62 | "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
63 | "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
64 | "dev": true,
65 | "requires": {
66 | "fill-range": "2.2.3"
67 | }
68 | },
69 | "extglob": {
70 | "version": "0.3.2",
71 | "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
72 | "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
73 | "dev": true,
74 | "requires": {
75 | "is-extglob": "1.0.0"
76 | }
77 | },
78 | "filename-regex": {
79 | "version": "2.0.1",
80 | "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
81 | "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
82 | "dev": true
83 | },
84 | "fill-range": {
85 | "version": "2.2.3",
86 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
87 | "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
88 | "dev": true,
89 | "requires": {
90 | "is-number": "2.1.0",
91 | "isobject": "2.1.0",
92 | "randomatic": "1.1.7",
93 | "repeat-element": "1.1.2",
94 | "repeat-string": "1.6.1"
95 | }
96 | },
97 | "for-in": {
98 | "version": "1.0.2",
99 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
100 | "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
101 | "dev": true
102 | },
103 | "for-own": {
104 | "version": "0.1.5",
105 | "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
106 | "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
107 | "dev": true,
108 | "requires": {
109 | "for-in": "1.0.2"
110 | }
111 | },
112 | "glob-base": {
113 | "version": "0.3.0",
114 | "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
115 | "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
116 | "dev": true,
117 | "requires": {
118 | "glob-parent": "2.0.0",
119 | "is-glob": "2.0.1"
120 | }
121 | },
122 | "glob-parent": {
123 | "version": "2.0.0",
124 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
125 | "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
126 | "dev": true,
127 | "requires": {
128 | "is-glob": "2.0.1"
129 | }
130 | },
131 | "is-buffer": {
132 | "version": "1.1.6",
133 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
134 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
135 | "dev": true
136 | },
137 | "is-dotfile": {
138 | "version": "1.0.3",
139 | "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
140 | "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
141 | "dev": true
142 | },
143 | "is-equal-shallow": {
144 | "version": "0.1.3",
145 | "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
146 | "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
147 | "dev": true,
148 | "requires": {
149 | "is-primitive": "2.0.0"
150 | }
151 | },
152 | "is-extendable": {
153 | "version": "0.1.1",
154 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
155 | "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
156 | "dev": true
157 | },
158 | "is-extglob": {
159 | "version": "1.0.0",
160 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
161 | "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
162 | "dev": true
163 | },
164 | "is-glob": {
165 | "version": "2.0.1",
166 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
167 | "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
168 | "dev": true,
169 | "requires": {
170 | "is-extglob": "1.0.0"
171 | }
172 | },
173 | "is-module": {
174 | "version": "1.0.0",
175 | "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
176 | "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
177 | "dev": true
178 | },
179 | "is-number": {
180 | "version": "2.1.0",
181 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
182 | "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
183 | "dev": true,
184 | "requires": {
185 | "kind-of": "3.2.2"
186 | }
187 | },
188 | "is-posix-bracket": {
189 | "version": "0.1.1",
190 | "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
191 | "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
192 | "dev": true
193 | },
194 | "is-primitive": {
195 | "version": "2.0.0",
196 | "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
197 | "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
198 | "dev": true
199 | },
200 | "isarray": {
201 | "version": "1.0.0",
202 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
203 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
204 | "dev": true
205 | },
206 | "isobject": {
207 | "version": "2.1.0",
208 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
209 | "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
210 | "dev": true,
211 | "requires": {
212 | "isarray": "1.0.0"
213 | }
214 | },
215 | "kind-of": {
216 | "version": "3.2.2",
217 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
218 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
219 | "dev": true,
220 | "requires": {
221 | "is-buffer": "1.1.6"
222 | }
223 | },
224 | "magic-string": {
225 | "version": "0.22.4",
226 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.4.tgz",
227 | "integrity": "sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw==",
228 | "dev": true,
229 | "requires": {
230 | "vlq": "0.2.3"
231 | }
232 | },
233 | "micromatch": {
234 | "version": "2.3.11",
235 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
236 | "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
237 | "dev": true,
238 | "requires": {
239 | "arr-diff": "2.0.0",
240 | "array-unique": "0.2.1",
241 | "braces": "1.8.5",
242 | "expand-brackets": "0.1.5",
243 | "extglob": "0.3.2",
244 | "filename-regex": "2.0.1",
245 | "is-extglob": "1.0.0",
246 | "is-glob": "2.0.1",
247 | "kind-of": "3.2.2",
248 | "normalize-path": "2.1.1",
249 | "object.omit": "2.0.1",
250 | "parse-glob": "3.0.4",
251 | "regex-cache": "0.4.4"
252 | }
253 | },
254 | "ms": {
255 | "version": "2.1.1",
256 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
257 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
258 | },
259 | "normalize-path": {
260 | "version": "2.1.1",
261 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
262 | "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
263 | "dev": true,
264 | "requires": {
265 | "remove-trailing-separator": "1.1.0"
266 | }
267 | },
268 | "object.omit": {
269 | "version": "2.0.1",
270 | "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
271 | "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
272 | "dev": true,
273 | "requires": {
274 | "for-own": "0.1.5",
275 | "is-extendable": "0.1.1"
276 | }
277 | },
278 | "parse-glob": {
279 | "version": "3.0.4",
280 | "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
281 | "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
282 | "dev": true,
283 | "requires": {
284 | "glob-base": "0.3.0",
285 | "is-dotfile": "1.0.3",
286 | "is-extglob": "1.0.0",
287 | "is-glob": "2.0.1"
288 | }
289 | },
290 | "path-parse": {
291 | "version": "1.0.5",
292 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
293 | "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
294 | "dev": true
295 | },
296 | "preserve": {
297 | "version": "0.2.0",
298 | "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
299 | "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
300 | "dev": true
301 | },
302 | "randomatic": {
303 | "version": "1.1.7",
304 | "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
305 | "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
306 | "dev": true,
307 | "requires": {
308 | "is-number": "3.0.0",
309 | "kind-of": "4.0.0"
310 | },
311 | "dependencies": {
312 | "is-number": {
313 | "version": "3.0.0",
314 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
315 | "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
316 | "dev": true,
317 | "requires": {
318 | "kind-of": "3.2.2"
319 | },
320 | "dependencies": {
321 | "kind-of": {
322 | "version": "3.2.2",
323 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
324 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
325 | "dev": true,
326 | "requires": {
327 | "is-buffer": "1.1.6"
328 | }
329 | }
330 | }
331 | },
332 | "kind-of": {
333 | "version": "4.0.0",
334 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
335 | "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
336 | "dev": true,
337 | "requires": {
338 | "is-buffer": "1.1.6"
339 | }
340 | }
341 | }
342 | },
343 | "regex-cache": {
344 | "version": "0.4.4",
345 | "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
346 | "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
347 | "dev": true,
348 | "requires": {
349 | "is-equal-shallow": "0.1.3"
350 | }
351 | },
352 | "remove-trailing-separator": {
353 | "version": "1.1.0",
354 | "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
355 | "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
356 | "dev": true
357 | },
358 | "repeat-element": {
359 | "version": "1.1.2",
360 | "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
361 | "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
362 | "dev": true
363 | },
364 | "repeat-string": {
365 | "version": "1.6.1",
366 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
367 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
368 | "dev": true
369 | },
370 | "resolve": {
371 | "version": "1.5.0",
372 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
373 | "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
374 | "dev": true,
375 | "requires": {
376 | "path-parse": "1.0.5"
377 | }
378 | },
379 | "rollup": {
380 | "version": "0.56.5",
381 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.56.5.tgz",
382 | "integrity": "sha512-IGPk5vdWrsc4vkiW9XMeXr5QMtxmvATTttTi59w2jBQWe9G/MMQtn8teIBAj+DdK51TrpVT6P0aQUaQUlUYCJA==",
383 | "dev": true
384 | },
385 | "rollup-plugin-commonjs": {
386 | "version": "9.1.0",
387 | "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.1.0.tgz",
388 | "integrity": "sha512-NrfE0g30QljNCnlJr7I2Xguz+44mh0dCxvfxwLnCwtaCK2LwFUp1zzAs8MQuOfhH4mRskqsjfOwGUap/L+WtEw==",
389 | "dev": true,
390 | "requires": {
391 | "estree-walker": "0.5.1",
392 | "magic-string": "0.22.4",
393 | "resolve": "1.5.0",
394 | "rollup-pluginutils": "2.0.1"
395 | }
396 | },
397 | "rollup-plugin-node-resolve": {
398 | "version": "3.2.0",
399 | "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.2.0.tgz",
400 | "integrity": "sha512-stvVrKaQiNu65ObGJLCHyHH/NXjiPMt/ZHwvl444KgJPrii1zCgyg+NTK2Uy6WExL+OuUWdHd7T8EoPQDtYEkw==",
401 | "dev": true,
402 | "requires": {
403 | "builtin-modules": "2.0.0",
404 | "is-module": "1.0.0",
405 | "resolve": "1.5.0"
406 | }
407 | },
408 | "rollup-pluginutils": {
409 | "version": "2.0.1",
410 | "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz",
411 | "integrity": "sha1-fslbNXP2VDpGpkYb2afFRFJdD8A=",
412 | "dev": true,
413 | "requires": {
414 | "estree-walker": "0.3.1",
415 | "micromatch": "2.3.11"
416 | },
417 | "dependencies": {
418 | "estree-walker": {
419 | "version": "0.3.1",
420 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz",
421 | "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=",
422 | "dev": true
423 | }
424 | }
425 | },
426 | "vlq": {
427 | "version": "0.2.3",
428 | "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
429 | "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
430 | "dev": true
431 | }
432 | }
433 | }
434 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@zadvorsky/ranger",
3 | "repository": "https://github.com/zadvorsky/ranger",
4 | "description": "A small, standalone JavaScript library for working with ranges of numbers.",
5 | "version": "1.0.4",
6 | "main": "dist/ranger.cjs.js",
7 | "jsnext:main": "dist/ranger.esm.js",
8 | "module": "dist/ranger.esm.js",
9 | "browser": "dist/ranger.umd.js",
10 | "dependencies": {},
11 | "devDependencies": {
12 | "babel-core": "^6.26.3",
13 | "babel-preset-env": "^1.7.0",
14 | "babelrc-rollup": "^3.0.0",
15 | "jsdoc": "^3.5.5",
16 | "minami": "^1.2.3",
17 | "rollup": "^0.58.0",
18 | "rollup-plugin-babel": "^3.0.4",
19 | "rollup-plugin-commonjs": "^9.1.0",
20 | "rollup-plugin-node-resolve": "^3.0.0"
21 | },
22 | "scripts": {
23 | "build": "rollup -c",
24 | "dev": "rollup -c -w",
25 | "test": "node test/test.js",
26 | "pretest": "npm run build",
27 | "docs": "node_modules/.bin/jsdoc --configure .jsdoc.json --verbose"
28 | },
29 | "files": [
30 | "dist"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel';
2 | import babelrc from 'babelrc-rollup';
3 | import pkg from './package.json';
4 |
5 | const babelConfig = {
6 | 'presets': [
7 | ['env']
8 | ]
9 | };
10 |
11 | export default [
12 | {
13 | input: 'src/main.umd.js',
14 | output: {
15 | name: 'ranger',
16 | file: pkg.browser,
17 | format: 'umd'
18 | },
19 | plugins: [
20 | babel(babelrc({
21 | addExternalHelpersPlugin: false,
22 | config: babelConfig,
23 | exclude: 'node_modules/**'
24 | }))
25 | ],
26 | },
27 | {
28 | input: 'src/main.cjs.js',
29 | output: {
30 | file: pkg.main,
31 | format: 'cjs'
32 | }
33 | },
34 | {
35 | input: 'src/main.es.js',
36 | output: [
37 | {
38 | file: pkg.module,
39 | format: 'es',
40 | exports: 'named'
41 | }
42 | ]
43 | }
44 | ];
45 |
--------------------------------------------------------------------------------
/src/Range.js:
--------------------------------------------------------------------------------
1 | import ranger from './ranger';
2 |
3 | /**
4 | * Creates a new Range instance with a min, max, and curve for repeated use.
5 | * No validation is performed to check if min is less or equal to max.
6 | *
7 | * @class
8 | * @constructor
9 | */
10 | class Range {
11 | /**
12 | * Creates a new Range instance with a min, max, and curve for repeated use.
13 | * No validation is performed to check if min is less or equal to max.
14 | *
15 | * @param {number} min - Min value for this range.
16 | * @param {number} max - Max value for this range.
17 | * @param {function} [curve] - The curve function to apply by default.
18 | */
19 | constructor(min = 0, max = 0, curve = ranger.LINEAR) {
20 | /**
21 | * Min value for this range
22 | * @type {number}
23 | */
24 | this.min = min;
25 | /**
26 | * Max value for this range
27 | * @type {number}
28 | */
29 | this.max = max;
30 | /**
31 | * The curve used by this range.
32 | * This should be a function that takes a number (0.0 to 1.0), and returns a transformed number.
33 | * @type {Function}
34 | */
35 | this.curve = curve;
36 | }
37 |
38 | /**
39 | * Sets this range min and max based on a size and a center.
40 | * Min will be set to size * -0.5 + center.
41 | * Max will be set to size * 0.5 + center.
42 | *
43 | * @param {Number} size - The total size of the range.
44 | * @param {Number} [center=0] - The center of the range. Defaults to 0.
45 | * @param {function} [curve] - The curve function to apply by default.
46 | * @returns {Range}
47 | */
48 | fromSizeAndCenter(size, center = 0, curve = this.curve) {
49 | this.min = size * -0.5 + center;
50 | this.max = size * 0.5 + center;
51 | this.curve = curve;
52 |
53 | return this;
54 | }
55 |
56 | /**
57 | * Sets the min, max, and curve for this range.
58 | *
59 | * @param {number} min - Min value for this range.
60 | * @param {number} max - Max value for this range.
61 | * @param {function} [curve] - The curve function to apply by default.
62 | * @returns {Range}
63 | */
64 | set(min = this.min, max = this.max, curve = this.curve) {
65 | this.min = min;
66 | this.max = max;
67 | this.curve = curve;
68 |
69 | return this;
70 | }
71 |
72 | /**
73 | * Sets the min value for this range. This method mostly exists for chaining.
74 | *
75 | * @param {number} min - Min value for this range.
76 | * @returns {Range}
77 | */
78 | setMin(min) {
79 | this.min = min;
80 |
81 | return this;
82 | }
83 |
84 | /**
85 | * Sets the max value for this range. This method mostly exists for chaining.
86 | *
87 | * @param {number} max - Max value for this range.
88 | * @returns {Range}
89 | */
90 | setMax(max) {
91 | this.max = max;
92 |
93 | return this;
94 | }
95 |
96 | /**
97 | * Sets the default curve for this range. This method mostly exists for chaining.
98 | *
99 | * @param {function} curve - The curve function to apply by default.
100 | * @returns {Range}
101 | */
102 | setCurve(curve) {
103 | this.curve = curve;
104 |
105 | return this;
106 | }
107 |
108 | /**
109 | * Multiplies this range's min and max with the given scalar.
110 | * Values below 1.0 will make the range smaller.
111 | * Values over 1.0 will make it bigger.
112 | *
113 | * @param {number} s - The scalar to use.
114 | * @returns {Range}
115 | */
116 | scale(s) {
117 | this.min *= s;
118 | this.max *= s;
119 |
120 | return this;
121 | }
122 |
123 | /**
124 | * Expands this range by a given delta.
125 | * The delta is subtracted from this.min, and added to this.max.
126 | *
127 | * @param {Number} d - The delta to expand this range by.
128 | * @returns {Range}
129 | */
130 | expand(d) {
131 | this.min -= d;
132 | this.max += d;
133 |
134 | return this;
135 | }
136 |
137 | /**
138 | * Contracts this range by a given delta.
139 | * The delta is added to this.min, and subtracted from this.max.
140 | *
141 | * @param {number} d - The delta to contract this range by.
142 | * @returns {Range}
143 | */
144 | contract(d) {
145 | this.min += d;
146 | this.max -= d;
147 |
148 | return this;
149 | }
150 |
151 | /**
152 | * Shifts this range by a given delta.
153 | * The delta is added to this.min and this.max.
154 | *
155 | * @param {number} d - The delta to shift this range by.
156 | * @returns {Range}
157 | */
158 | shift(d) {
159 | this.min += d;
160 | this.max += d;
161 |
162 | return this;
163 | }
164 |
165 | /**
166 | * Copies another range's min, max, and curve into this one.
167 | * The curve is passed by reference.
168 | *
169 | * @param {Range} range - The range to copy from.
170 | * @returns {Range}
171 | */
172 | copy(range) {
173 | this.min = range.min;
174 | this.max = range.max;
175 | this.curve = range.curve;
176 |
177 | return this;
178 | }
179 |
180 | /**
181 | * Creates a shallow copy of this range.
182 | *
183 | * @returns {Range}
184 | */
185 | clone() {
186 | return new Range(this.min, this.max, this.curve);
187 | }
188 |
189 | /**
190 | * Checks if this range is empty.
191 | * A range is empty if its min === max.
192 | *
193 | * @returns {boolean}
194 | */
195 | isEmpty() {
196 | return this.min === this.max;
197 | }
198 |
199 | /**
200 | * Sets this range's min and max to 0.
201 | *
202 | * @returns {Range}
203 | */
204 | makeEmpty() {
205 | this.min = 0;
206 | this.max = 0;
207 |
208 | return this;
209 | }
210 |
211 | /**
212 | * @see ranger.length
213 | * @returns {number}
214 | */
215 | length() {
216 | return ranger.length(this.min, this.max);
217 | }
218 |
219 | /**
220 | * @see ranger.getPosition
221 | *
222 | * @param {number} x - The value to check.
223 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
224 | * @returns {number}
225 | */
226 | getPosition(x, curve = this.curve) {
227 | return ranger.getPosition(x, this.min, this.max, curve)
228 | }
229 |
230 | /**
231 | * @see ranger.getValue
232 | *
233 | * @param {number} x - The position to check. Should be between 0.0 and 1.0.
234 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
235 | * @returns {number}
236 | */
237 | getValue(x, curve = this.curve) {
238 | return ranger.getValue(x, this.min, this.max, curve);
239 | }
240 |
241 | /**
242 | * @see ranger.map
243 | *
244 | * @param {number} x - The value to map. Should be contained in sourceRange.
245 | * @param {Range} range - The range to map from.
246 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
247 | * @returns {Number}
248 | */
249 | map(x, range, curve = this.curve) {
250 | return ranger.map(x, range, this, curve);
251 | }
252 |
253 | /**
254 | * @see ranger.mapFloat
255 | *
256 | * @param {number} x - The value to map. Should be contained in the source range.
257 | * @param {number} min - Min value for the source range.
258 | * @param {number} max - Max value for the source range.
259 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
260 | * @returns {number}
261 | */
262 | mapFloat(x, min, max, curve = this.curve) {
263 | return ranger.mapFloat(x, min, max, this.min, this.max, curve);
264 | }
265 |
266 | /**
267 | * @see ranger.random
268 | *
269 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
270 | * @returns {number}
271 | */
272 | random(curve = this.curve) {
273 | return ranger.random(this.min, this.max, curve);
274 | }
275 |
276 | /**
277 | * @see ranger.randomInt
278 | *
279 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
280 | * @returns {number}
281 | */
282 | randomInt(curve = this.curve) {
283 | return ranger.randomInt(this.min, this.max, curve);
284 | }
285 |
286 | /**
287 | * Creates an array of values spread inside this range.
288 | * Values are inclusive, ie values[0] === this.min, and values[values.length - 1] === this.max.
289 | *
290 | * @param {number} count - Number of values (slices) to create. Should be >= 2.
291 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
292 | * @returns {number[]}
293 | */
294 | slice(count, curve = this.curve) {
295 | if (count < 2) return [this.min, this.max];
296 |
297 | const values = [];
298 |
299 | for (let i = 0; i < count; i++) {
300 | values[i] = this.getValue(i / (count - 1), curve);
301 | }
302 |
303 | return values;
304 | }
305 |
306 | /**
307 | * Divides this range into a number of smaller ranges.
308 | * Each range will copy this range's curve.
309 | *
310 | * todo: add support for margin and padding.
311 | *
312 | * @param {number} count - The number of sub-ranges to create.
313 | * @param {function} [curve] - The curve function to apply. Overrides the default set for this range.
314 | * @returns {Range[]}
315 | */
316 | divide(count, curve = this.curve) {
317 | if (count <= 1) return [this.clone()];
318 |
319 | const ranges = [];
320 |
321 | for (let i = 0; i < count; i++) {
322 | const min = this.getValue(i / count);
323 | const max = this.getValue((i + 1) / count);
324 |
325 | ranges[i] = new Range(min, max, this.curve);
326 | }
327 |
328 | return ranges;
329 | }
330 |
331 | /**
332 | * @see ranger.clamp
333 | *
334 | * @param {number} x - The value to check.
335 | * @returns {number}
336 | */
337 | clamp(x) {
338 | return ranger.clamp(x, this.min, this.max);
339 | }
340 |
341 | /**
342 | * @see ranger.wrap
343 | *
344 | * @param {number} x - The value to wrap.
345 | * @returns {number}
346 | */
347 | wrap(x) {
348 | return ranger.wrap(x, this.min, this.max);
349 | }
350 |
351 | /**
352 | * @see ranger.contains
353 | *
354 | * @param {number} x - The value to check.
355 | * @returns {boolean}
356 | */
357 | contains(x) {
358 | return ranger.contains(x, this.min, this.max);
359 | }
360 |
361 | /**
362 | * @see ranger.containsRange
363 | *
364 | * @param {Range} range - The range to check.
365 | * @returns {boolean}
366 | */
367 | containsRange(range) {
368 | return ranger.containsRange(range, this);
369 | }
370 | }
371 |
372 | export default Range;
373 |
--------------------------------------------------------------------------------
/src/main.cjs.js:
--------------------------------------------------------------------------------
1 | import ranger from './ranger';
2 | import Range from './Range';
3 |
4 | ranger.Range = Range;
5 |
6 | module.exports = ranger;
7 |
--------------------------------------------------------------------------------
/src/main.es.js:
--------------------------------------------------------------------------------
1 | import ranger from './ranger';
2 | import Range from './Range';
3 |
4 | export { Range };
5 | export default ranger;
6 |
--------------------------------------------------------------------------------
/src/main.umd.js:
--------------------------------------------------------------------------------
1 | import ranger from './ranger';
2 | import Range from './Range';
3 |
4 | ranger.Range = Range;
5 |
6 | export default ranger;
7 |
--------------------------------------------------------------------------------
/src/ranger.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @namespace
3 | */
4 | const ranger = {
5 |
6 | /**
7 | * Default curve, which is just a pass-through function.
8 | *
9 | * @param {number} x
10 | * @returns {number}
11 | */
12 | LINEAR: x => x,
13 |
14 | // measurements
15 |
16 | /**
17 | * Calculates the length of a range, or just (max - min). Used internally.
18 | * No validation is performed to check if the range is valid (max >= min).
19 | *
20 | * @param {number} min - Min value of the range.
21 | * @param {number} max - Max value of the range.
22 | * @returns {number} Length of the range.
23 | */
24 | length(min, max) {
25 | return max - min;
26 | },
27 |
28 | /**
29 | * A range is valid if max >= min.
30 | *
31 | * @param {number} min - Min value of the range.
32 | * @param {number} max - Max value of the range.
33 | * @returns {boolean}
34 | */
35 | isValid(min, max) {
36 | return max >= min;
37 | },
38 |
39 | /**
40 | * Returns the position of a value in the range, as a float 0.0 and 1.0.
41 | * The supplied value is not clamped. If it's out of bounds, the returned position will be proportionally out of bounds.
42 | *
43 | * @param {number} x - The value to check.
44 | * @param {number} min - Min value of the range.
45 | * @param {number} max - Max value of the range.
46 | * @param {function} [curve] - The curve function to apply.
47 | * @returns {number} - Position of the supplied value.
48 | */
49 | getPosition(x, min, max, curve = ranger.LINEAR) {
50 | return curve((x - min) / ranger.length(min, max));
51 | },
52 |
53 | /**
54 | * Returns the value at a given position in the rage.
55 | * The returned value is not clamped.
56 | *
57 | * @param {number} x - The position to check. Should be between 0.0 and 1.0.
58 | * @param {number} min - Min value of the range.
59 | * @param {number} max - Max value of the range.
60 | * @param {function} [curve] - The curve function to apply.
61 | * @returns {*} - Value at the supplied position.
62 | */
63 | getValue(x, min, max, curve = ranger.LINEAR) {
64 | return min + curve(x) * ranger.length(min, max);
65 | },
66 |
67 | // mapping
68 |
69 | /**
70 | * Maps a value from one range to a value from another range at the same position.
71 | * The source range is sampled linearly.
72 | * None of the values are clamped.
73 | *
74 | * @param {number} x - The value to map. Should be contained in sourceRange.
75 | * @param {Range} sourceRange - The range to map from.
76 | * @param {Range} targetRange - The range to map to.
77 | * @param {function} [curve] - The curve function to apply to the targetRange.
78 | * @returns {Number} - The mapped value, between targetRange.min and targetRange.max.
79 | */
80 | map(x, sourceRange, targetRange, curve = ranger.LINEAR) {
81 | return ranger.getValue(sourceRange.getPosition(x, ranger.LINEAR), targetRange.min, targetRange.max, curve);
82 | },
83 |
84 | /**
85 | * Same as map, but the source and target ranges should be provided as numbers.
86 | *
87 | * @see map
88 | *
89 | * @param {number} x - The value to map. Should be contained in the source range.
90 | * @param {number} sourceMin - Min value for the source range.
91 | * @param {number} sourceMax - Max value for the source range.
92 | * @param {number} targetMin - Min value for the target range.
93 | * @param {number} targetMax - Max value for the target range.
94 | * @param {function} [curve] - The curve function to apply to the target range.
95 | * @returns {number} - The mapped value, between targetMin and targetMax.
96 | */
97 | mapFloat(x, sourceMin, sourceMax, targetMin, targetMax, curve = ranger.LINEAR) {
98 | return ranger.getValue(ranger.getPosition(x, sourceMin, sourceMax, ranger.LINEAR), targetMin, targetMax, curve);
99 | },
100 |
101 | // random
102 |
103 | /**
104 | * Returns a random float between min and max.
105 | *
106 | * @param {number} min - Min value of the range.
107 | * @param {number} max - Max value of the range.
108 | * @param {function} [curve] - The curve function to apply.
109 | * @returns {number}
110 | */
111 | random(min, max, curve = ranger.LINEAR) {
112 | return min + curve(Math.random()) * ranger.length(min, max);
113 | },
114 |
115 | /**
116 | * Returns a random int between min and max.
117 | * The returned value is floored, so it will never equal max.
118 | *
119 | * @param {number} min - Min value of the range.
120 | * @param {number} max - Max value of the range.
121 | * @param {function} [curve] - The curve function to apply.
122 | * @returns {number}
123 | */
124 | randomInt(min, max, curve = ranger.LINEAR) {
125 | return ranger.random(min, max, curve) | 0;
126 | },
127 |
128 | // common operations
129 |
130 | /**
131 | * Returns min if x < min.
132 | * Returns max if x > max.
133 | * Returns x otherwise.
134 | *
135 | * @param {number} x - The value to check.
136 | * @param {number} min - Min value of the range.
137 | * @param {number} max - Max value of the range.
138 | * @returns {number} - The clamped value.
139 | */
140 | clamp(x, min, max) {
141 | return x < min ? min : x > max ? max : x;
142 | },
143 |
144 | /**
145 | * Wraps a value around the range.
146 | * This is similar to the modulo operator, but for arbitrary ranges.
147 | *
148 | * @param {number} x - The value to wrap.
149 | * @param {number} min - Min value of the range.
150 | * @param {number} max - Max value of the range.
151 | * @returns {number} - The wrapped value.
152 | */
153 | wrap(x, min, max) {
154 | const l = ranger.length(min, max);
155 |
156 | return (((x - min) % l) + l) % l + min;
157 | },
158 |
159 | /**
160 | * Checks if a value is inside the range.
161 | *
162 | * @param {number} x - The value to check.
163 | * @param {number} min - Min value of the range.
164 | * @param {number} max - Max value of the range.
165 | * @returns {boolean}
166 | */
167 | contains(x, min, max) {
168 | return x >= min && x <= max;
169 | },
170 |
171 | /**
172 | * Checks if the source range is contained in the target range.
173 | *
174 | * @param {Range} sourceRange - The range to check.
175 | * @param {Range} targetRange - The range the sourceRange will be compared to.
176 | * @returns {boolean}
177 | */
178 | containsRange(sourceRange, targetRange) {
179 | return ranger.contains(sourceRange.min, targetRange.min, targetRange.max) && ranger.contains(sourceRange.max, targetRange.min, targetRange.max);
180 | },
181 | };
182 |
183 | export default ranger;
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert');
2 | const ranger = require('../');
3 | const { Range } = require('../');
4 |
5 | console.log('TESTING RANGER');
6 |
7 | assert.equal(ranger.length(10, 20), 10);
8 |
9 | const range1 = new Range(0, 1);
10 |
11 | assert.equal(range1.isEmpty(), false);
12 |
13 | range1.makeEmpty();
14 |
15 | assert.equal(range1.isEmpty(), true);
16 |
17 | range1.set(20, 40);
18 |
19 | assert.equal(range1.length(), 20);
20 |
21 | range1.fromSizeAndCenter(40);
22 |
23 | assert.equal(range1.length(), 40);
24 | assert.equal(range1.min, -20);
25 | assert.equal(range1.max, 20);
26 |
27 | range1.fromSizeAndCenter(40, 40);
28 |
29 | assert.equal(range1.length(), 40);
30 | assert.equal(range1.min, 20);
31 | assert.equal(range1.max, 60);
32 |
33 | range1.set(10, 20).scale(0.5);
34 |
35 | assert.equal(range1.length(), 5);
36 | assert.equal(range1.min, 5);
37 | assert.equal(range1.max, 10);
38 |
39 | range1.set(6, 12).shift(-6);
40 |
41 | assert.equal(range1.length(), 6);
42 | assert.equal(range1.min, 0);
43 | assert.equal(range1.max, 6);
44 |
45 | range1.set(6, 12).expand(6);
46 |
47 | assert.equal(range1.length(), 18);
48 | assert.equal(range1.min, 0);
49 | assert.equal(range1.max, 18);
50 |
51 | range1.set(6, 12).contract(2);
52 |
53 | assert.equal(range1.length(), 2);
54 | assert.equal(range1.min, 8);
55 | assert.equal(range1.max, 10);
56 |
57 | range1.set(10, 20);
58 |
59 | assert.equal(range1.getValue(0.5), 15);
60 | assert.equal(range1.getValue(0), 10);
61 | assert.equal(range1.getPosition(15), 0.5);
62 | assert.equal(range1.getPosition(10), 0);
63 |
64 | range1.set(0, 100);
65 |
66 | assert.equal(range1.map(0.1, new Range(0, 1)), 10);
67 | assert.equal(range1.map(0.9, new Range(0, 1)), 90);
68 | assert.equal(range1.mapFloat(0.5, 0, 1), 50);
69 | assert.equal(range1.mapFloat(32, 0, 64), 50);
70 |
71 | range1.set(-10, 10);
72 |
73 | assert.equal(range1.contains(0), true);
74 | assert.equal(range1.contains(-11), false);
75 | assert.equal(range1.contains(11), false);
76 | assert.equal(range1.contains(10), true);
77 |
78 | assert.equal(range1.containsRange(new Range(-5, 5)), true);
79 | assert.equal(range1.containsRange(new Range(-11, 5)), false);
80 | assert.equal(range1.containsRange(new Range(-5, 11)), false);
81 |
82 | console.log('TEST COMPLETE!');
--------------------------------------------------------------------------------