@itwin/itwinui-react
Version:
A react component library for iTwinUI
450 lines (449 loc) • 12.7 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', {
value: true,
});
function _export(target, all) {
for (var name in all)
Object.defineProperty(target, name, {
enumerable: true,
get: all[name],
});
}
_export(exports, {
ColorValue: function () {
return ColorValue;
},
isHslColor: function () {
return isHslColor;
},
isHsvColor: function () {
return isHsvColor;
},
isRgbColor: function () {
return isRgbColor;
},
});
const _define_property = require('@swc/helpers/_/_define_property');
const _numbers = require('../functions/numbers.js');
const scratchBytes = new Uint8Array(4);
const scratchUInt32 = new Uint32Array(scratchBytes.buffer);
const isRgbColor = (value) =>
'string' != typeof value && 'r' in value && 'g' in value && 'b' in value;
const isHslColor = (value) =>
'string' != typeof value && 'h' in value && 's' in value && 'l' in value;
const isHsvColor = (value) =>
'string' != typeof value && 'h' in value && 's' in value && 'v' in value;
class ColorValue {
static create(val) {
if (!val) return ColorValue.fromTbgr(0);
if (isRgbColor(val)) return ColorValue.fromRGB(val);
if (isHslColor(val)) return ColorValue.fromHSL(val);
if (isHsvColor(val)) return ColorValue.fromHSV(val);
if ('string' == typeof val)
return ColorValue.fromString(val, ColorValue.fromTbgr(0));
return ColorValue.fromTbgr(0);
}
toTbgr() {
return this._tbgr;
}
static fromTbgr(tbgr) {
return new ColorValue(tbgr);
}
static fromRgbt(red, green, blue, transparency) {
return this.fromTbgr(
this.computeTbgrFromComponents(red, green, blue, transparency),
);
}
static computeTbgrFromComponents(red, green, blue, transparency) {
scratchBytes[0] = red;
scratchBytes[1] = green;
scratchBytes[2] = blue;
scratchBytes[3] = transparency || 0;
return scratchUInt32[0];
}
static fromString(val, defaultColorIfNotParsed) {
let [tbgr, hue] = this.computeTbgrFromString(
val,
defaultColorIfNotParsed?.toTbgr(),
);
return new ColorValue(tbgr, hue);
}
static fromHSL(hsl) {
let alpha = hsl.a ?? 1;
return new ColorValue(
this.computeTbgrFromHSL(
hsl.h / 360,
hsl.s / 100,
hsl.l / 100,
Math.round((1 - alpha) * 255),
),
hsl.h,
);
}
static fromRGB(rgb) {
let alpha = rgb.a ?? 1;
return ColorValue.fromRgbt(
rgb.r,
rgb.g,
rgb.b,
Math.round((1 - alpha) * 255),
);
}
static fromHSV(hsv) {
let alpha = hsv.a ?? 1;
let transparency = Math.round((1 - alpha) * 255);
if (!hsv.s || -1 === hsv.h) {
let white = 0xff & Math.floor((255.0 * hsv.v) / 100.0 + 0.5 + 3.0e-14);
return ColorValue.fromRgbt(white, white, white, 0);
}
let dhue = hsv.h,
dsaturation = hsv.s,
dvalue = hsv.v;
if (360 === dhue) dhue = 0.0;
dhue /= 60;
let hueIntpart = Math.floor(dhue);
let hueFractpart = dhue - hueIntpart;
dvalue /= 100;
dsaturation /= 100;
let p = 0xff & Math.floor(dvalue * (1.0 - dsaturation) * 255.0 + 0.5);
let q =
0xff &
Math.floor(dvalue * (1.0 - dsaturation * hueFractpart) * 255.0 + 0.5);
let t =
0xff &
Math.floor(
dvalue * (1.0 - dsaturation * (1.0 - hueFractpart)) * 255.0 + 0.5,
);
let v = 0xff & Math.floor(255 * dvalue + 0.5);
let r = 0,
b = 0,
g = 0;
switch (hueIntpart) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
(r = q), (g = v);
b = p;
break;
case 2:
(r = p), (g = v);
b = t;
break;
case 3:
(r = p), (g = q);
b = v;
break;
case 4:
(r = t), (g = p);
b = v;
break;
case 5:
(r = v), (g = p);
b = q;
break;
}
return new ColorValue(
ColorValue.computeTbgrFromComponents(r, g, b, transparency),
hsv.h,
);
}
static computeTbgrFromString(val, defaultColorIfNotParsed) {
val = val.toLowerCase();
let m = /^((?:rgb|hsl)a?)\(([^\)]*)\)/.exec(val);
if (m) {
let color;
let name = m[1];
let components = m[2];
let hasPercent = (str) => '%' === str[str.length - 1];
let floatOrPercent = (str) => {
let v = parseFloat(str);
return (
255 *
(0, _numbers.getBoundedValue)(hasPercent(str) ? v / 100 : v, 0, 1)
);
};
let intOrPercent = (str) => {
let v = hasPercent(str)
? (parseFloat(str) / 100) * 255
: parseInt(str, 10);
return (0, _numbers.getBoundedValue)(v, 0, 255);
};
switch (name) {
case 'rgb':
case 'rgba':
color =
/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(
components,
);
if (color)
return [
this.computeTbgrFromComponents(
intOrPercent(color[1]),
intOrPercent(color[2]),
intOrPercent(color[3]),
'string' == typeof color[4]
? 255 - floatOrPercent(color[4])
: 0,
),
void 0,
];
break;
case 'hsl':
case 'hsla':
color =
/^(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(
components,
);
if (color) {
let h = parseFloat(color[1]);
let s = parseInt(color[2], 10) / 100;
let l = parseInt(color[3], 10) / 100;
let t =
'string' == typeof color[4] ? 255 - floatOrPercent(color[4]) : 0;
return [this.computeTbgrFromHSL(h / 360, s, l, t), h];
}
break;
}
} else if ((m = /^\#([A-Fa-f\d]+)$/.exec(val))) {
let hex = m[1];
let size = hex.length;
if (3 === size)
return [
this.computeTbgrFromComponents(
parseInt(hex.charAt(0) + hex.charAt(0), 16),
parseInt(hex.charAt(1) + hex.charAt(1), 16),
parseInt(hex.charAt(2) + hex.charAt(2), 16),
0,
),
void 0,
];
if (6 === size)
return [
this.computeTbgrFromComponents(
parseInt(hex.charAt(0) + hex.charAt(1), 16),
parseInt(hex.charAt(2) + hex.charAt(3), 16),
parseInt(hex.charAt(4) + hex.charAt(5), 16),
0,
),
void 0,
];
if (8 === size)
return [
this.computeTbgrFromComponents(
parseInt(hex.charAt(0) + hex.charAt(1), 16),
parseInt(hex.charAt(2) + hex.charAt(3), 16),
parseInt(hex.charAt(4) + hex.charAt(5), 16),
255 - parseInt(hex.charAt(6) + hex.charAt(7), 16),
),
void 0,
];
}
if (defaultColorIfNotParsed) return [defaultColorIfNotParsed, void 0];
throw new Error('unable to parse string into ColorValue');
}
static getColors(tbgr) {
scratchUInt32[0] = tbgr;
return {
b: scratchBytes[2],
g: scratchBytes[1],
r: scratchBytes[0],
t: scratchBytes[3],
};
}
getRgb(includeAlpha) {
scratchUInt32[0] = this._tbgr;
if (includeAlpha)
return (
(scratchBytes[0] << 24) +
(scratchBytes[1] << 16) +
(scratchBytes[2] << 8) +
(255 - scratchBytes[3])
);
return (scratchBytes[0] << 16) + (scratchBytes[1] << 8) + scratchBytes[2];
}
getAlpha() {
return ColorValue.getAlpha(this._tbgr);
}
static getAlpha(tbgr) {
scratchUInt32[0] = tbgr;
return 255 - scratchBytes[3];
}
toHexString(includeAlpha) {
if (includeAlpha) {
let value = this.getRgb(includeAlpha);
if (value < 0) value = 0xffffffff + value + 1;
return `#${`00000000${value.toString(16)}`.slice(-8)}`;
}
return `#${`000000${this.getRgb().toString(16)}`.slice(-6)}`;
}
static computeTbgrFromHSL(h, s, l, transparency = 0) {
let torgb = (p1, q1, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p1 + (q1 - p1) * 6 * t;
if (t < 0.5) return q1;
if (t < 2 / 3) return p1 + (q1 - p1) * 6 * (2 / 3 - t);
return p1;
};
let hue2rgb = (p1, q1, t) => Math.round(255 * torgb(p1, q1, t));
let modulo = (n, m) => ((n % m) + m) % m;
h = modulo(h, 1);
s = (0, _numbers.getBoundedValue)(s, 0, 1);
l = (0, _numbers.getBoundedValue)(l, 0, 1);
if (0 === s) {
l *= 255;
return this.computeTbgrFromComponents(l, l, l, transparency);
}
let p = l <= 0.5 ? l * (1 + s) : l + s - l * s;
let q = 2 * l - p;
return this.computeTbgrFromComponents(
hue2rgb(q, p, h + 1 / 3),
hue2rgb(q, p, h),
hue2rgb(q, p, h - 1 / 3),
transparency,
);
}
toHslColor() {
return {
...ColorValue.toHsl(this._tbgr),
...(void 0 != this._hue && {
h: this._hue,
}),
};
}
static toHsl(tbgr) {
let { r, g, b } = ColorValue.getColors(tbgr);
let red = r / 255;
let green = g / 255;
let blue = b / 255;
let cMin = Math.min(red, green, blue);
let cMax = Math.max(red, green, blue);
let delta = cMax - cMin;
let hue = 0;
let saturation = 0;
hue =
0 === delta
? 0
: red === cMax
? ((green - blue) / delta) % 6
: green === cMax
? (blue - red) / delta + 2
: (red - green) / delta + 4;
hue = Math.round(60 * hue);
if (hue < 0) hue += 360;
let lightness = (cMax + cMin) / 2;
saturation = 0 === delta ? 0 : delta / (1 - Math.abs(2 * lightness - 1));
saturation = Number((100 * saturation).toFixed(1));
lightness = Number((100 * lightness).toFixed(1));
return {
h: hue,
s: saturation,
l: lightness,
a: this.getAlpha(tbgr) / 255,
};
}
toRgbColor() {
let { r, g, b } = ColorValue.getColors(this._tbgr);
return {
r,
g,
b,
a: this.getAlpha() / 255,
};
}
toHsvColor() {
return {
...ColorValue.toHsv(this._tbgr),
...(void 0 != this._hue && {
h: this._hue,
}),
};
}
static toHsv(tbgr) {
let { r, g, b } = ColorValue.getColors(tbgr);
let red = r / 255;
let green = g / 255;
let blue = b / 255;
let cMin = Math.min(red, green, blue);
let cMax = Math.max(red, green, blue);
let delta = cMax - cMin;
let hue = 0;
hue =
0 === delta
? 0
: red === cMax
? ((green - blue) / delta) % 6
: green === cMax
? (blue - red) / delta + 2
: (red - green) / delta + 4;
hue = Math.round(60 * hue);
if (hue < 0) hue += 360;
let brightness = cMax;
let saturation = 0 === cMax ? 0 : delta / cMax;
saturation = Number((100 * saturation).toFixed(1));
brightness = Number((100 * brightness).toFixed(1));
return {
h: hue,
s: saturation,
v: brightness,
a: this.getAlpha(tbgr) / 255,
};
}
equals(other) {
return this._tbgr === other._tbgr;
}
static getFormattedColorNumber(value, precision = 1) {
if (0 === precision) Math.round(value).toString();
return Number(value.toFixed(precision)).toString();
}
toRgbString(includeAlpha) {
let rgb = this.toRgbColor();
let rgbString = `${rgb.r}, ${rgb.g}, ${rgb.b}`;
if (includeAlpha) {
let alpha = rgb.a ?? 1;
return `rgba(${rgbString}, ${ColorValue.getFormattedColorNumber(
alpha,
2,
)})`;
}
return `rgb(${rgbString})`;
}
toHslString(includeAlpha) {
let hsl = this.toHslColor();
let hslString = `${ColorValue.getFormattedColorNumber(
this._hue ?? hsl.h,
)}, ${ColorValue.getFormattedColorNumber(
hsl.s,
)}%, ${ColorValue.getFormattedColorNumber(hsl.l)}%`;
if (includeAlpha) {
let alpha = hsl.a ?? 1;
return `hsla(${hslString}, ${ColorValue.getFormattedColorNumber(
alpha,
2,
)})`;
}
return `hsl(${hslString})`;
}
toHsvString(includeAlpha) {
let hsv = this.toHsvColor();
let hsvString = `${this._hue ?? hsv.h}, ${hsv.s}%, ${hsv.v}%`;
if (includeAlpha) {
let alpha = hsv.a ?? 1;
return `hsva(${hsvString}, ${ColorValue.getFormattedColorNumber(
alpha,
2,
)})`;
}
return `hsv(${hsvString})`;
}
constructor(tbgr, hue) {
_define_property._(this, '_tbgr', void 0);
_define_property._(this, '_hue', void 0);
scratchUInt32[0] = tbgr;
this._tbgr = scratchUInt32[0];
this._hue = hue;
}
}