@likec4/core 1.8.1 → 1.10.0

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.
Files changed (94) hide show
  1. package/dist/index.cjs +4467 -0
  2. package/dist/index.d.cts +793 -0
  3. package/dist/index.d.mts +793 -0
  4. package/dist/index.d.ts +793 -7
  5. package/dist/index.mjs +4390 -0
  6. package/dist/shared/core.CpR2fq5B.d.cts +833 -0
  7. package/dist/shared/core.CpR2fq5B.d.mts +833 -0
  8. package/dist/shared/core.CpR2fq5B.d.ts +833 -0
  9. package/dist/shared/core.Db3ntVII.cjs +318 -0
  10. package/dist/shared/core.DeifT5lC.mjs +263 -0
  11. package/dist/types/index.cjs +55 -0
  12. package/dist/types/index.d.cts +1 -0
  13. package/dist/types/index.d.mts +1 -0
  14. package/dist/types/index.d.ts +1 -14
  15. package/dist/types/index.mjs +1 -0
  16. package/package.json +43 -33
  17. package/src/colors/index.ts +27 -1
  18. package/src/errors/index.ts +3 -95
  19. package/src/index.ts +6 -6
  20. package/src/model/LikeC4Model.ts +480 -0
  21. package/src/model/LikeC4ViewModel.ts +318 -0
  22. package/src/model/__test__/LikeC4Model.spec.ts +79 -0
  23. package/src/model/__test__/fixture.ts +333 -0
  24. package/src/model/index.ts +2 -0
  25. package/src/model/types.ts +10 -0
  26. package/src/types/_common.ts +4 -2
  27. package/src/types/element.ts +11 -8
  28. package/src/types/expression.ts +7 -3
  29. package/src/types/index.ts +0 -1
  30. package/src/types/model.ts +16 -6
  31. package/src/types/relation.ts +18 -5
  32. package/src/types/theme.ts +28 -12
  33. package/src/types/view-notation.ts +3 -4
  34. package/src/types/view.ts +51 -16
  35. package/src/utils/compare-natural.spec.ts +37 -0
  36. package/src/utils/compare-natural.ts +14 -0
  37. package/src/utils/fqn.spec.ts +99 -2
  38. package/src/utils/fqn.ts +45 -5
  39. package/src/utils/index.ts +1 -0
  40. package/src/utils/relations.spec.ts +2 -4
  41. package/src/utils/relations.ts +14 -24
  42. package/dist/colors/element.d.ts +0 -69
  43. package/dist/colors/element.js +0 -75
  44. package/dist/colors/index.d.ts +0 -133
  45. package/dist/colors/index.js +0 -9
  46. package/dist/colors/relationships.d.ts +0 -58
  47. package/dist/colors/relationships.js +0 -49
  48. package/dist/errors/errors.spec.d.ts +0 -2
  49. package/dist/errors/errors.spec.js +0 -69
  50. package/dist/errors/index.d.ts +0 -39
  51. package/dist/errors/index.js +0 -104
  52. package/dist/index.js +0 -4
  53. package/dist/types/_common.d.ts +0 -9
  54. package/dist/types/_common.js +0 -1
  55. package/dist/types/element.d.ts +0 -55
  56. package/dist/types/element.js +0 -15
  57. package/dist/types/expression.d.ts +0 -119
  58. package/dist/types/expression.js +0 -67
  59. package/dist/types/index.js +0 -14
  60. package/dist/types/model.d.ts +0 -14
  61. package/dist/types/model.js +0 -1
  62. package/dist/types/opaque.d.ts +0 -103
  63. package/dist/types/opaque.js +0 -1
  64. package/dist/types/operators.d.ts +0 -44
  65. package/dist/types/operators.js +0 -59
  66. package/dist/types/overview-graph.d.ts +0 -41
  67. package/dist/types/overview-graph.js +0 -1
  68. package/dist/types/relation.d.ts +0 -30
  69. package/dist/types/relation.js +0 -3
  70. package/dist/types/theme.d.ts +0 -27
  71. package/dist/types/theme.js +0 -1
  72. package/dist/types/view-changes.d.ts +0 -26
  73. package/dist/types/view-changes.js +0 -1
  74. package/dist/types/view-notation.d.ts +0 -9
  75. package/dist/types/view-notation.js +0 -1
  76. package/dist/types/view.d.ts +0 -243
  77. package/dist/types/view.js +0 -50
  78. package/dist/utils/fqn.d.ts +0 -39
  79. package/dist/utils/fqn.js +0 -102
  80. package/dist/utils/fqn.spec.d.ts +0 -2
  81. package/dist/utils/fqn.spec.js +0 -82
  82. package/dist/utils/guards.d.ts +0 -5
  83. package/dist/utils/guards.js +0 -7
  84. package/dist/utils/index.d.ts +0 -5
  85. package/dist/utils/index.js +0 -4
  86. package/dist/utils/promises.d.ts +0 -2
  87. package/dist/utils/promises.js +0 -8
  88. package/dist/utils/relations.d.ts +0 -30
  89. package/dist/utils/relations.js +0 -79
  90. package/dist/utils/relations.spec.d.ts +0 -2
  91. package/dist/utils/relations.spec.js +0 -210
  92. package/src/errors/errors.spec.ts +0 -88
  93. package/src/reset.d.ts +0 -2
  94. package/src/types/opaque.ts +0 -108
package/dist/index.cjs ADDED
@@ -0,0 +1,4467 @@
1
+ 'use strict';
2
+
3
+ const types_index = require('./shared/core.Db3ntVII.cjs');
4
+
5
+ const limit = (x, low = 0, high = 1) => {
6
+ return min$3(max$3(low, x), high);
7
+ };
8
+
9
+ const clip_rgb = (rgb) => {
10
+ rgb._clipped = false;
11
+ rgb._unclipped = rgb.slice(0);
12
+ for (let i = 0; i <= 3; i++) {
13
+ if (i < 3) {
14
+ if (rgb[i] < 0 || rgb[i] > 255) rgb._clipped = true;
15
+ rgb[i] = limit(rgb[i], 0, 255);
16
+ } else if (i === 3) {
17
+ rgb[i] = limit(rgb[i], 0, 1);
18
+ }
19
+ }
20
+ return rgb;
21
+ };
22
+
23
+ // ported from jQuery's $.type
24
+ const classToType = {};
25
+ for (let name of [
26
+ 'Boolean',
27
+ 'Number',
28
+ 'String',
29
+ 'Function',
30
+ 'Array',
31
+ 'Date',
32
+ 'RegExp',
33
+ 'Undefined',
34
+ 'Null'
35
+ ]) {
36
+ classToType[`[object ${name}]`] = name.toLowerCase();
37
+ }
38
+ function type (obj) {
39
+ return classToType[Object.prototype.toString.call(obj)] || 'object';
40
+ }
41
+
42
+ const unpack = (args, keyOrder = null) => {
43
+ // if called with more than 3 arguments, we return the arguments
44
+ if (args.length >= 3) return Array.prototype.slice.call(args);
45
+ // with less than 3 args we check if first arg is object
46
+ // and use the keyOrder string to extract and sort properties
47
+ if (type(args[0]) == 'object' && keyOrder) {
48
+ return keyOrder
49
+ .split('')
50
+ .filter((k) => args[0][k] !== undefined)
51
+ .map((k) => args[0][k]);
52
+ }
53
+ // otherwise we just return the first argument
54
+ // (which we suppose is an array of args)
55
+ return args[0].slice(0);
56
+ };
57
+
58
+ const last = (args) => {
59
+ if (args.length < 2) return null;
60
+ const l = args.length - 1;
61
+ if (type(args[l]) == 'string') return args[l].toLowerCase();
62
+ return null;
63
+ };
64
+
65
+ const { PI: PI$2, min: min$3, max: max$3 } = Math;
66
+
67
+ const rnd2 = (a) => Math.round(a * 100) / 100;
68
+ const rnd3 = (a) => Math.round(a * 100) / 100;
69
+
70
+ const TWOPI = PI$2 * 2;
71
+ const PITHIRD = PI$2 / 3;
72
+ const DEG2RAD = PI$2 / 180;
73
+ const RAD2DEG = 180 / PI$2;
74
+
75
+ const input = {
76
+ format: {},
77
+ autodetect: []
78
+ };
79
+
80
+ class Color {
81
+ constructor(...args) {
82
+ const me = this;
83
+ if (
84
+ type(args[0]) === 'object' &&
85
+ args[0].constructor &&
86
+ args[0].constructor === this.constructor
87
+ ) {
88
+ // the argument is already a Color instance
89
+ return args[0];
90
+ }
91
+ // last argument could be the mode
92
+ let mode = last(args);
93
+ let autodetect = false;
94
+ if (!mode) {
95
+ autodetect = true;
96
+
97
+ if (!input.sorted) {
98
+ input.autodetect = input.autodetect.sort((a, b) => b.p - a.p);
99
+ input.sorted = true;
100
+ }
101
+
102
+ // auto-detect format
103
+ for (let chk of input.autodetect) {
104
+ mode = chk.test(...args);
105
+ if (mode) break;
106
+ }
107
+ }
108
+ if (input.format[mode]) {
109
+ const rgb = input.format[mode].apply(
110
+ null,
111
+ autodetect ? args : args.slice(0, -1)
112
+ );
113
+ me._rgb = clip_rgb(rgb);
114
+ } else {
115
+ throw new Error('unknown format: ' + args);
116
+ }
117
+ // add alpha channel
118
+ if (me._rgb.length === 3) me._rgb.push(1);
119
+ }
120
+ toString() {
121
+ if (type(this.hex) == 'function') return this.hex();
122
+ return `[${this._rgb.join(',')}]`;
123
+ }
124
+ }
125
+
126
+ // this gets updated automatically
127
+ const version = '3.0.0';
128
+
129
+ const chroma = (...args) => {
130
+ return new Color(...args);
131
+ };
132
+
133
+ chroma.version = version;
134
+
135
+ /**
136
+ X11 color names
137
+
138
+ http://www.w3.org/TR/css3-color/#svg-color
139
+ */
140
+
141
+ const w3cx11 = {
142
+ aliceblue: '#f0f8ff',
143
+ antiquewhite: '#faebd7',
144
+ aqua: '#00ffff',
145
+ aquamarine: '#7fffd4',
146
+ azure: '#f0ffff',
147
+ beige: '#f5f5dc',
148
+ bisque: '#ffe4c4',
149
+ black: '#000000',
150
+ blanchedalmond: '#ffebcd',
151
+ blue: '#0000ff',
152
+ blueviolet: '#8a2be2',
153
+ brown: '#a52a2a',
154
+ burlywood: '#deb887',
155
+ cadetblue: '#5f9ea0',
156
+ chartreuse: '#7fff00',
157
+ chocolate: '#d2691e',
158
+ coral: '#ff7f50',
159
+ cornflowerblue: '#6495ed',
160
+ cornsilk: '#fff8dc',
161
+ crimson: '#dc143c',
162
+ cyan: '#00ffff',
163
+ darkblue: '#00008b',
164
+ darkcyan: '#008b8b',
165
+ darkgoldenrod: '#b8860b',
166
+ darkgray: '#a9a9a9',
167
+ darkgreen: '#006400',
168
+ darkgrey: '#a9a9a9',
169
+ darkkhaki: '#bdb76b',
170
+ darkmagenta: '#8b008b',
171
+ darkolivegreen: '#556b2f',
172
+ darkorange: '#ff8c00',
173
+ darkorchid: '#9932cc',
174
+ darkred: '#8b0000',
175
+ darksalmon: '#e9967a',
176
+ darkseagreen: '#8fbc8f',
177
+ darkslateblue: '#483d8b',
178
+ darkslategray: '#2f4f4f',
179
+ darkslategrey: '#2f4f4f',
180
+ darkturquoise: '#00ced1',
181
+ darkviolet: '#9400d3',
182
+ deeppink: '#ff1493',
183
+ deepskyblue: '#00bfff',
184
+ dimgray: '#696969',
185
+ dimgrey: '#696969',
186
+ dodgerblue: '#1e90ff',
187
+ firebrick: '#b22222',
188
+ floralwhite: '#fffaf0',
189
+ forestgreen: '#228b22',
190
+ fuchsia: '#ff00ff',
191
+ gainsboro: '#dcdcdc',
192
+ ghostwhite: '#f8f8ff',
193
+ gold: '#ffd700',
194
+ goldenrod: '#daa520',
195
+ gray: '#808080',
196
+ green: '#008000',
197
+ greenyellow: '#adff2f',
198
+ grey: '#808080',
199
+ honeydew: '#f0fff0',
200
+ hotpink: '#ff69b4',
201
+ indianred: '#cd5c5c',
202
+ indigo: '#4b0082',
203
+ ivory: '#fffff0',
204
+ khaki: '#f0e68c',
205
+ laserlemon: '#ffff54',
206
+ lavender: '#e6e6fa',
207
+ lavenderblush: '#fff0f5',
208
+ lawngreen: '#7cfc00',
209
+ lemonchiffon: '#fffacd',
210
+ lightblue: '#add8e6',
211
+ lightcoral: '#f08080',
212
+ lightcyan: '#e0ffff',
213
+ lightgoldenrod: '#fafad2',
214
+ lightgoldenrodyellow: '#fafad2',
215
+ lightgray: '#d3d3d3',
216
+ lightgreen: '#90ee90',
217
+ lightgrey: '#d3d3d3',
218
+ lightpink: '#ffb6c1',
219
+ lightsalmon: '#ffa07a',
220
+ lightseagreen: '#20b2aa',
221
+ lightskyblue: '#87cefa',
222
+ lightslategray: '#778899',
223
+ lightslategrey: '#778899',
224
+ lightsteelblue: '#b0c4de',
225
+ lightyellow: '#ffffe0',
226
+ lime: '#00ff00',
227
+ limegreen: '#32cd32',
228
+ linen: '#faf0e6',
229
+ magenta: '#ff00ff',
230
+ maroon: '#800000',
231
+ maroon2: '#7f0000',
232
+ maroon3: '#b03060',
233
+ mediumaquamarine: '#66cdaa',
234
+ mediumblue: '#0000cd',
235
+ mediumorchid: '#ba55d3',
236
+ mediumpurple: '#9370db',
237
+ mediumseagreen: '#3cb371',
238
+ mediumslateblue: '#7b68ee',
239
+ mediumspringgreen: '#00fa9a',
240
+ mediumturquoise: '#48d1cc',
241
+ mediumvioletred: '#c71585',
242
+ midnightblue: '#191970',
243
+ mintcream: '#f5fffa',
244
+ mistyrose: '#ffe4e1',
245
+ moccasin: '#ffe4b5',
246
+ navajowhite: '#ffdead',
247
+ navy: '#000080',
248
+ oldlace: '#fdf5e6',
249
+ olive: '#808000',
250
+ olivedrab: '#6b8e23',
251
+ orange: '#ffa500',
252
+ orangered: '#ff4500',
253
+ orchid: '#da70d6',
254
+ palegoldenrod: '#eee8aa',
255
+ palegreen: '#98fb98',
256
+ paleturquoise: '#afeeee',
257
+ palevioletred: '#db7093',
258
+ papayawhip: '#ffefd5',
259
+ peachpuff: '#ffdab9',
260
+ peru: '#cd853f',
261
+ pink: '#ffc0cb',
262
+ plum: '#dda0dd',
263
+ powderblue: '#b0e0e6',
264
+ purple: '#800080',
265
+ purple2: '#7f007f',
266
+ purple3: '#a020f0',
267
+ rebeccapurple: '#663399',
268
+ red: '#ff0000',
269
+ rosybrown: '#bc8f8f',
270
+ royalblue: '#4169e1',
271
+ saddlebrown: '#8b4513',
272
+ salmon: '#fa8072',
273
+ sandybrown: '#f4a460',
274
+ seagreen: '#2e8b57',
275
+ seashell: '#fff5ee',
276
+ sienna: '#a0522d',
277
+ silver: '#c0c0c0',
278
+ skyblue: '#87ceeb',
279
+ slateblue: '#6a5acd',
280
+ slategray: '#708090',
281
+ slategrey: '#708090',
282
+ snow: '#fffafa',
283
+ springgreen: '#00ff7f',
284
+ steelblue: '#4682b4',
285
+ tan: '#d2b48c',
286
+ teal: '#008080',
287
+ thistle: '#d8bfd8',
288
+ tomato: '#ff6347',
289
+ turquoise: '#40e0d0',
290
+ violet: '#ee82ee',
291
+ wheat: '#f5deb3',
292
+ white: '#ffffff',
293
+ whitesmoke: '#f5f5f5',
294
+ yellow: '#ffff00',
295
+ yellowgreen: '#9acd32'
296
+ };
297
+
298
+ const RE_HEX = /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
299
+ const RE_HEXA = /^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/;
300
+
301
+ const hex2rgb = (hex) => {
302
+ if (hex.match(RE_HEX)) {
303
+ // remove optional leading #
304
+ if (hex.length === 4 || hex.length === 7) {
305
+ hex = hex.substr(1);
306
+ }
307
+ // expand short-notation to full six-digit
308
+ if (hex.length === 3) {
309
+ hex = hex.split('');
310
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
311
+ }
312
+ const u = parseInt(hex, 16);
313
+ const r = u >> 16;
314
+ const g = (u >> 8) & 0xff;
315
+ const b = u & 0xff;
316
+ return [r, g, b, 1];
317
+ }
318
+
319
+ // match rgba hex format, eg #FF000077
320
+ if (hex.match(RE_HEXA)) {
321
+ if (hex.length === 5 || hex.length === 9) {
322
+ // remove optional leading #
323
+ hex = hex.substr(1);
324
+ }
325
+ // expand short-notation to full eight-digit
326
+ if (hex.length === 4) {
327
+ hex = hex.split('');
328
+ hex =
329
+ hex[0] +
330
+ hex[0] +
331
+ hex[1] +
332
+ hex[1] +
333
+ hex[2] +
334
+ hex[2] +
335
+ hex[3] +
336
+ hex[3];
337
+ }
338
+ const u = parseInt(hex, 16);
339
+ const r = (u >> 24) & 0xff;
340
+ const g = (u >> 16) & 0xff;
341
+ const b = (u >> 8) & 0xff;
342
+ const a = Math.round(((u & 0xff) / 0xff) * 100) / 100;
343
+ return [r, g, b, a];
344
+ }
345
+
346
+ // we used to check for css colors here
347
+ // if _input.css? and rgb = _input.css hex
348
+ // return rgb
349
+
350
+ throw new Error(`unknown hex color: ${hex}`);
351
+ };
352
+
353
+ const { round: round$5 } = Math;
354
+
355
+ const rgb2hex = (...args) => {
356
+ let [r, g, b, a] = unpack(args, 'rgba');
357
+ let mode = last(args) || 'auto';
358
+ if (a === undefined) a = 1;
359
+ if (mode === 'auto') {
360
+ mode = a < 1 ? 'rgba' : 'rgb';
361
+ }
362
+ r = round$5(r);
363
+ g = round$5(g);
364
+ b = round$5(b);
365
+ const u = (r << 16) | (g << 8) | b;
366
+ let str = '000000' + u.toString(16); //#.toUpperCase();
367
+ str = str.substr(str.length - 6);
368
+ let hxa = '0' + round$5(a * 255).toString(16);
369
+ hxa = hxa.substr(hxa.length - 2);
370
+ switch (mode.toLowerCase()) {
371
+ case 'rgba':
372
+ return `#${str}${hxa}`;
373
+ case 'argb':
374
+ return `#${hxa}${str}`;
375
+ default:
376
+ return `#${str}`;
377
+ }
378
+ };
379
+
380
+ Color.prototype.name = function () {
381
+ const hex = rgb2hex(this._rgb, 'rgb');
382
+ for (let n of Object.keys(w3cx11)) {
383
+ if (w3cx11[n] === hex) return n.toLowerCase();
384
+ }
385
+ return hex;
386
+ };
387
+
388
+ input.format.named = (name) => {
389
+ name = name.toLowerCase();
390
+ if (w3cx11[name]) return hex2rgb(w3cx11[name]);
391
+ throw new Error('unknown color name: ' + name);
392
+ };
393
+
394
+ input.autodetect.push({
395
+ p: 5,
396
+ test: (h, ...rest) => {
397
+ if (!rest.length && type(h) === 'string' && w3cx11[h.toLowerCase()]) {
398
+ return 'named';
399
+ }
400
+ }
401
+ });
402
+
403
+ Color.prototype.alpha = function (a, mutate = false) {
404
+ if (a !== undefined && type(a) === 'number') {
405
+ if (mutate) {
406
+ this._rgb[3] = a;
407
+ return this;
408
+ }
409
+ return new Color([this._rgb[0], this._rgb[1], this._rgb[2], a], 'rgb');
410
+ }
411
+ return this._rgb[3];
412
+ };
413
+
414
+ Color.prototype.clipped = function () {
415
+ return this._rgb._clipped || false;
416
+ };
417
+
418
+ const labConstants = {
419
+ // Corresponds roughly to RGB brighter/darker
420
+ Kn: 18,
421
+
422
+ // D65 standard referent
423
+ labWhitePoint: 'd65',
424
+ Xn: 0.95047,
425
+ Yn: 1,
426
+ Zn: 1.08883,
427
+
428
+ t0: 0.137931034, // 4 / 29
429
+ t1: 0.206896552, // 6 / 29
430
+ t2: 0.12841855, // 3 * t1 * t1
431
+ t3: 0.008856452, // t1 * t1 * t1,
432
+
433
+ kE: 216.0 / 24389.0,
434
+ kKE: 8.0,
435
+ kK: 24389.0 / 27.0,
436
+
437
+ RefWhiteRGB: {
438
+ // sRGB
439
+ X: 0.95047,
440
+ Y: 1,
441
+ Z: 1.08883
442
+ },
443
+
444
+ MtxRGB2XYZ: {
445
+ m00: 0.4124564390896922,
446
+ m01: 0.21267285140562253,
447
+ m02: 0.0193338955823293,
448
+ m10: 0.357576077643909,
449
+ m11: 0.715152155287818,
450
+ m12: 0.11919202588130297,
451
+ m20: 0.18043748326639894,
452
+ m21: 0.07217499330655958,
453
+ m22: 0.9503040785363679
454
+ },
455
+
456
+ MtxXYZ2RGB: {
457
+ m00: 3.2404541621141045,
458
+ m01: -0.9692660305051868,
459
+ m02: 0.055643430959114726,
460
+ m10: -1.5371385127977166,
461
+ m11: 1.8760108454466942,
462
+ m12: -0.2040259135167538,
463
+ m20: -0.498531409556016,
464
+ m21: 0.041556017530349834,
465
+ m22: 1.0572251882231791
466
+ },
467
+
468
+ // used in rgb2xyz
469
+ As: 0.9414285350000001,
470
+ Bs: 1.040417467,
471
+ Cs: 1.089532651,
472
+
473
+ MtxAdaptMa: {
474
+ m00: 0.8951,
475
+ m01: -0.7502,
476
+ m02: 0.0389,
477
+ m10: 0.2664,
478
+ m11: 1.7135,
479
+ m12: -0.0685,
480
+ m20: -0.1614,
481
+ m21: 0.0367,
482
+ m22: 1.0296
483
+ },
484
+
485
+ MtxAdaptMaI: {
486
+ m00: 0.9869929054667123,
487
+ m01: 0.43230526972339456,
488
+ m02: -0.008528664575177328,
489
+ m10: -0.14705425642099013,
490
+ m11: 0.5183602715367776,
491
+ m12: 0.04004282165408487,
492
+ m20: 0.15996265166373125,
493
+ m21: 0.0492912282128556,
494
+ m22: 0.9684866957875502
495
+ }
496
+ };
497
+
498
+ // taken from https://de.mathworks.com/help/images/ref/whitepoint.html
499
+ const ILLUMINANTS = new Map([
500
+ // ASTM E308-01
501
+ ['a', [1.0985, 0.35585]],
502
+ // Wyszecki & Stiles, p. 769
503
+ ['b', [1.0985, 0.35585]],
504
+ // C ASTM E308-01
505
+ ['c', [0.98074, 1.18232]],
506
+ // D50 (ASTM E308-01)
507
+ ['d50', [0.96422, 0.82521]],
508
+ // D55 (ASTM E308-01)
509
+ ['d55', [0.95682, 0.92149]],
510
+ // D65 (ASTM E308-01)
511
+ ['d65', [0.95047, 1.08883]],
512
+ // E (ASTM E308-01)
513
+ ['e', [1, 1, 1]],
514
+ // F2 (ASTM E308-01)
515
+ ['f2', [0.99186, 0.67393]],
516
+ // F7 (ASTM E308-01)
517
+ ['f7', [0.95041, 1.08747]],
518
+ // F11 (ASTM E308-01)
519
+ ['f11', [1.00962, 0.6435]],
520
+ ['icc', [0.96422, 0.82521]]
521
+ ]);
522
+
523
+ function setLabWhitePoint(name) {
524
+ const ill = ILLUMINANTS.get(String(name).toLowerCase());
525
+ if (!ill) {
526
+ throw new Error('unknown Lab illuminant ' + name);
527
+ }
528
+ labConstants.labWhitePoint = name;
529
+ labConstants.Xn = ill[0];
530
+ labConstants.Zn = ill[1];
531
+ }
532
+
533
+ function getLabWhitePoint() {
534
+ return labConstants.labWhitePoint;
535
+ }
536
+
537
+ /*
538
+ * L* [0..100]
539
+ * a [-100..100]
540
+ * b [-100..100]
541
+ */
542
+ const lab2rgb = (...args) => {
543
+ args = unpack(args, 'lab');
544
+ const [L, a, b] = args;
545
+ const [x, y, z] = lab2xyz(L, a, b);
546
+ const [r, g, b_] = xyz2rgb(x, y, z);
547
+ return [r, g, b_, args.length > 3 ? args[3] : 1];
548
+ };
549
+
550
+ const lab2xyz = (L, a, b) => {
551
+ const { kE, kK, kKE, Xn, Yn, Zn } = labConstants;
552
+
553
+ const fy = (L + 16.0) / 116.0;
554
+ const fx = 0.002 * a + fy;
555
+ const fz = fy - 0.005 * b;
556
+
557
+ const fx3 = fx * fx * fx;
558
+ const fz3 = fz * fz * fz;
559
+
560
+ const xr = fx3 > kE ? fx3 : (116.0 * fx - 16.0) / kK;
561
+ const yr = L > kKE ? Math.pow((L + 16.0) / 116.0, 3.0) : L / kK;
562
+ const zr = fz3 > kE ? fz3 : (116.0 * fz - 16.0) / kK;
563
+
564
+ const x = xr * Xn;
565
+ const y = yr * Yn;
566
+ const z = zr * Zn;
567
+
568
+ return [x, y, z];
569
+ };
570
+
571
+ const compand = (linear) => {
572
+ /* sRGB */
573
+ const sign = Math.sign(linear);
574
+ linear = Math.abs(linear);
575
+ return (
576
+ (linear <= 0.0031308
577
+ ? linear * 12.92
578
+ : 1.055 * Math.pow(linear, 1.0 / 2.4) - 0.055) * sign
579
+ );
580
+ };
581
+
582
+ const xyz2rgb = (x, y, z) => {
583
+ const { MtxAdaptMa, MtxAdaptMaI, MtxXYZ2RGB, RefWhiteRGB, Xn, Yn, Zn } =
584
+ labConstants;
585
+
586
+ const As = Xn * MtxAdaptMa.m00 + Yn * MtxAdaptMa.m10 + Zn * MtxAdaptMa.m20;
587
+ const Bs = Xn * MtxAdaptMa.m01 + Yn * MtxAdaptMa.m11 + Zn * MtxAdaptMa.m21;
588
+ const Cs = Xn * MtxAdaptMa.m02 + Yn * MtxAdaptMa.m12 + Zn * MtxAdaptMa.m22;
589
+
590
+ const Ad =
591
+ RefWhiteRGB.X * MtxAdaptMa.m00 +
592
+ RefWhiteRGB.Y * MtxAdaptMa.m10 +
593
+ RefWhiteRGB.Z * MtxAdaptMa.m20;
594
+ const Bd =
595
+ RefWhiteRGB.X * MtxAdaptMa.m01 +
596
+ RefWhiteRGB.Y * MtxAdaptMa.m11 +
597
+ RefWhiteRGB.Z * MtxAdaptMa.m21;
598
+ const Cd =
599
+ RefWhiteRGB.X * MtxAdaptMa.m02 +
600
+ RefWhiteRGB.Y * MtxAdaptMa.m12 +
601
+ RefWhiteRGB.Z * MtxAdaptMa.m22;
602
+
603
+ const X1 =
604
+ (x * MtxAdaptMa.m00 + y * MtxAdaptMa.m10 + z * MtxAdaptMa.m20) *
605
+ (Ad / As);
606
+ const Y1 =
607
+ (x * MtxAdaptMa.m01 + y * MtxAdaptMa.m11 + z * MtxAdaptMa.m21) *
608
+ (Bd / Bs);
609
+ const Z1 =
610
+ (x * MtxAdaptMa.m02 + y * MtxAdaptMa.m12 + z * MtxAdaptMa.m22) *
611
+ (Cd / Cs);
612
+
613
+ const X2 =
614
+ X1 * MtxAdaptMaI.m00 + Y1 * MtxAdaptMaI.m10 + Z1 * MtxAdaptMaI.m20;
615
+ const Y2 =
616
+ X1 * MtxAdaptMaI.m01 + Y1 * MtxAdaptMaI.m11 + Z1 * MtxAdaptMaI.m21;
617
+ const Z2 =
618
+ X1 * MtxAdaptMaI.m02 + Y1 * MtxAdaptMaI.m12 + Z1 * MtxAdaptMaI.m22;
619
+
620
+ const r = compand(
621
+ X2 * MtxXYZ2RGB.m00 + Y2 * MtxXYZ2RGB.m10 + Z2 * MtxXYZ2RGB.m20
622
+ );
623
+ const g = compand(
624
+ X2 * MtxXYZ2RGB.m01 + Y2 * MtxXYZ2RGB.m11 + Z2 * MtxXYZ2RGB.m21
625
+ );
626
+ const b = compand(
627
+ X2 * MtxXYZ2RGB.m02 + Y2 * MtxXYZ2RGB.m12 + Z2 * MtxXYZ2RGB.m22
628
+ );
629
+
630
+ return [r * 255, g * 255, b * 255];
631
+ };
632
+
633
+ const rgb2lab = (...args) => {
634
+ const [r, g, b, ...rest] = unpack(args, 'rgb');
635
+ const [x, y, z] = rgb2xyz(r, g, b);
636
+ const [L, a, b_] = xyz2lab(x, y, z);
637
+ return [L, a, b_, ...(rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])];
638
+ };
639
+
640
+ function xyz2lab(x, y, z) {
641
+ const { Xn, Yn, Zn, kE, kK } = labConstants;
642
+ const xr = x / Xn;
643
+ const yr = y / Yn;
644
+ const zr = z / Zn;
645
+
646
+ const fx = xr > kE ? Math.pow(xr, 1.0 / 3.0) : (kK * xr + 16.0) / 116.0;
647
+ const fy = yr > kE ? Math.pow(yr, 1.0 / 3.0) : (kK * yr + 16.0) / 116.0;
648
+ const fz = zr > kE ? Math.pow(zr, 1.0 / 3.0) : (kK * zr + 16.0) / 116.0;
649
+
650
+ return [116.0 * fy - 16.0, 500.0 * (fx - fy), 200.0 * (fy - fz)];
651
+ }
652
+
653
+ function gammaAdjustSRGB(companded) {
654
+ const sign = Math.sign(companded);
655
+ companded = Math.abs(companded);
656
+ const linear =
657
+ companded <= 0.04045
658
+ ? companded / 12.92
659
+ : Math.pow((companded + 0.055) / 1.055, 2.4);
660
+ return linear * sign;
661
+ }
662
+
663
+ const rgb2xyz = (r, g, b) => {
664
+ // normalize and gamma adjust
665
+ r = gammaAdjustSRGB(r / 255);
666
+ g = gammaAdjustSRGB(g / 255);
667
+ b = gammaAdjustSRGB(b / 255);
668
+
669
+ const { MtxRGB2XYZ, MtxAdaptMa, MtxAdaptMaI, Xn, Yn, Zn, As, Bs, Cs } =
670
+ labConstants;
671
+
672
+ let x = r * MtxRGB2XYZ.m00 + g * MtxRGB2XYZ.m10 + b * MtxRGB2XYZ.m20;
673
+ let y = r * MtxRGB2XYZ.m01 + g * MtxRGB2XYZ.m11 + b * MtxRGB2XYZ.m21;
674
+ let z = r * MtxRGB2XYZ.m02 + g * MtxRGB2XYZ.m12 + b * MtxRGB2XYZ.m22;
675
+
676
+ const Ad = Xn * MtxAdaptMa.m00 + Yn * MtxAdaptMa.m10 + Zn * MtxAdaptMa.m20;
677
+ const Bd = Xn * MtxAdaptMa.m01 + Yn * MtxAdaptMa.m11 + Zn * MtxAdaptMa.m21;
678
+ const Cd = Xn * MtxAdaptMa.m02 + Yn * MtxAdaptMa.m12 + Zn * MtxAdaptMa.m22;
679
+
680
+ let X = x * MtxAdaptMa.m00 + y * MtxAdaptMa.m10 + z * MtxAdaptMa.m20;
681
+ let Y = x * MtxAdaptMa.m01 + y * MtxAdaptMa.m11 + z * MtxAdaptMa.m21;
682
+ let Z = x * MtxAdaptMa.m02 + y * MtxAdaptMa.m12 + z * MtxAdaptMa.m22;
683
+
684
+ X *= Ad / As;
685
+ Y *= Bd / Bs;
686
+ Z *= Cd / Cs;
687
+
688
+ x = X * MtxAdaptMaI.m00 + Y * MtxAdaptMaI.m10 + Z * MtxAdaptMaI.m20;
689
+ y = X * MtxAdaptMaI.m01 + Y * MtxAdaptMaI.m11 + Z * MtxAdaptMaI.m21;
690
+ z = X * MtxAdaptMaI.m02 + Y * MtxAdaptMaI.m12 + Z * MtxAdaptMaI.m22;
691
+
692
+ return [x, y, z];
693
+ };
694
+
695
+ Color.prototype.lab = function () {
696
+ return rgb2lab(this._rgb);
697
+ };
698
+
699
+ const lab$1 = (...args) => new Color(...args, 'lab');
700
+ Object.assign(chroma, { lab: lab$1, getLabWhitePoint, setLabWhitePoint });
701
+
702
+ input.format.lab = lab2rgb;
703
+
704
+ input.autodetect.push({
705
+ p: 2,
706
+ test: (...args) => {
707
+ args = unpack(args, 'lab');
708
+ if (type(args) === 'array' && args.length === 3) {
709
+ return 'lab';
710
+ }
711
+ }
712
+ });
713
+
714
+ Color.prototype.darken = function (amount = 1) {
715
+ const me = this;
716
+ const lab = me.lab();
717
+ lab[0] -= labConstants.Kn * amount;
718
+ return new Color(lab, 'lab').alpha(me.alpha(), true);
719
+ };
720
+
721
+ Color.prototype.brighten = function (amount = 1) {
722
+ return this.darken(-amount);
723
+ };
724
+
725
+ Color.prototype.darker = Color.prototype.darken;
726
+ Color.prototype.brighter = Color.prototype.brighten;
727
+
728
+ Color.prototype.get = function (mc) {
729
+ const [mode, channel] = mc.split('.');
730
+ const src = this[mode]();
731
+ if (channel) {
732
+ const i = mode.indexOf(channel) - (mode.substr(0, 2) === 'ok' ? 2 : 0);
733
+ if (i > -1) return src[i];
734
+ throw new Error(`unknown channel ${channel} in mode ${mode}`);
735
+ } else {
736
+ return src;
737
+ }
738
+ };
739
+
740
+ const { pow: pow$6 } = Math;
741
+
742
+ const EPS = 1e-7;
743
+ const MAX_ITER = 20;
744
+
745
+ Color.prototype.luminance = function (lum, mode = 'rgb') {
746
+ if (lum !== undefined && type(lum) === 'number') {
747
+ if (lum === 0) {
748
+ // return pure black
749
+ return new Color([0, 0, 0, this._rgb[3]], 'rgb');
750
+ }
751
+ if (lum === 1) {
752
+ // return pure white
753
+ return new Color([255, 255, 255, this._rgb[3]], 'rgb');
754
+ }
755
+ // compute new color using...
756
+ let cur_lum = this.luminance();
757
+ let max_iter = MAX_ITER;
758
+
759
+ const test = (low, high) => {
760
+ const mid = low.interpolate(high, 0.5, mode);
761
+ const lm = mid.luminance();
762
+ if (Math.abs(lum - lm) < EPS || !max_iter--) {
763
+ // close enough
764
+ return mid;
765
+ }
766
+ return lm > lum ? test(low, mid) : test(mid, high);
767
+ };
768
+
769
+ const rgb = (
770
+ cur_lum > lum
771
+ ? test(new Color([0, 0, 0]), this)
772
+ : test(this, new Color([255, 255, 255]))
773
+ ).rgb();
774
+ return new Color([...rgb, this._rgb[3]]);
775
+ }
776
+ return rgb2luminance(...this._rgb.slice(0, 3));
777
+ };
778
+
779
+ const rgb2luminance = (r, g, b) => {
780
+ // relative luminance
781
+ // see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
782
+ r = luminance_x(r);
783
+ g = luminance_x(g);
784
+ b = luminance_x(b);
785
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
786
+ };
787
+
788
+ const luminance_x = (x) => {
789
+ x /= 255;
790
+ return x <= 0.03928 ? x / 12.92 : pow$6((x + 0.055) / 1.055, 2.4);
791
+ };
792
+
793
+ const index = {};
794
+
795
+ const mix = (col1, col2, f = 0.5, ...rest) => {
796
+ let mode = rest[0] || 'lrgb';
797
+ if (!index[mode] && !rest.length) {
798
+ // fall back to the first supported mode
799
+ mode = Object.keys(index)[0];
800
+ }
801
+ if (!index[mode]) {
802
+ throw new Error(`interpolation mode ${mode} is not defined`);
803
+ }
804
+ if (type(col1) !== 'object') col1 = new Color(col1);
805
+ if (type(col2) !== 'object') col2 = new Color(col2);
806
+ return index[mode](col1, col2, f).alpha(
807
+ col1.alpha() + f * (col2.alpha() - col1.alpha())
808
+ );
809
+ };
810
+
811
+ Color.prototype.mix = Color.prototype.interpolate = function (
812
+ col2,
813
+ f = 0.5,
814
+ ...rest
815
+ ) {
816
+ return mix(this, col2, f, ...rest);
817
+ };
818
+
819
+ Color.prototype.premultiply = function (mutate = false) {
820
+ const rgb = this._rgb;
821
+ const a = rgb[3];
822
+ if (mutate) {
823
+ this._rgb = [rgb[0] * a, rgb[1] * a, rgb[2] * a, a];
824
+ return this;
825
+ } else {
826
+ return new Color([rgb[0] * a, rgb[1] * a, rgb[2] * a, a], 'rgb');
827
+ }
828
+ };
829
+
830
+ const { sin: sin$3, cos: cos$4 } = Math;
831
+
832
+ const lch2lab = (...args) => {
833
+ /*
834
+ Convert from a qualitative parameter h and a quantitative parameter l to a 24-bit pixel.
835
+ These formulas were invented by David Dalrymple to obtain maximum contrast without going
836
+ out of gamut if the parameters are in the range 0-1.
837
+
838
+ A saturation multiplier was added by Gregor Aisch
839
+ */
840
+ let [l, c, h] = unpack(args, 'lch');
841
+ if (isNaN(h)) h = 0;
842
+ h = h * DEG2RAD;
843
+ return [l, cos$4(h) * c, sin$3(h) * c];
844
+ };
845
+
846
+ const lch2rgb = (...args) => {
847
+ args = unpack(args, 'lch');
848
+ const [l, c, h] = args;
849
+ const [L, a, b_] = lch2lab(l, c, h);
850
+ const [r, g, b] = lab2rgb(L, a, b_);
851
+ return [r, g, b, args.length > 3 ? args[3] : 1];
852
+ };
853
+
854
+ const hcl2rgb = (...args) => {
855
+ const hcl = unpack(args, 'hcl').reverse();
856
+ return lch2rgb(...hcl);
857
+ };
858
+
859
+ const { sqrt: sqrt$4, atan2: atan2$2, round: round$4 } = Math;
860
+
861
+ const lab2lch = (...args) => {
862
+ const [l, a, b] = unpack(args, 'lab');
863
+ const c = sqrt$4(a * a + b * b);
864
+ let h = (atan2$2(b, a) * RAD2DEG + 360) % 360;
865
+ if (round$4(c * 10000) === 0) h = Number.NaN;
866
+ return [l, c, h];
867
+ };
868
+
869
+ const rgb2lch = (...args) => {
870
+ const [r, g, b, ...rest] = unpack(args, 'rgb');
871
+ const [l, a, b_] = rgb2lab(r, g, b);
872
+ const [L, c, h] = lab2lch(l, a, b_);
873
+ return [L, c, h, ...(rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])];
874
+ };
875
+
876
+ Color.prototype.lch = function () {
877
+ return rgb2lch(this._rgb);
878
+ };
879
+ Color.prototype.hcl = function () {
880
+ return rgb2lch(this._rgb).reverse();
881
+ };
882
+
883
+ const lch$1 = (...args) => new Color(...args, 'lch');
884
+ const hcl = (...args) => new Color(...args, 'hcl');
885
+
886
+ Object.assign(chroma, { lch: lch$1, hcl });
887
+
888
+ input.format.lch = lch2rgb;
889
+ input.format.hcl = hcl2rgb;
890
+ ['lch', 'hcl'].forEach((m) =>
891
+ input.autodetect.push({
892
+ p: 2,
893
+ test: (...args) => {
894
+ args = unpack(args, m);
895
+ if (type(args) === 'array' && args.length === 3) {
896
+ return m;
897
+ }
898
+ }
899
+ })
900
+ );
901
+
902
+ Color.prototype.saturate = function (amount = 1) {
903
+ const me = this;
904
+ const lch = me.lch();
905
+ lch[1] += labConstants.Kn * amount;
906
+ if (lch[1] < 0) lch[1] = 0;
907
+ return new Color(lch, 'lch').alpha(me.alpha(), true);
908
+ };
909
+
910
+ Color.prototype.desaturate = function (amount = 1) {
911
+ return this.saturate(-amount);
912
+ };
913
+
914
+ Color.prototype.set = function (mc, value, mutate = false) {
915
+ const [mode, channel] = mc.split('.');
916
+ const src = this[mode]();
917
+ if (channel) {
918
+ const i = mode.indexOf(channel) - (mode.substr(0, 2) === 'ok' ? 2 : 0);
919
+ if (i > -1) {
920
+ if (type(value) == 'string') {
921
+ switch (value.charAt(0)) {
922
+ case '+':
923
+ src[i] += +value;
924
+ break;
925
+ case '-':
926
+ src[i] += +value;
927
+ break;
928
+ case '*':
929
+ src[i] *= +value.substr(1);
930
+ break;
931
+ case '/':
932
+ src[i] /= +value.substr(1);
933
+ break;
934
+ default:
935
+ src[i] = +value;
936
+ }
937
+ } else if (type(value) === 'number') {
938
+ src[i] = value;
939
+ } else {
940
+ throw new Error(`unsupported value for Color.set`);
941
+ }
942
+ const out = new Color(src, mode);
943
+ if (mutate) {
944
+ this._rgb = out._rgb;
945
+ return this;
946
+ }
947
+ return out;
948
+ }
949
+ throw new Error(`unknown channel ${channel} in mode ${mode}`);
950
+ } else {
951
+ return src;
952
+ }
953
+ };
954
+
955
+ Color.prototype.tint = function (f = 0.5, ...rest) {
956
+ return mix(this, 'white', f, ...rest);
957
+ };
958
+
959
+ Color.prototype.shade = function (f = 0.5, ...rest) {
960
+ return mix(this, 'black', f, ...rest);
961
+ };
962
+
963
+ const rgb$1 = (col1, col2, f) => {
964
+ const xyz0 = col1._rgb;
965
+ const xyz1 = col2._rgb;
966
+ return new Color(
967
+ xyz0[0] + f * (xyz1[0] - xyz0[0]),
968
+ xyz0[1] + f * (xyz1[1] - xyz0[1]),
969
+ xyz0[2] + f * (xyz1[2] - xyz0[2]),
970
+ 'rgb'
971
+ );
972
+ };
973
+
974
+ // register interpolator
975
+ index.rgb = rgb$1;
976
+
977
+ const { sqrt: sqrt$3, pow: pow$5 } = Math;
978
+
979
+ const lrgb = (col1, col2, f) => {
980
+ const [x1, y1, z1] = col1._rgb;
981
+ const [x2, y2, z2] = col2._rgb;
982
+ return new Color(
983
+ sqrt$3(pow$5(x1, 2) * (1 - f) + pow$5(x2, 2) * f),
984
+ sqrt$3(pow$5(y1, 2) * (1 - f) + pow$5(y2, 2) * f),
985
+ sqrt$3(pow$5(z1, 2) * (1 - f) + pow$5(z2, 2) * f),
986
+ 'rgb'
987
+ );
988
+ };
989
+
990
+ // register interpolator
991
+ index.lrgb = lrgb;
992
+
993
+ const lab = (col1, col2, f) => {
994
+ const xyz0 = col1.lab();
995
+ const xyz1 = col2.lab();
996
+ return new Color(
997
+ xyz0[0] + f * (xyz1[0] - xyz0[0]),
998
+ xyz0[1] + f * (xyz1[1] - xyz0[1]),
999
+ xyz0[2] + f * (xyz1[2] - xyz0[2]),
1000
+ 'lab'
1001
+ );
1002
+ };
1003
+
1004
+ // register interpolator
1005
+ index.lab = lab;
1006
+
1007
+ const interpolate_hsx = (col1, col2, f, m) => {
1008
+ let xyz0, xyz1;
1009
+ if (m === 'hsl') {
1010
+ xyz0 = col1.hsl();
1011
+ xyz1 = col2.hsl();
1012
+ } else if (m === 'hsv') {
1013
+ xyz0 = col1.hsv();
1014
+ xyz1 = col2.hsv();
1015
+ } else if (m === 'hcg') {
1016
+ xyz0 = col1.hcg();
1017
+ xyz1 = col2.hcg();
1018
+ } else if (m === 'hsi') {
1019
+ xyz0 = col1.hsi();
1020
+ xyz1 = col2.hsi();
1021
+ } else if (m === 'lch' || m === 'hcl') {
1022
+ m = 'hcl';
1023
+ xyz0 = col1.hcl();
1024
+ xyz1 = col2.hcl();
1025
+ } else if (m === 'oklch') {
1026
+ xyz0 = col1.oklch().reverse();
1027
+ xyz1 = col2.oklch().reverse();
1028
+ }
1029
+
1030
+ let hue0, hue1, sat0, sat1, lbv0, lbv1;
1031
+ if (m.substr(0, 1) === 'h' || m === 'oklch') {
1032
+ [hue0, sat0, lbv0] = xyz0;
1033
+ [hue1, sat1, lbv1] = xyz1;
1034
+ }
1035
+
1036
+ let sat, hue, lbv, dh;
1037
+
1038
+ if (!isNaN(hue0) && !isNaN(hue1)) {
1039
+ // both colors have hue
1040
+ if (hue1 > hue0 && hue1 - hue0 > 180) {
1041
+ dh = hue1 - (hue0 + 360);
1042
+ } else if (hue1 < hue0 && hue0 - hue1 > 180) {
1043
+ dh = hue1 + 360 - hue0;
1044
+ } else {
1045
+ dh = hue1 - hue0;
1046
+ }
1047
+ hue = hue0 + f * dh;
1048
+ } else if (!isNaN(hue0)) {
1049
+ hue = hue0;
1050
+ if ((lbv1 == 1 || lbv1 == 0) && m != 'hsv') sat = sat0;
1051
+ } else if (!isNaN(hue1)) {
1052
+ hue = hue1;
1053
+ if ((lbv0 == 1 || lbv0 == 0) && m != 'hsv') sat = sat1;
1054
+ } else {
1055
+ hue = Number.NaN;
1056
+ }
1057
+
1058
+ if (sat === undefined) sat = sat0 + f * (sat1 - sat0);
1059
+ lbv = lbv0 + f * (lbv1 - lbv0);
1060
+ return m === 'oklch'
1061
+ ? new Color([lbv, sat, hue], m)
1062
+ : new Color([hue, sat, lbv], m);
1063
+ };
1064
+
1065
+ const lch = (col1, col2, f) => {
1066
+ return interpolate_hsx(col1, col2, f, 'lch');
1067
+ };
1068
+
1069
+ // register interpolator
1070
+ index.lch = lch;
1071
+ index.hcl = lch;
1072
+
1073
+ const num2rgb = (num) => {
1074
+ if (type(num) == 'number' && num >= 0 && num <= 0xffffff) {
1075
+ const r = num >> 16;
1076
+ const g = (num >> 8) & 0xff;
1077
+ const b = num & 0xff;
1078
+ return [r, g, b, 1];
1079
+ }
1080
+ throw new Error('unknown num color: ' + num);
1081
+ };
1082
+
1083
+ const rgb2num = (...args) => {
1084
+ const [r, g, b] = unpack(args, 'rgb');
1085
+ return (r << 16) + (g << 8) + b;
1086
+ };
1087
+
1088
+ Color.prototype.num = function () {
1089
+ return rgb2num(this._rgb);
1090
+ };
1091
+
1092
+ const num$1 = (...args) => new Color(...args, 'num');
1093
+
1094
+ Object.assign(chroma, { num: num$1 });
1095
+
1096
+ input.format.num = num2rgb;
1097
+
1098
+ input.autodetect.push({
1099
+ p: 5,
1100
+ test: (...args) => {
1101
+ if (
1102
+ args.length === 1 &&
1103
+ type(args[0]) === 'number' &&
1104
+ args[0] >= 0 &&
1105
+ args[0] <= 0xffffff
1106
+ ) {
1107
+ return 'num';
1108
+ }
1109
+ }
1110
+ });
1111
+
1112
+ const num = (col1, col2, f) => {
1113
+ const c1 = col1.num();
1114
+ const c2 = col2.num();
1115
+ return new Color(c1 + f * (c2 - c1), 'num');
1116
+ };
1117
+
1118
+ // register interpolator
1119
+ index.num = num;
1120
+
1121
+ const { floor: floor$3 } = Math;
1122
+
1123
+ /*
1124
+ * this is basically just HSV with some minor tweaks
1125
+ *
1126
+ * hue.. [0..360]
1127
+ * chroma .. [0..1]
1128
+ * grayness .. [0..1]
1129
+ */
1130
+
1131
+ const hcg2rgb = (...args) => {
1132
+ args = unpack(args, 'hcg');
1133
+ let [h, c, _g] = args;
1134
+ let r, g, b;
1135
+ _g = _g * 255;
1136
+ const _c = c * 255;
1137
+ if (c === 0) {
1138
+ r = g = b = _g;
1139
+ } else {
1140
+ if (h === 360) h = 0;
1141
+ if (h > 360) h -= 360;
1142
+ if (h < 0) h += 360;
1143
+ h /= 60;
1144
+ const i = floor$3(h);
1145
+ const f = h - i;
1146
+ const p = _g * (1 - c);
1147
+ const q = p + _c * (1 - f);
1148
+ const t = p + _c * f;
1149
+ const v = p + _c;
1150
+ switch (i) {
1151
+ case 0:
1152
+ [r, g, b] = [v, t, p];
1153
+ break;
1154
+ case 1:
1155
+ [r, g, b] = [q, v, p];
1156
+ break;
1157
+ case 2:
1158
+ [r, g, b] = [p, v, t];
1159
+ break;
1160
+ case 3:
1161
+ [r, g, b] = [p, q, v];
1162
+ break;
1163
+ case 4:
1164
+ [r, g, b] = [t, p, v];
1165
+ break;
1166
+ case 5:
1167
+ [r, g, b] = [v, p, q];
1168
+ break;
1169
+ }
1170
+ }
1171
+ return [r, g, b, args.length > 3 ? args[3] : 1];
1172
+ };
1173
+
1174
+ const rgb2hcg = (...args) => {
1175
+ const [r, g, b] = unpack(args, 'rgb');
1176
+ const minRgb = min$3(r, g, b);
1177
+ const maxRgb = max$3(r, g, b);
1178
+ const delta = maxRgb - minRgb;
1179
+ const c = (delta * 100) / 255;
1180
+ const _g = (minRgb / (255 - delta)) * 100;
1181
+ let h;
1182
+ if (delta === 0) {
1183
+ h = Number.NaN;
1184
+ } else {
1185
+ if (r === maxRgb) h = (g - b) / delta;
1186
+ if (g === maxRgb) h = 2 + (b - r) / delta;
1187
+ if (b === maxRgb) h = 4 + (r - g) / delta;
1188
+ h *= 60;
1189
+ if (h < 0) h += 360;
1190
+ }
1191
+ return [h, c, _g];
1192
+ };
1193
+
1194
+ Color.prototype.hcg = function () {
1195
+ return rgb2hcg(this._rgb);
1196
+ };
1197
+
1198
+ const hcg$1 = (...args) => new Color(...args, 'hcg');
1199
+ chroma.hcg = hcg$1;
1200
+
1201
+ input.format.hcg = hcg2rgb;
1202
+
1203
+ input.autodetect.push({
1204
+ p: 1,
1205
+ test: (...args) => {
1206
+ args = unpack(args, 'hcg');
1207
+ if (type(args) === 'array' && args.length === 3) {
1208
+ return 'hcg';
1209
+ }
1210
+ }
1211
+ });
1212
+
1213
+ const hcg = (col1, col2, f) => {
1214
+ return interpolate_hsx(col1, col2, f, 'hcg');
1215
+ };
1216
+
1217
+ // register interpolator
1218
+ index.hcg = hcg;
1219
+
1220
+ const { cos: cos$3 } = Math;
1221
+
1222
+ /*
1223
+ * hue [0..360]
1224
+ * saturation [0..1]
1225
+ * intensity [0..1]
1226
+ */
1227
+ const hsi2rgb = (...args) => {
1228
+ /*
1229
+ borrowed from here:
1230
+ http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/hsi2rgb.cpp
1231
+ */
1232
+ args = unpack(args, 'hsi');
1233
+ let [h, s, i] = args;
1234
+ let r, g, b;
1235
+
1236
+ if (isNaN(h)) h = 0;
1237
+ if (isNaN(s)) s = 0;
1238
+ // normalize hue
1239
+ if (h > 360) h -= 360;
1240
+ if (h < 0) h += 360;
1241
+ h /= 360;
1242
+ if (h < 1 / 3) {
1243
+ b = (1 - s) / 3;
1244
+ r = (1 + (s * cos$3(TWOPI * h)) / cos$3(PITHIRD - TWOPI * h)) / 3;
1245
+ g = 1 - (b + r);
1246
+ } else if (h < 2 / 3) {
1247
+ h -= 1 / 3;
1248
+ r = (1 - s) / 3;
1249
+ g = (1 + (s * cos$3(TWOPI * h)) / cos$3(PITHIRD - TWOPI * h)) / 3;
1250
+ b = 1 - (r + g);
1251
+ } else {
1252
+ h -= 2 / 3;
1253
+ g = (1 - s) / 3;
1254
+ b = (1 + (s * cos$3(TWOPI * h)) / cos$3(PITHIRD - TWOPI * h)) / 3;
1255
+ r = 1 - (g + b);
1256
+ }
1257
+ r = limit(i * r * 3);
1258
+ g = limit(i * g * 3);
1259
+ b = limit(i * b * 3);
1260
+ return [r * 255, g * 255, b * 255, args.length > 3 ? args[3] : 1];
1261
+ };
1262
+
1263
+ const { min: min$2, sqrt: sqrt$2, acos } = Math;
1264
+
1265
+ const rgb2hsi = (...args) => {
1266
+ /*
1267
+ borrowed from here:
1268
+ http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/rgb2hsi.cpp
1269
+ */
1270
+ let [r, g, b] = unpack(args, 'rgb');
1271
+ r /= 255;
1272
+ g /= 255;
1273
+ b /= 255;
1274
+ let h;
1275
+ const min_ = min$2(r, g, b);
1276
+ const i = (r + g + b) / 3;
1277
+ const s = i > 0 ? 1 - min_ / i : 0;
1278
+ if (s === 0) {
1279
+ h = NaN;
1280
+ } else {
1281
+ h = (r - g + (r - b)) / 2;
1282
+ h /= sqrt$2((r - g) * (r - g) + (r - b) * (g - b));
1283
+ h = acos(h);
1284
+ if (b > g) {
1285
+ h = TWOPI - h;
1286
+ }
1287
+ h /= TWOPI;
1288
+ }
1289
+ return [h * 360, s, i];
1290
+ };
1291
+
1292
+ Color.prototype.hsi = function () {
1293
+ return rgb2hsi(this._rgb);
1294
+ };
1295
+
1296
+ const hsi$1 = (...args) => new Color(...args, 'hsi');
1297
+ chroma.hsi = hsi$1;
1298
+
1299
+ input.format.hsi = hsi2rgb;
1300
+
1301
+ input.autodetect.push({
1302
+ p: 2,
1303
+ test: (...args) => {
1304
+ args = unpack(args, 'hsi');
1305
+ if (type(args) === 'array' && args.length === 3) {
1306
+ return 'hsi';
1307
+ }
1308
+ }
1309
+ });
1310
+
1311
+ const hsi = (col1, col2, f) => {
1312
+ return interpolate_hsx(col1, col2, f, 'hsi');
1313
+ };
1314
+
1315
+ // register interpolator
1316
+ index.hsi = hsi;
1317
+
1318
+ const hsl2rgb = (...args) => {
1319
+ args = unpack(args, 'hsl');
1320
+ const [h, s, l] = args;
1321
+ let r, g, b;
1322
+ if (s === 0) {
1323
+ r = g = b = l * 255;
1324
+ } else {
1325
+ const t3 = [0, 0, 0];
1326
+ const c = [0, 0, 0];
1327
+ const t2 = l < 0.5 ? l * (1 + s) : l + s - l * s;
1328
+ const t1 = 2 * l - t2;
1329
+ const h_ = h / 360;
1330
+ t3[0] = h_ + 1 / 3;
1331
+ t3[1] = h_;
1332
+ t3[2] = h_ - 1 / 3;
1333
+ for (let i = 0; i < 3; i++) {
1334
+ if (t3[i] < 0) t3[i] += 1;
1335
+ if (t3[i] > 1) t3[i] -= 1;
1336
+ if (6 * t3[i] < 1) c[i] = t1 + (t2 - t1) * 6 * t3[i];
1337
+ else if (2 * t3[i] < 1) c[i] = t2;
1338
+ else if (3 * t3[i] < 2) c[i] = t1 + (t2 - t1) * (2 / 3 - t3[i]) * 6;
1339
+ else c[i] = t1;
1340
+ }
1341
+ [r, g, b] = [c[0] * 255, c[1] * 255, c[2] * 255];
1342
+ }
1343
+ if (args.length > 3) {
1344
+ // keep alpha channel
1345
+ return [r, g, b, args[3]];
1346
+ }
1347
+ return [r, g, b, 1];
1348
+ };
1349
+
1350
+ /*
1351
+ * supported arguments:
1352
+ * - rgb2hsl(r,g,b)
1353
+ * - rgb2hsl(r,g,b,a)
1354
+ * - rgb2hsl([r,g,b])
1355
+ * - rgb2hsl([r,g,b,a])
1356
+ * - rgb2hsl({r,g,b,a})
1357
+ */
1358
+ const rgb2hsl$1 = (...args) => {
1359
+ args = unpack(args, 'rgba');
1360
+ let [r, g, b] = args;
1361
+
1362
+ r /= 255;
1363
+ g /= 255;
1364
+ b /= 255;
1365
+
1366
+ const minRgb = min$3(r, g, b);
1367
+ const maxRgb = max$3(r, g, b);
1368
+
1369
+ const l = (maxRgb + minRgb) / 2;
1370
+ let s, h;
1371
+
1372
+ if (maxRgb === minRgb) {
1373
+ s = 0;
1374
+ h = Number.NaN;
1375
+ } else {
1376
+ s =
1377
+ l < 0.5
1378
+ ? (maxRgb - minRgb) / (maxRgb + minRgb)
1379
+ : (maxRgb - minRgb) / (2 - maxRgb - minRgb);
1380
+ }
1381
+
1382
+ if (r == maxRgb) h = (g - b) / (maxRgb - minRgb);
1383
+ else if (g == maxRgb) h = 2 + (b - r) / (maxRgb - minRgb);
1384
+ else if (b == maxRgb) h = 4 + (r - g) / (maxRgb - minRgb);
1385
+
1386
+ h *= 60;
1387
+ if (h < 0) h += 360;
1388
+ if (args.length > 3 && args[3] !== undefined) return [h, s, l, args[3]];
1389
+ return [h, s, l];
1390
+ };
1391
+
1392
+ Color.prototype.hsl = function () {
1393
+ return rgb2hsl$1(this._rgb);
1394
+ };
1395
+
1396
+ const hsl$1 = (...args) => new Color(...args, 'hsl');
1397
+ chroma.hsl = hsl$1;
1398
+
1399
+ input.format.hsl = hsl2rgb;
1400
+
1401
+ input.autodetect.push({
1402
+ p: 2,
1403
+ test: (...args) => {
1404
+ args = unpack(args, 'hsl');
1405
+ if (type(args) === 'array' && args.length === 3) {
1406
+ return 'hsl';
1407
+ }
1408
+ }
1409
+ });
1410
+
1411
+ const hsl = (col1, col2, f) => {
1412
+ return interpolate_hsx(col1, col2, f, 'hsl');
1413
+ };
1414
+
1415
+ // register interpolator
1416
+ index.hsl = hsl;
1417
+
1418
+ const { floor: floor$2 } = Math;
1419
+
1420
+ const hsv2rgb = (...args) => {
1421
+ args = unpack(args, 'hsv');
1422
+ let [h, s, v] = args;
1423
+ let r, g, b;
1424
+ v *= 255;
1425
+ if (s === 0) {
1426
+ r = g = b = v;
1427
+ } else {
1428
+ if (h === 360) h = 0;
1429
+ if (h > 360) h -= 360;
1430
+ if (h < 0) h += 360;
1431
+ h /= 60;
1432
+
1433
+ const i = floor$2(h);
1434
+ const f = h - i;
1435
+ const p = v * (1 - s);
1436
+ const q = v * (1 - s * f);
1437
+ const t = v * (1 - s * (1 - f));
1438
+
1439
+ switch (i) {
1440
+ case 0:
1441
+ [r, g, b] = [v, t, p];
1442
+ break;
1443
+ case 1:
1444
+ [r, g, b] = [q, v, p];
1445
+ break;
1446
+ case 2:
1447
+ [r, g, b] = [p, v, t];
1448
+ break;
1449
+ case 3:
1450
+ [r, g, b] = [p, q, v];
1451
+ break;
1452
+ case 4:
1453
+ [r, g, b] = [t, p, v];
1454
+ break;
1455
+ case 5:
1456
+ [r, g, b] = [v, p, q];
1457
+ break;
1458
+ }
1459
+ }
1460
+ return [r, g, b, args.length > 3 ? args[3] : 1];
1461
+ };
1462
+
1463
+ const { min: min$1, max: max$2 } = Math;
1464
+
1465
+ /*
1466
+ * supported arguments:
1467
+ * - rgb2hsv(r,g,b)
1468
+ * - rgb2hsv([r,g,b])
1469
+ * - rgb2hsv({r,g,b})
1470
+ */
1471
+ const rgb2hsl = (...args) => {
1472
+ args = unpack(args, 'rgb');
1473
+ let [r, g, b] = args;
1474
+ const min_ = min$1(r, g, b);
1475
+ const max_ = max$2(r, g, b);
1476
+ const delta = max_ - min_;
1477
+ let h, s, v;
1478
+ v = max_ / 255.0;
1479
+ if (max_ === 0) {
1480
+ h = Number.NaN;
1481
+ s = 0;
1482
+ } else {
1483
+ s = delta / max_;
1484
+ if (r === max_) h = (g - b) / delta;
1485
+ if (g === max_) h = 2 + (b - r) / delta;
1486
+ if (b === max_) h = 4 + (r - g) / delta;
1487
+ h *= 60;
1488
+ if (h < 0) h += 360;
1489
+ }
1490
+ return [h, s, v];
1491
+ };
1492
+
1493
+ Color.prototype.hsv = function () {
1494
+ return rgb2hsl(this._rgb);
1495
+ };
1496
+
1497
+ const hsv$1 = (...args) => new Color(...args, 'hsv');
1498
+ chroma.hsv = hsv$1;
1499
+
1500
+ input.format.hsv = hsv2rgb;
1501
+
1502
+ input.autodetect.push({
1503
+ p: 2,
1504
+ test: (...args) => {
1505
+ args = unpack(args, 'hsv');
1506
+ if (type(args) === 'array' && args.length === 3) {
1507
+ return 'hsv';
1508
+ }
1509
+ }
1510
+ });
1511
+
1512
+ const hsv = (col1, col2, f) => {
1513
+ return interpolate_hsx(col1, col2, f, 'hsv');
1514
+ };
1515
+
1516
+ // register interpolator
1517
+ index.hsv = hsv;
1518
+
1519
+ // from https://www.w3.org/TR/css-color-4/multiply-matrices.js
1520
+ function multiplyMatrices(A, B) {
1521
+ let m = A.length;
1522
+
1523
+ if (!Array.isArray(A[0])) {
1524
+ // A is vector, convert to [[a, b, c, ...]]
1525
+ A = [A];
1526
+ }
1527
+
1528
+ if (!Array.isArray(B[0])) {
1529
+ // B is vector, convert to [[a], [b], [c], ...]]
1530
+ B = B.map((x) => [x]);
1531
+ }
1532
+
1533
+ let p = B[0].length;
1534
+ let B_cols = B[0].map((_, i) => B.map((x) => x[i])); // transpose B
1535
+ let product = A.map((row) =>
1536
+ B_cols.map((col) => {
1537
+ if (!Array.isArray(row)) {
1538
+ return col.reduce((a, c) => a + c * row, 0);
1539
+ }
1540
+
1541
+ return row.reduce((a, c, i) => a + c * (col[i] || 0), 0);
1542
+ })
1543
+ );
1544
+
1545
+ if (m === 1) {
1546
+ product = product[0]; // Avoid [[a, b, c, ...]]
1547
+ }
1548
+
1549
+ if (p === 1) {
1550
+ return product.map((x) => x[0]); // Avoid [[a], [b], [c], ...]]
1551
+ }
1552
+
1553
+ return product;
1554
+ }
1555
+
1556
+ const oklab2rgb = (...args) => {
1557
+ args = unpack(args, 'lab');
1558
+ const [L, a, b, ...rest] = args;
1559
+ const [X, Y, Z] = OKLab_to_XYZ([L, a, b]);
1560
+ const [r, g, b_] = xyz2rgb(X, Y, Z);
1561
+ return [r, g, b_, ...(rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])];
1562
+ };
1563
+
1564
+ // from https://www.w3.org/TR/css-color-4/#color-conversion-code
1565
+ function OKLab_to_XYZ(OKLab) {
1566
+ // Given OKLab, convert to XYZ relative to D65
1567
+ var LMStoXYZ = [
1568
+ [1.2268798758459243, -0.5578149944602171, 0.2813910456659647],
1569
+ [-0.0405757452148008, 1.112286803280317, -0.0717110580655164],
1570
+ [-0.0763729366746601, -0.4214933324022432, 1.5869240198367816]
1571
+ ];
1572
+ var OKLabtoLMS = [
1573
+ [1.0, 0.3963377773761749, 0.2158037573099136],
1574
+ [1.0, -0.1055613458156586, -0.0638541728258133],
1575
+ [1.0, -0.0894841775298119, -1.2914855480194092]
1576
+ ];
1577
+
1578
+ var LMSnl = multiplyMatrices(OKLabtoLMS, OKLab);
1579
+ return multiplyMatrices(
1580
+ LMStoXYZ,
1581
+ LMSnl.map((c) => c ** 3)
1582
+ );
1583
+ }
1584
+
1585
+ const rgb2oklab = (...args) => {
1586
+ const [r, g, b, ...rest] = unpack(args, 'rgb');
1587
+ const xyz = rgb2xyz(r, g, b);
1588
+ const oklab = XYZ_to_OKLab(xyz);
1589
+ return [...oklab, ...(rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])];
1590
+ };
1591
+
1592
+ // from https://www.w3.org/TR/css-color-4/#color-conversion-code
1593
+ function XYZ_to_OKLab(XYZ) {
1594
+ // Given XYZ relative to D65, convert to OKLab
1595
+ const XYZtoLMS = [
1596
+ [0.819022437996703, 0.3619062600528904, -0.1288737815209879],
1597
+ [0.0329836539323885, 0.9292868615863434, 0.0361446663506424],
1598
+ [0.0481771893596242, 0.2642395317527308, 0.6335478284694309]
1599
+ ];
1600
+ const LMStoOKLab = [
1601
+ [0.210454268309314, 0.7936177747023054, -0.0040720430116193],
1602
+ [1.9779985324311684, -2.4285922420485799, 0.450593709617411],
1603
+ [0.0259040424655478, 0.7827717124575296, -0.8086757549230774]
1604
+ ];
1605
+
1606
+ const LMS = multiplyMatrices(XYZtoLMS, XYZ);
1607
+ // JavaScript Math.cbrt returns a sign-matched cube root
1608
+ // beware if porting to other languages
1609
+ // especially if tempted to use a general power function
1610
+ return multiplyMatrices(
1611
+ LMStoOKLab,
1612
+ LMS.map((c) => Math.cbrt(c))
1613
+ );
1614
+ // L in range [0,1]. For use in CSS, multiply by 100 and add a percent
1615
+ }
1616
+
1617
+ Color.prototype.oklab = function () {
1618
+ return rgb2oklab(this._rgb);
1619
+ };
1620
+
1621
+ const oklab$1 = (...args) => new Color(...args, 'oklab');
1622
+ Object.assign(chroma, { oklab: oklab$1 });
1623
+
1624
+ input.format.oklab = oklab2rgb;
1625
+
1626
+ input.autodetect.push({
1627
+ p: 2,
1628
+ test: (...args) => {
1629
+ args = unpack(args, 'oklab');
1630
+ if (type(args) === 'array' && args.length === 3) {
1631
+ return 'oklab';
1632
+ }
1633
+ }
1634
+ });
1635
+
1636
+ const oklab = (col1, col2, f) => {
1637
+ const xyz0 = col1.oklab();
1638
+ const xyz1 = col2.oklab();
1639
+ return new Color(
1640
+ xyz0[0] + f * (xyz1[0] - xyz0[0]),
1641
+ xyz0[1] + f * (xyz1[1] - xyz0[1]),
1642
+ xyz0[2] + f * (xyz1[2] - xyz0[2]),
1643
+ 'oklab'
1644
+ );
1645
+ };
1646
+
1647
+ // register interpolator
1648
+ index.oklab = oklab;
1649
+
1650
+ const oklch$1 = (col1, col2, f) => {
1651
+ return interpolate_hsx(col1, col2, f, 'oklch');
1652
+ };
1653
+
1654
+ // register interpolator
1655
+ index.oklch = oklch$1;
1656
+
1657
+ const { pow: pow$4, sqrt: sqrt$1, PI: PI$1, cos: cos$2, sin: sin$2, atan2: atan2$1 } = Math;
1658
+
1659
+ const average = (colors, mode = 'lrgb', weights = null) => {
1660
+ const l = colors.length;
1661
+ if (!weights) weights = Array.from(new Array(l)).map(() => 1);
1662
+ // normalize weights
1663
+ const k =
1664
+ l /
1665
+ weights.reduce(function (a, b) {
1666
+ return a + b;
1667
+ });
1668
+ weights.forEach((w, i) => {
1669
+ weights[i] *= k;
1670
+ });
1671
+ // convert colors to Color objects
1672
+ colors = colors.map((c) => new Color(c));
1673
+ if (mode === 'lrgb') {
1674
+ return _average_lrgb(colors, weights);
1675
+ }
1676
+ const first = colors.shift();
1677
+ const xyz = first.get(mode);
1678
+ const cnt = [];
1679
+ let dx = 0;
1680
+ let dy = 0;
1681
+ // initial color
1682
+ for (let i = 0; i < xyz.length; i++) {
1683
+ xyz[i] = (xyz[i] || 0) * weights[0];
1684
+ cnt.push(isNaN(xyz[i]) ? 0 : weights[0]);
1685
+ if (mode.charAt(i) === 'h' && !isNaN(xyz[i])) {
1686
+ const A = (xyz[i] / 180) * PI$1;
1687
+ dx += cos$2(A) * weights[0];
1688
+ dy += sin$2(A) * weights[0];
1689
+ }
1690
+ }
1691
+
1692
+ let alpha = first.alpha() * weights[0];
1693
+ colors.forEach((c, ci) => {
1694
+ const xyz2 = c.get(mode);
1695
+ alpha += c.alpha() * weights[ci + 1];
1696
+ for (let i = 0; i < xyz.length; i++) {
1697
+ if (!isNaN(xyz2[i])) {
1698
+ cnt[i] += weights[ci + 1];
1699
+ if (mode.charAt(i) === 'h') {
1700
+ const A = (xyz2[i] / 180) * PI$1;
1701
+ dx += cos$2(A) * weights[ci + 1];
1702
+ dy += sin$2(A) * weights[ci + 1];
1703
+ } else {
1704
+ xyz[i] += xyz2[i] * weights[ci + 1];
1705
+ }
1706
+ }
1707
+ }
1708
+ });
1709
+
1710
+ for (let i = 0; i < xyz.length; i++) {
1711
+ if (mode.charAt(i) === 'h') {
1712
+ let A = (atan2$1(dy / cnt[i], dx / cnt[i]) / PI$1) * 180;
1713
+ while (A < 0) A += 360;
1714
+ while (A >= 360) A -= 360;
1715
+ xyz[i] = A;
1716
+ } else {
1717
+ xyz[i] = xyz[i] / cnt[i];
1718
+ }
1719
+ }
1720
+ alpha /= l;
1721
+ return new Color(xyz, mode).alpha(alpha > 0.99999 ? 1 : alpha, true);
1722
+ };
1723
+
1724
+ const _average_lrgb = (colors, weights) => {
1725
+ const l = colors.length;
1726
+ const xyz = [0, 0, 0, 0];
1727
+ for (let i = 0; i < colors.length; i++) {
1728
+ const col = colors[i];
1729
+ const f = weights[i] / l;
1730
+ const rgb = col._rgb;
1731
+ xyz[0] += pow$4(rgb[0], 2) * f;
1732
+ xyz[1] += pow$4(rgb[1], 2) * f;
1733
+ xyz[2] += pow$4(rgb[2], 2) * f;
1734
+ xyz[3] += rgb[3] * f;
1735
+ }
1736
+ xyz[0] = sqrt$1(xyz[0]);
1737
+ xyz[1] = sqrt$1(xyz[1]);
1738
+ xyz[2] = sqrt$1(xyz[2]);
1739
+ if (xyz[3] > 0.9999999) xyz[3] = 1;
1740
+ return new Color(clip_rgb(xyz));
1741
+ };
1742
+
1743
+ // minimal multi-purpose interface
1744
+
1745
+
1746
+ const { pow: pow$3 } = Math;
1747
+
1748
+ function scale (colors) {
1749
+ // constructor
1750
+ let _mode = 'rgb';
1751
+ let _nacol = chroma('#ccc');
1752
+ let _spread = 0;
1753
+ // const _fixed = false;
1754
+ let _domain = [0, 1];
1755
+ let _pos = [];
1756
+ let _padding = [0, 0];
1757
+ let _classes = false;
1758
+ let _colors = [];
1759
+ let _out = false;
1760
+ let _min = 0;
1761
+ let _max = 1;
1762
+ let _correctLightness = false;
1763
+ let _colorCache = {};
1764
+ let _useCache = true;
1765
+ let _gamma = 1;
1766
+
1767
+ // private methods
1768
+
1769
+ const setColors = function (colors) {
1770
+ colors = colors || ['#fff', '#000'];
1771
+ if (
1772
+ colors &&
1773
+ type(colors) === 'string' &&
1774
+ chroma.brewer &&
1775
+ chroma.brewer[colors.toLowerCase()]
1776
+ ) {
1777
+ colors = chroma.brewer[colors.toLowerCase()];
1778
+ }
1779
+ if (type(colors) === 'array') {
1780
+ // handle single color
1781
+ if (colors.length === 1) {
1782
+ colors = [colors[0], colors[0]];
1783
+ }
1784
+ // make a copy of the colors
1785
+ colors = colors.slice(0);
1786
+ // convert to chroma classes
1787
+ for (let c = 0; c < colors.length; c++) {
1788
+ colors[c] = chroma(colors[c]);
1789
+ }
1790
+ // auto-fill color position
1791
+ _pos.length = 0;
1792
+ for (let c = 0; c < colors.length; c++) {
1793
+ _pos.push(c / (colors.length - 1));
1794
+ }
1795
+ }
1796
+ resetCache();
1797
+ return (_colors = colors);
1798
+ };
1799
+
1800
+ const getClass = function (value) {
1801
+ if (_classes != null) {
1802
+ const n = _classes.length - 1;
1803
+ let i = 0;
1804
+ while (i < n && value >= _classes[i]) {
1805
+ i++;
1806
+ }
1807
+ return i - 1;
1808
+ }
1809
+ return 0;
1810
+ };
1811
+
1812
+ let tMapLightness = (t) => t;
1813
+ let tMapDomain = (t) => t;
1814
+
1815
+ // const classifyValue = function(value) {
1816
+ // let val = value;
1817
+ // if (_classes.length > 2) {
1818
+ // const n = _classes.length-1;
1819
+ // const i = getClass(value);
1820
+ // const minc = _classes[0] + ((_classes[1]-_classes[0]) * (0 + (_spread * 0.5))); // center of 1st class
1821
+ // const maxc = _classes[n-1] + ((_classes[n]-_classes[n-1]) * (1 - (_spread * 0.5))); // center of last class
1822
+ // val = _min + ((((_classes[i] + ((_classes[i+1] - _classes[i]) * 0.5)) - minc) / (maxc-minc)) * (_max - _min));
1823
+ // }
1824
+ // return val;
1825
+ // };
1826
+
1827
+ const getColor = function (val, bypassMap) {
1828
+ let col, t;
1829
+ if (bypassMap == null) {
1830
+ bypassMap = false;
1831
+ }
1832
+ if (isNaN(val) || val === null) {
1833
+ return _nacol;
1834
+ }
1835
+ if (!bypassMap) {
1836
+ if (_classes && _classes.length > 2) {
1837
+ // find the class
1838
+ const c = getClass(val);
1839
+ t = c / (_classes.length - 2);
1840
+ } else if (_max !== _min) {
1841
+ // just interpolate between min/max
1842
+ t = (val - _min) / (_max - _min);
1843
+ } else {
1844
+ t = 1;
1845
+ }
1846
+ } else {
1847
+ t = val;
1848
+ }
1849
+
1850
+ // domain map
1851
+ t = tMapDomain(t);
1852
+
1853
+ if (!bypassMap) {
1854
+ t = tMapLightness(t); // lightness correction
1855
+ }
1856
+
1857
+ if (_gamma !== 1) {
1858
+ t = pow$3(t, _gamma);
1859
+ }
1860
+
1861
+ t = _padding[0] + t * (1 - _padding[0] - _padding[1]);
1862
+
1863
+ t = limit(t, 0, 1);
1864
+
1865
+ const k = Math.floor(t * 10000);
1866
+
1867
+ if (_useCache && _colorCache[k]) {
1868
+ col = _colorCache[k];
1869
+ } else {
1870
+ if (type(_colors) === 'array') {
1871
+ //for i in [0.._pos.length-1]
1872
+ for (let i = 0; i < _pos.length; i++) {
1873
+ const p = _pos[i];
1874
+ if (t <= p) {
1875
+ col = _colors[i];
1876
+ break;
1877
+ }
1878
+ if (t >= p && i === _pos.length - 1) {
1879
+ col = _colors[i];
1880
+ break;
1881
+ }
1882
+ if (t > p && t < _pos[i + 1]) {
1883
+ t = (t - p) / (_pos[i + 1] - p);
1884
+ col = chroma.interpolate(
1885
+ _colors[i],
1886
+ _colors[i + 1],
1887
+ t,
1888
+ _mode
1889
+ );
1890
+ break;
1891
+ }
1892
+ }
1893
+ } else if (type(_colors) === 'function') {
1894
+ col = _colors(t);
1895
+ }
1896
+ if (_useCache) {
1897
+ _colorCache[k] = col;
1898
+ }
1899
+ }
1900
+ return col;
1901
+ };
1902
+
1903
+ var resetCache = () => (_colorCache = {});
1904
+
1905
+ setColors(colors);
1906
+
1907
+ // public interface
1908
+
1909
+ const f = function (v) {
1910
+ const c = chroma(getColor(v));
1911
+ if (_out && c[_out]) {
1912
+ return c[_out]();
1913
+ } else {
1914
+ return c;
1915
+ }
1916
+ };
1917
+
1918
+ f.classes = function (classes) {
1919
+ if (classes != null) {
1920
+ if (type(classes) === 'array') {
1921
+ _classes = classes;
1922
+ _domain = [classes[0], classes[classes.length - 1]];
1923
+ } else {
1924
+ const d = chroma.analyze(_domain);
1925
+ if (classes === 0) {
1926
+ _classes = [d.min, d.max];
1927
+ } else {
1928
+ _classes = chroma.limits(d, 'e', classes);
1929
+ }
1930
+ }
1931
+ return f;
1932
+ }
1933
+ return _classes;
1934
+ };
1935
+
1936
+ f.domain = function (domain) {
1937
+ if (!arguments.length) {
1938
+ return _domain;
1939
+ }
1940
+ _min = domain[0];
1941
+ _max = domain[domain.length - 1];
1942
+ _pos = [];
1943
+ const k = _colors.length;
1944
+ if (domain.length === k && _min !== _max) {
1945
+ // update positions
1946
+ for (let d of Array.from(domain)) {
1947
+ _pos.push((d - _min) / (_max - _min));
1948
+ }
1949
+ } else {
1950
+ for (let c = 0; c < k; c++) {
1951
+ _pos.push(c / (k - 1));
1952
+ }
1953
+ if (domain.length > 2) {
1954
+ // set domain map
1955
+ const tOut = domain.map((d, i) => i / (domain.length - 1));
1956
+ const tBreaks = domain.map((d) => (d - _min) / (_max - _min));
1957
+ if (!tBreaks.every((val, i) => tOut[i] === val)) {
1958
+ tMapDomain = (t) => {
1959
+ if (t <= 0 || t >= 1) return t;
1960
+ let i = 0;
1961
+ while (t >= tBreaks[i + 1]) i++;
1962
+ const f =
1963
+ (t - tBreaks[i]) / (tBreaks[i + 1] - tBreaks[i]);
1964
+ const out = tOut[i] + f * (tOut[i + 1] - tOut[i]);
1965
+ return out;
1966
+ };
1967
+ }
1968
+ }
1969
+ }
1970
+ _domain = [_min, _max];
1971
+ return f;
1972
+ };
1973
+
1974
+ f.mode = function (_m) {
1975
+ if (!arguments.length) {
1976
+ return _mode;
1977
+ }
1978
+ _mode = _m;
1979
+ resetCache();
1980
+ return f;
1981
+ };
1982
+
1983
+ f.range = function (colors, _pos) {
1984
+ setColors(colors);
1985
+ return f;
1986
+ };
1987
+
1988
+ f.out = function (_o) {
1989
+ _out = _o;
1990
+ return f;
1991
+ };
1992
+
1993
+ f.spread = function (val) {
1994
+ if (!arguments.length) {
1995
+ return _spread;
1996
+ }
1997
+ _spread = val;
1998
+ return f;
1999
+ };
2000
+
2001
+ f.correctLightness = function (v) {
2002
+ if (v == null) {
2003
+ v = true;
2004
+ }
2005
+ _correctLightness = v;
2006
+ resetCache();
2007
+ if (_correctLightness) {
2008
+ tMapLightness = function (t) {
2009
+ const L0 = getColor(0, true).lab()[0];
2010
+ const L1 = getColor(1, true).lab()[0];
2011
+ const pol = L0 > L1;
2012
+ let L_actual = getColor(t, true).lab()[0];
2013
+ const L_ideal = L0 + (L1 - L0) * t;
2014
+ let L_diff = L_actual - L_ideal;
2015
+ let t0 = 0;
2016
+ let t1 = 1;
2017
+ let max_iter = 20;
2018
+ while (Math.abs(L_diff) > 1e-2 && max_iter-- > 0) {
2019
+ (function () {
2020
+ if (pol) {
2021
+ L_diff *= -1;
2022
+ }
2023
+ if (L_diff < 0) {
2024
+ t0 = t;
2025
+ t += (t1 - t) * 0.5;
2026
+ } else {
2027
+ t1 = t;
2028
+ t += (t0 - t) * 0.5;
2029
+ }
2030
+ L_actual = getColor(t, true).lab()[0];
2031
+ return (L_diff = L_actual - L_ideal);
2032
+ })();
2033
+ }
2034
+ return t;
2035
+ };
2036
+ } else {
2037
+ tMapLightness = (t) => t;
2038
+ }
2039
+ return f;
2040
+ };
2041
+
2042
+ f.padding = function (p) {
2043
+ if (p != null) {
2044
+ if (type(p) === 'number') {
2045
+ p = [p, p];
2046
+ }
2047
+ _padding = p;
2048
+ return f;
2049
+ } else {
2050
+ return _padding;
2051
+ }
2052
+ };
2053
+
2054
+ f.colors = function (numColors, out) {
2055
+ // If no arguments are given, return the original colors that were provided
2056
+ if (arguments.length < 2) {
2057
+ out = 'hex';
2058
+ }
2059
+ let result = [];
2060
+
2061
+ if (arguments.length === 0) {
2062
+ result = _colors.slice(0);
2063
+ } else if (numColors === 1) {
2064
+ result = [f(0.5)];
2065
+ } else if (numColors > 1) {
2066
+ const dm = _domain[0];
2067
+ const dd = _domain[1] - dm;
2068
+ result = __range__(0, numColors).map((i) =>
2069
+ f(dm + (i / (numColors - 1)) * dd)
2070
+ );
2071
+ } else {
2072
+ // returns all colors based on the defined classes
2073
+ colors = [];
2074
+ let samples = [];
2075
+ if (_classes && _classes.length > 2) {
2076
+ for (
2077
+ let i = 1, end = _classes.length, asc = 1 <= end;
2078
+ asc ? i < end : i > end;
2079
+ asc ? i++ : i--
2080
+ ) {
2081
+ samples.push((_classes[i - 1] + _classes[i]) * 0.5);
2082
+ }
2083
+ } else {
2084
+ samples = _domain;
2085
+ }
2086
+ result = samples.map((v) => f(v));
2087
+ }
2088
+
2089
+ if (chroma[out]) {
2090
+ result = result.map((c) => c[out]());
2091
+ }
2092
+ return result;
2093
+ };
2094
+
2095
+ f.cache = function (c) {
2096
+ if (c != null) {
2097
+ _useCache = c;
2098
+ return f;
2099
+ } else {
2100
+ return _useCache;
2101
+ }
2102
+ };
2103
+
2104
+ f.gamma = function (g) {
2105
+ if (g != null) {
2106
+ _gamma = g;
2107
+ return f;
2108
+ } else {
2109
+ return _gamma;
2110
+ }
2111
+ };
2112
+
2113
+ f.nodata = function (d) {
2114
+ if (d != null) {
2115
+ _nacol = chroma(d);
2116
+ return f;
2117
+ } else {
2118
+ return _nacol;
2119
+ }
2120
+ };
2121
+
2122
+ return f;
2123
+ }
2124
+
2125
+ function __range__(left, right, inclusive) {
2126
+ let range = [];
2127
+ let ascending = left < right;
2128
+ let end = right ;
2129
+ for (let i = left; ascending ? i < end : i > end; ascending ? i++ : i--) {
2130
+ range.push(i);
2131
+ }
2132
+ return range;
2133
+ }
2134
+
2135
+ //
2136
+ // interpolates between a set of colors uzing a bezier spline
2137
+ //
2138
+
2139
+
2140
+ // nth row of the pascal triangle
2141
+ const binom_row = function (n) {
2142
+ let row = [1, 1];
2143
+ for (let i = 1; i < n; i++) {
2144
+ let newrow = [1];
2145
+ for (let j = 1; j <= row.length; j++) {
2146
+ newrow[j] = (row[j] || 0) + row[j - 1];
2147
+ }
2148
+ row = newrow;
2149
+ }
2150
+ return row;
2151
+ };
2152
+
2153
+ const bezier = function (colors) {
2154
+ let I, lab0, lab1, lab2;
2155
+ colors = colors.map((c) => new Color(c));
2156
+ if (colors.length === 2) {
2157
+ // linear interpolation
2158
+ [lab0, lab1] = colors.map((c) => c.lab());
2159
+ I = function (t) {
2160
+ const lab = [0, 1, 2].map((i) => lab0[i] + t * (lab1[i] - lab0[i]));
2161
+ return new Color(lab, 'lab');
2162
+ };
2163
+ } else if (colors.length === 3) {
2164
+ // quadratic bezier interpolation
2165
+ [lab0, lab1, lab2] = colors.map((c) => c.lab());
2166
+ I = function (t) {
2167
+ const lab = [0, 1, 2].map(
2168
+ (i) =>
2169
+ (1 - t) * (1 - t) * lab0[i] +
2170
+ 2 * (1 - t) * t * lab1[i] +
2171
+ t * t * lab2[i]
2172
+ );
2173
+ return new Color(lab, 'lab');
2174
+ };
2175
+ } else if (colors.length === 4) {
2176
+ // cubic bezier interpolation
2177
+ let lab3;
2178
+ [lab0, lab1, lab2, lab3] = colors.map((c) => c.lab());
2179
+ I = function (t) {
2180
+ const lab = [0, 1, 2].map(
2181
+ (i) =>
2182
+ (1 - t) * (1 - t) * (1 - t) * lab0[i] +
2183
+ 3 * (1 - t) * (1 - t) * t * lab1[i] +
2184
+ 3 * (1 - t) * t * t * lab2[i] +
2185
+ t * t * t * lab3[i]
2186
+ );
2187
+ return new Color(lab, 'lab');
2188
+ };
2189
+ } else if (colors.length >= 5) {
2190
+ // general case (degree n bezier)
2191
+ let labs, row, n;
2192
+ labs = colors.map((c) => c.lab());
2193
+ n = colors.length - 1;
2194
+ row = binom_row(n);
2195
+ I = function (t) {
2196
+ const u = 1 - t;
2197
+ const lab = [0, 1, 2].map((i) =>
2198
+ labs.reduce(
2199
+ (sum, el, j) =>
2200
+ sum + row[j] * u ** (n - j) * t ** j * el[i],
2201
+ 0
2202
+ )
2203
+ );
2204
+ return new Color(lab, 'lab');
2205
+ };
2206
+ } else {
2207
+ throw new RangeError('No point in running bezier with only one color.');
2208
+ }
2209
+ return I;
2210
+ };
2211
+
2212
+ const bezier$1 = (colors) => {
2213
+ const f = bezier(colors);
2214
+ f.scale = () => scale(f);
2215
+ return f;
2216
+ };
2217
+
2218
+ const { round: round$3 } = Math;
2219
+
2220
+ Color.prototype.rgb = function (rnd = true) {
2221
+ if (rnd === false) return this._rgb.slice(0, 3);
2222
+ return this._rgb.slice(0, 3).map(round$3);
2223
+ };
2224
+
2225
+ Color.prototype.rgba = function (rnd = true) {
2226
+ return this._rgb.slice(0, 4).map((v, i) => {
2227
+ return i < 3 ? (rnd === false ? v : round$3(v)) : v;
2228
+ });
2229
+ };
2230
+
2231
+ const rgb = (...args) => new Color(...args, 'rgb');
2232
+ Object.assign(chroma, { rgb });
2233
+
2234
+ input.format.rgb = (...args) => {
2235
+ const rgba = unpack(args, 'rgba');
2236
+ if (rgba[3] === undefined) rgba[3] = 1;
2237
+ return rgba;
2238
+ };
2239
+
2240
+ input.autodetect.push({
2241
+ p: 3,
2242
+ test: (...args) => {
2243
+ args = unpack(args, 'rgba');
2244
+ if (
2245
+ type(args) === 'array' &&
2246
+ (args.length === 3 ||
2247
+ (args.length === 4 &&
2248
+ type(args[3]) == 'number' &&
2249
+ args[3] >= 0 &&
2250
+ args[3] <= 1))
2251
+ ) {
2252
+ return 'rgb';
2253
+ }
2254
+ }
2255
+ });
2256
+
2257
+ /*
2258
+ * interpolates between a set of colors uzing a bezier spline
2259
+ * blend mode formulas taken from https://web.archive.org/web/20180110014946/http://www.venture-ware.com/kevin/coding/lets-learn-math-photoshop-blend-modes/
2260
+ */
2261
+
2262
+
2263
+ const blend = (bottom, top, mode) => {
2264
+ if (!blend[mode]) {
2265
+ throw new Error('unknown blend mode ' + mode);
2266
+ }
2267
+ return blend[mode](bottom, top);
2268
+ };
2269
+
2270
+ const blend_f = (f) => (bottom, top) => {
2271
+ const c0 = chroma(top).rgb();
2272
+ const c1 = chroma(bottom).rgb();
2273
+ return chroma.rgb(f(c0, c1));
2274
+ };
2275
+
2276
+ const each = (f) => (c0, c1) => {
2277
+ const out = [];
2278
+ out[0] = f(c0[0], c1[0]);
2279
+ out[1] = f(c0[1], c1[1]);
2280
+ out[2] = f(c0[2], c1[2]);
2281
+ return out;
2282
+ };
2283
+
2284
+ const normal = (a) => a;
2285
+ const multiply = (a, b) => (a * b) / 255;
2286
+ const darken = (a, b) => (a > b ? b : a);
2287
+ const lighten = (a, b) => (a > b ? a : b);
2288
+ const screen = (a, b) => 255 * (1 - (1 - a / 255) * (1 - b / 255));
2289
+ const overlay = (a, b) =>
2290
+ b < 128 ? (2 * a * b) / 255 : 255 * (1 - 2 * (1 - a / 255) * (1 - b / 255));
2291
+ const burn = (a, b) => 255 * (1 - (1 - b / 255) / (a / 255));
2292
+ const dodge = (a, b) => {
2293
+ if (a === 255) return 255;
2294
+ a = (255 * (b / 255)) / (1 - a / 255);
2295
+ return a > 255 ? 255 : a;
2296
+ };
2297
+
2298
+ // # add = (a,b) ->
2299
+ // # if (a + b > 255) then 255 else a + b
2300
+
2301
+ blend.normal = blend_f(each(normal));
2302
+ blend.multiply = blend_f(each(multiply));
2303
+ blend.screen = blend_f(each(screen));
2304
+ blend.overlay = blend_f(each(overlay));
2305
+ blend.darken = blend_f(each(darken));
2306
+ blend.lighten = blend_f(each(lighten));
2307
+ blend.dodge = blend_f(each(dodge));
2308
+ blend.burn = blend_f(each(burn));
2309
+
2310
+ // cubehelix interpolation
2311
+ // based on D.A. Green "A colour scheme for the display of astronomical intensity images"
2312
+ // http://astron-soc.in/bulletin/11June/289392011.pdf
2313
+ const { pow: pow$2, sin: sin$1, cos: cos$1 } = Math;
2314
+
2315
+ function cubehelix (
2316
+ start = 300,
2317
+ rotations = -1.5,
2318
+ hue = 1,
2319
+ gamma = 1,
2320
+ lightness = [0, 1]
2321
+ ) {
2322
+ let dh = 0,
2323
+ dl;
2324
+ if (type(lightness) === 'array') {
2325
+ dl = lightness[1] - lightness[0];
2326
+ } else {
2327
+ dl = 0;
2328
+ lightness = [lightness, lightness];
2329
+ }
2330
+ const f = function (fract) {
2331
+ const a = TWOPI * ((start + 120) / 360 + rotations * fract);
2332
+ const l = pow$2(lightness[0] + dl * fract, gamma);
2333
+ const h = dh !== 0 ? hue[0] + fract * dh : hue;
2334
+ const amp = (h * l * (1 - l)) / 2;
2335
+ const cos_a = cos$1(a);
2336
+ const sin_a = sin$1(a);
2337
+ const r = l + amp * (-0.14861 * cos_a + 1.78277 * sin_a);
2338
+ const g = l + amp * (-0.29227 * cos_a - 0.90649 * sin_a);
2339
+ const b = l + amp * (+1.97294 * cos_a);
2340
+ return chroma(clip_rgb([r * 255, g * 255, b * 255, 1]));
2341
+ };
2342
+ f.start = function (s) {
2343
+ if (s == null) {
2344
+ return start;
2345
+ }
2346
+ start = s;
2347
+ return f;
2348
+ };
2349
+ f.rotations = function (r) {
2350
+ if (r == null) {
2351
+ return rotations;
2352
+ }
2353
+ rotations = r;
2354
+ return f;
2355
+ };
2356
+ f.gamma = function (g) {
2357
+ if (g == null) {
2358
+ return gamma;
2359
+ }
2360
+ gamma = g;
2361
+ return f;
2362
+ };
2363
+ f.hue = function (h) {
2364
+ if (h == null) {
2365
+ return hue;
2366
+ }
2367
+ hue = h;
2368
+ if (type(hue) === 'array') {
2369
+ dh = hue[1] - hue[0];
2370
+ if (dh === 0) {
2371
+ hue = hue[1];
2372
+ }
2373
+ } else {
2374
+ dh = 0;
2375
+ }
2376
+ return f;
2377
+ };
2378
+ f.lightness = function (h) {
2379
+ if (h == null) {
2380
+ return lightness;
2381
+ }
2382
+ if (type(h) === 'array') {
2383
+ lightness = h;
2384
+ dl = h[1] - h[0];
2385
+ } else {
2386
+ lightness = [h, h];
2387
+ dl = 0;
2388
+ }
2389
+ return f;
2390
+ };
2391
+ f.scale = () => chroma.scale(f);
2392
+ f.hue(hue);
2393
+ return f;
2394
+ }
2395
+
2396
+ const digits = '0123456789abcdef';
2397
+
2398
+ const { floor: floor$1, random } = Math;
2399
+
2400
+ const random$1 = () => {
2401
+ let code = '#';
2402
+ for (let i = 0; i < 6; i++) {
2403
+ code += digits.charAt(floor$1(random() * 16));
2404
+ }
2405
+ return new Color(code, 'hex');
2406
+ };
2407
+
2408
+ const { log: log$1, pow: pow$1, floor, abs: abs$1 } = Math;
2409
+
2410
+ function analyze(data, key = null) {
2411
+ const r = {
2412
+ min: Number.MAX_VALUE,
2413
+ max: Number.MAX_VALUE * -1,
2414
+ sum: 0,
2415
+ values: [],
2416
+ count: 0
2417
+ };
2418
+ if (type(data) === 'object') {
2419
+ data = Object.values(data);
2420
+ }
2421
+ data.forEach((val) => {
2422
+ if (key && type(val) === 'object') val = val[key];
2423
+ if (val !== undefined && val !== null && !isNaN(val)) {
2424
+ r.values.push(val);
2425
+ r.sum += val;
2426
+ if (val < r.min) r.min = val;
2427
+ if (val > r.max) r.max = val;
2428
+ r.count += 1;
2429
+ }
2430
+ });
2431
+
2432
+ r.domain = [r.min, r.max];
2433
+
2434
+ r.limits = (mode, num) => limits(r, mode, num);
2435
+
2436
+ return r;
2437
+ }
2438
+
2439
+ function limits(data, mode = 'equal', num = 7) {
2440
+ if (type(data) == 'array') {
2441
+ data = analyze(data);
2442
+ }
2443
+ const { min, max } = data;
2444
+ const values = data.values.sort((a, b) => a - b);
2445
+
2446
+ if (num === 1) {
2447
+ return [min, max];
2448
+ }
2449
+
2450
+ const limits = [];
2451
+
2452
+ if (mode.substr(0, 1) === 'c') {
2453
+ // continuous
2454
+ limits.push(min);
2455
+ limits.push(max);
2456
+ }
2457
+
2458
+ if (mode.substr(0, 1) === 'e') {
2459
+ // equal interval
2460
+ limits.push(min);
2461
+ for (let i = 1; i < num; i++) {
2462
+ limits.push(min + (i / num) * (max - min));
2463
+ }
2464
+ limits.push(max);
2465
+ } else if (mode.substr(0, 1) === 'l') {
2466
+ // log scale
2467
+ if (min <= 0) {
2468
+ throw new Error(
2469
+ 'Logarithmic scales are only possible for values > 0'
2470
+ );
2471
+ }
2472
+ const min_log = Math.LOG10E * log$1(min);
2473
+ const max_log = Math.LOG10E * log$1(max);
2474
+ limits.push(min);
2475
+ for (let i = 1; i < num; i++) {
2476
+ limits.push(pow$1(10, min_log + (i / num) * (max_log - min_log)));
2477
+ }
2478
+ limits.push(max);
2479
+ } else if (mode.substr(0, 1) === 'q') {
2480
+ // quantile scale
2481
+ limits.push(min);
2482
+ for (let i = 1; i < num; i++) {
2483
+ const p = ((values.length - 1) * i) / num;
2484
+ const pb = floor(p);
2485
+ if (pb === p) {
2486
+ limits.push(values[pb]);
2487
+ } else {
2488
+ // p > pb
2489
+ const pr = p - pb;
2490
+ limits.push(values[pb] * (1 - pr) + values[pb + 1] * pr);
2491
+ }
2492
+ }
2493
+ limits.push(max);
2494
+ } else if (mode.substr(0, 1) === 'k') {
2495
+ // k-means clustering
2496
+ /*
2497
+ implementation based on
2498
+ http://code.google.com/p/figue/source/browse/trunk/figue.js#336
2499
+ simplified for 1-d input values
2500
+ */
2501
+ let cluster;
2502
+ const n = values.length;
2503
+ const assignments = new Array(n);
2504
+ const clusterSizes = new Array(num);
2505
+ let repeat = true;
2506
+ let nb_iters = 0;
2507
+ let centroids = null;
2508
+
2509
+ // get seed values
2510
+ centroids = [];
2511
+ centroids.push(min);
2512
+ for (let i = 1; i < num; i++) {
2513
+ centroids.push(min + (i / num) * (max - min));
2514
+ }
2515
+ centroids.push(max);
2516
+
2517
+ while (repeat) {
2518
+ // assignment step
2519
+ for (let j = 0; j < num; j++) {
2520
+ clusterSizes[j] = 0;
2521
+ }
2522
+ for (let i = 0; i < n; i++) {
2523
+ const value = values[i];
2524
+ let mindist = Number.MAX_VALUE;
2525
+ let best;
2526
+ for (let j = 0; j < num; j++) {
2527
+ const dist = abs$1(centroids[j] - value);
2528
+ if (dist < mindist) {
2529
+ mindist = dist;
2530
+ best = j;
2531
+ }
2532
+ clusterSizes[best]++;
2533
+ assignments[i] = best;
2534
+ }
2535
+ }
2536
+
2537
+ // update centroids step
2538
+ const newCentroids = new Array(num);
2539
+ for (let j = 0; j < num; j++) {
2540
+ newCentroids[j] = null;
2541
+ }
2542
+ for (let i = 0; i < n; i++) {
2543
+ cluster = assignments[i];
2544
+ if (newCentroids[cluster] === null) {
2545
+ newCentroids[cluster] = values[i];
2546
+ } else {
2547
+ newCentroids[cluster] += values[i];
2548
+ }
2549
+ }
2550
+ for (let j = 0; j < num; j++) {
2551
+ newCentroids[j] *= 1 / clusterSizes[j];
2552
+ }
2553
+
2554
+ // check convergence
2555
+ repeat = false;
2556
+ for (let j = 0; j < num; j++) {
2557
+ if (newCentroids[j] !== centroids[j]) {
2558
+ repeat = true;
2559
+ break;
2560
+ }
2561
+ }
2562
+
2563
+ centroids = newCentroids;
2564
+ nb_iters++;
2565
+
2566
+ if (nb_iters > 200) {
2567
+ repeat = false;
2568
+ }
2569
+ }
2570
+
2571
+ // finished k-means clustering
2572
+ // the next part is borrowed from gabrielflor.it
2573
+ const kClusters = {};
2574
+ for (let j = 0; j < num; j++) {
2575
+ kClusters[j] = [];
2576
+ }
2577
+ for (let i = 0; i < n; i++) {
2578
+ cluster = assignments[i];
2579
+ kClusters[cluster].push(values[i]);
2580
+ }
2581
+ let tmpKMeansBreaks = [];
2582
+ for (let j = 0; j < num; j++) {
2583
+ tmpKMeansBreaks.push(kClusters[j][0]);
2584
+ tmpKMeansBreaks.push(kClusters[j][kClusters[j].length - 1]);
2585
+ }
2586
+ tmpKMeansBreaks = tmpKMeansBreaks.sort((a, b) => a - b);
2587
+ limits.push(tmpKMeansBreaks[0]);
2588
+ for (let i = 1; i < tmpKMeansBreaks.length; i += 2) {
2589
+ const v = tmpKMeansBreaks[i];
2590
+ if (!isNaN(v) && limits.indexOf(v) === -1) {
2591
+ limits.push(v);
2592
+ }
2593
+ }
2594
+ }
2595
+ return limits;
2596
+ }
2597
+
2598
+ const contrast = (a, b) => {
2599
+ // WCAG contrast ratio
2600
+ // see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
2601
+ a = new Color(a);
2602
+ b = new Color(b);
2603
+ const l1 = a.luminance();
2604
+ const l2 = b.luminance();
2605
+ return l1 > l2 ? (l1 + 0.05) / (l2 + 0.05) : (l2 + 0.05) / (l1 + 0.05);
2606
+ };
2607
+
2608
+ const { sqrt, pow, min, max: max$1, atan2, abs, cos, sin, exp, PI } = Math;
2609
+
2610
+ function deltaE (a, b, Kl = 1, Kc = 1, Kh = 1) {
2611
+ // Delta E (CIE 2000)
2612
+ // see http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE2000.html
2613
+ var rad2deg = function (rad) {
2614
+ return (360 * rad) / (2 * PI);
2615
+ };
2616
+ var deg2rad = function (deg) {
2617
+ return (2 * PI * deg) / 360;
2618
+ };
2619
+ a = new Color(a);
2620
+ b = new Color(b);
2621
+ const [L1, a1, b1] = Array.from(a.lab());
2622
+ const [L2, a2, b2] = Array.from(b.lab());
2623
+ const avgL = (L1 + L2) / 2;
2624
+ const C1 = sqrt(pow(a1, 2) + pow(b1, 2));
2625
+ const C2 = sqrt(pow(a2, 2) + pow(b2, 2));
2626
+ const avgC = (C1 + C2) / 2;
2627
+ const G = 0.5 * (1 - sqrt(pow(avgC, 7) / (pow(avgC, 7) + pow(25, 7))));
2628
+ const a1p = a1 * (1 + G);
2629
+ const a2p = a2 * (1 + G);
2630
+ const C1p = sqrt(pow(a1p, 2) + pow(b1, 2));
2631
+ const C2p = sqrt(pow(a2p, 2) + pow(b2, 2));
2632
+ const avgCp = (C1p + C2p) / 2;
2633
+ const arctan1 = rad2deg(atan2(b1, a1p));
2634
+ const arctan2 = rad2deg(atan2(b2, a2p));
2635
+ const h1p = arctan1 >= 0 ? arctan1 : arctan1 + 360;
2636
+ const h2p = arctan2 >= 0 ? arctan2 : arctan2 + 360;
2637
+ const avgHp =
2638
+ abs(h1p - h2p) > 180 ? (h1p + h2p + 360) / 2 : (h1p + h2p) / 2;
2639
+ const T =
2640
+ 1 -
2641
+ 0.17 * cos(deg2rad(avgHp - 30)) +
2642
+ 0.24 * cos(deg2rad(2 * avgHp)) +
2643
+ 0.32 * cos(deg2rad(3 * avgHp + 6)) -
2644
+ 0.2 * cos(deg2rad(4 * avgHp - 63));
2645
+ let deltaHp = h2p - h1p;
2646
+ deltaHp =
2647
+ abs(deltaHp) <= 180
2648
+ ? deltaHp
2649
+ : h2p <= h1p
2650
+ ? deltaHp + 360
2651
+ : deltaHp - 360;
2652
+ deltaHp = 2 * sqrt(C1p * C2p) * sin(deg2rad(deltaHp) / 2);
2653
+ const deltaL = L2 - L1;
2654
+ const deltaCp = C2p - C1p;
2655
+ const sl = 1 + (0.015 * pow(avgL - 50, 2)) / sqrt(20 + pow(avgL - 50, 2));
2656
+ const sc = 1 + 0.045 * avgCp;
2657
+ const sh = 1 + 0.015 * avgCp * T;
2658
+ const deltaTheta = 30 * exp(-pow((avgHp - 275) / 25, 2));
2659
+ const Rc = 2 * sqrt(pow(avgCp, 7) / (pow(avgCp, 7) + pow(25, 7)));
2660
+ const Rt = -Rc * sin(2 * deg2rad(deltaTheta));
2661
+ const result = sqrt(
2662
+ pow(deltaL / (Kl * sl), 2) +
2663
+ pow(deltaCp / (Kc * sc), 2) +
2664
+ pow(deltaHp / (Kh * sh), 2) +
2665
+ Rt * (deltaCp / (Kc * sc)) * (deltaHp / (Kh * sh))
2666
+ );
2667
+ return max$1(0, min(100, result));
2668
+ }
2669
+
2670
+ // simple Euclidean distance
2671
+ function distance (a, b, mode = 'lab') {
2672
+ // Delta E (CIE 1976)
2673
+ // see http://www.brucelindbloom.com/index.html?Equations.html
2674
+ a = new Color(a);
2675
+ b = new Color(b);
2676
+ const l1 = a.get(mode);
2677
+ const l2 = b.get(mode);
2678
+ let sum_sq = 0;
2679
+ for (let i in l1) {
2680
+ const d = (l1[i] || 0) - (l2[i] || 0);
2681
+ sum_sq += d * d;
2682
+ }
2683
+ return Math.sqrt(sum_sq);
2684
+ }
2685
+
2686
+ const valid = (...args) => {
2687
+ try {
2688
+ new Color(...args);
2689
+ return true;
2690
+ // eslint-disable-next-line
2691
+ } catch (e) {
2692
+ return false;
2693
+ }
2694
+ };
2695
+
2696
+ // some pre-defined color scales:
2697
+
2698
+ const scales = {
2699
+ cool() {
2700
+ return scale([chroma.hsl(180, 1, 0.9), chroma.hsl(250, 0.7, 0.4)]);
2701
+ },
2702
+ hot() {
2703
+ return scale(['#000', '#f00', '#ff0', '#fff']).mode(
2704
+ 'rgb'
2705
+ );
2706
+ }
2707
+ };
2708
+
2709
+ /**
2710
+ ColorBrewer colors for chroma.js
2711
+
2712
+ Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The
2713
+ Pennsylvania State University.
2714
+
2715
+ Licensed under the Apache License, Version 2.0 (the "License");
2716
+ you may not use this file except in compliance with the License.
2717
+ You may obtain a copy of the License at
2718
+ http://www.apache.org/licenses/LICENSE-2.0
2719
+
2720
+ Unless required by applicable law or agreed to in writing, software distributed
2721
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
2722
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
2723
+ specific language governing permissions and limitations under the License.
2724
+ */
2725
+
2726
+ const colorbrewer = {
2727
+ // sequential
2728
+ OrRd: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#b30000', '#7f0000'],
2729
+ PuBu: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#045a8d', '#023858'],
2730
+ BuPu: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#810f7c', '#4d004b'],
2731
+ Oranges: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#a63603', '#7f2704'],
2732
+ BuGn: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#006d2c', '#00441b'],
2733
+ YlOrBr: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#993404', '#662506'],
2734
+ YlGn: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#006837', '#004529'],
2735
+ Reds: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#a50f15', '#67000d'],
2736
+ RdPu: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177', '#49006a'],
2737
+ Greens: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#006d2c', '#00441b'],
2738
+ YlGnBu: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#253494', '#081d58'],
2739
+ Purples: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#54278f', '#3f007d'],
2740
+ GnBu: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#0868ac', '#084081'],
2741
+ Greys: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525', '#000000'],
2742
+ YlOrRd: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#bd0026', '#800026'],
2743
+ PuRd: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#980043', '#67001f'],
2744
+ Blues: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#08519c', '#08306b'],
2745
+ PuBuGn: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016c59', '#014636'],
2746
+ Viridis: ['#440154', '#482777', '#3f4a8a', '#31678e', '#26838f', '#1f9d8a', '#6cce5a', '#b6de2b', '#fee825'],
2747
+
2748
+ // diverging
2749
+ Spectral: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'],
2750
+ RdYlGn: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'],
2751
+ RdBu: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'],
2752
+ PiYG: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'],
2753
+ PRGn: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'],
2754
+ RdYlBu: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'],
2755
+ BrBG: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'],
2756
+ RdGy: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'],
2757
+ PuOr: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'],
2758
+
2759
+ // qualitative
2760
+ Set2: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494', '#b3b3b3'],
2761
+ Accent: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17', '#666666'],
2762
+ Set1: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf', '#999999'],
2763
+ Set3: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f'],
2764
+ Dark2: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d', '#666666'],
2765
+ Paired: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928'],
2766
+ Pastel2: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc', '#cccccc'],
2767
+ Pastel1: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec', '#f2f2f2']
2768
+ };
2769
+
2770
+ // add lowercase aliases for case-insensitive matches
2771
+ for (let key of Object.keys(colorbrewer)) {
2772
+ colorbrewer[key.toLowerCase()] = colorbrewer[key];
2773
+ }
2774
+
2775
+ const cmyk2rgb = (...args) => {
2776
+ args = unpack(args, 'cmyk');
2777
+ const [c, m, y, k] = args;
2778
+ const alpha = args.length > 4 ? args[4] : 1;
2779
+ if (k === 1) return [0, 0, 0, alpha];
2780
+ return [
2781
+ c >= 1 ? 0 : 255 * (1 - c) * (1 - k), // r
2782
+ m >= 1 ? 0 : 255 * (1 - m) * (1 - k), // g
2783
+ y >= 1 ? 0 : 255 * (1 - y) * (1 - k), // b
2784
+ alpha
2785
+ ];
2786
+ };
2787
+
2788
+ const { max } = Math;
2789
+
2790
+ const rgb2cmyk = (...args) => {
2791
+ let [r, g, b] = unpack(args, 'rgb');
2792
+ r = r / 255;
2793
+ g = g / 255;
2794
+ b = b / 255;
2795
+ const k = 1 - max(r, max(g, b));
2796
+ const f = k < 1 ? 1 / (1 - k) : 0;
2797
+ const c = (1 - r - k) * f;
2798
+ const m = (1 - g - k) * f;
2799
+ const y = (1 - b - k) * f;
2800
+ return [c, m, y, k];
2801
+ };
2802
+
2803
+ Color.prototype.cmyk = function () {
2804
+ return rgb2cmyk(this._rgb);
2805
+ };
2806
+
2807
+ const cmyk = (...args) => new Color(...args, 'cmyk');
2808
+ Object.assign(chroma, { cmyk });
2809
+
2810
+ input.format.cmyk = cmyk2rgb;
2811
+
2812
+ input.autodetect.push({
2813
+ p: 2,
2814
+ test: (...args) => {
2815
+ args = unpack(args, 'cmyk');
2816
+ if (type(args) === 'array' && args.length === 4) {
2817
+ return 'cmyk';
2818
+ }
2819
+ }
2820
+ });
2821
+
2822
+ /*
2823
+ * supported arguments:
2824
+ * - hsl2css(h,s,l)
2825
+ * - hsl2css(h,s,l,a)
2826
+ * - hsl2css([h,s,l], mode)
2827
+ * - hsl2css([h,s,l,a], mode)
2828
+ * - hsl2css({h,s,l,a}, mode)
2829
+ */
2830
+ const hsl2css = (...args) => {
2831
+ const hsla = unpack(args, 'hsla');
2832
+ let mode = last(args) || 'lsa';
2833
+ hsla[0] = rnd2(hsla[0] || 0) + 'deg';
2834
+ hsla[1] = rnd2(hsla[1] * 100) + '%';
2835
+ hsla[2] = rnd2(hsla[2] * 100) + '%';
2836
+ if (mode === 'hsla' || (hsla.length > 3 && hsla[3] < 1)) {
2837
+ hsla[3] = '/ ' + (hsla.length > 3 ? hsla[3] : 1);
2838
+ mode = 'hsla';
2839
+ } else {
2840
+ hsla.length = 3;
2841
+ }
2842
+ return `${mode.substr(0, 3)}(${hsla.join(' ')})`;
2843
+ };
2844
+
2845
+ /*
2846
+ * supported arguments:
2847
+ * - lab2css(l,a,b)
2848
+ * - lab2css(l,a,b,alpha)
2849
+ * - lab2css([l,a,b], mode)
2850
+ * - lab2css([l,a,b,alpha], mode)
2851
+ */
2852
+ const lab2css = (...args) => {
2853
+ const laba = unpack(args, 'lab');
2854
+ let mode = last(args) || 'lab';
2855
+ laba[0] = rnd2(laba[0]) + '%';
2856
+ laba[1] = rnd2(laba[1]);
2857
+ laba[2] = rnd2(laba[2]);
2858
+ if (mode === 'laba' || (laba.length > 3 && laba[3] < 1)) {
2859
+ laba[3] = '/ ' + (laba.length > 3 ? laba[3] : 1);
2860
+ } else {
2861
+ laba.length = 3;
2862
+ }
2863
+ return `lab(${laba.join(' ')})`;
2864
+ };
2865
+
2866
+ /*
2867
+ * supported arguments:
2868
+ * - lab2css(l,a,b)
2869
+ * - lab2css(l,a,b,alpha)
2870
+ * - lab2css([l,a,b], mode)
2871
+ * - lab2css([l,a,b,alpha], mode)
2872
+ */
2873
+ const lch2css = (...args) => {
2874
+ const lcha = unpack(args, 'lch');
2875
+ let mode = last(args) || 'lab';
2876
+ lcha[0] = rnd2(lcha[0]) + '%';
2877
+ lcha[1] = rnd2(lcha[1]);
2878
+ lcha[2] = rnd2(lcha[2]) + 'deg'; // add deg unit to hue
2879
+ if (mode === 'lcha' || (lcha.length > 3 && lcha[3] < 1)) {
2880
+ lcha[3] = '/ ' + (lcha.length > 3 ? lcha[3] : 1);
2881
+ } else {
2882
+ lcha.length = 3;
2883
+ }
2884
+ return `lch(${lcha.join(' ')})`;
2885
+ };
2886
+
2887
+ const oklab2css$1 = (...args) => {
2888
+ const laba = unpack(args, 'lab');
2889
+ laba[0] = rnd2(laba[0] * 100) + '%';
2890
+ laba[1] = rnd3(laba[1]);
2891
+ laba[2] = rnd3(laba[2]);
2892
+ if (laba.length > 3 && laba[3] < 1) {
2893
+ laba[3] = '/ ' + (laba.length > 3 ? laba[3] : 1);
2894
+ } else {
2895
+ laba.length = 3;
2896
+ }
2897
+ return `oklab(${laba.join(' ')})`;
2898
+ };
2899
+
2900
+ const rgb2oklch = (...args) => {
2901
+ const [r, g, b, ...rest] = unpack(args, 'rgb');
2902
+ const [l, a, b_] = rgb2oklab(r, g, b);
2903
+ const [L, c, h] = lab2lch(l, a, b_);
2904
+ return [L, c, h, ...(rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])];
2905
+ };
2906
+
2907
+ const oklab2css = (...args) => {
2908
+ const laba = unpack(args, 'lab');
2909
+ laba[0] = rnd2(laba[0] * 100) + '%';
2910
+ laba[1] = rnd3(laba[1]);
2911
+ laba[2] = rnd2(laba[2]) + 'deg';
2912
+ if (laba.length > 3 && laba[3] < 1) {
2913
+ laba[3] = '/ ' + (laba.length > 3 ? laba[3] : 1);
2914
+ } else {
2915
+ laba.length = 3;
2916
+ }
2917
+ return `oklch(${laba.join(' ')})`;
2918
+ };
2919
+
2920
+ const { round: round$2 } = Math;
2921
+
2922
+ /*
2923
+ * supported arguments:
2924
+ * - rgb2css(r,g,b)
2925
+ * - rgb2css(r,g,b,a)
2926
+ * - rgb2css([r,g,b], mode)
2927
+ * - rgb2css([r,g,b,a], mode)
2928
+ * - rgb2css({r,g,b,a}, mode)
2929
+ */
2930
+ const rgb2css = (...args) => {
2931
+ const rgba = unpack(args, 'rgba');
2932
+ let mode = last(args) || 'rgb';
2933
+ if (mode.substr(0, 3) === 'hsl') {
2934
+ return hsl2css(rgb2hsl$1(rgba), mode);
2935
+ }
2936
+ if (mode.substr(0, 3) === 'lab') {
2937
+ // change to D50 lab whitepoint since this is what W3C is using for CSS Lab colors
2938
+ const prevWhitePoint = getLabWhitePoint();
2939
+ setLabWhitePoint('d50');
2940
+ const cssColor = lab2css(rgb2lab(rgba), mode);
2941
+ setLabWhitePoint(prevWhitePoint);
2942
+ return cssColor;
2943
+ }
2944
+ if (mode.substr(0, 3) === 'lch') {
2945
+ // change to D50 lab whitepoint since this is what W3C is using for CSS Lab colors
2946
+ const prevWhitePoint = getLabWhitePoint();
2947
+ setLabWhitePoint('d50');
2948
+ const cssColor = lch2css(rgb2lch(rgba), mode);
2949
+ setLabWhitePoint(prevWhitePoint);
2950
+ return cssColor;
2951
+ }
2952
+ if (mode.substr(0, 5) === 'oklab') {
2953
+ return oklab2css$1(rgb2oklab(rgba));
2954
+ }
2955
+ if (mode.substr(0, 5) === 'oklch') {
2956
+ return oklab2css(rgb2oklch(rgba));
2957
+ }
2958
+ rgba[0] = round$2(rgba[0]);
2959
+ rgba[1] = round$2(rgba[1]);
2960
+ rgba[2] = round$2(rgba[2]);
2961
+ if (mode === 'rgba' || (rgba.length > 3 && rgba[3] < 1)) {
2962
+ rgba[3] = '/ ' + (rgba.length > 3 ? rgba[3] : 1);
2963
+ mode = 'rgba';
2964
+ }
2965
+ return `${mode.substr(0, 3)}(${rgba.slice(0, mode === 'rgb' ? 3 : 4).join(' ')})`;
2966
+ };
2967
+
2968
+ const oklch2rgb = (...args) => {
2969
+ args = unpack(args, 'lch');
2970
+ const [l, c, h, ...rest] = args;
2971
+ const [L, a, b_] = lch2lab(l, c, h);
2972
+ const [r, g, b] = oklab2rgb(L, a, b_);
2973
+ return [r, g, b, ...(rest.length > 0 && rest[0] < 1 ? [rest[0]] : [])];
2974
+ };
2975
+
2976
+ const RE_RGB = /^rgb\(\s*(-?\d+) \s*(-?\d+)\s* \s*(-?\d+)\s*\)$/;
2977
+ const RE_RGB_LEGACY = /^rgb\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*\)$/;
2978
+
2979
+ const RE_RGBA =
2980
+ /^rgba?\(\s*(-?\d+) \s*(-?\d+)\s* \s*(-?\d+)\s*\/\s*([01]|[01]?\.\d+)\)$/;
2981
+ const RE_RGBA_LEGACY =
2982
+ /^rgba\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*([01]|[01]?\.\d+)\)$/;
2983
+
2984
+ const RE_RGB_PCT =
2985
+ /^rgb\(\s*(-?\d+(?:\.\d+)?)% \s*(-?\d+(?:\.\d+)?)%\s* \s*(-?\d+(?:\.\d+)?)%\s*\)$/;
2986
+ const RE_RGB_PCT_LEGACY =
2987
+ /^rgb\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/;
2988
+
2989
+ const RE_RGBA_PCT =
2990
+ /^rgba?\(\s*(-?\d+(?:\.\d+)?)% \s*(-?\d+(?:\.\d+)?)%\s* \s*(-?\d+(?:\.\d+)?)%\s*\/\s*([01]|[01]?\.\d+)\)$/;
2991
+ const RE_RGBA_PCT_LEGACY =
2992
+ /^rgba\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/;
2993
+
2994
+ const RE_HSL =
2995
+ /^hsl\(\s*(-?\d+(?:\.\d+)?)deg \s*(-?\d+(?:\.\d+)?)%\s* \s*(-?\d+(?:\.\d+)?)%\s*\)$/;
2996
+ const RE_HSL_LEGACY =
2997
+ /^hsl\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/;
2998
+
2999
+ const RE_HSLA =
3000
+ /^hsla?\(\s*(-?\d+(?:\.\d+)?)deg \s*(-?\d+(?:\.\d+)?)%\s* \s*(-?\d+(?:\.\d+)?)%\s*\/\s*([01]|[01]?\.\d+)\)$/;
3001
+ const RE_HSLA_LEGACY =
3002
+ /^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/;
3003
+
3004
+ const RE_LAB =
3005
+ /^lab\(\s*(-?\d+(?:\.\d+)?%?) \s*(-?\d+(?:\.\d+)?%?) \s*(-?\d+(?:\.\d+)?%?)\s*(?:\/\s*(\d+(?:\.\d+)?))?\)?$/;
3006
+ const RE_LCH =
3007
+ /^lch\(\s*(-?\d+(?:\.\d+)?%?) \s*((?:-?\d+(?:\.\d+)?%?)|none) \s*(-?\d+(?:\.\d+)?(?:deg)?|none)\s*(?:\/\s*(\d+(?:\.\d+)?))?\)?$/;
3008
+ const RE_OKLAB =
3009
+ /^oklab\(\s*(-?\d+(?:\.\d+)?%?) \s*(-?\d+(?:\.\d+)?%?) \s*(-?\d+(?:\.\d+)?%?)\s*(?:\/\s*(\d+(?:\.\d+)?))?\)?$/;
3010
+ const RE_OKLCH =
3011
+ /^oklch\(\s*(-?\d+(?:\.\d+)?%?) \s*(?:(-?\d+(?:\.\d+)?%?)|none) \s*(-?\d+(?:\.\d+)?(?:deg)?|none)\s*(?:\/\s*(\d+(?:\.\d+)?))?\)?$/;
3012
+
3013
+ const { round: round$1 } = Math;
3014
+
3015
+ const roundRGB = (rgb) => {
3016
+ return rgb.map((v, i) => (i <= 2 ? limit(round$1(v), 0, 255) : v));
3017
+ };
3018
+
3019
+ const percentToAbsolute = (pct, min = 0, max = 100, signed = false) => {
3020
+ if (typeof pct === 'string' && pct.endsWith('%')) {
3021
+ pct = parseFloat(pct.substring(0, pct.length - 1)) / 100;
3022
+ if (signed) {
3023
+ // signed percentages are in the range -100% to 100%
3024
+ pct = min + (pct + 1) * 0.5 * (max - min);
3025
+ } else {
3026
+ pct = min + pct * (max - min);
3027
+ }
3028
+ }
3029
+ return +pct;
3030
+ };
3031
+
3032
+ const noneToValue = (v, noneValue) => {
3033
+ return v === 'none' ? noneValue : v;
3034
+ };
3035
+
3036
+ const css2rgb = (css) => {
3037
+ css = css.toLowerCase().trim();
3038
+ let m;
3039
+
3040
+ if (input.format.named) {
3041
+ try {
3042
+ return input.format.named(css);
3043
+ // eslint-disable-next-line
3044
+ } catch (e) {}
3045
+ }
3046
+
3047
+ // rgb(250 20 0) or rgb(250,20,0)
3048
+ if ((m = css.match(RE_RGB)) || (m = css.match(RE_RGB_LEGACY))) {
3049
+ const rgb = m.slice(1, 4);
3050
+ for (let i = 0; i < 3; i++) {
3051
+ rgb[i] = +rgb[i];
3052
+ }
3053
+ rgb[3] = 1; // default alpha
3054
+ return rgb;
3055
+ }
3056
+
3057
+ // rgba(250,20,0,0.4)
3058
+ if ((m = css.match(RE_RGBA)) || (m = css.match(RE_RGBA_LEGACY))) {
3059
+ const rgb = m.slice(1, 5);
3060
+ for (let i = 0; i < 4; i++) {
3061
+ rgb[i] = +rgb[i];
3062
+ }
3063
+ return rgb;
3064
+ }
3065
+
3066
+ // rgb(100%,0%,0%)
3067
+ if ((m = css.match(RE_RGB_PCT)) || (m = css.match(RE_RGB_PCT_LEGACY))) {
3068
+ const rgb = m.slice(1, 4);
3069
+ for (let i = 0; i < 3; i++) {
3070
+ rgb[i] = round$1(rgb[i] * 2.55);
3071
+ }
3072
+ rgb[3] = 1; // default alpha
3073
+ return rgb;
3074
+ }
3075
+
3076
+ // rgba(100%,0%,0%,0.4)
3077
+ if ((m = css.match(RE_RGBA_PCT)) || (m = css.match(RE_RGBA_PCT_LEGACY))) {
3078
+ const rgb = m.slice(1, 5);
3079
+ for (let i = 0; i < 3; i++) {
3080
+ rgb[i] = round$1(rgb[i] * 2.55);
3081
+ }
3082
+ rgb[3] = +rgb[3];
3083
+ return rgb;
3084
+ }
3085
+
3086
+ // hsl(0,100%,50%)
3087
+ if ((m = css.match(RE_HSL)) || (m = css.match(RE_HSL_LEGACY))) {
3088
+ const hsl = m.slice(1, 4);
3089
+ hsl[1] *= 0.01;
3090
+ hsl[2] *= 0.01;
3091
+ const rgb = hsl2rgb(hsl);
3092
+ for (let i = 0; i < 3; i++) {
3093
+ rgb[i] = round$1(rgb[i]);
3094
+ }
3095
+ rgb[3] = 1;
3096
+ return rgb;
3097
+ }
3098
+
3099
+ // hsla(0,100%,50%,0.5)
3100
+ if ((m = css.match(RE_HSLA)) || (m = css.match(RE_HSLA_LEGACY))) {
3101
+ const hsl = m.slice(1, 4);
3102
+ hsl[1] *= 0.01;
3103
+ hsl[2] *= 0.01;
3104
+ const rgb = hsl2rgb(hsl);
3105
+ for (let i = 0; i < 3; i++) {
3106
+ rgb[i] = round$1(rgb[i]);
3107
+ }
3108
+ rgb[3] = +m[4]; // default alpha = 1
3109
+ return rgb;
3110
+ }
3111
+
3112
+ if ((m = css.match(RE_LAB))) {
3113
+ const lab = m.slice(1, 4);
3114
+ lab[0] = percentToAbsolute(lab[0], 0, 100);
3115
+ lab[1] = percentToAbsolute(lab[1], -125, 125, true);
3116
+ lab[2] = percentToAbsolute(lab[2], -125, 125, true);
3117
+ // convert to D50 Lab whitepoint
3118
+ const wp = getLabWhitePoint();
3119
+ setLabWhitePoint('d50');
3120
+ const rgb = roundRGB(lab2rgb(lab));
3121
+ // convert back to original Lab whitepoint
3122
+ setLabWhitePoint(wp);
3123
+ rgb[3] = m[4] !== undefined ? +m[4] : 1;
3124
+ return rgb;
3125
+ }
3126
+
3127
+ if ((m = css.match(RE_LCH))) {
3128
+ const lch = m.slice(1, 4);
3129
+ lch[0] = percentToAbsolute(lch[0], 0, 100);
3130
+ lch[1] = percentToAbsolute(noneToValue(lch[1], 0), 0, 150, false);
3131
+ lch[2] = +noneToValue(lch[2].replace('deg', ''), 0);
3132
+ // convert to D50 Lab whitepoint
3133
+ const wp = getLabWhitePoint();
3134
+ setLabWhitePoint('d50');
3135
+ const rgb = roundRGB(lch2rgb(lch));
3136
+ // convert back to original Lab whitepoint
3137
+ setLabWhitePoint(wp);
3138
+ rgb[3] = m[4] !== undefined ? +m[4] : 1;
3139
+ return rgb;
3140
+ }
3141
+
3142
+ if ((m = css.match(RE_OKLAB))) {
3143
+ const oklab = m.slice(1, 4);
3144
+ oklab[0] = percentToAbsolute(oklab[0], 0, 1);
3145
+ oklab[1] = percentToAbsolute(oklab[1], -0.4, 0.4, true);
3146
+ oklab[2] = percentToAbsolute(oklab[2], -0.4, 0.4, true);
3147
+ const rgb = roundRGB(oklab2rgb(oklab));
3148
+ rgb[3] = m[4] !== undefined ? +m[4] : 1;
3149
+ return rgb;
3150
+ }
3151
+
3152
+ if ((m = css.match(RE_OKLCH))) {
3153
+ const oklch = m.slice(1, 4);
3154
+ oklch[0] = percentToAbsolute(oklch[0], 0, 1);
3155
+ oklch[1] = percentToAbsolute(noneToValue(oklch[1], 0), 0, 0.4, false);
3156
+ oklch[2] = +noneToValue(oklch[2].replace('deg', ''), 0);
3157
+ const rgb = roundRGB(oklch2rgb(oklch));
3158
+ rgb[3] = m[4] !== undefined ? +m[4] : 1;
3159
+ return rgb;
3160
+ }
3161
+ };
3162
+
3163
+ css2rgb.test = (s) => {
3164
+ return (
3165
+ // modern
3166
+ RE_RGB.test(s) ||
3167
+ RE_RGBA.test(s) ||
3168
+ RE_RGB_PCT.test(s) ||
3169
+ RE_RGBA_PCT.test(s) ||
3170
+ RE_HSL.test(s) ||
3171
+ RE_HSLA.test(s) ||
3172
+ RE_LAB.test(s) ||
3173
+ RE_LCH.test(s) ||
3174
+ RE_OKLAB.test(s) ||
3175
+ RE_OKLCH.test(s) ||
3176
+ // legacy
3177
+ RE_RGB_LEGACY.test(s) ||
3178
+ RE_RGBA_LEGACY.test(s) ||
3179
+ RE_RGB_PCT_LEGACY.test(s) ||
3180
+ RE_RGBA_PCT_LEGACY.test(s) ||
3181
+ RE_HSL_LEGACY.test(s) ||
3182
+ RE_HSLA_LEGACY.test(s)
3183
+ );
3184
+ };
3185
+
3186
+ Color.prototype.css = function (mode) {
3187
+ return rgb2css(this._rgb, mode);
3188
+ };
3189
+
3190
+ const css = (...args) => new Color(...args, 'css');
3191
+ chroma.css = css;
3192
+
3193
+ input.format.css = css2rgb;
3194
+
3195
+ input.autodetect.push({
3196
+ p: 5,
3197
+ test: (h, ...rest) => {
3198
+ if (!rest.length && type(h) === 'string' && css2rgb.test(h)) {
3199
+ return 'css';
3200
+ }
3201
+ }
3202
+ });
3203
+
3204
+ input.format.gl = (...args) => {
3205
+ const rgb = unpack(args, 'rgba');
3206
+ rgb[0] *= 255;
3207
+ rgb[1] *= 255;
3208
+ rgb[2] *= 255;
3209
+ return rgb;
3210
+ };
3211
+
3212
+ const gl = (...args) => new Color(...args, 'gl');
3213
+ chroma.gl = gl;
3214
+
3215
+ Color.prototype.gl = function () {
3216
+ const rgb = this._rgb;
3217
+ return [rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, rgb[3]];
3218
+ };
3219
+
3220
+ Color.prototype.hex = function (mode) {
3221
+ return rgb2hex(this._rgb, mode);
3222
+ };
3223
+
3224
+ const hex = (...args) => new Color(...args, 'hex');
3225
+ chroma.hex = hex;
3226
+
3227
+ input.format.hex = hex2rgb;
3228
+ input.autodetect.push({
3229
+ p: 4,
3230
+ test: (h, ...rest) => {
3231
+ if (
3232
+ !rest.length &&
3233
+ type(h) === 'string' &&
3234
+ [3, 4, 5, 6, 7, 8, 9].indexOf(h.length) >= 0
3235
+ ) {
3236
+ return 'hex';
3237
+ }
3238
+ }
3239
+ });
3240
+
3241
+ /*
3242
+ * Based on implementation by Neil Bartlett
3243
+ * https://github.com/neilbartlett/color-temperature
3244
+ */
3245
+
3246
+ const { log } = Math;
3247
+
3248
+ const temperature2rgb = (kelvin) => {
3249
+ const temp = kelvin / 100;
3250
+ let r, g, b;
3251
+ if (temp < 66) {
3252
+ r = 255;
3253
+ g =
3254
+ temp < 6
3255
+ ? 0
3256
+ : -155.25485562709179 -
3257
+ 0.44596950469579133 * (g = temp - 2) +
3258
+ 104.49216199393888 * log(g);
3259
+ b =
3260
+ temp < 20
3261
+ ? 0
3262
+ : -254.76935184120902 +
3263
+ 0.8274096064007395 * (b = temp - 10) +
3264
+ 115.67994401066147 * log(b);
3265
+ } else {
3266
+ r =
3267
+ 351.97690566805693 +
3268
+ 0.114206453784165 * (r = temp - 55) -
3269
+ 40.25366309332127 * log(r);
3270
+ g =
3271
+ 325.4494125711974 +
3272
+ 0.07943456536662342 * (g = temp - 50) -
3273
+ 28.0852963507957 * log(g);
3274
+ b = 255;
3275
+ }
3276
+ return [r, g, b, 1];
3277
+ };
3278
+
3279
+ /*
3280
+ * Based on implementation by Neil Bartlett
3281
+ * https://github.com/neilbartlett/color-temperature
3282
+ **/
3283
+
3284
+ const { round } = Math;
3285
+
3286
+ const rgb2temperature = (...args) => {
3287
+ const rgb = unpack(args, 'rgb');
3288
+ const r = rgb[0],
3289
+ b = rgb[2];
3290
+ let minTemp = 1000;
3291
+ let maxTemp = 40000;
3292
+ const eps = 0.4;
3293
+ let temp;
3294
+ while (maxTemp - minTemp > eps) {
3295
+ temp = (maxTemp + minTemp) * 0.5;
3296
+ const rgb = temperature2rgb(temp);
3297
+ if (rgb[2] / rgb[0] >= b / r) {
3298
+ maxTemp = temp;
3299
+ } else {
3300
+ minTemp = temp;
3301
+ }
3302
+ }
3303
+ return round(temp);
3304
+ };
3305
+
3306
+ Color.prototype.temp =
3307
+ Color.prototype.kelvin =
3308
+ Color.prototype.temperature =
3309
+ function () {
3310
+ return rgb2temperature(this._rgb);
3311
+ };
3312
+
3313
+ const temp = (...args) => new Color(...args, 'temp');
3314
+ Object.assign(chroma, { temp, kelvin: temp, temperature: temp });
3315
+
3316
+ input.format.temp =
3317
+ input.format.kelvin =
3318
+ input.format.temperature =
3319
+ temperature2rgb;
3320
+
3321
+ Color.prototype.oklch = function () {
3322
+ return rgb2oklch(this._rgb);
3323
+ };
3324
+
3325
+ const oklch = (...args) => new Color(...args, 'oklch');
3326
+ Object.assign(chroma, { oklch });
3327
+
3328
+ input.format.oklch = oklch2rgb;
3329
+
3330
+ input.autodetect.push({
3331
+ p: 2,
3332
+ test: (...args) => {
3333
+ args = unpack(args, 'oklch');
3334
+ if (type(args) === 'array' && args.length === 3) {
3335
+ return 'oklch';
3336
+ }
3337
+ }
3338
+ });
3339
+
3340
+ // feel free to comment out anything to rollup
3341
+ // a smaller chroma.js bundle
3342
+
3343
+ Object.assign(chroma, {
3344
+ analyze,
3345
+ average,
3346
+ bezier: bezier$1,
3347
+ blend,
3348
+ brewer: colorbrewer,
3349
+ Color,
3350
+ colors: w3cx11,
3351
+ contrast,
3352
+ cubehelix,
3353
+ deltaE,
3354
+ distance,
3355
+ input,
3356
+ interpolate: mix,
3357
+ limits,
3358
+ mix,
3359
+ random: random$1,
3360
+ scale,
3361
+ scales,
3362
+ valid
3363
+ });
3364
+
3365
+ const LIGHTNESS_MAP = [0.96, 0.907, 0.805, 0.697, 0.605, 0.547, 0.518, 0.445, 0.395, 0.34];
3366
+ const SATURATION_MAP = [0.32, 0.16, 0.08, 0.04, 0, 0, 0.04, 0.08, 0.16, 0.32];
3367
+ function getClosestLightness(colorObject) {
3368
+ const lightnessGoal = colorObject.get("hsl.l");
3369
+ return LIGHTNESS_MAP.reduce(
3370
+ (prev, curr) => Math.abs(curr - lightnessGoal) < Math.abs(prev - lightnessGoal) ? curr : prev
3371
+ );
3372
+ }
3373
+ function generateColorsMap(color) {
3374
+ const colorObject = chroma(color);
3375
+ const closestLightness = getClosestLightness(colorObject);
3376
+ const baseColorIndex = LIGHTNESS_MAP.findIndex((l) => l === closestLightness);
3377
+ const colors = LIGHTNESS_MAP.map((l) => colorObject.set("hsl.l", l)).map((c) => chroma(c)).map((c, i) => {
3378
+ const saturationDelta = SATURATION_MAP[i] - SATURATION_MAP[baseColorIndex];
3379
+ return saturationDelta >= 0 ? c.saturate(saturationDelta) : c.desaturate(saturationDelta * -1);
3380
+ });
3381
+ return { baseColorIndex, colors };
3382
+ }
3383
+ function generateColors(color) {
3384
+ return generateColorsMap(color).colors.map((c) => c.hex());
3385
+ }
3386
+
3387
+ const blue$1 = {
3388
+ fill: "#3b82f6",
3389
+ stroke: "#2563eb",
3390
+ hiContrast: "#eff6ff",
3391
+ loContrast: "#bfdbfe"
3392
+ };
3393
+ const sky$1 = {
3394
+ fill: "#0284c7",
3395
+ stroke: "#0369a1",
3396
+ hiContrast: "#f0f9ff",
3397
+ loContrast: "#B6ECF7"
3398
+ };
3399
+ const slate$1 = {
3400
+ fill: "#64748b",
3401
+ stroke: "#475569",
3402
+ hiContrast: "#f8fafc",
3403
+ loContrast: "#cbd5e1"
3404
+ };
3405
+ const ElementColors = {
3406
+ primary: blue$1,
3407
+ blue: blue$1,
3408
+ secondary: sky$1,
3409
+ sky: sky$1,
3410
+ muted: slate$1,
3411
+ slate: slate$1,
3412
+ gray: {
3413
+ // fill: colors.neutral[500],
3414
+ // stroke: colors.neutral[600],
3415
+ // hiContrast: colors.neutral[50],
3416
+ // loContrast: colors.neutral[200],
3417
+ fill: "#737373",
3418
+ stroke: "#525252",
3419
+ hiContrast: "#fafafa",
3420
+ loContrast: "#d4d4d4"
3421
+ },
3422
+ red: {
3423
+ // fill: colors.red[500],
3424
+ // stroke: colors.red[600],
3425
+ // hiContrast: colors.red[50],
3426
+ // loContrast: colors.red[200],
3427
+ fill: "#AC4D39",
3428
+ // fill: '#b54548',
3429
+ stroke: "#853A2D",
3430
+ // hiContrast: '#fef2f2',
3431
+ // loContrast: '#fecaca',
3432
+ // hiContrast: '#191111', // colors.gray[900],
3433
+ // loContrast: '#3b1219' // colors.gray[800],
3434
+ hiContrast: "#FBD3CB",
3435
+ // hiContrast: '#f8fafc',
3436
+ // loContrast: '#fdd8d8' // radix black red 12
3437
+ loContrast: "#f5b2a3"
3438
+ },
3439
+ green: {
3440
+ fill: "#428a4f",
3441
+ stroke: "#2d5d39",
3442
+ hiContrast: "#f8fafc",
3443
+ loContrast: "#c2f0c2"
3444
+ },
3445
+ amber: {
3446
+ fill: "#A35829",
3447
+ stroke: "#7E451D",
3448
+ hiContrast: "#FFE0C2",
3449
+ loContrast: "#f9b27c"
3450
+ },
3451
+ indigo: {
3452
+ // fill: colors.indigo[500],
3453
+ // stroke: colors.indigo[600],
3454
+ // hiContrast: colors.indigo[50],
3455
+ // loContrast: colors.indigo[200],
3456
+ fill: "#6366f1",
3457
+ stroke: "#4f46e5",
3458
+ hiContrast: "#eef2ff",
3459
+ loContrast: "#c7d2fe"
3460
+ }
3461
+ };
3462
+
3463
+ const gray = {
3464
+ lineColor: "#6E6E6E",
3465
+ labelBgColor: "#18191b",
3466
+ labelColor: "#C6C6C6"
3467
+ };
3468
+ const slate = {
3469
+ lineColor: "#64748b",
3470
+ // 500
3471
+ labelBgColor: "#0f172a",
3472
+ // 900
3473
+ labelColor: "#cbd5e1"
3474
+ // 300
3475
+ };
3476
+ const blue = {
3477
+ lineColor: "#3b82f6",
3478
+ // 500
3479
+ labelBgColor: "#172554",
3480
+ // 950
3481
+ labelColor: "#60a5fa"
3482
+ // 400
3483
+ };
3484
+ const sky = {
3485
+ lineColor: "#0ea5e9",
3486
+ // 500
3487
+ labelBgColor: "#082f49",
3488
+ // 950
3489
+ labelColor: "#38bdf8"
3490
+ // 400
3491
+ };
3492
+ const RelationshipColors = {
3493
+ amber: {
3494
+ lineColor: "#b45309",
3495
+ labelBgColor: "#78350f",
3496
+ labelColor: "#FFE0C2"
3497
+ },
3498
+ blue,
3499
+ gray,
3500
+ green: {
3501
+ lineColor: "#15803d",
3502
+ // 700
3503
+ labelBgColor: "#052e16",
3504
+ // 950
3505
+ labelColor: "#22c55e"
3506
+ // 500
3507
+ },
3508
+ indigo: {
3509
+ lineColor: "#6366f1",
3510
+ // 500
3511
+ labelBgColor: "#1e1b4b",
3512
+ // 950
3513
+ labelColor: "#818cf8"
3514
+ // 400
3515
+ },
3516
+ muted: slate,
3517
+ primary: blue,
3518
+ red: {
3519
+ lineColor: "#AC4D39",
3520
+ labelBgColor: "#b91c1c",
3521
+ labelColor: "#f5b2a3"
3522
+ },
3523
+ secondary: sky,
3524
+ sky,
3525
+ slate
3526
+ };
3527
+
3528
+ const defaultTheme = {
3529
+ elements: ElementColors,
3530
+ relationships: RelationshipColors,
3531
+ font: "Arial",
3532
+ shadow: "#0a0a0a"
3533
+ };
3534
+ function computeColorValues(color) {
3535
+ if (color.match(/^#([0-9a-f]{3}){1,2}$/i)) {
3536
+ const colors = generateColors(color);
3537
+ return {
3538
+ elements: {
3539
+ fill: colors[6],
3540
+ stroke: colors[7],
3541
+ hiContrast: colors[0],
3542
+ loContrast: colors[1]
3543
+ },
3544
+ relationships: {
3545
+ lineColor: colors[4],
3546
+ labelColor: colors[3],
3547
+ labelBgColor: colors[9]
3548
+ }
3549
+ };
3550
+ } else {
3551
+ return {
3552
+ elements: defaultTheme.elements["primary"],
3553
+ relationships: defaultTheme.relationships["primary"]
3554
+ };
3555
+ }
3556
+ }
3557
+
3558
+ function r$1(...t){return types_index.u(Object.values,t)}
3559
+
3560
+ function i(...e){return types_index.u(r,e)}var r=(e,t)=>e.length>=t;
3561
+
3562
+ function t(r){return typeof r=="string"}
3563
+
3564
+ function n(e){return !!e}
3565
+
3566
+ function getDefaultExportFromCjs (x) {
3567
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
3568
+ }
3569
+
3570
+ var naturalCompareLite = {exports: {}};
3571
+
3572
+ /*
3573
+ * @version 1.4.0
3574
+ * @date 2015-10-26
3575
+ * @stability 3 - Stable
3576
+ * @author Lauri Rooden (https://github.com/litejs/natural-compare-lite)
3577
+ * @license MIT License
3578
+ */
3579
+
3580
+
3581
+ var naturalCompare = function(a, b) {
3582
+ var i, codeA
3583
+ , codeB = 1
3584
+ , posA = 0
3585
+ , posB = 0
3586
+ , alphabet = String.alphabet;
3587
+
3588
+ function getCode(str, pos, code) {
3589
+ if (code) {
3590
+ for (i = pos; code = getCode(str, i), code < 76 && code > 65;) ++i;
3591
+ return +str.slice(pos - 1, i)
3592
+ }
3593
+ code = alphabet && alphabet.indexOf(str.charAt(pos));
3594
+ return code > -1 ? code + 76 : ((code = str.charCodeAt(pos) || 0), code < 45 || code > 127) ? code
3595
+ : code < 46 ? 65 // -
3596
+ : code < 48 ? code - 1
3597
+ : code < 58 ? code + 18 // 0-9
3598
+ : code < 65 ? code - 11
3599
+ : code < 91 ? code + 11 // A-Z
3600
+ : code < 97 ? code - 37
3601
+ : code < 123 ? code + 5 // a-z
3602
+ : code - 63
3603
+ }
3604
+
3605
+
3606
+ if ((a+="") != (b+="")) for (;codeB;) {
3607
+ codeA = getCode(a, posA++);
3608
+ codeB = getCode(b, posB++);
3609
+
3610
+ if (codeA < 76 && codeB < 76 && codeA > 66 && codeB > 66) {
3611
+ codeA = getCode(a, posA, posA);
3612
+ codeB = getCode(b, posB, posA = i);
3613
+ posB = i;
3614
+ }
3615
+
3616
+ if (codeA != codeB) return (codeA < codeB) ? -1 : 1
3617
+ }
3618
+ return 0
3619
+ };
3620
+
3621
+ try {
3622
+ naturalCompareLite.exports = naturalCompare;
3623
+ } catch (e) {
3624
+ String.naturalCompare = naturalCompare;
3625
+ }
3626
+
3627
+ var naturalCompareLiteExports = naturalCompareLite.exports;
3628
+ const compare = /*@__PURE__*/getDefaultExportFromCjs(naturalCompareLiteExports);
3629
+
3630
+ function compareNatural(a, b) {
3631
+ if (a === b) return 0;
3632
+ if (t(a)) {
3633
+ if (t(b)) {
3634
+ return compare(a, b);
3635
+ }
3636
+ return 1;
3637
+ }
3638
+ return t(b) ? -1 : 0;
3639
+ }
3640
+
3641
+ function isString(value) {
3642
+ return value != null && typeof value === "string";
3643
+ }
3644
+ function isNonEmptyArray(arr) {
3645
+ return !!arr && Array.isArray(arr) && arr.length > 0;
3646
+ }
3647
+
3648
+ function nameFromFqn(fqn) {
3649
+ const lastDot = fqn.lastIndexOf(".");
3650
+ if (lastDot > 0) {
3651
+ return fqn.slice(lastDot + 1);
3652
+ } else {
3653
+ return fqn;
3654
+ }
3655
+ }
3656
+ function isAncestor(...args) {
3657
+ const ancestor = isString(args[0]) ? args[0] : args[0].id;
3658
+ const another = isString(args[1]) ? args[1] : args[1].id;
3659
+ return another.startsWith(ancestor + ".");
3660
+ }
3661
+ function isSameHierarchy(one, another) {
3662
+ const first = isString(one) ? one : one.id;
3663
+ const second = isString(another) ? another : another.id;
3664
+ return first === second || second.startsWith(first + ".") || first.startsWith(second + ".");
3665
+ }
3666
+ function isDescendantOf(ancestors) {
3667
+ const predicates = ancestors.flatMap((a) => [(e) => e.id === a.id, (e) => isAncestor(a, e)]);
3668
+ return (e) => predicates.some((p) => p(e));
3669
+ }
3670
+ function notDescendantOf(ancestors) {
3671
+ const isDescendant = isDescendantOf(ancestors);
3672
+ return (e) => !isDescendant(e);
3673
+ }
3674
+ function commonAncestor(first, second) {
3675
+ const parentA = parentFqn(first);
3676
+ const parentB = parentFqn(second);
3677
+ if (parentA === parentB) {
3678
+ return parentA;
3679
+ }
3680
+ if (!parentA || !parentB) {
3681
+ return null;
3682
+ }
3683
+ const a = first.split(".");
3684
+ const b = second.split(".");
3685
+ let ancestor = null;
3686
+ while (a.length > 1 && b.length > 1 && !!a[0] && a[0] === b[0]) {
3687
+ ancestor = ancestor ? `${ancestor}.${a[0]}` : a[0];
3688
+ a.shift();
3689
+ b.shift();
3690
+ }
3691
+ return ancestor;
3692
+ }
3693
+ function parentFqn(fqn) {
3694
+ const lastDot = fqn.lastIndexOf(".");
3695
+ if (lastDot > 0) {
3696
+ return fqn.slice(0, lastDot);
3697
+ }
3698
+ return null;
3699
+ }
3700
+ function parentFqnPredicate(parent) {
3701
+ const prefix = parent + ".";
3702
+ return (e) => !!e.parent && (e.parent === parent || e.parent.startsWith(prefix));
3703
+ }
3704
+ function ancestorsFqn(fqn) {
3705
+ const path = fqn.split(".");
3706
+ path.pop();
3707
+ if (path.length === 0) {
3708
+ return [];
3709
+ }
3710
+ return path.reduce((acc, part, idx) => {
3711
+ if (idx === 0) {
3712
+ acc.push(part);
3713
+ return acc;
3714
+ }
3715
+ acc.unshift(`${acc[0]}.${part}`);
3716
+ return acc;
3717
+ }, []);
3718
+ }
3719
+ function compareFqnHierarchically(a, b) {
3720
+ const depthA = a.split(".").length;
3721
+ const depthB = b.split(".").length;
3722
+ switch (true) {
3723
+ case depthA > depthB: {
3724
+ return 1;
3725
+ }
3726
+ case depthA < depthB: {
3727
+ return -1;
3728
+ }
3729
+ default: {
3730
+ return 0;
3731
+ }
3732
+ }
3733
+ }
3734
+ function compareByFqnHierarchically(a, b) {
3735
+ return compareFqnHierarchically(a.id, b.id);
3736
+ }
3737
+ function sortByFqnHierarchically(array) {
3738
+ return array.map((item) => ({ item, fqn: item.id.split(".") })).sort((a, b) => {
3739
+ return a.fqn.length - b.fqn.length;
3740
+ }).map(({ item }) => item);
3741
+ }
3742
+ function sortNaturalByFqn(array) {
3743
+ return array.map((item) => ({ item, fqn: item.id.split(".") })).sort((a, b) => {
3744
+ if (a.fqn.length !== b.fqn.length) {
3745
+ return a.fqn.length - b.fqn.length;
3746
+ }
3747
+ for (let i = 0; i < a.fqn.length; i++) {
3748
+ const compare = compareNatural(a.fqn[i], b.fqn[i]);
3749
+ if (compare !== 0) {
3750
+ return compare;
3751
+ }
3752
+ }
3753
+ return 0;
3754
+ }).map(({ item }) => item);
3755
+ }
3756
+
3757
+ class LikeC4ViewModel {
3758
+ constructor(view, model) {
3759
+ this.view = view;
3760
+ this.model = model;
3761
+ for (const node of view.nodes) {
3762
+ const el = new LikeC4ViewModel.Element(node, this);
3763
+ this.#elements.set(node.id, el);
3764
+ if (types_index.e(node.parent)) {
3765
+ this.#rootElements.add(el);
3766
+ }
3767
+ }
3768
+ this.#connections = new Map(view.edges.map((e) => [e.id, new LikeC4ViewModel.Connection(e, this)]));
3769
+ }
3770
+ #rootElements = /* @__PURE__ */ new Set();
3771
+ #elements = /* @__PURE__ */ new Map();
3772
+ #connections;
3773
+ get id() {
3774
+ return this.view.id;
3775
+ }
3776
+ get title() {
3777
+ return this.view.title;
3778
+ }
3779
+ get viewOf() {
3780
+ if (this.view.__ !== "dynamic") {
3781
+ return this.view.viewOf ? this.model.element(this.view.viewOf) : null;
3782
+ }
3783
+ return null;
3784
+ }
3785
+ get tags() {
3786
+ return this.view.tags ?? [];
3787
+ }
3788
+ roots() {
3789
+ return [...this.#rootElements];
3790
+ }
3791
+ elements() {
3792
+ return [...this.#elements.values()];
3793
+ }
3794
+ element(id) {
3795
+ return types_index.nonNullable(this.#elements.get(id), `LikeC4ViewModel.Element ${id} in view ${this.view.id} not found`);
3796
+ }
3797
+ hasElement(id) {
3798
+ return this.#elements.has(id);
3799
+ }
3800
+ connections() {
3801
+ return [...this.#connections.values()];
3802
+ }
3803
+ connection(id) {
3804
+ return types_index.nonNullable(this.#connections.get(id), `Connection ${id} in view ${this.view.id} not found`);
3805
+ }
3806
+ findConnections(source, target, direction = "direct") {
3807
+ const sourceId = t(source) ? source : source.id;
3808
+ const targetId = t(target) ? target : target.id;
3809
+ return this.connections().filter(
3810
+ (c) => c.source.id === sourceId && c.target.id === targetId || direction === "both" && c.source.id === targetId && c.target.id === sourceId
3811
+ );
3812
+ }
3813
+ parent(element) {
3814
+ const el = this.element(t(element) ? element : element.id);
3815
+ return el.node.parent ? this.element(el.node.parent) : null;
3816
+ }
3817
+ children(element) {
3818
+ const el = this.element(t(element) ? element : element.id);
3819
+ return el.node.children.map((c) => this.element(c));
3820
+ }
3821
+ // Get all sibling (i.e. same parent)
3822
+ siblings(element) {
3823
+ const id = t(element) ? element : element.id;
3824
+ const parent = this.parent(id);
3825
+ const siblings = parent ? this.children(parent) : this.roots();
3826
+ return siblings.filter((e) => e.id !== id);
3827
+ }
3828
+ /**
3829
+ * Get all ancestor elements (i.e. parent, parent’s parent, etc.)
3830
+ * (from closest to root)
3831
+ */
3832
+ ancestors(element) {
3833
+ let id = t(element) ? element : element.id;
3834
+ const result = [];
3835
+ let parent;
3836
+ while (parent = this.parent(id)) {
3837
+ result.push(parent);
3838
+ id = parent.id;
3839
+ }
3840
+ return result;
3841
+ }
3842
+ descendants(element) {
3843
+ const children = this.children(element);
3844
+ return children.flatMap((c) => [c, ...this.descendants(c.id)]);
3845
+ }
3846
+ incoming(element, filter = "all") {
3847
+ const el = this.element(t(element) ? element : element.id);
3848
+ const edges = el.node.inEdges.map((e) => types_index.nonNullable(this.#connections.get(e), `Edge ${e} not found`));
3849
+ if (filter === "all" || edges.length === 0) {
3850
+ return edges;
3851
+ }
3852
+ return edges.filter((rel) => {
3853
+ if (filter === "direct") {
3854
+ return rel.target.id === el.id;
3855
+ }
3856
+ return rel.target.id !== el.id;
3857
+ });
3858
+ }
3859
+ incomers(element, filter = "all") {
3860
+ return this.incoming(element, filter).map((r) => r.source);
3861
+ }
3862
+ /**
3863
+ * Outgoing relationships from the element and its descendants
3864
+ */
3865
+ outgoing(element, filter = "all") {
3866
+ const el = this.element(t(element) ? element : element.id);
3867
+ const edges = el.node.outEdges.map((e) => types_index.nonNullable(this.#connections.get(e), `Edge ${e} not found`));
3868
+ if (filter === "all" || edges.length === 0) {
3869
+ return edges;
3870
+ }
3871
+ return edges.filter((rel) => {
3872
+ if (filter === "direct") {
3873
+ return rel.source.id === el.id;
3874
+ }
3875
+ return rel.source.id !== el.id;
3876
+ });
3877
+ }
3878
+ outgoers(element, filter = "all") {
3879
+ return this.outgoing(element, filter).map((r) => r.target);
3880
+ }
3881
+ }
3882
+ ((LikeC4ViewModel2) => {
3883
+ class Element {
3884
+ constructor(node, viewmodel) {
3885
+ this.node = node;
3886
+ this.viewmodel = viewmodel;
3887
+ }
3888
+ get id() {
3889
+ return this.node.id;
3890
+ }
3891
+ get title() {
3892
+ return this.node.title;
3893
+ }
3894
+ get kind() {
3895
+ return this.node.kind;
3896
+ }
3897
+ get isRoot() {
3898
+ return types_index.e(this.node.parent);
3899
+ }
3900
+ get hasNested() {
3901
+ return this.node.children.length > 0;
3902
+ }
3903
+ get shape() {
3904
+ return this.node.shape;
3905
+ }
3906
+ get color() {
3907
+ return this.node.color;
3908
+ }
3909
+ get tags() {
3910
+ return this.node.tags ?? [];
3911
+ }
3912
+ model() {
3913
+ return this.viewmodel.model.element(this.id);
3914
+ }
3915
+ parent() {
3916
+ return this.node.parent ? this.viewmodel.element(this.node.parent) : null;
3917
+ }
3918
+ metadata(key, defaultValue) {
3919
+ return this.model().metadata(key) ?? defaultValue;
3920
+ }
3921
+ hasMetadata(key) {
3922
+ return this.model().hasMetadata(key);
3923
+ }
3924
+ ancestors() {
3925
+ return this.viewmodel.ancestors(this);
3926
+ }
3927
+ siblings() {
3928
+ return this.viewmodel.siblings(this);
3929
+ }
3930
+ descendants() {
3931
+ return this.viewmodel.descendants(this);
3932
+ }
3933
+ children() {
3934
+ return this.viewmodel.children(this);
3935
+ }
3936
+ incoming(filter = "all") {
3937
+ return this.viewmodel.incoming(this, filter);
3938
+ }
3939
+ incomers(filter = "all") {
3940
+ return this.viewmodel.incomers(this, filter);
3941
+ }
3942
+ outgoing(filter = "all") {
3943
+ return this.viewmodel.outgoing(this, filter);
3944
+ }
3945
+ outgoers(filter = "all") {
3946
+ return this.viewmodel.outgoers(this, filter);
3947
+ }
3948
+ connectionsTo(target) {
3949
+ return this.viewmodel.findConnections(this, target);
3950
+ }
3951
+ }
3952
+ LikeC4ViewModel2.Element = Element;
3953
+ class Connection {
3954
+ constructor(edge, viewmodel) {
3955
+ this.edge = edge;
3956
+ this.viewmodel = viewmodel;
3957
+ }
3958
+ get id() {
3959
+ return this.edge.id;
3960
+ }
3961
+ get source() {
3962
+ return this.viewmodel.element(this.edge.source);
3963
+ }
3964
+ get target() {
3965
+ return this.viewmodel.element(this.edge.target);
3966
+ }
3967
+ get tags() {
3968
+ return this.edge.tags ?? [];
3969
+ }
3970
+ /**
3971
+ * Model relationships
3972
+ */
3973
+ relationships() {
3974
+ return this.edge.relations.map((r) => types_index.nonNullable(this.viewmodel.model.relationship(r)));
3975
+ }
3976
+ }
3977
+ LikeC4ViewModel2.Connection = Connection;
3978
+ })(LikeC4ViewModel || (LikeC4ViewModel = {}));
3979
+
3980
+ const RelationsSet = Set;
3981
+ const MapRelations = Map;
3982
+ class LikeC4Model {
3983
+ constructor(computed) {
3984
+ this.computed = computed;
3985
+ for (const el of r$1(computed.elements)) {
3986
+ this.addElement(el);
3987
+ }
3988
+ for (const rel of r$1(computed.relations)) {
3989
+ this.addRelation(rel);
3990
+ }
3991
+ this.#views = new Map(
3992
+ r$1(computed.views).map((v) => [v.id, new LikeC4ViewModel(v, this)])
3993
+ );
3994
+ }
3995
+ #elements = /* @__PURE__ */ new Map();
3996
+ // Parent element for given FQN
3997
+ #parents = /* @__PURE__ */ new Map();
3998
+ // Children elements for given FQN
3999
+ #children = /* @__PURE__ */ new Map();
4000
+ #rootElements = /* @__PURE__ */ new Set();
4001
+ #relations = /* @__PURE__ */ new Map();
4002
+ // Incoming to an element or its descendants
4003
+ #incoming = new MapRelations();
4004
+ // Outgoing from an element or its descendants
4005
+ #outgoing = new MapRelations();
4006
+ // Relationships inside the element, among descendants
4007
+ #internal = new MapRelations();
4008
+ #cacheAscendingSiblings = /* @__PURE__ */ new Map();
4009
+ #views;
4010
+ static from(computed) {
4011
+ return new LikeC4Model(computed);
4012
+ }
4013
+ /**
4014
+ * Returns the root elements of the model.
4015
+ */
4016
+ roots() {
4017
+ return [...this.#rootElements];
4018
+ }
4019
+ /**
4020
+ * Returns all elements in the model.
4021
+ */
4022
+ elements() {
4023
+ return [...this.#elements.values()];
4024
+ }
4025
+ /**
4026
+ * Returns a specific element by its FQN.
4027
+ */
4028
+ element(id) {
4029
+ return types_index.nonNullable(this.#elements.get(id), `Element ${id} not found`);
4030
+ }
4031
+ /**
4032
+ * Returns all relationships in the model.
4033
+ */
4034
+ relationships() {
4035
+ return [...this.#relations.values()];
4036
+ }
4037
+ /**
4038
+ * Returns a specific relationship by its ID.
4039
+ */
4040
+ relationship(id) {
4041
+ return types_index.nonNullable(this.#relations.get(id), `Relation ${id} not found`);
4042
+ }
4043
+ /**
4044
+ * Returns all views in the model.
4045
+ */
4046
+ views() {
4047
+ return [...this.#views.values()];
4048
+ }
4049
+ /**
4050
+ * Returns a specific view by its ID.
4051
+ */
4052
+ view(viewId) {
4053
+ return types_index.nonNullable(this.#views.get(viewId), `View ${viewId} not found`);
4054
+ }
4055
+ /**
4056
+ * Returns the parent element of given element.
4057
+ * @see ancestors
4058
+ */
4059
+ parent(element) {
4060
+ const id = t(element) ? element : element.id;
4061
+ return this.#parents.get(id) || null;
4062
+ }
4063
+ /**
4064
+ * Get all children of the element (only direct children),
4065
+ * @see descendants
4066
+ */
4067
+ children(element) {
4068
+ const id = t(element) ? element : element.id;
4069
+ return this._childrenOf(id);
4070
+ }
4071
+ /**
4072
+ * Get all sibling (i.e. same parent)
4073
+ */
4074
+ siblings(element) {
4075
+ const id = t(element) ? element : element.id;
4076
+ const parent = this.#parents.get(id);
4077
+ const siblings = parent ? this._childrenOf(parent.id) : this.roots();
4078
+ return siblings.filter((e) => e.id !== id);
4079
+ }
4080
+ /**
4081
+ * Get all ancestor elements (i.e. parent, parent’s parent, etc.)
4082
+ * (from closest to root)
4083
+ */
4084
+ ancestors(element) {
4085
+ let id = t(element) ? element : element.id;
4086
+ const result = [];
4087
+ let parent;
4088
+ while (parent = this.#parents.get(id)) {
4089
+ result.push(parent);
4090
+ id = parent.id;
4091
+ }
4092
+ return result;
4093
+ }
4094
+ /**
4095
+ * Get all descendant elements (i.e. children, children’s children, etc.)
4096
+ */
4097
+ descendants(element) {
4098
+ const id = t(element) ? element : element.id;
4099
+ const children = this._childrenOf(id);
4100
+ return children.flatMap((c) => [c, ...this.descendants(c.id)]);
4101
+ }
4102
+ /**
4103
+ * Incoming relationships to the element and its descendants
4104
+ * @see incomers
4105
+ */
4106
+ incoming(element, filter = "all") {
4107
+ const id = t(element) ? element : element.id;
4108
+ const incoming = Array.from(this._incomingTo(id));
4109
+ if (filter === "all" || incoming.length === 0) {
4110
+ return incoming;
4111
+ }
4112
+ return incoming.filter((rel) => {
4113
+ if (filter === "direct") {
4114
+ return rel.target.id === id;
4115
+ }
4116
+ return rel.target.id !== id;
4117
+ });
4118
+ }
4119
+ /**
4120
+ * Source elements of incoming relationships
4121
+ */
4122
+ incomers(element, filter = "all") {
4123
+ return this.incoming(element, filter).map((r) => r.source);
4124
+ }
4125
+ /**
4126
+ * Outgoing relationships from the element and its descendants
4127
+ * @see outgoers
4128
+ */
4129
+ outgoing(element, filter = "all") {
4130
+ const id = t(element) ? element : element.id;
4131
+ const outgoing = Array.from(this._outgoingFrom(id));
4132
+ if (filter === "all" || outgoing.length === 0) {
4133
+ return outgoing;
4134
+ }
4135
+ return outgoing.filter((rel) => {
4136
+ if (filter === "direct") {
4137
+ return rel.source.id === id;
4138
+ }
4139
+ return rel.source.id !== id;
4140
+ });
4141
+ }
4142
+ /**
4143
+ * Target elements of outgoing relationships
4144
+ */
4145
+ outgoers(element, filter = "all") {
4146
+ return this.outgoing(element, filter).map((r) => r.target);
4147
+ }
4148
+ /**
4149
+ * Relationships inside the element, among descendants
4150
+ */
4151
+ internal(element) {
4152
+ const id = t(element) ? element : element.id;
4153
+ return Array.from(this._internalOf(id));
4154
+ }
4155
+ /**
4156
+ * Resolve siblings of the element and siblings of ancestors
4157
+ * (from closest to root)
4158
+ */
4159
+ ascendingSiblings(element) {
4160
+ const id = t(element) ? element : element.id;
4161
+ let siblings = this.#cacheAscendingSiblings.get(id);
4162
+ if (!siblings) {
4163
+ siblings = [
4164
+ ...this.siblings(id),
4165
+ ...this.ancestors(id).flatMap((a) => this.siblings(a.id))
4166
+ ];
4167
+ this.#cacheAscendingSiblings.set(id, siblings);
4168
+ }
4169
+ return siblings.slice();
4170
+ }
4171
+ /**
4172
+ * Resolve all views that contain the element
4173
+ */
4174
+ viewsWithElement(element) {
4175
+ const id = t(element) ? element : element.id;
4176
+ return [...this.#views.values()].filter((v) => v.hasElement(id));
4177
+ }
4178
+ addElement(parsed) {
4179
+ if (this.#elements.has(parsed.id)) {
4180
+ throw new Error(`Element ${parsed.id} already exists`);
4181
+ }
4182
+ const el = new LikeC4Model.Element(parsed, this);
4183
+ this.#elements.set(el.id, el);
4184
+ const parentId = parentFqn(el.id);
4185
+ if (parentId) {
4186
+ this.#parents.set(el.id, this.element(parentId));
4187
+ this._childrenOf(parentId).push(el);
4188
+ } else {
4189
+ this.#rootElements.add(el);
4190
+ }
4191
+ }
4192
+ addRelation(relation) {
4193
+ if (this.#relations.has(relation.id)) {
4194
+ throw new Error(`Relation ${relation.id} already exists`);
4195
+ }
4196
+ const rel = new LikeC4Model.Relationship(relation, this);
4197
+ this.#relations.set(rel.id, rel);
4198
+ this._incomingTo(relation.target).add(rel);
4199
+ this._outgoingFrom(relation.source).add(rel);
4200
+ const relParent = commonAncestor(relation.source, relation.target);
4201
+ if (relParent) {
4202
+ for (const ancestor of [relParent, ...ancestorsFqn(relParent)]) {
4203
+ this._internalOf(ancestor).add(rel);
4204
+ }
4205
+ }
4206
+ for (const sourceAncestor of ancestorsFqn(relation.source)) {
4207
+ if (sourceAncestor === relParent) {
4208
+ break;
4209
+ }
4210
+ this._outgoingFrom(sourceAncestor).add(rel);
4211
+ }
4212
+ for (const targetAncestor of ancestorsFqn(relation.target)) {
4213
+ if (targetAncestor === relParent) {
4214
+ break;
4215
+ }
4216
+ this._incomingTo(targetAncestor).add(rel);
4217
+ }
4218
+ }
4219
+ _childrenOf(id) {
4220
+ let children = this.#children.get(id);
4221
+ if (!children) {
4222
+ children = [];
4223
+ this.#children.set(id, children);
4224
+ }
4225
+ return children;
4226
+ }
4227
+ _incomingTo(id) {
4228
+ let incoming = this.#incoming.get(id);
4229
+ if (!incoming) {
4230
+ incoming = new RelationsSet();
4231
+ this.#incoming.set(id, incoming);
4232
+ }
4233
+ return incoming;
4234
+ }
4235
+ _outgoingFrom(id) {
4236
+ let outgoing = this.#outgoing.get(id);
4237
+ if (!outgoing) {
4238
+ outgoing = new RelationsSet();
4239
+ this.#outgoing.set(id, outgoing);
4240
+ }
4241
+ return outgoing;
4242
+ }
4243
+ _internalOf(id) {
4244
+ let internal = this.#internal.get(id);
4245
+ if (!internal) {
4246
+ internal = new RelationsSet();
4247
+ this.#internal.set(id, internal);
4248
+ }
4249
+ return internal;
4250
+ }
4251
+ }
4252
+ ((LikeC4Model2) => {
4253
+ class Element {
4254
+ constructor(element, model) {
4255
+ this.element = element;
4256
+ this.model = model;
4257
+ }
4258
+ get id() {
4259
+ return this.element.id;
4260
+ }
4261
+ get title() {
4262
+ return this.element.title;
4263
+ }
4264
+ get kind() {
4265
+ return this.element.kind;
4266
+ }
4267
+ get isRoot() {
4268
+ return parentFqn(this.element.id) === null;
4269
+ }
4270
+ get hasNested() {
4271
+ return this.model.children(this).length > 0;
4272
+ }
4273
+ get shape() {
4274
+ return this.element.shape ?? types_index.DefaultElementShape;
4275
+ }
4276
+ get color() {
4277
+ return this.element.color ?? types_index.DefaultThemeColor;
4278
+ }
4279
+ get tags() {
4280
+ return this.element.tags ?? [];
4281
+ }
4282
+ parent() {
4283
+ return this.model.parent(this);
4284
+ }
4285
+ metadata(key, defaultValue) {
4286
+ return this.element.metadata?.[key] ?? defaultValue;
4287
+ }
4288
+ hasMetadata(key) {
4289
+ return n(this.element.metadata?.[key]);
4290
+ }
4291
+ ancestors() {
4292
+ return this.model.ancestors(this);
4293
+ }
4294
+ siblings() {
4295
+ return this.model.siblings(this);
4296
+ }
4297
+ descendants() {
4298
+ return this.model.descendants(this);
4299
+ }
4300
+ children() {
4301
+ return this.model.children(this);
4302
+ }
4303
+ /**
4304
+ * Views that contain this element
4305
+ */
4306
+ views() {
4307
+ return this.model.viewsWithElement(this);
4308
+ }
4309
+ incoming(filter) {
4310
+ return this.model.incoming(this, filter);
4311
+ }
4312
+ incomers(filter) {
4313
+ return this.model.incomers(this, filter);
4314
+ }
4315
+ outgoing(filter) {
4316
+ return this.model.outgoing(this, filter);
4317
+ }
4318
+ outgoers(filter) {
4319
+ return this.model.outgoers(this, filter);
4320
+ }
4321
+ internal() {
4322
+ return this.model.internal(this);
4323
+ }
4324
+ // public *descendants(): IterableIterator<LikeC4Element> {
4325
+ // return
4326
+ // }
4327
+ }
4328
+ LikeC4Model2.Element = Element;
4329
+ class Relationship {
4330
+ constructor(relationship, model) {
4331
+ this.relationship = relationship;
4332
+ this.model = model;
4333
+ }
4334
+ get id() {
4335
+ return this.relationship.id;
4336
+ }
4337
+ get title() {
4338
+ return this.relationship.title;
4339
+ }
4340
+ get kind() {
4341
+ return this.relationship.kind ?? null;
4342
+ }
4343
+ get tags() {
4344
+ return this.relationship.tags ?? [];
4345
+ }
4346
+ get source() {
4347
+ return this.model.element(this.relationship.source);
4348
+ }
4349
+ get target() {
4350
+ return this.model.element(this.relationship.target);
4351
+ }
4352
+ metadata(key, defaultValue) {
4353
+ return this.relationship.metadata?.[key] ?? defaultValue;
4354
+ }
4355
+ hasMetadata(key) {
4356
+ return n(this.relationship.metadata?.[key]);
4357
+ }
4358
+ }
4359
+ LikeC4Model2.Relationship = Relationship;
4360
+ })(LikeC4Model || (LikeC4Model = {}));
4361
+
4362
+ const DELAY = "LIKEC4_DELAY";
4363
+ function delay(ms = 100) {
4364
+ return new Promise((resolve) => {
4365
+ setTimeout(() => {
4366
+ resolve(DELAY);
4367
+ }, ms);
4368
+ });
4369
+ }
4370
+
4371
+ const compareRelations = (a, b) => {
4372
+ const parentA = commonAncestor(a.source, a.target);
4373
+ const parentB = commonAncestor(b.source, b.target);
4374
+ if (parentA && !parentB) {
4375
+ return 1;
4376
+ }
4377
+ if (!parentA && parentB) {
4378
+ return -1;
4379
+ }
4380
+ const compareParents = parentA && parentB ? compareFqnHierarchically(parentA, parentB) : 0;
4381
+ if (compareParents !== 0) {
4382
+ return compareParents;
4383
+ }
4384
+ const compareSource = compareFqnHierarchically(a.source, b.source);
4385
+ if (compareSource !== 0) {
4386
+ return compareSource;
4387
+ }
4388
+ return compareFqnHierarchically(a.target, b.target);
4389
+ };
4390
+
4391
+ exports.AsFqn = types_index.AsFqn;
4392
+ exports.BorderStyles = types_index.BorderStyles;
4393
+ exports.DefaultArrowType = types_index.DefaultArrowType;
4394
+ exports.DefaultElementShape = types_index.DefaultElementShape;
4395
+ exports.DefaultLineStyle = types_index.DefaultLineStyle;
4396
+ exports.DefaultRelationshipColor = types_index.DefaultRelationshipColor;
4397
+ exports.DefaultThemeColor = types_index.DefaultThemeColor;
4398
+ exports.ElementShapes = types_index.ElementShapes;
4399
+ exports.Expr = types_index.expression;
4400
+ exports.StepEdgeId = types_index.StepEdgeId;
4401
+ exports.extractStep = types_index.extractStep;
4402
+ exports.getBBoxCenter = types_index.getBBoxCenter;
4403
+ exports.getParallelStepsPrefix = types_index.getParallelStepsPrefix;
4404
+ exports.invariant = types_index.invariant;
4405
+ exports.isAndOperator = types_index.isAndOperator;
4406
+ exports.isComputedDynamicView = types_index.isComputedDynamicView;
4407
+ exports.isComputedElementView = types_index.isComputedElementView;
4408
+ exports.isCustomElement = types_index.isCustomElement;
4409
+ exports.isCustomRelationExpr = types_index.isCustomRelationExpr;
4410
+ exports.isDynamicView = types_index.isDynamicView;
4411
+ exports.isDynamicViewIncludeRule = types_index.isDynamicViewIncludeRule;
4412
+ exports.isDynamicViewParallelSteps = types_index.isDynamicViewParallelSteps;
4413
+ exports.isElement = types_index.isElement;
4414
+ exports.isElementKindExpr = types_index.isElementKindExpr;
4415
+ exports.isElementPredicateExpr = types_index.isElementPredicateExpr;
4416
+ exports.isElementRef = types_index.isElementRef;
4417
+ exports.isElementTagExpr = types_index.isElementTagExpr;
4418
+ exports.isElementView = types_index.isElementView;
4419
+ exports.isElementWhere = types_index.isElementWhere;
4420
+ exports.isExpandedElementExpr = types_index.isExpandedElementExpr;
4421
+ exports.isExtendsElementView = types_index.isExtendsElementView;
4422
+ exports.isInOut = types_index.isInOut;
4423
+ exports.isIncoming = types_index.isIncoming;
4424
+ exports.isKindEqual = types_index.isKindEqual;
4425
+ exports.isNotOperator = types_index.isNotOperator;
4426
+ exports.isOrOperator = types_index.isOrOperator;
4427
+ exports.isOutgoing = types_index.isOutgoing;
4428
+ exports.isRelation = types_index.isRelation;
4429
+ exports.isRelationExpression = types_index.isRelationExpression;
4430
+ exports.isRelationPredicateExpr = types_index.isRelationPredicateExpr;
4431
+ exports.isRelationWhere = types_index.isRelationWhere;
4432
+ exports.isScopedElementView = types_index.isScopedElementView;
4433
+ exports.isStepEdgeId = types_index.isStepEdgeId;
4434
+ exports.isTagEqual = types_index.isTagEqual;
4435
+ exports.isThemeColor = types_index.isThemeColor;
4436
+ exports.isViewRuleAutoLayout = types_index.isViewRuleAutoLayout;
4437
+ exports.isViewRulePredicate = types_index.isViewRulePredicate;
4438
+ exports.isViewRuleStyle = types_index.isViewRuleStyle;
4439
+ exports.isWildcard = types_index.isWildcard;
4440
+ exports.nonNullable = types_index.nonNullable;
4441
+ exports.nonexhaustive = types_index.nonexhaustive;
4442
+ exports.whereOperatorAsPredicate = types_index.whereOperatorAsPredicate;
4443
+ exports.ElementColors = ElementColors;
4444
+ exports.LikeC4Model = LikeC4Model;
4445
+ exports.LikeC4ViewModel = LikeC4ViewModel;
4446
+ exports.RelationshipColors = RelationshipColors;
4447
+ exports.ancestorsFqn = ancestorsFqn;
4448
+ exports.commonAncestor = commonAncestor;
4449
+ exports.compareByFqnHierarchically = compareByFqnHierarchically;
4450
+ exports.compareFqnHierarchically = compareFqnHierarchically;
4451
+ exports.compareNatural = compareNatural;
4452
+ exports.compareRelations = compareRelations;
4453
+ exports.computeColorValues = computeColorValues;
4454
+ exports.defaultTheme = defaultTheme;
4455
+ exports.delay = delay;
4456
+ exports.hasAtLeast = i;
4457
+ exports.isAncestor = isAncestor;
4458
+ exports.isDescendantOf = isDescendantOf;
4459
+ exports.isNonEmptyArray = isNonEmptyArray;
4460
+ exports.isSameHierarchy = isSameHierarchy;
4461
+ exports.isString = isString;
4462
+ exports.nameFromFqn = nameFromFqn;
4463
+ exports.notDescendantOf = notDescendantOf;
4464
+ exports.parentFqn = parentFqn;
4465
+ exports.parentFqnPredicate = parentFqnPredicate;
4466
+ exports.sortByFqnHierarchically = sortByFqnHierarchically;
4467
+ exports.sortNaturalByFqn = sortNaturalByFqn;