@zag-js/color-utils
Version:
Color utilities for zag.js
143 lines (141 loc) • 4.8 kB
JavaScript
import {
__publicField
} from "./chunk-QZ7TP4HQ.mjs";
// src/hsb-color.ts
import { clampValue, mod, toFixedNumber } from "@zag-js/utils";
import { Color } from "./color.mjs";
import { HSLColor } from "./hsl-color.mjs";
import { RGBColor } from "./rgb-color.mjs";
var HSB_REGEX = /hsb\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%)\)|hsba\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d(.\d+)?)\)/;
var _HSBColor = class _HSBColor extends Color {
constructor(hue, saturation, brightness, alpha) {
super();
__publicField(this, "hue", hue);
__publicField(this, "saturation", saturation);
__publicField(this, "brightness", brightness);
__publicField(this, "alpha", alpha);
}
static parse(value) {
let m;
if (m = value.match(HSB_REGEX)) {
const [h, s, b, a] = (m[1] ?? m[2]).split(",").map((n) => Number(n.trim().replace("%", "")));
return new _HSBColor(mod(h, 360), clampValue(s, 0, 100), clampValue(b, 0, 100), clampValue(a ?? 1, 0, 1));
}
}
toString(format = "css") {
switch (format) {
case "css":
return this.toHSL().toString("css");
case "hex":
return this.toRGB().toString("hex");
case "hexa":
return this.toRGB().toString("hexa");
case "hsb":
return `hsb(${this.hue}, ${toFixedNumber(this.saturation, 2)}%, ${toFixedNumber(this.brightness, 2)}%)`;
case "hsba":
return `hsba(${this.hue}, ${toFixedNumber(this.saturation, 2)}%, ${toFixedNumber(this.brightness, 2)}%, ${this.alpha})`;
case "hsl":
return this.toHSL().toString("hsl");
case "rgb":
return this.toRGB().toString("rgb");
default:
return this.toFormat(format).toString(format);
}
}
toFormat(format) {
switch (format) {
case "hsba":
return this;
case "hsla":
return this.toHSL();
case "rgba":
return this.toRGB();
default:
throw new Error("Unsupported color conversion: hsb -> " + format);
}
}
/**
* Converts a HSB color to HSL.
* Conversion formula adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_HSL.
* @returns An HSLColor object.
*/
toHSL() {
let saturation = this.saturation / 100;
let brightness = this.brightness / 100;
let lightness = brightness * (1 - saturation / 2);
saturation = lightness === 0 || lightness === 1 ? 0 : (brightness - lightness) / Math.min(lightness, 1 - lightness);
return new HSLColor(
toFixedNumber(this.hue, 2),
toFixedNumber(saturation * 100, 2),
toFixedNumber(lightness * 100, 2),
toFixedNumber(this.alpha, 2)
);
}
/**
* Converts a HSV color value to RGB.
* Conversion formula adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative.
* @returns An RGBColor object.
*/
toRGB() {
let hue = this.hue;
let saturation = this.saturation / 100;
let brightness = this.brightness / 100;
let fn = (n, k = (n + hue / 60) % 6) => brightness - saturation * brightness * Math.max(Math.min(k, 4 - k, 1), 0);
return new RGBColor(
Math.round(fn(5) * 255),
Math.round(fn(3) * 255),
Math.round(fn(1) * 255),
toFixedNumber(this.alpha, 2)
);
}
clone() {
return new _HSBColor(this.hue, this.saturation, this.brightness, this.alpha);
}
getChannelFormatOptions(channel) {
switch (channel) {
case "hue":
return { style: "unit", unit: "degree", unitDisplay: "narrow" };
case "saturation":
case "brightness":
case "alpha":
return { style: "percent" };
default:
throw new Error("Unknown color channel: " + channel);
}
}
formatChannelValue(channel, locale) {
let options = this.getChannelFormatOptions(channel);
let value = this.getChannelValue(channel);
if (channel === "saturation" || channel === "brightness") {
value /= 100;
}
return new Intl.NumberFormat(locale, options).format(value);
}
getChannelRange(channel) {
switch (channel) {
case "hue":
return { minValue: 0, maxValue: 360, step: 1, pageSize: 15 };
case "saturation":
case "brightness":
return { minValue: 0, maxValue: 100, step: 1, pageSize: 10 };
case "alpha":
return { minValue: 0, maxValue: 1, step: 0.01, pageSize: 0.1 };
default:
throw new Error("Unknown color channel: " + channel);
}
}
toJSON() {
return { h: this.hue, s: this.saturation, b: this.brightness, a: this.alpha };
}
getFormat() {
return "hsba";
}
getChannels() {
return _HSBColor.colorChannels;
}
};
__publicField(_HSBColor, "colorChannels", ["hue", "saturation", "brightness"]);
var HSBColor = _HSBColor;
export {
HSBColor
};