@cowave-cli/utils 2.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/js.cjs ADDED
@@ -0,0 +1,1652 @@
1
+ 'use strict';
2
+
3
+ var axios = require('axios');
4
+
5
+ /*
6
+ * @Description: 字符串处理
7
+ * @Author: Zye
8
+ * @Date: 2024-03-11
9
+ */
10
+ /**
11
+ * @deprecated 这个函数已弃用,请使用 toHump() 代替
12
+ */
13
+ const pathToHump = (path, isGreatHump = true) => {
14
+ if (isGreatHump) {
15
+ path = path.replace(/^([a-z])/g, (_, p1) => p1.toUpperCase());
16
+ }
17
+ path = path.replace(/-([a-z])/g, (_, p1) => p1.toUpperCase());
18
+ return path;
19
+ };
20
+ /**
21
+ * 将连接符字符串转换为驼峰字符串
22
+ *
23
+ * @param strings 字符串(列表)
24
+ * @param hyphenType 连接符
25
+ * @param isGreatHump 是否为大驼峰
26
+ * @returns humpString
27
+ */
28
+ const toHump = (strings, hyphenType = '-', isGreatHump = false) => {
29
+ hyphenType = hyphenType || '-';
30
+ const results = (typeof strings === 'string' ? [strings] : strings).map(string => {
31
+ if (isGreatHump) {
32
+ string = string.replace(/^([a-z])/g, (_, p1) => p1.toUpperCase());
33
+ }
34
+ string = string.replace(new RegExp(hyphenType + '([a-z])', 'g'), (_, p1) => p1.toUpperCase());
35
+ return string;
36
+ });
37
+ return typeof strings === 'string' ? results[0] : results;
38
+ };
39
+ /**
40
+ * 将驼峰字符串转换为连接符字符串
41
+ *
42
+ * @param strings 字符串(列表)
43
+ * @param hyphenType 连接符
44
+ * @returns hyphenString
45
+ */
46
+ const toHyphen = (strings, hyphenType = '-') => {
47
+ const results = (typeof strings === 'string' ? [strings] : strings).map(string => {
48
+ string = string.replace(/^([A-Z])/g, (_, p1) => p1.toLowerCase());
49
+ string = string.replace(/([A-Z])/g, (_, p1) => hyphenType + p1.toLowerCase());
50
+ });
51
+ return typeof strings === 'string' ? results[0] : results;
52
+ };
53
+ // 字符串拼接
54
+ /**
55
+ * 将object转换成query参数
56
+ *
57
+ * @param keyValue 对象
58
+ * @returns query参数
59
+ */
60
+ const query = (keyValue) => {
61
+ return keyValue
62
+ ? '?' +
63
+ Object.keys(keyValue)
64
+ .filter((key) => keyValue[key] !== undefined && keyValue[key] !== null)
65
+ .map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(keyValue[key]))
66
+ .join('&')
67
+ : '';
68
+ };
69
+ /**
70
+ *
71
+ * 将url 传参转成data格式
72
+ *
73
+ * @param url (?********)
74
+ * @returns
75
+ */
76
+ const urlToData = (url) => {
77
+ const res = [];
78
+ const index = url.indexOf('?');
79
+ if (index === -1)
80
+ return [{ key: '', value: '' }];
81
+ url
82
+ .slice(index + 1)
83
+ .split('&')
84
+ .forEach((v) => {
85
+ res.push({
86
+ key: decodeURI(v.split('=')[0]),
87
+ value: decodeURI(v.split('=')[1]),
88
+ });
89
+ });
90
+ return [
91
+ ...res,
92
+ {
93
+ key: '',
94
+ value: '',
95
+ },
96
+ ];
97
+ };
98
+ /**
99
+ *
100
+ * 判断url格式
101
+ *
102
+ * @param url
103
+ * @returns
104
+ */
105
+ const isUrl = (path) => {
106
+ const reg = /^(https?:\/\/)([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)\/?(\?[^\s#]*)?$/;
107
+ return reg.test(path);
108
+ };
109
+
110
+ /*
111
+ * @Description: 时间处理
112
+ * @Author: Zye
113
+ * @Date: 2024-03-11
114
+ *
115
+ * setTime(time) time -> 服务器时间
116
+ * getTime() 返回服务器时间戳
117
+ *
118
+ */
119
+ // 服务器时间戳 减去 客户端时间戳
120
+ let _time_diff = 0;
121
+ // 同步时间
122
+ /**
123
+ * @param callback 获取服务器时间的回调函数,需要返回服务器时间
124
+ *
125
+ * @example
126
+ *
127
+ * setTime(async () => {
128
+ * return await getServerTime()
129
+ * })
130
+ *
131
+ */
132
+ const setTime = async (callback) => {
133
+ let _time_before, _time_after, _time_server;
134
+ _time_before = new Date().getTime();
135
+ _time_server = new Date(await callback()).getTime();
136
+ _time_after = new Date().getTime();
137
+ _time_diff = _time_diff
138
+ ? (_time_diff + _time_server - _time_before / 2 - _time_after / 2) / 2
139
+ : _time_server - _time_before / 2 - _time_after / 2;
140
+ };
141
+ // 获取本地时间戳
142
+ const _local_time = () => new Date().getTime();
143
+ /**
144
+ * 获取服务器时间戳
145
+ *
146
+ * @returns 服务器时间戳
147
+ */
148
+ const getTime = () => _local_time() + _time_diff;
149
+ /** 时间格式化 (参考dayjs)
150
+ *
151
+ * @param date 时间
152
+ * @param formatStr 格式如下
153
+ * @returns 格式化后的时间
154
+ *
155
+ * @formatStr
156
+ *
157
+ * |格式 |输出| 描述|
158
+ * |----|----|----|
159
+ * |YY| 18 |两位数年份|
160
+ * |YYYY| 2018 |四位数年份|
161
+ * |M| 1-12 |月份,从 1 开始|
162
+ * |MM |01-12 |月份,2 位数字|
163
+ * |D |1-31 |该月的哪一天|
164
+ * |DD| 01-31| 月份中的日期,2 位数字|
165
+ * |h| 0-23| 小时|
166
+ * |hh |00-23 |小时,2 位数字|
167
+ * |m| 0-59| 分钟|
168
+ * |mm |00-59 |分钟,2 位数字|
169
+ * |s |0-59| 秒钟|
170
+ * |ss |00-59 |秒钟,2 位数字|
171
+ */
172
+ const getDate = (date, formatStr) => {
173
+ if (!date)
174
+ date = getTime();
175
+ if (typeof date == 'string' || typeof date == 'number') {
176
+ date = new Date(date);
177
+ }
178
+ if (!formatStr)
179
+ return new Date(date);
180
+ let ret;
181
+ let d = {
182
+ year: date.getFullYear().toString(),
183
+ month: (date.getMonth() + 1).toString(),
184
+ day: date.getDate().toString(),
185
+ hour: date.getHours().toString(),
186
+ minutes: date.getMinutes().toString(),
187
+ seconds: date.getSeconds().toString(),
188
+ week: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'][date.getDay()],
189
+ };
190
+ let keys = {
191
+ 'YYYY': d.year,
192
+ 'YY': d.year.slice(2),
193
+ 'M+': d.month,
194
+ 'D+': d.day,
195
+ '[Hh]+': d.hour,
196
+ 'm+': d.minutes,
197
+ 's+': d.seconds,
198
+ '[Ww]+': d.week,
199
+ };
200
+ for (let key in keys) {
201
+ ret = new RegExp('(' + key + ')').exec(formatStr);
202
+ if (ret) {
203
+ formatStr = formatStr.replace(ret[1], keys[key].padStart(ret[1].length, '0'));
204
+ }
205
+ }
206
+ return formatStr;
207
+ };
208
+ /** 获取特殊时间节点
209
+ *
210
+ * @param {'weekstart' | 'weekend' | 'monthstart' | 'monthend' | 'yearstart' | 'yearend' | 'weekbefore' |'weekafter'| 'monthbefore' | 'yearbefore' | 'yearafter'} dateType 获取特殊时间
211
+ * @param {string } formatter 格式字符串或预设方案数字
212
+ *
213
+ * dateType:
214
+ *
215
+ * - weekstart —— 本周起始日期
216
+ *
217
+ * - weekend —— 本周结束日期
218
+ *
219
+ * - weekbefore —— 一周前日期
220
+ *
221
+ * - weekafter —— 一周后日期
222
+ *
223
+ * - monthstart —— 本月起始日期
224
+ *
225
+ * - monthend —— 本月结束日期
226
+ *
227
+ * - monthbefore—— 一个月前日期
228
+ *
229
+ * - yearstart —— 今年1月1日
230
+ *
231
+ * - yearend —— 今年12月31日
232
+ *
233
+ * - yearbefore —— 一年前日期
234
+ *
235
+ * - yearafter —— 一年后日期
236
+ *
237
+ * formatter: 参考 getDate
238
+ *
239
+ * @returns {Date | string}
240
+ */
241
+ const getSpecialDate = (dateType, date, formatter) => {
242
+ // 是否为开始时间
243
+ let isStart = true;
244
+ let time = new Date(date || getTime());
245
+ const setTime = () => {
246
+ if (isStart) {
247
+ time.setHours(0);
248
+ time.setMinutes(0);
249
+ time.setSeconds(0);
250
+ }
251
+ else {
252
+ time.setHours(23);
253
+ time.setMinutes(59);
254
+ time.setSeconds(59);
255
+ }
256
+ };
257
+ switch (dateType) {
258
+ case 'daybefore':
259
+ time = new Date(time.getTime() - 24 * 60 * 60 * 1000);
260
+ break;
261
+ case 'dayafter':
262
+ isStart = false;
263
+ time = new Date(time.getTime() + 24 * 60 * 60 * 1000);
264
+ break;
265
+ case 'weekstart':
266
+ time = new Date(time.getTime() - (time.getDay() - 1) * 24 * 60 * 60 * 1000);
267
+ break;
268
+ case 'weekstart7': //从周日开始
269
+ time = new Date(time.getTime() - time.getDay() * 24 * 60 * 60 * 1000);
270
+ break;
271
+ case 'weekend':
272
+ isStart = false;
273
+ time = new Date(time.getTime() + (7 - time.getDay()) * 24 * 60 * 60 * 1000);
274
+ break;
275
+ case 'weekbefore':
276
+ time = new Date(time.getTime() - 7 * 24 * 60 * 60 * 1000);
277
+ break;
278
+ case 'weekafter':
279
+ isStart = false;
280
+ time = (new Date(time.getTime() + 7 * 24 * 60 * 60 * 1000));
281
+ break;
282
+ case 'monthstart':
283
+ time = (new Date(time.getFullYear(), time.getMonth(), 1));
284
+ break;
285
+ case 'monthend':
286
+ isStart = false;
287
+ time = new Date(time.getFullYear(), time.getMonth() + 1, 0);
288
+ break;
289
+ case 'monthbefore':
290
+ time.setMonth(time.getMonth() - 1);
291
+ break;
292
+ case 'monthafter':
293
+ isStart = false;
294
+ time.setMonth(time.getMonth() + 1);
295
+ break;
296
+ case 'yearstart':
297
+ time.setMonth(0);
298
+ time.setDate(1);
299
+ break;
300
+ case 'yearend':
301
+ isStart = false;
302
+ time.setMonth(11);
303
+ time.setDate(31);
304
+ break;
305
+ case 'yearbefore':
306
+ time.setFullYear(time.getFullYear() - 1);
307
+ break;
308
+ case 'yearafter':
309
+ isStart = false;
310
+ time.setFullYear(time.getFullYear() + 1);
311
+ break;
312
+ }
313
+ setTime();
314
+ return getDate(time, formatter);
315
+ };
316
+
317
+ /*
318
+ * @Description: 对象处理
319
+ * @Author: Zye
320
+ * @Date: 2022-09-08
321
+ */
322
+ /**
323
+ * 从对象数组中获取匹配特定键值对的对象。
324
+ * @param objectArr 对象数组,每个对象至少包含一个键值对。
325
+ * @param keyName 需要匹配的键的名称。
326
+ * @param keyValue 需要匹配的键对应的值。可以是具体值或函数,如果为函数,则会将函数应用于数组中每个对象的键值进行匹配。
327
+ * @param foundKeyName 如果找到匹配的对象,从该对象中返回的键的名称。如果未指定,则返回整个对象。
328
+ * @returns 如果找到匹配的对象且指定了`foundKeyName`,则返回该键的值;如果未指定`foundKeyName`,则返回整个匹配的对象。如果没有找到匹配的对象,则返回一个空对象。
329
+ */
330
+ const getObject = (objectArr, keyName, keyValue, foundKeyName) => {
331
+ // 使用find方法查找数组中匹配的元素,如果未找到则返回一个空对象
332
+ let obj = objectArr.find((v) => (typeof keyValue == 'function' ? keyValue(v[keyName]) : v[keyName] == keyValue)) || new Object();
333
+ // 根据是否指定了foundKeyName返回不同的结果
334
+ return foundKeyName ? obj[foundKeyName] : obj;
335
+ };
336
+ /**
337
+ * 将源对象[src]的属性分配到目标对象[dist],并递归地合并它们的属性。
338
+ * 如果源对象的属性是一个对象(且不是数组),则会递归地将其属性分配到目标对象的相应属性中。
339
+ * 如果源对象的属性是数组或其他类型,则直接覆盖目标对象的相应属性。
340
+ *
341
+ * @param dist 目标对象,其属性将被源对象的属性覆盖或合并。
342
+ * @param src 源对象,其属性将覆盖或合并到目标对象中。
343
+ * @returns 返回合并后的目标对象。
344
+ * @template T 目标对象和源对象的类型,该类型必须是可深度写入的对象类型。
345
+ */
346
+ const assignObject = (dist, src) => {
347
+ const obj = {};
348
+ for (const [key, value] of Object.entries(dist)) {
349
+ if (typeof value !== 'object' || value === null) {
350
+ obj[key] = value;
351
+ }
352
+ }
353
+ for (const [key, value] of Object.entries(src)) {
354
+ if (!dist[key] || typeof value !== 'object' || value === null) {
355
+ obj[key] = value;
356
+ }
357
+ else {
358
+ // 如果源对象中的键值是可深度写入的对象,则递归调用assignObject函数进行合并
359
+ obj[key] = assignObject(dist[key], value);
360
+ }
361
+ }
362
+ return obj;
363
+ };
364
+ /**
365
+ * 此函数用来处理中间件向上透传方法 (仅用于Vue组件封装)
366
+ *
367
+ * @example
368
+ *
369
+ * com.vue
370
+ * !暴露form表单的所有方法,table表格的所有方法,以及onClick
371
+ * defineExpose( { onClick: () => { console.log('click') } }, formRef,tableRef)
372
+ * !父组件调用
373
+ * com.value.change() //调用表单change方法
374
+ * com.value.onClick() //调用onClick方法
375
+ *
376
+ * @param callback 回调函数,传onMounted
377
+ * @param option 默认暴露对象
378
+ * @param refs 要暴露的组件
379
+ * @returns 暴露对象
380
+ */
381
+ const expose = (option, ...refs) => {
382
+ return new Proxy(option, {
383
+ get(_, prop) {
384
+ for (const ref of refs) {
385
+ if (ref.value && prop in ref.value) {
386
+ return ref.value?.[prop];
387
+ }
388
+ }
389
+ },
390
+ has(_, prop) {
391
+ for (const ref of refs) {
392
+ if (ref.value && prop in ref.value) {
393
+ return true;
394
+ }
395
+ }
396
+ return false;
397
+ }
398
+ });
399
+ };
400
+ /**
401
+ * 此函数用来处理中间件向上透传事件 (仅用于Vue组件封装)
402
+ *
403
+ * @param emit emit
404
+ * @param emitStrs
405
+ * @returns
406
+ */
407
+ const on = (emit, emitStrs) => {
408
+ const emits = {};
409
+ if (!Array.isArray(emitStrs)) {
410
+ emitStrs = Object.keys(emitStrs);
411
+ }
412
+ emitStrs.forEach(key => {
413
+ emits[key] = (...args) => {
414
+ emit(key, ...args);
415
+ };
416
+ });
417
+ return emits;
418
+ };
419
+
420
+ /*
421
+ * @Description: 逻辑处理
422
+ * @Author: Zye
423
+ * @Date: 2022-11-21
424
+ */
425
+ const setValue = (condition, value, def = undefined) => {
426
+ return condition ? value : def;
427
+ };
428
+
429
+ /*
430
+ * @Description: 全屏
431
+ * @Author: Zye
432
+ * @Date: 2022-09-29
433
+ */
434
+ /**
435
+ * 是否全屏
436
+ *
437
+ * @returns boolean
438
+ */
439
+ function isFullscreen() {
440
+ return !!(document.fullscreenElement ||
441
+ document.mozFullScreenElement ||
442
+ document.webkitFullscreenElement ||
443
+ document.msFullscreenElement);
444
+ }
445
+ /**
446
+ * 进入全屏
447
+ *
448
+ * @param { HTMLElement } el 需要进入全屏的元素
449
+ *
450
+ */
451
+ function inFullscreen(el = document.querySelector('body')) {
452
+ if (el.requestFullscreen) {
453
+ el.requestFullscreen();
454
+ }
455
+ else if (el.mozRequestFullScreen) {
456
+ // Firefox
457
+ el.mozRequestFullScreen();
458
+ }
459
+ else if (el.webkitRequestFullscreen) {
460
+ // Chrome, Safari, Opera
461
+ el.webkitRequestFullscreen();
462
+ }
463
+ else if (el.msRequestFullscreen) {
464
+ // IE/Edge
465
+ el.msRequestFullscreen();
466
+ }
467
+ }
468
+ /**
469
+ * 退出全屏
470
+ *
471
+ */
472
+ function exitFullscreen() {
473
+ if (document.exitFullscreen) {
474
+ document.exitFullscreen();
475
+ }
476
+ else if (document.mozCancelFullScreen) {
477
+ // Firefox
478
+ document.mozCancelFullScreen();
479
+ }
480
+ else if (document.webkitExitFullscreen) {
481
+ // Chrome, Safari, Opera
482
+ document.webkitExitFullscreen();
483
+ }
484
+ else if (document.msExitFullscreen) {
485
+ // IE/Edge
486
+ document.msExitFullscreen();
487
+ }
488
+ }
489
+ /**
490
+ * 切换全屏显示
491
+ *
492
+ * @param { HTMLElement } el 需要进入全屏的元素
493
+ */
494
+ function fullscreen(el = document.querySelector('body')) {
495
+ isFullscreen() ? exitFullscreen() : inFullscreen(el);
496
+ }
497
+
498
+ /*
499
+ * @Description: 数字处理
500
+ * @Author: Zye
501
+ * @Date: 2021-11-04
502
+ */
503
+ /**
504
+ * 取近似值,取整
505
+ *
506
+ * @param num 数字
507
+ * @param factor 近似因子
508
+ * @returns 数字
509
+ *
510
+ * @ep
511
+ *
512
+ * Num(13,5) // 15
513
+ *
514
+ * Num(1.264,0.01) //1.26
515
+ *
516
+ */
517
+ const Num = (num, factor) => {
518
+ if (!num)
519
+ return 0;
520
+ if (typeof num == 'string') {
521
+ num = parseFloat(num);
522
+ }
523
+ return factor ? Math.round(num / factor) * factor : num;
524
+ };
525
+
526
+ /**
527
+ * 浏览器引擎判断
528
+ *
529
+ * Gecke 火狐(Firefox)
530
+ * Blink (谷歌, 欧朋)
531
+ * WebKit (苹果,老版谷歌)
532
+ * Unknown (其他)
533
+ */
534
+ function browserEngine() {
535
+ var userAgent = navigator.userAgent;
536
+ var isGecko = /Gecko\/\d+\.\d+/i.test(userAgent) && !/like Gecko/.test(userAgent);
537
+ var isBlink = /Chrome\/[\d.]+/.test(userAgent) && /Safari\/[\d.]+/.test(userAgent);
538
+ var isWebKit = /AppleWebKit\/[\d.]+/.test(userAgent) && !isBlink;
539
+ if (isGecko) {
540
+ return 'Gecko';
541
+ }
542
+ else if (isBlink) {
543
+ return 'Blink';
544
+ }
545
+ else if (isWebKit) {
546
+ return 'WebKit';
547
+ }
548
+ else {
549
+ return 'Unknown';
550
+ }
551
+ }
552
+
553
+ /**
554
+ *
555
+ * @param px 像素或者数字
556
+ * @returns
557
+ */
558
+ function addPx(px) {
559
+ return typeof px === 'number' ? px + 'px' : px;
560
+ }
561
+
562
+ /**
563
+ *
564
+ * @param config 配置 (如配置 baseUrl、timeout 等 )
565
+ * @param request 请求拦截
566
+ * @param response 响应成功拦截
567
+ * @param reject 响应错误拦截 (正常情况用不到)
568
+ * @returns
569
+ */
570
+ const createHttp = ({ config = {}, request = config => config, response = data => data, reject = error => Promise.reject(error), }) => {
571
+ // 创建Axios
572
+ const axiosClone = axios.create({ timeout: 1000 * 60 * 5, ...(config || {}) });
573
+ // 请求
574
+ axiosClone.interceptors.request.use((config) => {
575
+ return request(config);
576
+ });
577
+ // 响应
578
+ axiosClone.interceptors.response.use((res) => {
579
+ // 处理文件
580
+ const contentType = res.headers['content-type'];
581
+ if ((contentType && contentType.includes('application/octet-stream')) || contentType.includes('file'))
582
+ return res.data;
583
+ // 处理数据
584
+ return response(res.data, res);
585
+ }, (error) => {
586
+ return Promise.reject(reject(error));
587
+ });
588
+ // 重写http
589
+ const http = (config) => {
590
+ return axiosClone(config);
591
+ };
592
+ const get = (method) => {
593
+ return http[method] = (url, params = {}, config = {}) => {
594
+ return axiosClone[method](url, {
595
+ ...config,
596
+ params,
597
+ });
598
+ };
599
+ };
600
+ const post = (method) => {
601
+ return http[method] = (url, data = {}, config = {}) => {
602
+ return axiosClone[method](url, data, config);
603
+ };
604
+ };
605
+ http.get = get('get');
606
+ http.delete = get('delete');
607
+ http.head = get('head');
608
+ http.post = post('post');
609
+ http.put = post('put');
610
+ http.patch = post('patch');
611
+ return http;
612
+ };
613
+
614
+ let trimLeft = /^\s+/;
615
+ let trimRight = /\s+$/;
616
+ let mathRound = Math.round;
617
+ let mathMin = Math.min;
618
+ let mathMax = Math.max;
619
+ let mathRandom = Math.random;
620
+ class TinyColor {
621
+ matchers;
622
+ names;
623
+ _originalInput;
624
+ _r;
625
+ _g;
626
+ _b;
627
+ _a;
628
+ _roundA;
629
+ _format;
630
+ _gradientType;
631
+ _ok;
632
+ isDark;
633
+ isLight;
634
+ isValid;
635
+ constructor(color, opts) {
636
+ // If input is already a tinycolor, return itself
637
+ if (color instanceof TinyColor) {
638
+ return color;
639
+ }
640
+ this.init(color, opts);
641
+ }
642
+ init(color, opts) {
643
+ this.matchers = this.initMatchers();
644
+ this.names = TinyColor.initNames();
645
+ const rgb = this.inputToRGB(color);
646
+ this._originalInput = typeof color !== 'undefined' ? color : '';
647
+ this._r = rgb.r;
648
+ this._g = rgb.g;
649
+ this._b = rgb.b;
650
+ this._a = rgb.a;
651
+ this._roundA = mathRound(100 * this._a) / 100;
652
+ // this._format = typeof opts !== 'undefined' && typeof opts.format !== 'undefined' ? opts.format : rgb.format || ''
653
+ this._format = opts?.format || rgb?.format || '';
654
+ // this._gradientType = typeof opts !== 'undefined' && typeof opts.gradientType !== 'undefined' ? opts.gradientType : ''
655
+ this._gradientType = opts?.gradientType || '';
656
+ // Don't let the range of [0,255] come back in [0,1].
657
+ // Potentially lose a little bit of precision here, but will fix issues where
658
+ // .5 gets interpreted as half of the total, instead of half of 1
659
+ // If it was supposed to be 128, this was already taken care of by `inputToRgb`
660
+ if (this._r < 1) {
661
+ this._r = mathRound(this._r);
662
+ }
663
+ if (this._g < 1) {
664
+ this._g = mathRound(this._g);
665
+ }
666
+ if (this._b < 1) {
667
+ this._b = mathRound(this._b);
668
+ }
669
+ this._ok = rgb.ok;
670
+ this.initAttr();
671
+ }
672
+ initAttr() {
673
+ this.isDark = this.getBrightness() < 128;
674
+ this.isLight = !this.isDark;
675
+ this.isValid = this._ok;
676
+ }
677
+ static initNames() {
678
+ // Big List of Colors
679
+ // ------------------
680
+ // <http://www.w3.org/TR/css3-color/#svg-color>
681
+ return {
682
+ aliceblue: 'f0f8ff',
683
+ antiquewhite: 'faebd7',
684
+ aqua: '0ff',
685
+ aquamarine: '7fffd4',
686
+ azure: 'f0ffff',
687
+ beige: 'f5f5dc',
688
+ bisque: 'ffe4c4',
689
+ black: '000',
690
+ blanchedalmond: 'ffebcd',
691
+ blue: '00f',
692
+ blueviolet: '8a2be2',
693
+ brown: 'a52a2a',
694
+ burlywood: 'deb887',
695
+ burntsienna: 'ea7e5d',
696
+ cadetblue: '5f9ea0',
697
+ chartreuse: '7fff00',
698
+ chocolate: 'd2691e',
699
+ coral: 'ff7f50',
700
+ cornflowerblue: '6495ed',
701
+ cornsilk: 'fff8dc',
702
+ crimson: 'dc143c',
703
+ cyan: '0ff',
704
+ darkblue: '00008b',
705
+ darkcyan: '008b8b',
706
+ darkgoldenrod: 'b8860b',
707
+ darkgray: 'a9a9a9',
708
+ darkgreen: '006400',
709
+ darkgrey: 'a9a9a9',
710
+ darkkhaki: 'bdb76b',
711
+ darkmagenta: '8b008b',
712
+ darkolivegreen: '556b2f',
713
+ darkorange: 'ff8c00',
714
+ darkorchid: '9932cc',
715
+ darkred: '8b0000',
716
+ darksalmon: 'e9967a',
717
+ darkseagreen: '8fbc8f',
718
+ darkslateblue: '483d8b',
719
+ darkslategray: '2f4f4f',
720
+ darkslategrey: '2f4f4f',
721
+ darkturquoise: '00ced1',
722
+ darkviolet: '9400d3',
723
+ deeppink: 'ff1493',
724
+ deepskyblue: '00bfff',
725
+ dimgray: '696969',
726
+ dimgrey: '696969',
727
+ dodgerblue: '1e90ff',
728
+ firebrick: 'b22222',
729
+ floralwhite: 'fffaf0',
730
+ forestgreen: '228b22',
731
+ fuchsia: 'f0f',
732
+ gainsboro: 'dcdcdc',
733
+ ghostwhite: 'f8f8ff',
734
+ gold: 'ffd700',
735
+ goldenrod: 'daa520',
736
+ gray: '808080',
737
+ green: '008000',
738
+ greenyellow: 'adff2f',
739
+ grey: '808080',
740
+ honeydew: 'f0fff0',
741
+ hotpink: 'ff69b4',
742
+ indianred: 'cd5c5c',
743
+ indigo: '4b0082',
744
+ ivory: 'fffff0',
745
+ khaki: 'f0e68c',
746
+ lavender: 'e6e6fa',
747
+ lavenderblush: 'fff0f5',
748
+ lawngreen: '7cfc00',
749
+ lemonchiffon: 'fffacd',
750
+ lightblue: 'add8e6',
751
+ lightcoral: 'f08080',
752
+ lightcyan: 'e0ffff',
753
+ lightgoldenrodyellow: 'fafad2',
754
+ lightgray: 'd3d3d3',
755
+ lightgreen: '90ee90',
756
+ lightgrey: 'd3d3d3',
757
+ lightpink: 'ffb6c1',
758
+ lightsalmon: 'ffa07a',
759
+ lightseagreen: '20b2aa',
760
+ lightskyblue: '87cefa',
761
+ lightslategray: '789',
762
+ lightslategrey: '789',
763
+ lightsteelblue: 'b0c4de',
764
+ lightyellow: 'ffffe0',
765
+ lime: '0f0',
766
+ limegreen: '32cd32',
767
+ linen: 'faf0e6',
768
+ magenta: 'f0f',
769
+ maroon: '800000',
770
+ mediumaquamarine: '66cdaa',
771
+ mediumblue: '0000cd',
772
+ mediumorchid: 'ba55d3',
773
+ mediumpurple: '9370db',
774
+ mediumseagreen: '3cb371',
775
+ mediumslateblue: '7b68ee',
776
+ mediumspringgreen: '00fa9a',
777
+ mediumturquoise: '48d1cc',
778
+ mediumvioletred: 'c71585',
779
+ midnightblue: '191970',
780
+ mintcream: 'f5fffa',
781
+ mistyrose: 'ffe4e1',
782
+ moccasin: 'ffe4b5',
783
+ navajowhite: 'ffdead',
784
+ navy: '000080',
785
+ oldlace: 'fdf5e6',
786
+ olive: '808000',
787
+ olivedrab: '6b8e23',
788
+ orange: 'ffa500',
789
+ orangered: 'ff4500',
790
+ orchid: 'da70d6',
791
+ palegoldenrod: 'eee8aa',
792
+ palegreen: '98fb98',
793
+ paleturquoise: 'afeeee',
794
+ palevioletred: 'db7093',
795
+ papayawhip: 'ffefd5',
796
+ peachpuff: 'ffdab9',
797
+ peru: 'cd853f',
798
+ pink: 'ffc0cb',
799
+ plum: 'dda0dd',
800
+ powderblue: 'b0e0e6',
801
+ purple: '800080',
802
+ rebeccapurple: '663399',
803
+ red: 'f00',
804
+ rosybrown: 'bc8f8f',
805
+ royalblue: '4169e1',
806
+ saddlebrown: '8b4513',
807
+ salmon: 'fa8072',
808
+ sandybrown: 'f4a460',
809
+ seagreen: '2e8b57',
810
+ seashell: 'fff5ee',
811
+ sienna: 'a0522d',
812
+ silver: 'c0c0c0',
813
+ skyblue: '87ceeb',
814
+ slateblue: '6a5acd',
815
+ slategray: '708090',
816
+ slategrey: '708090',
817
+ snow: 'fffafa',
818
+ springgreen: '00ff7f',
819
+ steelblue: '4682b4',
820
+ tan: 'd2b48c',
821
+ teal: '008080',
822
+ thistle: 'd8bfd8',
823
+ tomato: 'ff6347',
824
+ turquoise: '40e0d0',
825
+ violet: 'ee82ee',
826
+ wheat: 'f5deb3',
827
+ white: 'fff',
828
+ whitesmoke: 'f5f5f5',
829
+ yellow: 'ff0',
830
+ yellowgreen: '9acd32',
831
+ };
832
+ }
833
+ initMatchers() {
834
+ // <http://www.w3.org/TR/css3-values/#integers>
835
+ const CSS_INTEGER = '[-\\+]?\\d+%?';
836
+ // <http://www.w3.org/TR/css3-values/#number-value>
837
+ const CSS_NUMBER = '[-\\+]?\\d*\\.\\d+%?';
838
+ // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
839
+ const CSS_UNIT = '(?:' + CSS_NUMBER + ')|(?:' + CSS_INTEGER + ')';
840
+ // Actual matching.
841
+ // Parentheses and commas are optional, but not required.
842
+ // Whitespace can take the place of commas or opening paren
843
+ const PERMISSIVE_MATCH3 = '[\\s|\\(]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')\\s*\\)?';
844
+ const PERMISSIVE_MATCH4 = '[\\s|\\(]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')\\s*\\)?';
845
+ return {
846
+ CSS_UNIT: new RegExp(CSS_UNIT),
847
+ rgb: new RegExp('rgb' + PERMISSIVE_MATCH3),
848
+ rgba: new RegExp('rgba' + PERMISSIVE_MATCH4),
849
+ hsl: new RegExp('hsl' + PERMISSIVE_MATCH3),
850
+ hsla: new RegExp('hsla' + PERMISSIVE_MATCH4),
851
+ hsv: new RegExp('hsv' + PERMISSIVE_MATCH3),
852
+ hsva: new RegExp('hsva' + PERMISSIVE_MATCH4),
853
+ hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
854
+ hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
855
+ hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
856
+ hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
857
+ };
858
+ }
859
+ getBrightness() {
860
+ //http://www.w3.org/TR/AERT#color-contrast
861
+ const rgb = this.toRgb();
862
+ return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
863
+ }
864
+ toRgb() {
865
+ return {
866
+ r: mathRound(this._r),
867
+ g: mathRound(this._g),
868
+ b: mathRound(this._b),
869
+ a: this._a,
870
+ };
871
+ }
872
+ static getNames() {
873
+ return this.initNames();
874
+ }
875
+ getOriginalInput() {
876
+ return this._originalInput;
877
+ }
878
+ getFormat() {
879
+ return this._format;
880
+ }
881
+ getAlpha() {
882
+ return this._a;
883
+ }
884
+ getLuminance() {
885
+ //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
886
+ const rgb = this.toRgb();
887
+ let RsRGB, GsRGB, BsRGB, R, G, B;
888
+ RsRGB = rgb.r / 255;
889
+ GsRGB = rgb.g / 255;
890
+ BsRGB = rgb.b / 255;
891
+ if (RsRGB <= 0.03928) {
892
+ R = RsRGB / 12.92;
893
+ }
894
+ else {
895
+ R = Math.pow((RsRGB + 0.055) / 1.055, 2.4);
896
+ }
897
+ if (GsRGB <= 0.03928) {
898
+ G = GsRGB / 12.92;
899
+ }
900
+ else {
901
+ G = Math.pow((GsRGB + 0.055) / 1.055, 2.4);
902
+ }
903
+ if (BsRGB <= 0.03928) {
904
+ B = BsRGB / 12.92;
905
+ }
906
+ else {
907
+ B = Math.pow((BsRGB + 0.055) / 1.055, 2.4);
908
+ }
909
+ return 0.2126 * R + 0.7152 * G + 0.0722 * B;
910
+ }
911
+ setAlpha(value) {
912
+ this._a = this.boundAlpha(value);
913
+ this._roundA = mathRound(100 * this._a) / 100;
914
+ return this;
915
+ }
916
+ toHsv() {
917
+ let hsv = this.rgbToHsv(this._r, this._g, this._b);
918
+ return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
919
+ }
920
+ toHsvString() {
921
+ let hsv = this.rgbToHsv(this._r, this._g, this._b);
922
+ let h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
923
+ return this._a == 1 ? 'hsv(' + h + ', ' + s + '%, ' + v + '%)' : 'hsva(' + h + ', ' + s + '%, ' + v + '%, ' + this._roundA + ')';
924
+ }
925
+ toHsl() {
926
+ let hsl = this.rgbToHsl(this._r, this._g, this._b);
927
+ return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
928
+ }
929
+ toHslString() {
930
+ let hsl = this.rgbToHsl(this._r, this._g, this._b);
931
+ let h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
932
+ return this._a == 1 ? 'hsl(' + h + ', ' + s + '%, ' + l + '%)' : 'hsla(' + h + ', ' + s + '%, ' + l + '%, ' + this._roundA + ')';
933
+ }
934
+ toHex(allow3Char) {
935
+ return this.rgbToHex(this._r, this._g, this._b, allow3Char);
936
+ }
937
+ toHexString(allow3Char) {
938
+ return '#' + this.toHex(allow3Char);
939
+ }
940
+ toHex8(allow4Char) {
941
+ return this.rgbaToHex(this._r, this._g, this._b, this._a, allow4Char);
942
+ }
943
+ toHex8String(allow4Char) {
944
+ return '#' + this.toHex8(allow4Char);
945
+ }
946
+ toRgbString() {
947
+ return this._a == 1
948
+ ? 'rgb(' + mathRound(this._r) + ', ' + mathRound(this._g) + ', ' + mathRound(this._b) + ')'
949
+ : 'rgba(' + mathRound(this._r) + ', ' + mathRound(this._g) + ', ' + mathRound(this._b) + ', ' + this._roundA + ')';
950
+ }
951
+ toPercentageRgb() {
952
+ return {
953
+ r: mathRound(this.bound01(this._r, 255) * 100) + '%',
954
+ g: mathRound(this.bound01(this._g, 255) * 100) + '%',
955
+ b: mathRound(this.bound01(this._b, 255) * 100) + '%',
956
+ a: this._a,
957
+ };
958
+ }
959
+ toPercentageRgbString() {
960
+ return this._a == 1
961
+ ? 'rgb(' +
962
+ mathRound(this.bound01(this._r, 255) * 100) +
963
+ '%, ' +
964
+ mathRound(this.bound01(this._g, 255) * 100) +
965
+ '%, ' +
966
+ mathRound(this.bound01(this._b, 255) * 100) +
967
+ '%)'
968
+ : 'rgba(' +
969
+ mathRound(this.bound01(this._r, 255) * 100) +
970
+ '%, ' +
971
+ mathRound(this.bound01(this._g, 255) * 100) +
972
+ '%, ' +
973
+ mathRound(this.bound01(this._b, 255) * 100) +
974
+ '%, ' +
975
+ this._roundA +
976
+ ')';
977
+ }
978
+ toName() {
979
+ if (this._a === 0) {
980
+ return 'transparent';
981
+ }
982
+ if (this._a < 1) {
983
+ return false;
984
+ }
985
+ return this._flip()[this.rgbToHex(this._r, this._g, this._b, true)] || false;
986
+ }
987
+ toFilter(secondColor) {
988
+ let hex8String = '#' + this.rgbaToArgbHex(this._r, this._g, this._b, this._a);
989
+ let secondHex8String = hex8String;
990
+ let gradientType = this._gradientType ? 'GradientType = 1, ' : '';
991
+ if (secondColor) {
992
+ const tinyColorObj = new TinyColor(secondColor);
993
+ secondHex8String = '#' + this.rgbaToArgbHex(tinyColorObj._r, tinyColorObj._g, tinyColorObj._b, tinyColorObj._a);
994
+ }
995
+ return ('progid:DXImageTransform.Microsoft.gradient(' +
996
+ gradientType +
997
+ 'startColorstr=' +
998
+ hex8String +
999
+ ',endColorstr=' +
1000
+ secondHex8String +
1001
+ ')');
1002
+ }
1003
+ toString(format) {
1004
+ let formatSet = !!format;
1005
+ format = format || this._format;
1006
+ let formattedString = '';
1007
+ let hasAlpha = this._a < 1 && this._a >= 0;
1008
+ let needsAlphaFormat = !formatSet &&
1009
+ hasAlpha &&
1010
+ (format === 'hex' || format === 'hex6' || format === 'hex3' || format === 'hex4' || format === 'hex8' || format === 'name');
1011
+ if (needsAlphaFormat) {
1012
+ if (format === 'name' && this._a === 0) {
1013
+ return this.toName();
1014
+ }
1015
+ return this.toRgbString();
1016
+ }
1017
+ if (format === 'rgb') {
1018
+ formattedString = this.toRgbString();
1019
+ }
1020
+ if (format === 'prgb') {
1021
+ formattedString = this.toPercentageRgbString();
1022
+ }
1023
+ if (format === 'hex' || format === 'hex6') {
1024
+ formattedString = this.toHexString();
1025
+ }
1026
+ if (format === 'hex3') {
1027
+ formattedString = this.toHexString(true);
1028
+ }
1029
+ if (format === 'hex4') {
1030
+ formattedString = this.toHex8String(true);
1031
+ }
1032
+ if (format === 'hex8') {
1033
+ formattedString = this.toHex8String();
1034
+ }
1035
+ if (format === 'name') {
1036
+ formattedString = this.toName();
1037
+ }
1038
+ if (format === 'hsl') {
1039
+ formattedString = this.toHslString();
1040
+ }
1041
+ if (format === 'hsv') {
1042
+ formattedString = this.toHsvString();
1043
+ }
1044
+ return formattedString || this.toHexString();
1045
+ }
1046
+ clone() {
1047
+ return new TinyColor(this.toString());
1048
+ }
1049
+ _applyModification(fn, args) {
1050
+ let color = fn.apply(null, [this].concat([].slice.call(args)));
1051
+ this._r = color._r;
1052
+ this._g = color._g;
1053
+ this._b = color._b;
1054
+ this.setAlpha(color._a);
1055
+ return this;
1056
+ }
1057
+ _lighten(color, amount) {
1058
+ amount = amount === 0 ? 0 : amount || 10;
1059
+ let hsl = new TinyColor(color).toHsl();
1060
+ hsl.l += amount / 100;
1061
+ hsl.l = color.clamp01(hsl.l);
1062
+ return new TinyColor(hsl);
1063
+ }
1064
+ lighten(...args) {
1065
+ return this._applyModification(this._lighten, args);
1066
+ }
1067
+ _brighten(color, amount) {
1068
+ amount = amount === 0 ? 0 : amount || 10;
1069
+ let rgb = new TinyColor(color).toRgb();
1070
+ rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * -(amount / 100))));
1071
+ rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * -(amount / 100))));
1072
+ rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * -(amount / 100))));
1073
+ return new TinyColor(rgb);
1074
+ }
1075
+ brighten(...args) {
1076
+ return this._applyModification(this._brighten, args);
1077
+ }
1078
+ _darken(color, amount) {
1079
+ amount = amount === 0 ? 0 : amount || 10;
1080
+ let hsl = new TinyColor(color).toHsl();
1081
+ hsl.l -= amount / 100;
1082
+ hsl.l = color.clamp01(hsl.l);
1083
+ return new TinyColor(hsl);
1084
+ }
1085
+ darken(...args) {
1086
+ return this._applyModification(this._darken, args);
1087
+ }
1088
+ _desaturate(color, amount) {
1089
+ amount = amount === 0 ? 0 : amount || 10;
1090
+ let hsl = new TinyColor(color).toHsl();
1091
+ hsl.s -= amount / 100;
1092
+ hsl.s = color.clamp01(hsl.s);
1093
+ return new TinyColor(hsl);
1094
+ }
1095
+ desaturate(...args) {
1096
+ return this._applyModification(this._desaturate, args);
1097
+ }
1098
+ _saturate(color, amount) {
1099
+ amount = amount === 0 ? 0 : amount || 10;
1100
+ let hsl = new TinyColor(color).toHsl();
1101
+ hsl.s += amount / 100;
1102
+ hsl.s = color.clamp01(hsl.s);
1103
+ return new TinyColor(hsl);
1104
+ }
1105
+ saturate(...args) {
1106
+ return this._applyModification(this._saturate, args);
1107
+ }
1108
+ _greyscale(color) {
1109
+ return new TinyColor(color).desaturate(100);
1110
+ }
1111
+ greyscale(...args) {
1112
+ return this._applyModification(this._greyscale, args);
1113
+ }
1114
+ _spin(color, amount) {
1115
+ let hsl = new TinyColor(color).toHsl();
1116
+ let hue = (hsl.h + amount) % 360;
1117
+ hsl.h = hue < 0 ? 360 + hue : hue;
1118
+ return new TinyColor(hsl);
1119
+ }
1120
+ spin(...args) {
1121
+ return this._applyModification(this._spin, args);
1122
+ }
1123
+ _applyCombination(fn, args) {
1124
+ return fn.apply(null, [this].concat([].slice.call(args)));
1125
+ }
1126
+ _analogous(color, results, slices) {
1127
+ results = results || 6;
1128
+ slices = slices || 30;
1129
+ let hsl = new TinyColor(color).toHsl();
1130
+ let part = 360 / slices;
1131
+ let ret = [new TinyColor(color)];
1132
+ for (hsl.h = (hsl.h - ((part * results) >> 1) + 720) % 360; --results;) {
1133
+ hsl.h = (hsl.h + part) % 360;
1134
+ ret.push(new TinyColor(hsl));
1135
+ }
1136
+ return ret;
1137
+ }
1138
+ analogous(...args) {
1139
+ return this._applyCombination(this._analogous, args);
1140
+ }
1141
+ _complement(color) {
1142
+ let hsl = new TinyColor(color).toHsl();
1143
+ hsl.h = (hsl.h + 180) % 360;
1144
+ return new TinyColor(hsl);
1145
+ }
1146
+ complement(...args) {
1147
+ return this._applyCombination(this._complement, args);
1148
+ }
1149
+ _monochromatic(color, results) {
1150
+ results = results || 6;
1151
+ let hsv = new TinyColor(color).toHsv();
1152
+ let h = hsv.h, s = hsv.s, v = hsv.v;
1153
+ let ret = [];
1154
+ let modification = 1 / results;
1155
+ while (results--) {
1156
+ ret.push(new TinyColor({ h: h, s: s, v: v }));
1157
+ v = (v + modification) % 1;
1158
+ }
1159
+ return ret;
1160
+ }
1161
+ monochromatic(...args) {
1162
+ return this._applyCombination(this._monochromatic, args);
1163
+ }
1164
+ _splitcomplement(color) {
1165
+ let hsl = new TinyColor(color).toHsl();
1166
+ let h = hsl.h;
1167
+ return [
1168
+ new TinyColor(color),
1169
+ new TinyColor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l }),
1170
+ new TinyColor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l }),
1171
+ ];
1172
+ }
1173
+ splitcomplement(...args) {
1174
+ return this._applyCombination(this._splitcomplement, args);
1175
+ }
1176
+ _triad(color) {
1177
+ let hsl = new TinyColor(color).toHsl();
1178
+ let h = hsl.h;
1179
+ return [
1180
+ new TinyColor(color),
1181
+ new TinyColor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
1182
+ new TinyColor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }),
1183
+ ];
1184
+ }
1185
+ triad(...args) {
1186
+ return this._applyCombination(this._triad, args);
1187
+ }
1188
+ _tetrad(obj) {
1189
+ let hsl = new TinyColor(obj).toHsl();
1190
+ let h = hsl.h;
1191
+ return [
1192
+ new TinyColor(obj),
1193
+ new TinyColor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
1194
+ new TinyColor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
1195
+ new TinyColor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }),
1196
+ ];
1197
+ }
1198
+ tetrad(...args) {
1199
+ return this._applyCombination(this._tetrad, args);
1200
+ }
1201
+ static fromRatio(color, opts) {
1202
+ if (typeof color == 'object') {
1203
+ let newColor = {};
1204
+ for (let i in color) {
1205
+ if (color.hasOwnProperty(i)) {
1206
+ if (i === 'a') {
1207
+ newColor[i] = color[i];
1208
+ }
1209
+ else {
1210
+ newColor[i] = TinyColor.convertToPercentage(color[i]);
1211
+ }
1212
+ }
1213
+ }
1214
+ color = newColor;
1215
+ }
1216
+ return new TinyColor(color, opts);
1217
+ }
1218
+ static equals(color1, color2) {
1219
+ if (!color1 || !color2) {
1220
+ return false;
1221
+ }
1222
+ return new TinyColor(color1).toRgbString() == new TinyColor(color2).toRgbString();
1223
+ }
1224
+ static random() {
1225
+ return TinyColor.fromRatio({
1226
+ r: mathRandom(),
1227
+ g: mathRandom(),
1228
+ b: mathRandom(),
1229
+ });
1230
+ }
1231
+ static mix(color1, color2, amount) {
1232
+ amount = amount === 0 ? 0 : amount || 50;
1233
+ let rgb1 = new TinyColor(color1).toRgb();
1234
+ let rgb2 = new TinyColor(color2).toRgb();
1235
+ let p = amount / 100;
1236
+ let rgba = {
1237
+ r: (rgb2.r - rgb1.r) * p + rgb1.r,
1238
+ g: (rgb2.g - rgb1.g) * p + rgb1.g,
1239
+ b: (rgb2.b - rgb1.b) * p + rgb1.b,
1240
+ a: (rgb2.a - rgb1.a) * p + rgb1.a,
1241
+ };
1242
+ return new TinyColor(rgba);
1243
+ }
1244
+ static readability(color1, color2) {
1245
+ let c1 = new TinyColor(color1);
1246
+ let c2 = new TinyColor(color2);
1247
+ return (Math.max(c1.getLuminance(), c2.getLuminance()) + 0.05) / (Math.min(c1.getLuminance(), c2.getLuminance()) + 0.05);
1248
+ }
1249
+ static isReadable(color1, color2, wcag2) {
1250
+ let readability = TinyColor.readability(color1, color2);
1251
+ let wcag2Parms, out;
1252
+ out = false;
1253
+ wcag2Parms = TinyColor.validateWCAG2Parms(wcag2);
1254
+ switch (wcag2Parms.level + wcag2Parms.size) {
1255
+ case 'AAsmall':
1256
+ case 'AAAlarge':
1257
+ out = readability >= 4.5;
1258
+ break;
1259
+ case 'AAlarge':
1260
+ out = readability >= 3;
1261
+ break;
1262
+ case 'AAAsmall':
1263
+ out = readability >= 7;
1264
+ break;
1265
+ }
1266
+ return out;
1267
+ }
1268
+ static mostReadable(baseColor, colorList, args) {
1269
+ let bestColor = '';
1270
+ let bestScore = 0;
1271
+ let readability;
1272
+ let includeFallbackColors, level, size;
1273
+ args = args || {};
1274
+ includeFallbackColors = args.includeFallbackColors;
1275
+ level = args.level;
1276
+ size = args.size;
1277
+ for (let item of colorList) {
1278
+ readability = TinyColor.readability(baseColor, item);
1279
+ if (readability > bestScore) {
1280
+ bestScore = readability;
1281
+ bestColor = new TinyColor(item);
1282
+ }
1283
+ }
1284
+ if (TinyColor.isReadable(baseColor, bestColor, {
1285
+ level: level,
1286
+ size: size,
1287
+ }) ||
1288
+ !includeFallbackColors) {
1289
+ return bestColor;
1290
+ }
1291
+ else {
1292
+ args.includeFallbackColors = false;
1293
+ return TinyColor.mostReadable(baseColor, ['#fff', '#000'], args);
1294
+ }
1295
+ }
1296
+ clamp01(val) {
1297
+ return mathMin(1, mathMax(0, val));
1298
+ }
1299
+ _flip() {
1300
+ let flipped = {};
1301
+ let allName = TinyColor.initNames();
1302
+ for (let i in allName) {
1303
+ if (allName.hasOwnProperty(i)) {
1304
+ flipped[allName[i]] = i;
1305
+ }
1306
+ }
1307
+ return flipped;
1308
+ }
1309
+ isValidCSSUnit(color) {
1310
+ return !!this.matchers.CSS_UNIT.exec(color);
1311
+ }
1312
+ isOnePointZero(n) {
1313
+ return typeof n == 'string' && n.indexOf('.') != -1 && parseFloat(n) === 1;
1314
+ }
1315
+ isPercentage(n) {
1316
+ return typeof n === 'string' && n.indexOf('%') != -1;
1317
+ }
1318
+ pad2(c) {
1319
+ return c.length == 1 ? '0' + c : '' + c;
1320
+ }
1321
+ bound01(n, max) {
1322
+ if (this.isOnePointZero(n)) {
1323
+ n = '100%';
1324
+ }
1325
+ let processPercent = this.isPercentage(n);
1326
+ n = mathMin(max, mathMax(0, parseFloat(n)));
1327
+ // Automatically convert percentage into number
1328
+ if (processPercent) {
1329
+ n = parseInt('' + n * max, 10) / 100;
1330
+ }
1331
+ // Handle floating point rounding errors
1332
+ if (Math.abs(n - max) < 0.000001) {
1333
+ return 1;
1334
+ }
1335
+ // Convert into [0, 1] range if it isn't already
1336
+ return (n % max) / parseFloat(max);
1337
+ }
1338
+ convertDecimalToHex(d) {
1339
+ return Math.round(parseFloat(d) * 255).toString(16);
1340
+ }
1341
+ rgbToRgb(r, g, b) {
1342
+ return {
1343
+ r: this.bound01(r, 255) * 255,
1344
+ g: this.bound01(g, 255) * 255,
1345
+ b: this.bound01(b, 255) * 255,
1346
+ };
1347
+ }
1348
+ hsvToRgb(h, s, v) {
1349
+ h = this.bound01(h, 360) * 6;
1350
+ s = this.bound01(s, 100);
1351
+ v = this.bound01(v, 100);
1352
+ let i = Math.floor(h), f = h - i, p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s), mod = i % 6, r = [v, q, p, p, t, v][mod], g = [t, v, v, q, p, p][mod], b = [p, p, t, v, v, q][mod];
1353
+ return { r: r * 255, g: g * 255, b: b * 255 };
1354
+ }
1355
+ hslToRgb(h, s, l) {
1356
+ let r, g, b;
1357
+ h = this.bound01(h, 360);
1358
+ s = this.bound01(s, 100);
1359
+ l = this.bound01(l, 100);
1360
+ function hue2rgb(p, q, t) {
1361
+ if (t < 0)
1362
+ t += 1;
1363
+ if (t > 1)
1364
+ t -= 1;
1365
+ if (t < 1 / 6)
1366
+ return p + (q - p) * 6 * t;
1367
+ if (t < 1 / 2)
1368
+ return q;
1369
+ if (t < 2 / 3)
1370
+ return p + (q - p) * (2 / 3 - t) * 6;
1371
+ return p;
1372
+ }
1373
+ if (s === 0) {
1374
+ r = g = b = l; // achromatic
1375
+ }
1376
+ else {
1377
+ let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1378
+ let p = 2 * l - q;
1379
+ r = hue2rgb(p, q, h + 1 / 3);
1380
+ g = hue2rgb(p, q, h);
1381
+ b = hue2rgb(p, q, h - 1 / 3);
1382
+ }
1383
+ return { r: r * 255, g: g * 255, b: b * 255 };
1384
+ }
1385
+ rgbToHsl(r, g, b) {
1386
+ r = this.bound01(r, 255);
1387
+ g = this.bound01(g, 255);
1388
+ b = this.bound01(b, 255);
1389
+ let max = mathMax(r, g, b), min = mathMin(r, g, b);
1390
+ let h, s, l = (max + min) / 2;
1391
+ if (max == min) {
1392
+ h = s = 0; // achromatic
1393
+ }
1394
+ else {
1395
+ let d = max - min;
1396
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1397
+ switch (max) {
1398
+ case r:
1399
+ h = (g - b) / d + (g < b ? 6 : 0);
1400
+ break;
1401
+ case g:
1402
+ h = (b - r) / d + 2;
1403
+ break;
1404
+ case b:
1405
+ h = (r - g) / d + 4;
1406
+ break;
1407
+ }
1408
+ h /= 6;
1409
+ }
1410
+ return { h: h, s: s, l: l };
1411
+ }
1412
+ rgbToHsv(r, g, b) {
1413
+ r = this.bound01(r, 255);
1414
+ g = this.bound01(g, 255);
1415
+ b = this.bound01(b, 255);
1416
+ let max = mathMax(r, g, b), min = mathMin(r, g, b);
1417
+ let h, s, v = max;
1418
+ let d = max - min;
1419
+ s = max === 0 ? 0 : d / max;
1420
+ if (max == min) {
1421
+ h = 0; // achromatic
1422
+ }
1423
+ else {
1424
+ switch (max) {
1425
+ case r:
1426
+ h = (g - b) / d + (g < b ? 6 : 0);
1427
+ break;
1428
+ case g:
1429
+ h = (b - r) / d + 2;
1430
+ break;
1431
+ case b:
1432
+ h = (r - g) / d + 4;
1433
+ break;
1434
+ }
1435
+ h /= 6;
1436
+ }
1437
+ return { h: h, s: s, v: v };
1438
+ }
1439
+ rgbToHex(r, g, b, allow3Char) {
1440
+ let hex = [this.pad2(mathRound(r).toString(16)), this.pad2(mathRound(g).toString(16)), this.pad2(mathRound(b).toString(16))];
1441
+ // Return a 3 character hex if possible
1442
+ if (allow3Char &&
1443
+ hex[0].charAt(0) == hex[0].charAt(1) &&
1444
+ hex[1].charAt(0) == hex[1].charAt(1) &&
1445
+ hex[2].charAt(0) == hex[2].charAt(1)) {
1446
+ return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
1447
+ }
1448
+ return hex.join('');
1449
+ }
1450
+ rgbaToHex(r, g, b, a, allow4Char) {
1451
+ let hex = [
1452
+ this.pad2(mathRound(r).toString(16)),
1453
+ this.pad2(mathRound(g).toString(16)),
1454
+ this.pad2(mathRound(b).toString(16)),
1455
+ this.pad2(this.convertDecimalToHex('' + a)),
1456
+ ];
1457
+ // Return a 4 character hex if possible
1458
+ if (allow4Char &&
1459
+ hex[0].charAt(0) == hex[0].charAt(1) &&
1460
+ hex[1].charAt(0) == hex[1].charAt(1) &&
1461
+ hex[2].charAt(0) == hex[2].charAt(1) &&
1462
+ hex[3].charAt(0) == hex[3].charAt(1)) {
1463
+ return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
1464
+ }
1465
+ return hex.join('');
1466
+ }
1467
+ rgbaToArgbHex(r, g, b, a) {
1468
+ let hex = [
1469
+ this.pad2(this.convertDecimalToHex('' + a)),
1470
+ this.pad2(mathRound(r).toString(16)),
1471
+ this.pad2(mathRound(g).toString(16)),
1472
+ this.pad2(mathRound(b).toString(16)),
1473
+ ];
1474
+ return hex.join('');
1475
+ }
1476
+ static convertToPercentage(n) {
1477
+ if (n <= 1) {
1478
+ n = n * 100 + '%';
1479
+ }
1480
+ return n;
1481
+ }
1482
+ boundAlpha(a) {
1483
+ a = parseFloat(a);
1484
+ if (isNaN(a) || a < 0 || a > 1) {
1485
+ a = 1;
1486
+ }
1487
+ return a;
1488
+ }
1489
+ inputToRGB(color) {
1490
+ let rgb = { r: 0, g: 0, b: 0 };
1491
+ let a = 1;
1492
+ let s = null;
1493
+ let v = null;
1494
+ let l = null;
1495
+ let ok = false;
1496
+ let format = '';
1497
+ if (color === null) {
1498
+ color = '';
1499
+ }
1500
+ if (typeof color == 'string') {
1501
+ color = this.stringInputToObject(color);
1502
+ }
1503
+ if (typeof color == 'object') {
1504
+ if (this.isValidCSSUnit(color.r) && this.isValidCSSUnit(color.g) && this.isValidCSSUnit(color.b)) {
1505
+ rgb = this.rgbToRgb(color.r, color.g, color.b);
1506
+ ok = true;
1507
+ format = String(color.r).substr(-1) === '%' ? 'prgb' : 'rgb';
1508
+ }
1509
+ else if (this.isValidCSSUnit(color.h) && this.isValidCSSUnit(color.s) && this.isValidCSSUnit(color.v)) {
1510
+ s = TinyColor.convertToPercentage(color.s);
1511
+ v = TinyColor.convertToPercentage(color.v);
1512
+ rgb = this.hsvToRgb(color.h, s, v);
1513
+ ok = true;
1514
+ format = 'hsv';
1515
+ }
1516
+ else if (this.isValidCSSUnit(color.h) && this.isValidCSSUnit(color.s) && this.isValidCSSUnit(color.l)) {
1517
+ s = TinyColor.convertToPercentage(color.s);
1518
+ l = TinyColor.convertToPercentage(color.l);
1519
+ rgb = this.hslToRgb(color.h, s, l);
1520
+ ok = true;
1521
+ format = 'hsl';
1522
+ }
1523
+ if (color.hasOwnProperty('a')) {
1524
+ a = color.a;
1525
+ }
1526
+ }
1527
+ a = this.boundAlpha(a);
1528
+ return {
1529
+ ok: ok,
1530
+ format: color.format || format,
1531
+ r: mathMin(255, mathMax(rgb.r, 0)),
1532
+ g: mathMin(255, mathMax(rgb.g, 0)),
1533
+ b: mathMin(255, mathMax(rgb.b, 0)),
1534
+ a: a,
1535
+ };
1536
+ }
1537
+ parseIntFromHex(val) {
1538
+ return parseInt(val, 16);
1539
+ }
1540
+ convertHexToDecimal(h) {
1541
+ return this.parseIntFromHex(h) / 255;
1542
+ }
1543
+ stringInputToObject(color) {
1544
+ color = color.replace(trimLeft, '').replace(trimRight, '').toLowerCase();
1545
+ let named = false;
1546
+ if (this.names[color]) {
1547
+ color = this.names[color];
1548
+ named = true;
1549
+ }
1550
+ else if (color == 'transparent') {
1551
+ return { r: 0, g: 0, b: 0, a: 0, format: 'name' };
1552
+ }
1553
+ // Try to match string input using regular expressions.
1554
+ // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
1555
+ // Just return an object and let the conversion functions handle that.
1556
+ // This way the result will be the same whether the tinycolor is initialized with string or object.
1557
+ let match;
1558
+ if ((match = this.matchers.rgb.exec(color))) {
1559
+ return { r: match[1], g: match[2], b: match[3] };
1560
+ }
1561
+ if ((match = this.matchers.rgba.exec(color))) {
1562
+ return { r: match[1], g: match[2], b: match[3], a: match[4] };
1563
+ }
1564
+ if ((match = this.matchers.hsl.exec(color))) {
1565
+ return { h: match[1], s: match[2], l: match[3] };
1566
+ }
1567
+ if ((match = this.matchers.hsla.exec(color))) {
1568
+ return { h: match[1], s: match[2], l: match[3], a: match[4] };
1569
+ }
1570
+ if ((match = this.matchers.hsv.exec(color))) {
1571
+ return { h: match[1], s: match[2], v: match[3] };
1572
+ }
1573
+ if ((match = this.matchers.hsva.exec(color))) {
1574
+ return { h: match[1], s: match[2], v: match[3], a: match[4] };
1575
+ }
1576
+ if ((match = this.matchers.hex8.exec(color))) {
1577
+ return {
1578
+ r: this.parseIntFromHex(match[1]),
1579
+ g: this.parseIntFromHex(match[2]),
1580
+ b: this.parseIntFromHex(match[3]),
1581
+ a: this.convertHexToDecimal(match[4]),
1582
+ format: named ? 'name' : 'hex8',
1583
+ };
1584
+ }
1585
+ if ((match = this.matchers.hex6.exec(color))) {
1586
+ return {
1587
+ r: this.parseIntFromHex(match[1]),
1588
+ g: this.parseIntFromHex(match[2]),
1589
+ b: this.parseIntFromHex(match[3]),
1590
+ format: named ? 'name' : 'hex',
1591
+ };
1592
+ }
1593
+ if ((match = this.matchers.hex4.exec(color))) {
1594
+ return {
1595
+ r: this.parseIntFromHex(match[1] + '' + match[1]),
1596
+ g: this.parseIntFromHex(match[2] + '' + match[2]),
1597
+ b: this.parseIntFromHex(match[3] + '' + match[3]),
1598
+ a: this.convertHexToDecimal(match[4] + '' + match[4]),
1599
+ format: named ? 'name' : 'hex8',
1600
+ };
1601
+ }
1602
+ if ((match = this.matchers.hex3.exec(color))) {
1603
+ return {
1604
+ r: this.parseIntFromHex(match[1] + '' + match[1]),
1605
+ g: this.parseIntFromHex(match[2] + '' + match[2]),
1606
+ b: this.parseIntFromHex(match[3] + '' + match[3]),
1607
+ format: named ? 'name' : 'hex',
1608
+ };
1609
+ }
1610
+ return false;
1611
+ }
1612
+ static validateWCAG2Parms(parms) {
1613
+ // return valid WCAG2 parms for isReadable.
1614
+ // If input parms are invalid, return {"level":"AA", "size":"small"}
1615
+ let level, size;
1616
+ parms = parms || { level: 'AA', size: 'small' };
1617
+ level = (parms.level || 'AA').toUpperCase();
1618
+ size = (parms.size || 'small').toLowerCase();
1619
+ if (level !== 'AA' && level !== 'AAA') {
1620
+ level = 'AA';
1621
+ }
1622
+ if (size !== 'small' && size !== 'large') {
1623
+ size = 'small';
1624
+ }
1625
+ return { level: level, size: size };
1626
+ }
1627
+ }
1628
+
1629
+ exports.Num = Num;
1630
+ exports.TinyColor = TinyColor;
1631
+ exports.addPx = addPx;
1632
+ exports.assignObject = assignObject;
1633
+ exports.browserEngine = browserEngine;
1634
+ exports.createHttp = createHttp;
1635
+ exports.exitFullscreen = exitFullscreen;
1636
+ exports.expose = expose;
1637
+ exports.fullscreen = fullscreen;
1638
+ exports.getDate = getDate;
1639
+ exports.getObject = getObject;
1640
+ exports.getSpecialDate = getSpecialDate;
1641
+ exports.getTime = getTime;
1642
+ exports.inFullscreen = inFullscreen;
1643
+ exports.isFullscreen = isFullscreen;
1644
+ exports.isUrl = isUrl;
1645
+ exports.on = on;
1646
+ exports.pathToHump = pathToHump;
1647
+ exports.query = query;
1648
+ exports.setTime = setTime;
1649
+ exports.setValue = setValue;
1650
+ exports.toHump = toHump;
1651
+ exports.toHyphen = toHyphen;
1652
+ exports.urlToData = urlToData;