@opensumi/ide-theme 2.21.13 → 2.22.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 (117) hide show
  1. package/lib/browser/icon-theme-data.js.map +1 -1
  2. package/lib/browser/icon-theme-store.js.map +1 -1
  3. package/lib/browser/icon.service.d.ts +3 -1
  4. package/lib/browser/icon.service.d.ts.map +1 -1
  5. package/lib/browser/icon.service.js +56 -24
  6. package/lib/browser/icon.service.js.map +1 -1
  7. package/lib/browser/index.js.map +1 -1
  8. package/lib/browser/semantic-tokens-registry.js.map +1 -1
  9. package/lib/browser/style.service.js.map +1 -1
  10. package/lib/browser/theme-data.js +7 -7
  11. package/lib/browser/theme-data.js.map +1 -1
  12. package/lib/browser/theme-store.js.map +1 -1
  13. package/lib/browser/theme.contribution.js +3 -3
  14. package/lib/browser/theme.contribution.js.map +1 -1
  15. package/lib/browser/workbench.theme.service.js +2 -2
  16. package/lib/browser/workbench.theme.service.js.map +1 -1
  17. package/lib/common/color-tokens/basic-color.d.ts +1 -1
  18. package/lib/common/color-tokens/basic-color.d.ts.map +1 -1
  19. package/lib/common/color-tokens/editor.d.ts +13 -0
  20. package/lib/common/color-tokens/editor.d.ts.map +1 -1
  21. package/lib/common/color-tokens/editor.js +35 -1
  22. package/lib/common/color-tokens/editor.js.map +1 -1
  23. package/lib/common/color.js +40 -40
  24. package/lib/common/color.js.map +1 -1
  25. package/lib/common/mocks/theme.service.js.map +1 -1
  26. package/lib/common/plistParser.js +40 -40
  27. package/lib/common/plistParser.js.map +1 -1
  28. package/lib/common/semantic-tokens-registry.d.ts +7 -7
  29. package/lib/common/semantic-tokens-registry.d.ts.map +1 -1
  30. package/lib/common/theme.service.d.ts +26 -6
  31. package/lib/common/theme.service.d.ts.map +1 -1
  32. package/lib/common/theme.service.js.map +1 -1
  33. package/package.json +11 -10
  34. package/src/browser/default-theme.ts +547 -0
  35. package/src/browser/icon-theme-data.ts +294 -0
  36. package/src/browser/icon-theme-store.ts +38 -0
  37. package/src/browser/icon.less +15 -0
  38. package/src/browser/icon.service.ts +457 -0
  39. package/src/browser/index.ts +45 -0
  40. package/src/browser/semantic-tokens-registry.ts +217 -0
  41. package/src/browser/style.service.ts +51 -0
  42. package/src/browser/theme-data.ts +719 -0
  43. package/src/browser/theme-store.ts +95 -0
  44. package/src/browser/theme.contribution.ts +343 -0
  45. package/src/browser/workbench.theme.service.ts +703 -0
  46. package/src/common/color-registry.ts +52 -0
  47. package/src/common/color-tokens/activity-bar.ts +122 -0
  48. package/src/common/color-tokens/badge.ts +31 -0
  49. package/src/common/color-tokens/base.ts +90 -0
  50. package/src/common/color-tokens/basic-color.ts +9 -0
  51. package/src/common/color-tokens/breadcrumb.ts +60 -0
  52. package/src/common/color-tokens/button.ts +69 -0
  53. package/src/common/color-tokens/charts.ts +68 -0
  54. package/src/common/color-tokens/checkbox.ts +23 -0
  55. package/src/common/color-tokens/custom/actionbar.ts +51 -0
  56. package/src/common/color-tokens/custom/activity-bar.ts +16 -0
  57. package/src/common/color-tokens/custom/badge.ts +30 -0
  58. package/src/common/color-tokens/custom/base.ts +111 -0
  59. package/src/common/color-tokens/custom/button.ts +359 -0
  60. package/src/common/color-tokens/custom/checkbox.ts +36 -0
  61. package/src/common/color-tokens/custom/decoration.ts +71 -0
  62. package/src/common/color-tokens/custom/editor.ts +27 -0
  63. package/src/common/color-tokens/custom/extension.ts +9 -0
  64. package/src/common/color-tokens/custom/icon.ts +30 -0
  65. package/src/common/color-tokens/custom/index.ts +26 -0
  66. package/src/common/color-tokens/custom/input.ts +48 -0
  67. package/src/common/color-tokens/custom/menu.ts +61 -0
  68. package/src/common/color-tokens/custom/modal.ts +57 -0
  69. package/src/common/color-tokens/custom/notification.ts +16 -0
  70. package/src/common/color-tokens/custom/panel.ts +112 -0
  71. package/src/common/color-tokens/custom/popover.ts +28 -0
  72. package/src/common/color-tokens/custom/select.ts +155 -0
  73. package/src/common/color-tokens/custom/settings.ts +32 -0
  74. package/src/common/color-tokens/custom/statusbar.ts +16 -0
  75. package/src/common/color-tokens/custom/tab.ts +31 -0
  76. package/src/common/color-tokens/custom/tooltip.ts +55 -0
  77. package/src/common/color-tokens/custom/tree.ts +106 -0
  78. package/src/common/color-tokens/debug.ts +103 -0
  79. package/src/common/color-tokens/debugToolbar.ts +134 -0
  80. package/src/common/color-tokens/dropdown.ts +27 -0
  81. package/src/common/color-tokens/editor.ts +945 -0
  82. package/src/common/color-tokens/index.ts +35 -0
  83. package/src/common/color-tokens/input.ts +105 -0
  84. package/src/common/color-tokens/list-tree.ts +205 -0
  85. package/src/common/color-tokens/menu-bar.ts +43 -0
  86. package/src/common/color-tokens/menu.ts +53 -0
  87. package/src/common/color-tokens/merge-conflict.ts +145 -0
  88. package/src/common/color-tokens/minimap.ts +99 -0
  89. package/src/common/color-tokens/notification.ts +169 -0
  90. package/src/common/color-tokens/panel.ts +177 -0
  91. package/src/common/color-tokens/pick-view.ts +96 -0
  92. package/src/common/color-tokens/picker.ts +15 -0
  93. package/src/common/color-tokens/progress-bar.ts +12 -0
  94. package/src/common/color-tokens/quick-input.ts +57 -0
  95. package/src/common/color-tokens/scrollbar.ts +42 -0
  96. package/src/common/color-tokens/settings.ts +126 -0
  97. package/src/common/color-tokens/sidebar.ts +121 -0
  98. package/src/common/color-tokens/snippet.ts +33 -0
  99. package/src/common/color-tokens/status-bar.ts +350 -0
  100. package/src/common/color-tokens/tab.ts +346 -0
  101. package/src/common/color-tokens/testing.ts +105 -0
  102. package/src/common/color-tokens/text.ts +41 -0
  103. package/src/common/color-tokens/title-bar.ts +62 -0
  104. package/src/common/color-tokens/toolbar.ts +28 -0
  105. package/src/common/color-tokens/welcome-page.ts +27 -0
  106. package/src/common/color.ts +647 -0
  107. package/src/common/default-themes.ts +273 -0
  108. package/src/common/event.ts +9 -0
  109. package/src/common/index.ts +8 -0
  110. package/src/common/mocks/theme.service.ts +55 -0
  111. package/src/common/plistParser.ts +525 -0
  112. package/src/common/semantic-tokens-registry.ts +439 -0
  113. package/src/common/style.ts +9 -0
  114. package/src/common/theme.service.ts +363 -0
  115. package/src/common/themeCompatibility.ts +95 -0
  116. package/src/common/utils.ts +195 -0
  117. package/src/index.ts +1 -0
@@ -0,0 +1,647 @@
1
+ /* ---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ // Some code copied and modified from https://github.com/microsoft/vscode/blob/1.44.0/src/vs/base/common/color.ts
6
+
7
+ import { CharCode } from '@opensumi/ide-core-common';
8
+
9
+ function roundFloat(num: number, decimalPoints: number): number {
10
+ const decimal = Math.pow(10, decimalPoints);
11
+ return Math.round(num * decimal) / decimal;
12
+ }
13
+
14
+ export class RGBA {
15
+ _rgbaBrand: void;
16
+
17
+ /**
18
+ * Red: integer in [0-255]
19
+ */
20
+ readonly r: number;
21
+
22
+ /**
23
+ * Green: integer in [0-255]
24
+ */
25
+ readonly g: number;
26
+
27
+ /**
28
+ * Blue: integer in [0-255]
29
+ */
30
+ readonly b: number;
31
+
32
+ /**
33
+ * Alpha: float in [0-1]
34
+ */
35
+ readonly a: number;
36
+
37
+ constructor(r: number, g: number, b: number, a = 1) {
38
+ this.r = Math.min(255, Math.max(0, r)) | 0;
39
+ this.g = Math.min(255, Math.max(0, g)) | 0;
40
+ this.b = Math.min(255, Math.max(0, b)) | 0;
41
+ this.a = roundFloat(Math.max(Math.min(1, a), 0), 3);
42
+ }
43
+
44
+ static equals(a: RGBA, b: RGBA): boolean {
45
+ return a.r === b.r && a.g === b.g && a.b === b.b && a.a === b.a;
46
+ }
47
+ }
48
+
49
+ export class HSLA {
50
+ _hslaBrand: void;
51
+
52
+ /**
53
+ * Hue: integer in [0, 360]
54
+ */
55
+ readonly h: number;
56
+
57
+ /**
58
+ * Saturation: float in [0, 1]
59
+ */
60
+ readonly s: number;
61
+
62
+ /**
63
+ * Luminosity: float in [0, 1]
64
+ */
65
+ readonly l: number;
66
+
67
+ /**
68
+ * Alpha: float in [0, 1]
69
+ */
70
+ readonly a: number;
71
+
72
+ constructor(h: number, s: number, l: number, a: number) {
73
+ this.h = Math.max(Math.min(360, h), 0) | 0;
74
+ this.s = roundFloat(Math.max(Math.min(1, s), 0), 3);
75
+ this.l = roundFloat(Math.max(Math.min(1, l), 0), 3);
76
+ this.a = roundFloat(Math.max(Math.min(1, a), 0), 3);
77
+ }
78
+
79
+ static equals(a: HSLA, b: HSLA): boolean {
80
+ return a.h === b.h && a.s === b.s && a.l === b.l && a.a === b.a;
81
+ }
82
+
83
+ /**
84
+ * Converts an RGB color value to HSL. Conversion formula
85
+ * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
86
+ * Assumes r, g, and b are contained in the set [0, 255] and
87
+ * returns h in the set [0, 360], s, and l in the set [0, 1].
88
+ */
89
+ static fromRGBA(rgba: RGBA): HSLA {
90
+ const r = rgba.r / 255;
91
+ const g = rgba.g / 255;
92
+ const b = rgba.b / 255;
93
+ const a = rgba.a;
94
+
95
+ const max = Math.max(r, g, b);
96
+ const min = Math.min(r, g, b);
97
+ let h = 0;
98
+ let s = 0;
99
+ const l = (min + max) / 2;
100
+ const chroma = max - min;
101
+
102
+ if (chroma > 0) {
103
+ s = Math.min(l <= 0.5 ? chroma / (2 * l) : chroma / (2 - 2 * l), 1);
104
+
105
+ switch (max) {
106
+ case r:
107
+ h = (g - b) / chroma + (g < b ? 6 : 0);
108
+ break;
109
+ case g:
110
+ h = (b - r) / chroma + 2;
111
+ break;
112
+ case b:
113
+ h = (r - g) / chroma + 4;
114
+ break;
115
+ }
116
+
117
+ h *= 60;
118
+ h = Math.round(h);
119
+ }
120
+ return new HSLA(h, s, l, a);
121
+ }
122
+
123
+ private static _hue2rgb(p: number, q: number, t: number): number {
124
+ if (t < 0) {
125
+ t += 1;
126
+ }
127
+ if (t > 1) {
128
+ t -= 1;
129
+ }
130
+ if (t < 1 / 6) {
131
+ return p + (q - p) * 6 * t;
132
+ }
133
+ if (t < 1 / 2) {
134
+ return q;
135
+ }
136
+ if (t < 2 / 3) {
137
+ return p + (q - p) * (2 / 3 - t) * 6;
138
+ }
139
+ return p;
140
+ }
141
+
142
+ /**
143
+ * Converts an HSL color value to RGB. Conversion formula
144
+ * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
145
+ * Assumes h in the set [0, 360] s, and l are contained in the set [0, 1] and
146
+ * returns r, g, and b in the set [0, 255].
147
+ */
148
+ static toRGBA(hsla: HSLA): RGBA {
149
+ const h = hsla.h / 360;
150
+ const { s, l, a } = hsla;
151
+ let r: number;
152
+ let g: number;
153
+ let b: number;
154
+
155
+ if (s === 0) {
156
+ r = g = b = l; // achromatic
157
+ } else {
158
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
159
+ const p = 2 * l - q;
160
+ r = HSLA._hue2rgb(p, q, h + 1 / 3);
161
+ g = HSLA._hue2rgb(p, q, h);
162
+ b = HSLA._hue2rgb(p, q, h - 1 / 3);
163
+ }
164
+
165
+ return new RGBA(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a);
166
+ }
167
+ }
168
+
169
+ export class HSVA {
170
+ _hsvaBrand: void;
171
+
172
+ /**
173
+ * Hue: integer in [0, 360]
174
+ */
175
+ readonly h: number;
176
+
177
+ /**
178
+ * Saturation: float in [0, 1]
179
+ */
180
+ readonly s: number;
181
+
182
+ /**
183
+ * Value: float in [0, 1]
184
+ */
185
+ readonly v: number;
186
+
187
+ /**
188
+ * Alpha: float in [0, 1]
189
+ */
190
+ readonly a: number;
191
+
192
+ constructor(h: number, s: number, v: number, a: number) {
193
+ this.h = Math.max(Math.min(360, h), 0) | 0;
194
+ this.s = roundFloat(Math.max(Math.min(1, s), 0), 3);
195
+ this.v = roundFloat(Math.max(Math.min(1, v), 0), 3);
196
+ this.a = roundFloat(Math.max(Math.min(1, a), 0), 3);
197
+ }
198
+
199
+ static equals(a: HSVA, b: HSVA): boolean {
200
+ return a.h === b.h && a.s === b.s && a.v === b.v && a.a === b.a;
201
+ }
202
+
203
+ // from http://www.rapidtables.com/convert/color/rgb-to-hsv.htm
204
+ static fromRGBA(rgba: RGBA): HSVA {
205
+ const r = rgba.r / 255;
206
+ const g = rgba.g / 255;
207
+ const b = rgba.b / 255;
208
+ const cmax = Math.max(r, g, b);
209
+ const cmin = Math.min(r, g, b);
210
+ const delta = cmax - cmin;
211
+ const s = cmax === 0 ? 0 : delta / cmax;
212
+ let m: number;
213
+
214
+ if (delta === 0) {
215
+ m = 0;
216
+ } else if (cmax === r) {
217
+ m = ((((g - b) / delta) % 6) + 6) % 6;
218
+ } else if (cmax === g) {
219
+ m = (b - r) / delta + 2;
220
+ } else {
221
+ m = (r - g) / delta + 4;
222
+ }
223
+
224
+ return new HSVA(Math.round(m * 60), s, cmax, rgba.a);
225
+ }
226
+
227
+ // from http://www.rapidtables.com/convert/color/hsv-to-rgb.htm
228
+ static toRGBA(hsva: HSVA): RGBA {
229
+ const { h, s, v, a } = hsva;
230
+ const c = v * s;
231
+ const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
232
+ const m = v - c;
233
+ let [r, g, b] = [0, 0, 0];
234
+
235
+ if (h < 60) {
236
+ r = c;
237
+ g = x;
238
+ } else if (h < 120) {
239
+ r = x;
240
+ g = c;
241
+ } else if (h < 180) {
242
+ g = c;
243
+ b = x;
244
+ } else if (h < 240) {
245
+ g = x;
246
+ b = c;
247
+ } else if (h < 300) {
248
+ r = x;
249
+ b = c;
250
+ } else if (h < 360) {
251
+ r = c;
252
+ b = x;
253
+ }
254
+
255
+ r = Math.round((r + m) * 255);
256
+ g = Math.round((g + m) * 255);
257
+ b = Math.round((b + m) * 255);
258
+
259
+ return new RGBA(r, g, b, a);
260
+ }
261
+ }
262
+
263
+ export class Color {
264
+ static fromHex(hex: string): Color {
265
+ return Color.Format.CSS.parseHex(hex) || Color.red;
266
+ }
267
+
268
+ readonly rgba: RGBA;
269
+ private _hsla?: HSLA;
270
+ get hsla(): HSLA {
271
+ if (this._hsla) {
272
+ return this._hsla;
273
+ } else {
274
+ return HSLA.fromRGBA(this.rgba);
275
+ }
276
+ }
277
+
278
+ private _hsva?: HSVA;
279
+ get hsva(): HSVA {
280
+ if (this._hsva) {
281
+ return this._hsva;
282
+ }
283
+ return HSVA.fromRGBA(this.rgba);
284
+ }
285
+
286
+ constructor(arg: RGBA | HSLA | HSVA) {
287
+ if (!arg) {
288
+ throw new Error('Color needs a value');
289
+ } else if (arg instanceof RGBA) {
290
+ this.rgba = arg;
291
+ } else if (arg instanceof HSLA) {
292
+ this._hsla = arg;
293
+ this.rgba = HSLA.toRGBA(arg);
294
+ } else if (arg instanceof HSVA) {
295
+ this._hsva = arg;
296
+ this.rgba = HSVA.toRGBA(arg);
297
+ } else {
298
+ throw new Error('Invalid color ctor argument');
299
+ }
300
+ }
301
+
302
+ equals(other: Color): boolean {
303
+ return (
304
+ !!other &&
305
+ RGBA.equals(this.rgba, other.rgba) &&
306
+ HSLA.equals(this.hsla, other.hsla) &&
307
+ HSVA.equals(this.hsva, other.hsva)
308
+ );
309
+ }
310
+
311
+ /**
312
+ * http://www.w3.org/TR/WCAG20/#relativeluminancedef
313
+ * Returns the number in the set [0, 1]. O => Darkest Black. 1 => Lightest white.
314
+ */
315
+ getRelativeLuminance(): number {
316
+ const R = Color._relativeLuminanceForComponent(this.rgba.r);
317
+ const G = Color._relativeLuminanceForComponent(this.rgba.g);
318
+ const B = Color._relativeLuminanceForComponent(this.rgba.b);
319
+ const luminance = 0.2126 * R + 0.7152 * G + 0.0722 * B;
320
+
321
+ return roundFloat(luminance, 4);
322
+ }
323
+
324
+ private static _relativeLuminanceForComponent(color: number): number {
325
+ const c = color / 255;
326
+ return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
327
+ }
328
+
329
+ /**
330
+ * http://www.w3.org/TR/WCAG20/#contrast-ratiodef
331
+ * Returns the contrast ration number in the set [1, 21].
332
+ */
333
+ getContrastRatio(another: Color): number {
334
+ const lum1 = this.getRelativeLuminance();
335
+ const lum2 = another.getRelativeLuminance();
336
+ return lum1 > lum2 ? (lum1 + 0.05) / (lum2 + 0.05) : (lum2 + 0.05) / (lum1 + 0.05);
337
+ }
338
+
339
+ /**
340
+ * http://24ways.org/2010/calculating-color-contrast
341
+ * Return 'true' if darker color otherwise 'false'
342
+ */
343
+ isDarker(): boolean {
344
+ const yiq = (this.rgba.r * 299 + this.rgba.g * 587 + this.rgba.b * 114) / 1000;
345
+ return yiq < 128;
346
+ }
347
+
348
+ /**
349
+ * http://24ways.org/2010/calculating-color-contrast
350
+ * Return 'true' if lighter color otherwise 'false'
351
+ */
352
+ isLighter(): boolean {
353
+ const yiq = (this.rgba.r * 299 + this.rgba.g * 587 + this.rgba.b * 114) / 1000;
354
+ return yiq >= 128;
355
+ }
356
+
357
+ isLighterThan(another: Color): boolean {
358
+ const lum1 = this.getRelativeLuminance();
359
+ const lum2 = another.getRelativeLuminance();
360
+ return lum1 > lum2;
361
+ }
362
+
363
+ isDarkerThan(another: Color): boolean {
364
+ const lum1 = this.getRelativeLuminance();
365
+ const lum2 = another.getRelativeLuminance();
366
+ return lum1 < lum2;
367
+ }
368
+
369
+ lighten(factor: number): Color {
370
+ return new Color(new HSLA(this.hsla.h, this.hsla.s, this.hsla.l + this.hsla.l * factor, this.hsla.a));
371
+ }
372
+
373
+ darken(factor: number): Color {
374
+ return new Color(new HSLA(this.hsla.h, this.hsla.s, this.hsla.l - this.hsla.l * factor, this.hsla.a));
375
+ }
376
+
377
+ transparent(factor: number): Color {
378
+ const { r, g, b, a } = this.rgba;
379
+ return new Color(new RGBA(r, g, b, a * factor));
380
+ }
381
+
382
+ isTransparent(): boolean {
383
+ return this.rgba.a === 0;
384
+ }
385
+
386
+ isOpaque(): boolean {
387
+ return this.rgba.a === 1;
388
+ }
389
+
390
+ opposite(): Color {
391
+ return new Color(new RGBA(255 - this.rgba.r, 255 - this.rgba.g, 255 - this.rgba.b, this.rgba.a));
392
+ }
393
+
394
+ blend(c: Color): Color {
395
+ const rgba = c.rgba;
396
+
397
+ // Convert to 0..1 opacity
398
+ const thisA = this.rgba.a;
399
+ const colorA = rgba.a;
400
+
401
+ const a = thisA + colorA * (1 - thisA);
402
+ if (a < 1e-6) {
403
+ return Color.transparent;
404
+ }
405
+
406
+ const r = (this.rgba.r * thisA) / a + (rgba.r * colorA * (1 - thisA)) / a;
407
+ const g = (this.rgba.g * thisA) / a + (rgba.g * colorA * (1 - thisA)) / a;
408
+ const b = (this.rgba.b * thisA) / a + (rgba.b * colorA * (1 - thisA)) / a;
409
+
410
+ return new Color(new RGBA(r, g, b, a));
411
+ }
412
+
413
+ flatten(...backgrounds: Color[]): Color {
414
+ const background = backgrounds.reduceRight((accumulator, color) => Color._flatten(color, accumulator));
415
+ return Color._flatten(this, background);
416
+ }
417
+
418
+ private static _flatten(foreground: Color, background: Color) {
419
+ const backgroundAlpha = 1 - foreground.rgba.a;
420
+ return new Color(
421
+ new RGBA(
422
+ backgroundAlpha * background.rgba.r + foreground.rgba.a * foreground.rgba.r,
423
+ backgroundAlpha * background.rgba.g + foreground.rgba.a * foreground.rgba.g,
424
+ backgroundAlpha * background.rgba.b + foreground.rgba.a * foreground.rgba.b,
425
+ ),
426
+ );
427
+ }
428
+
429
+ toString(): string {
430
+ return '' + Color.Format.CSS.format(this);
431
+ }
432
+
433
+ static getLighterColor(of: Color, relative: Color, factor?: number): Color {
434
+ if (of.isLighterThan(relative)) {
435
+ return of;
436
+ }
437
+ factor = factor ? factor : 0.5;
438
+ const lum1 = of.getRelativeLuminance();
439
+ const lum2 = relative.getRelativeLuminance();
440
+ factor = (factor * (lum2 - lum1)) / lum2;
441
+ return of.lighten(factor);
442
+ }
443
+
444
+ static getDarkerColor(of: Color, relative: Color, factor?: number): Color {
445
+ if (of.isDarkerThan(relative)) {
446
+ return of;
447
+ }
448
+ factor = factor ? factor : 0.5;
449
+ const lum1 = of.getRelativeLuminance();
450
+ const lum2 = relative.getRelativeLuminance();
451
+ factor = (factor * (lum1 - lum2)) / lum1;
452
+ return of.darken(factor);
453
+ }
454
+
455
+ static readonly white = new Color(new RGBA(255, 255, 255, 1));
456
+ static readonly black = new Color(new RGBA(0, 0, 0, 1));
457
+ static readonly red = new Color(new RGBA(255, 0, 0, 1));
458
+ static readonly blue = new Color(new RGBA(0, 0, 255, 1));
459
+ static readonly green = new Color(new RGBA(0, 255, 0, 1));
460
+ static readonly cyan = new Color(new RGBA(0, 255, 255, 1));
461
+ static readonly lightgrey = new Color(new RGBA(211, 211, 211, 1));
462
+ static readonly transparent = new Color(new RGBA(0, 0, 0, 0));
463
+ }
464
+
465
+ export namespace Color {
466
+ export namespace Format {
467
+ export namespace CSS {
468
+ export function formatRGB(color: Color): string {
469
+ if (color.rgba.a === 1) {
470
+ return `rgb(${color.rgba.r}, ${color.rgba.g}, ${color.rgba.b})`;
471
+ }
472
+
473
+ return Color.Format.CSS.formatRGBA(color);
474
+ }
475
+
476
+ export function formatRGBA(color: Color): string {
477
+ return `rgba(${color.rgba.r}, ${color.rgba.g}, ${color.rgba.b}, ${+color.rgba.a.toFixed(2)})`;
478
+ }
479
+
480
+ export function formatHSL(color: Color): string {
481
+ if (color.hsla.a === 1) {
482
+ return `hsl(${color.hsla.h}, ${(color.hsla.s * 100).toFixed(2)}%, ${(color.hsla.l * 100).toFixed(2)}%)`;
483
+ }
484
+
485
+ return Color.Format.CSS.formatHSLA(color);
486
+ }
487
+
488
+ export function formatHSLA(color: Color): string {
489
+ return `hsla(${color.hsla.h}, ${(color.hsla.s * 100).toFixed(2)}%, ${(color.hsla.l * 100).toFixed(
490
+ 2,
491
+ )}%, ${color.hsla.a.toFixed(2)})`;
492
+ }
493
+
494
+ function _toTwoDigitHex(n: number): string {
495
+ const r = n.toString(16);
496
+ return r.length !== 2 ? '0' + r : r;
497
+ }
498
+
499
+ /**
500
+ * Formats the color as #RRGGBB
501
+ */
502
+ export function formatHex(color: Color): string {
503
+ return `#${_toTwoDigitHex(color.rgba.r)}${_toTwoDigitHex(color.rgba.g)}${_toTwoDigitHex(color.rgba.b)}`;
504
+ }
505
+
506
+ /**
507
+ * Formats the color as #RRGGBBAA
508
+ * If 'compact' is set, colors without transparancy will be printed as #RRGGBB
509
+ */
510
+ export function formatHexA(color: Color, compact = false): string {
511
+ if (compact && color.rgba.a === 1) {
512
+ return Color.Format.CSS.formatHex(color);
513
+ }
514
+
515
+ return `#${_toTwoDigitHex(color.rgba.r)}${_toTwoDigitHex(color.rgba.g)}${_toTwoDigitHex(
516
+ color.rgba.b,
517
+ )}${_toTwoDigitHex(Math.round(color.rgba.a * 255))}`;
518
+ }
519
+
520
+ /**
521
+ * The default format will use HEX if opaque and RGBA otherwise.
522
+ */
523
+ export function format(color: Color): string | null {
524
+ if (!color) {
525
+ return null;
526
+ }
527
+
528
+ if (color.isOpaque()) {
529
+ return Color.Format.CSS.formatHex(color);
530
+ }
531
+
532
+ return Color.Format.CSS.formatRGBA(color);
533
+ }
534
+
535
+ /**
536
+ * Converts an Hex color value to a Color.
537
+ * returns r, g, and b are contained in the set [0, 255]
538
+ * @param hex string (#RGB, #RGBA, #RRGGBB or #RRGGBBAA).
539
+ */
540
+ export function parseHex(hex: string): Color | null {
541
+ if (!hex) {
542
+ // Invalid color
543
+ return null;
544
+ }
545
+
546
+ const length = hex.length;
547
+
548
+ if (length === 0) {
549
+ // Invalid color
550
+ return null;
551
+ }
552
+
553
+ if (hex.charCodeAt(0) !== CharCode.Hash) {
554
+ // Does not begin with a #
555
+ return null;
556
+ }
557
+
558
+ if (length === 7) {
559
+ // #RRGGBB format
560
+ const r = 16 * _parseHexDigit(hex.charCodeAt(1)) + _parseHexDigit(hex.charCodeAt(2));
561
+ const g = 16 * _parseHexDigit(hex.charCodeAt(3)) + _parseHexDigit(hex.charCodeAt(4));
562
+ const b = 16 * _parseHexDigit(hex.charCodeAt(5)) + _parseHexDigit(hex.charCodeAt(6));
563
+ return new Color(new RGBA(r, g, b, 1));
564
+ }
565
+
566
+ if (length === 9) {
567
+ // #RRGGBBAA format
568
+ const r = 16 * _parseHexDigit(hex.charCodeAt(1)) + _parseHexDigit(hex.charCodeAt(2));
569
+ const g = 16 * _parseHexDigit(hex.charCodeAt(3)) + _parseHexDigit(hex.charCodeAt(4));
570
+ const b = 16 * _parseHexDigit(hex.charCodeAt(5)) + _parseHexDigit(hex.charCodeAt(6));
571
+ const a = 16 * _parseHexDigit(hex.charCodeAt(7)) + _parseHexDigit(hex.charCodeAt(8));
572
+ return new Color(new RGBA(r, g, b, a / 255));
573
+ }
574
+
575
+ if (length === 4) {
576
+ // #RGB format
577
+ const r = _parseHexDigit(hex.charCodeAt(1));
578
+ const g = _parseHexDigit(hex.charCodeAt(2));
579
+ const b = _parseHexDigit(hex.charCodeAt(3));
580
+ return new Color(new RGBA(16 * r + r, 16 * g + g, 16 * b + b));
581
+ }
582
+
583
+ if (length === 5) {
584
+ // #RGBA format
585
+ const r = _parseHexDigit(hex.charCodeAt(1));
586
+ const g = _parseHexDigit(hex.charCodeAt(2));
587
+ const b = _parseHexDigit(hex.charCodeAt(3));
588
+ const a = _parseHexDigit(hex.charCodeAt(4));
589
+ return new Color(new RGBA(16 * r + r, 16 * g + g, 16 * b + b, (16 * a + a) / 255));
590
+ }
591
+
592
+ // Invalid color
593
+ return null;
594
+ }
595
+
596
+ function _parseHexDigit(charCode: CharCode): number {
597
+ switch (charCode) {
598
+ case CharCode.Digit0:
599
+ return 0;
600
+ case CharCode.Digit1:
601
+ return 1;
602
+ case CharCode.Digit2:
603
+ return 2;
604
+ case CharCode.Digit3:
605
+ return 3;
606
+ case CharCode.Digit4:
607
+ return 4;
608
+ case CharCode.Digit5:
609
+ return 5;
610
+ case CharCode.Digit6:
611
+ return 6;
612
+ case CharCode.Digit7:
613
+ return 7;
614
+ case CharCode.Digit8:
615
+ return 8;
616
+ case CharCode.Digit9:
617
+ return 9;
618
+ case CharCode.a:
619
+ return 10;
620
+ case CharCode.A:
621
+ return 10;
622
+ case CharCode.b:
623
+ return 11;
624
+ case CharCode.B:
625
+ return 11;
626
+ case CharCode.c:
627
+ return 12;
628
+ case CharCode.C:
629
+ return 12;
630
+ case CharCode.d:
631
+ return 13;
632
+ case CharCode.D:
633
+ return 13;
634
+ case CharCode.e:
635
+ return 14;
636
+ case CharCode.E:
637
+ return 14;
638
+ case CharCode.f:
639
+ return 15;
640
+ case CharCode.F:
641
+ return 15;
642
+ }
643
+ return 0;
644
+ }
645
+ }
646
+ }
647
+ }