chrome-devtools-frontend 1.0.979699 → 1.0.980166
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/front_end/core/common/Color.ts +95 -29
- package/front_end/core/common/ColorUtils.ts +18 -2
- package/front_end/core/common/Settings.ts +2 -0
- package/front_end/models/persistence/PersistenceUtils.ts +1 -2
- package/front_end/ui/legacy/components/color_picker/Spectrum.ts +23 -9
- package/front_end/ui/legacy/components/inline_editor/ColorSwatch.ts +5 -0
- package/front_end/ui/legacy/inspectorCommon.css +9 -0
- package/inspector_overlay/highlight_common.ts +10 -3
- package/package.json +1 -1
@@ -33,10 +33,11 @@
|
|
33
33
|
|
34
34
|
import * as Platform from '../platform/platform.js';
|
35
35
|
|
36
|
-
import {blendColors, contrastRatioAPCA, desiredLuminanceAPCA, luminance, luminanceAPCA, rgbaToHsla} from './ColorUtils.js';
|
36
|
+
import {blendColors, contrastRatioAPCA, desiredLuminanceAPCA, luminance, luminanceAPCA, rgbaToHsla, rgbaToHwba} from './ColorUtils.js';
|
37
37
|
|
38
38
|
export class Color {
|
39
39
|
#hslaInternal: number[]|undefined;
|
40
|
+
#hwbaInternal: number[]|undefined;
|
40
41
|
#rgbaInternal: number[];
|
41
42
|
#originalText: string|null;
|
42
43
|
readonly #originalTextIsValid: boolean;
|
@@ -44,6 +45,7 @@ export class Color {
|
|
44
45
|
|
45
46
|
constructor(rgba: number[], format: Format, originalText?: string) {
|
46
47
|
this.#hslaInternal = undefined;
|
48
|
+
this.#hwbaInternal = undefined;
|
47
49
|
this.#rgbaInternal = rgba;
|
48
50
|
this.#originalText = originalText || null;
|
49
51
|
this.#originalTextIsValid = Boolean(this.#originalText);
|
@@ -110,29 +112,12 @@ export class Color {
|
|
110
112
|
return null;
|
111
113
|
}
|
112
114
|
|
113
|
-
// rgb/rgba(), hsl/hsla()
|
114
|
-
match = text.toLowerCase().match(/^\s*(?:(rgba?)|(hsla?))\((.*)\)\s*$/);
|
115
|
-
|
115
|
+
// rgb/rgba(), hsl/hsla(), hwb/hwba()
|
116
|
+
match = text.toLowerCase().match(/^\s*(?:(rgba?)|(hsla?)|(hwba?))\((.*)\)\s*$/);
|
116
117
|
if (match) {
|
117
|
-
|
118
|
-
|
119
|
-
if (values
|
120
|
-
values = components.split(/\s+/);
|
121
|
-
if (values[3] === '/') {
|
122
|
-
values.splice(3, 1);
|
123
|
-
if (values.length !== 4) {
|
124
|
-
return null;
|
125
|
-
}
|
126
|
-
} else if (
|
127
|
-
(values.length > 2 && values[2].indexOf('/') !== -1) ||
|
128
|
-
(values.length > 3 && values[3].indexOf('/') !== -1)) {
|
129
|
-
const alpha = values.slice(2, 4).join('');
|
130
|
-
values = values.slice(0, 2).concat(alpha.split(/\//)).concat(values.slice(4));
|
131
|
-
} else if (values.length >= 4) {
|
132
|
-
return null;
|
133
|
-
}
|
134
|
-
}
|
135
|
-
if (values.length !== 3 && values.length !== 4 || values.indexOf('') > -1) {
|
118
|
+
// hwb(a) must have white space delimiters between its parameters.
|
119
|
+
const values = this.splitColorFunctionParameters(match[4], !match[3]);
|
120
|
+
if (!values) {
|
136
121
|
return null;
|
137
122
|
}
|
138
123
|
const hasAlpha = (values[3] !== undefined);
|
@@ -150,19 +135,23 @@ export class Color {
|
|
150
135
|
return new Color((rgba as number[]), hasAlpha ? Format.RGBA : Format.RGB, text);
|
151
136
|
}
|
152
137
|
|
153
|
-
if (match[2]) { // hsl/hsla
|
154
|
-
const
|
138
|
+
if (match[2] || match[3]) { // hsl/hsla or hwb/hwba
|
139
|
+
const parameters = [
|
155
140
|
Color.parseHueNumeric(values[0]),
|
156
141
|
Color.parseSatLightNumeric(values[1]),
|
157
142
|
Color.parseSatLightNumeric(values[2]),
|
158
143
|
hasAlpha ? Color.parseAlphaNumeric(values[3]) : 1,
|
159
144
|
];
|
160
|
-
if (
|
145
|
+
if (parameters.indexOf(null) > -1) {
|
161
146
|
return null;
|
162
147
|
}
|
163
148
|
const rgba: number[] = [];
|
164
|
-
|
165
|
-
|
149
|
+
if (match[2]) {
|
150
|
+
Color.hsl2rgb((parameters as number[]), rgba);
|
151
|
+
return new Color(rgba, hasAlpha ? Format.HSLA : Format.HSL, text);
|
152
|
+
}
|
153
|
+
Color.hwb2rgb((parameters as number[]), rgba);
|
154
|
+
return new Color(rgba, hasAlpha ? Format.HWBA : Format.HWB, text);
|
166
155
|
}
|
167
156
|
}
|
168
157
|
|
@@ -179,6 +168,38 @@ export class Color {
|
|
179
168
|
return new Color(rgba, Format.HSLA);
|
180
169
|
}
|
181
170
|
|
171
|
+
/**
|
172
|
+
* Split the color parameters of (e.g.) rgb(a), hsl(a), hwb(a) functions.
|
173
|
+
*/
|
174
|
+
static splitColorFunctionParameters(content: string, allowCommas: boolean): string[]|null {
|
175
|
+
const components = content.trim();
|
176
|
+
let values: string[] = [];
|
177
|
+
|
178
|
+
if (allowCommas) {
|
179
|
+
values = components.split(/\s*,\s*/);
|
180
|
+
}
|
181
|
+
if (!allowCommas || values.length === 1) {
|
182
|
+
values = components.split(/\s+/);
|
183
|
+
if (values[3] === '/') {
|
184
|
+
values.splice(3, 1);
|
185
|
+
if (values.length !== 4) {
|
186
|
+
return null;
|
187
|
+
}
|
188
|
+
} else if (
|
189
|
+
(values.length > 2 && values[2].indexOf('/') !== -1) ||
|
190
|
+
(values.length > 3 && values[3].indexOf('/') !== -1)) {
|
191
|
+
const alpha = values.slice(2, 4).join('');
|
192
|
+
values = values.slice(0, 2).concat(alpha.split(/\//)).concat(values.slice(4));
|
193
|
+
} else if (values.length >= 4) {
|
194
|
+
return null;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
if (values.length !== 3 && values.length !== 4 || values.indexOf('') > -1) {
|
198
|
+
return null;
|
199
|
+
}
|
200
|
+
return values;
|
201
|
+
}
|
202
|
+
|
182
203
|
static parsePercentOrNumber(value: string): number|null {
|
183
204
|
// @ts-ignore: isNaN can accept strings
|
184
205
|
if (isNaN(value.replace('%', ''))) {
|
@@ -309,6 +330,24 @@ export class Color {
|
|
309
330
|
out_rgb[3] = hsl[3];
|
310
331
|
}
|
311
332
|
|
333
|
+
// See https://drafts.csswg.org/css-color-4/#hwb-to-rgb for formula reference.
|
334
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
335
|
+
static hwb2rgb(hwb: number[], out_rgb: number[]): void {
|
336
|
+
const h = hwb[0];
|
337
|
+
const w = hwb[1];
|
338
|
+
const b = hwb[2];
|
339
|
+
|
340
|
+
if (w + b >= 1) {
|
341
|
+
out_rgb[0] = out_rgb[1] = out_rgb[2] = w / (w + b);
|
342
|
+
out_rgb[3] = hwb[3];
|
343
|
+
} else {
|
344
|
+
Color.hsl2rgb([h, 1, 0.5, hwb[3]], out_rgb);
|
345
|
+
for (let i = 0; i < 3; ++i) {
|
346
|
+
out_rgb[i] += w - (w + b) * out_rgb[i];
|
347
|
+
}
|
348
|
+
}
|
349
|
+
}
|
350
|
+
|
312
351
|
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
|
313
352
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
314
353
|
static hsva2rgba(hsva: number[], out_rgba: number[]): void {
|
@@ -478,6 +517,21 @@ export class Color {
|
|
478
517
|
return [h, s !== 0 ? 2 * s / (l + s) : 0, (l + s), hsla[3]];
|
479
518
|
}
|
480
519
|
|
520
|
+
/** HWBA with components within [0..1]
|
521
|
+
*/
|
522
|
+
hwba(): number[] {
|
523
|
+
if (this.#hwbaInternal) {
|
524
|
+
return this.#hwbaInternal;
|
525
|
+
}
|
526
|
+
this.#hwbaInternal = rgbaToHwba(this.#rgbaInternal);
|
527
|
+
return this.#hwbaInternal;
|
528
|
+
}
|
529
|
+
|
530
|
+
canonicalHWBA(): number[] {
|
531
|
+
const hwba = this.hwba();
|
532
|
+
return [Math.round(hwba[0] * 360), Math.round(hwba[1] * 100), Math.round(hwba[2] * 100), hwba[3]];
|
533
|
+
}
|
534
|
+
|
481
535
|
hasAlpha(): boolean {
|
482
536
|
return this.#rgbaInternal[3] !== 1;
|
483
537
|
}
|
@@ -546,6 +600,16 @@ export class Color {
|
|
546
600
|
}
|
547
601
|
return start + ')';
|
548
602
|
}
|
603
|
+
case Format.HWB:
|
604
|
+
case Format.HWBA: {
|
605
|
+
const hwba = this.hwba();
|
606
|
+
const start = Platform.StringUtilities.sprintf(
|
607
|
+
'hwb(%ddeg %d% %d%', Math.round(hwba[0] * 360), Math.round(hwba[1] * 100), Math.round(hwba[2] * 100));
|
608
|
+
if (this.hasAlpha()) {
|
609
|
+
return start + Platform.StringUtilities.sprintf(' / %d%)', Math.round(hwba[3] * 100));
|
610
|
+
}
|
611
|
+
return start + ')';
|
612
|
+
}
|
549
613
|
case Format.HEXA: {
|
550
614
|
return Platform.StringUtilities
|
551
615
|
.sprintf(
|
@@ -670,7 +734,7 @@ export class Color {
|
|
670
734
|
}
|
671
735
|
|
672
736
|
export const Regex: RegExp =
|
673
|
-
/((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{8}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,4}|\b[a-zA-Z]+\b(?!-))/g;
|
737
|
+
/((?:rgb|hsl|hwb)a?\([^)]+\)|#[0-9a-fA-F]{8}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,4}|\b[a-zA-Z]+\b(?!-))/g;
|
674
738
|
|
675
739
|
// TODO(crbug.com/1167717): Make this a const enum again
|
676
740
|
// eslint-disable-next-line rulesdir/const_enum
|
@@ -685,6 +749,8 @@ export enum Format {
|
|
685
749
|
RGBA = 'rgba',
|
686
750
|
HSL = 'hsl',
|
687
751
|
HSLA = 'hsla',
|
752
|
+
HWB = 'hwb',
|
753
|
+
HWBA = 'hwba',
|
688
754
|
}
|
689
755
|
|
690
756
|
const COLOR_TO_RGBA_ENTRIES: Array<readonly[string, number[]]> = [
|
@@ -15,11 +15,10 @@ export function blendColors(fgRGBA: number[], bgRGBA: number[]): number[] {
|
|
15
15
|
];
|
16
16
|
}
|
17
17
|
|
18
|
-
|
18
|
+
function rgbToHue([r, g, b]: number[]): number {
|
19
19
|
const max = Math.max(r, g, b);
|
20
20
|
const min = Math.min(r, g, b);
|
21
21
|
const diff = max - min;
|
22
|
-
const sum = max + min;
|
23
22
|
|
24
23
|
let h;
|
25
24
|
if (min === max) {
|
@@ -31,7 +30,16 @@ export function rgbaToHsla([r, g, b, a]: number[]): number[] {
|
|
31
30
|
} else {
|
32
31
|
h = (1 / 6 * (r - g) / diff) + 2 / 3;
|
33
32
|
}
|
33
|
+
return h;
|
34
|
+
}
|
35
|
+
|
36
|
+
export function rgbaToHsla([r, g, b, a]: number[]): number[] {
|
37
|
+
const max = Math.max(r, g, b);
|
38
|
+
const min = Math.min(r, g, b);
|
39
|
+
const diff = max - min;
|
40
|
+
const sum = max + min;
|
34
41
|
|
42
|
+
const h = rgbToHue([r, g, b]);
|
35
43
|
const l = 0.5 * sum;
|
36
44
|
|
37
45
|
let s;
|
@@ -48,6 +56,14 @@ export function rgbaToHsla([r, g, b, a]: number[]): number[] {
|
|
48
56
|
return [h, s, l, a];
|
49
57
|
}
|
50
58
|
|
59
|
+
export function rgbaToHwba([r, g, b, a]: number[]): number[] {
|
60
|
+
const h = rgbToHue([r, g, b]);
|
61
|
+
const max = Math.max(r, g, b);
|
62
|
+
const min = Math.min(r, g, b);
|
63
|
+
|
64
|
+
return [h, min, 1 - max, a];
|
65
|
+
}
|
66
|
+
|
51
67
|
/**
|
52
68
|
* Calculate the luminance of this color using the WCAG algorithm.
|
53
69
|
* See http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
|
@@ -1113,6 +1113,8 @@ export function detectColorFormat(color: Color): Format {
|
|
1113
1113
|
format = cf.RGB;
|
1114
1114
|
} else if (formatSetting === cf.HSL) {
|
1115
1115
|
format = cf.HSL;
|
1116
|
+
} else if (formatSetting === cf.HWB) {
|
1117
|
+
format = cf.HWB;
|
1116
1118
|
} else if (formatSetting === cf.HEX) {
|
1117
1119
|
format = color.detectHEXFormat();
|
1118
1120
|
} else {
|
@@ -53,9 +53,8 @@ export class PersistenceUtils {
|
|
53
53
|
}
|
54
54
|
const icon = UI.Icon.Icon.create('mediumicon-file-sync');
|
55
55
|
UI.Tooltip.Tooltip.install(icon, PersistenceUtils.tooltipForUISourceCode(binding.network));
|
56
|
-
// TODO(allada) This will not work properly with dark theme.
|
57
56
|
if (NetworkPersistenceManager.instance().project() === binding.fileSystem.project()) {
|
58
|
-
icon.
|
57
|
+
icon.classList.add('purple-dot');
|
59
58
|
}
|
60
59
|
return icon;
|
61
60
|
}
|
@@ -224,7 +224,7 @@ export class Spectrum extends Common.ObjectWrapper.eventMixin<EventTypes, typeof
|
|
224
224
|
this.alphaElementBackground = this.alphaElement.createChild('div', 'spectrum-alpha-background');
|
225
225
|
this.alphaSlider = this.alphaElement.createChild('div', 'spectrum-slider');
|
226
226
|
|
227
|
-
// RGBA/HSLA display.
|
227
|
+
// RGBA/HSLA/HWBA display.
|
228
228
|
this.displayContainer = toolsContainer.createChild('div', 'spectrum-text source-code');
|
229
229
|
UI.ARIAUtils.markAsPoliteLiveRegion(this.displayContainer, true);
|
230
230
|
this.textValues = [];
|
@@ -937,6 +937,8 @@ export class Spectrum extends Common.ObjectWrapper.eventMixin<EventTypes, typeof
|
|
937
937
|
colorFormat = cf.RGB;
|
938
938
|
} else if (colorFormat === cf.HSLA) {
|
939
939
|
colorFormat = cf.HSL;
|
940
|
+
} else if (colorFormat === cf.HWBA) {
|
941
|
+
colorFormat = cf.HWB;
|
940
942
|
} else if (colorFormat === cf.HEXA) {
|
941
943
|
colorFormat = cf.HEX;
|
942
944
|
} else if (colorFormat === cf.ShortHEXA) {
|
@@ -988,6 +990,8 @@ export class Spectrum extends Common.ObjectWrapper.eventMixin<EventTypes, typeof
|
|
988
990
|
colorString = color.asString(cf.HEXA);
|
989
991
|
} else if (this.colorFormat === cf.HSL) {
|
990
992
|
colorString = color.asString(cf.HSLA);
|
993
|
+
} else if (this.colorFormat === cf.HWB) {
|
994
|
+
colorString = color.asString(cf.HWBA);
|
991
995
|
} else {
|
992
996
|
colorString = color.asString(cf.RGBA);
|
993
997
|
}
|
@@ -1033,12 +1037,21 @@ export class Spectrum extends Common.ObjectWrapper.eventMixin<EventTypes, typeof
|
|
1033
1037
|
this.hexValue.value = String(this.color().asString(this.color().hasAlpha() ? cf.HEXA : cf.HEX));
|
1034
1038
|
}
|
1035
1039
|
} else {
|
1036
|
-
// RGBA, HSLA display.
|
1040
|
+
// RGBA, HSLA, HWBA display.
|
1037
1041
|
this.hexContainer.hidden = true;
|
1038
1042
|
this.displayContainer.hidden = false;
|
1039
|
-
|
1040
|
-
this.
|
1041
|
-
|
1043
|
+
let colorValues;
|
1044
|
+
if (this.colorFormat === cf.RGB) {
|
1045
|
+
this.textLabels.textContent = 'RGBA';
|
1046
|
+
colorValues = this.color().canonicalRGBA();
|
1047
|
+
} else if (this.colorFormat === cf.HSL) {
|
1048
|
+
this.textLabels.textContent = 'HSLA';
|
1049
|
+
colorValues = this.color().canonicalHSLA();
|
1050
|
+
} else {
|
1051
|
+
this.textLabels.textContent = 'HWBA';
|
1052
|
+
colorValues = this.color().canonicalHWBA();
|
1053
|
+
}
|
1054
|
+
|
1042
1055
|
for (let i = 0; i < 3; ++i) {
|
1043
1056
|
UI.ARIAUtils.setAccessibleName(
|
1044
1057
|
this.textValues[i],
|
@@ -1047,7 +1060,7 @@ export class Spectrum extends Common.ObjectWrapper.eventMixin<EventTypes, typeof
|
|
1047
1060
|
PH2: this.textLabels.textContent,
|
1048
1061
|
}));
|
1049
1062
|
this.textValues[i].value = String(colorValues[i]);
|
1050
|
-
if (
|
1063
|
+
if (this.colorFormat !== cf.RGB && (i === 1 || i === 2)) {
|
1051
1064
|
this.textValues[i].value += '%';
|
1052
1065
|
}
|
1053
1066
|
}
|
@@ -1081,6 +1094,8 @@ export class Spectrum extends Common.ObjectWrapper.eventMixin<EventTypes, typeof
|
|
1081
1094
|
if (this.colorFormat === cf.RGB) {
|
1082
1095
|
format = cf.HSL;
|
1083
1096
|
} else if (this.colorFormat === cf.HSL) {
|
1097
|
+
format = cf.HWB;
|
1098
|
+
} else if (this.colorFormat === cf.HWB) {
|
1084
1099
|
format = (this.originalFormat === cf.ShortHEX || this.originalFormat === cf.ShortHEXA) ? cf.ShortHEX : cf.HEX;
|
1085
1100
|
}
|
1086
1101
|
this.innerSetColor(undefined, '', undefined /* colorName */, format, ChangeSource.Other);
|
@@ -1121,10 +1136,9 @@ export class Spectrum extends Common.ObjectWrapper.eventMixin<EventTypes, typeof
|
|
1121
1136
|
if (this.colorFormat === cf.Nickname || this.colorFormat === cf.HEX || this.colorFormat === cf.ShortHEX) {
|
1122
1137
|
colorString = this.hexValue.value;
|
1123
1138
|
} else {
|
1124
|
-
const format = this.colorFormat === cf.RGB ? 'rgb' : 'hsl';
|
1125
1139
|
const values = this.textValues.slice(0, -1).map(elementValue).join(' ');
|
1126
1140
|
const alpha = this.textValues.slice(-1).map(elementValue).join(' ');
|
1127
|
-
colorString = Platform.StringUtilities.sprintf('%s(%s)',
|
1141
|
+
colorString = Platform.StringUtilities.sprintf('%s(%s)', this.colorFormat, [values, alpha].join(' / '));
|
1128
1142
|
}
|
1129
1143
|
|
1130
1144
|
const color = Common.Color.Color.parse(colorString);
|
@@ -1291,7 +1305,7 @@ export class PaletteGenerator {
|
|
1291
1305
|
private async processStylesheet(stylesheet: SDK.CSSStyleSheetHeader.CSSStyleSheetHeader): Promise<void> {
|
1292
1306
|
let text: string = (await stylesheet.requestContent()).content || '';
|
1293
1307
|
text = text.toLowerCase();
|
1294
|
-
const regexResult = text.match(/((?:rgb|hsl)a?\([^)]+\)|#[0-9a-f]{6}|#[0-9a-f]{3})/g) || [];
|
1308
|
+
const regexResult = text.match(/((?:rgb|hsl|hwb)a?\([^)]+\)|#[0-9a-f]{6}|#[0-9a-f]{3})/g) || [];
|
1295
1309
|
for (const c of regexResult) {
|
1296
1310
|
let frequency = this.frequencyMap.get(c) || 0;
|
1297
1311
|
this.frequencyMap.set(c, ++frequency);
|
@@ -180,6 +180,7 @@ function nextColorFormat(color: Common.Color.Color, curFormat: string): string {
|
|
180
180
|
// * original
|
181
181
|
// * rgb(a)
|
182
182
|
// * hsl(a)
|
183
|
+
// * hwb(a)
|
183
184
|
// * nickname (if the color has a nickname)
|
184
185
|
// * shorthex (if has short hex)
|
185
186
|
// * hex
|
@@ -195,6 +196,10 @@ function nextColorFormat(color: Common.Color.Color, curFormat: string): string {
|
|
195
196
|
|
196
197
|
case cf.HSL:
|
197
198
|
case cf.HSLA:
|
199
|
+
return !color.hasAlpha() ? cf.HWB : cf.HWBA;
|
200
|
+
|
201
|
+
case cf.HWB:
|
202
|
+
case cf.HWBA:
|
198
203
|
if (color.nickname()) {
|
199
204
|
return cf.Nickname;
|
200
205
|
}
|
@@ -550,6 +550,15 @@ span[is="dt-icon-label"] {
|
|
550
550
|
background: var(--override-force-white-icons-background) !important; /* stylelint-disable-line declaration-no-important */
|
551
551
|
}
|
552
552
|
|
553
|
+
.mediumicon-file-sync.purple-dot {
|
554
|
+
filter: hue-rotate(160deg);
|
555
|
+
}
|
556
|
+
|
557
|
+
.-theme-with-dark-background [is="ui-icon"].icon-invert.mediumicon-file-sync.purple-dot,
|
558
|
+
:host-context(.-theme-with-dark-background) [is="ui-icon"].icon-invert.mediumicon-file-sync.purple-dot {
|
559
|
+
filter: invert(80%) hue-rotate(350deg);
|
560
|
+
}
|
561
|
+
|
553
562
|
.expandable-inline-button {
|
554
563
|
background-color: var(--color-background-elevation-2);
|
555
564
|
color: var(--color-text-primary);
|
@@ -28,7 +28,7 @@
|
|
28
28
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
29
29
|
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
30
|
|
31
|
-
import {rgbaToHsla} from '../front_end/core/common/ColorUtils.js'; // eslint-disable-line rulesdir/es_modules_import
|
31
|
+
import {rgbaToHsla, rgbaToHwba} from '../front_end/core/common/ColorUtils.js'; // eslint-disable-line rulesdir/es_modules_import
|
32
32
|
|
33
33
|
import type {Bounds, PathCommands, Quad} from './common.js';
|
34
34
|
|
@@ -258,7 +258,7 @@ export function parseHexa(hexa: string): Array<number> {
|
|
258
258
|
return (hexa.match(/#(\w\w)(\w\w)(\w\w)(\w\w)/) || []).slice(1).map(c => parseInt(c, 16) / 255);
|
259
259
|
}
|
260
260
|
|
261
|
-
export function formatRgba(rgba: number[], colorFormat: 'rgb'|'hsl'): string {
|
261
|
+
export function formatRgba(rgba: number[], colorFormat: 'rgb'|'hsl'|'hwb'): string {
|
262
262
|
if (colorFormat === 'rgb') {
|
263
263
|
const [r, g, b, a] = rgba;
|
264
264
|
// rgb(r g b [ / a])
|
@@ -273,11 +273,18 @@ export function formatRgba(rgba: number[], colorFormat: 'rgb'|'hsl'): string {
|
|
273
273
|
a === 1 ? '' : ' / ' + Math.round(a * 100) / 100})`;
|
274
274
|
}
|
275
275
|
|
276
|
+
if (colorFormat === 'hwb') {
|
277
|
+
const [h, w, b, a] = rgbaToHwba(rgba);
|
278
|
+
// hwb(hdeg w b [ / a])
|
279
|
+
return `hwb(${Math.round(h * 360)}deg ${Math.round(w * 100)} ${Math.round(b * 100)}${
|
280
|
+
a === 1 ? '' : ' / ' + Math.round(a * 100) / 100})`;
|
281
|
+
}
|
282
|
+
|
276
283
|
throw new Error('NOT_REACHED');
|
277
284
|
}
|
278
285
|
|
279
286
|
export function formatColor(hexa: string, colorFormat: string): string {
|
280
|
-
if (colorFormat === 'rgb' || colorFormat === 'hsl') {
|
287
|
+
if (colorFormat === 'rgb' || colorFormat === 'hsl' || colorFormat === 'hwb') {
|
281
288
|
return formatRgba(parseHexa(hexa), colorFormat);
|
282
289
|
}
|
283
290
|
|
package/package.json
CHANGED