UNPKG

@fimbul-works/vec-color

Version:

A comprehensive, type-safe color manipulation library for TypeScript that provides a wide range of color space conversions, blending operations, and accessibility utilities.

138 lines (137 loc) 4.6 kB
import { hslToRGB, rgbToHSL } from "./hsl"; import { Vec3 } from "@fimbul-works/vec"; /** * Converts a hex string to RGB color * @param hex - Hex color string (3, 6, or 8 digits with optional #) * @returns Vec3 containing RGB values * @throws Error if hex string is invalid */ export function parseHex(hex) { hex = hex.replace(/^#/, ""); if (hex.length === 3) { hex = hex .split("") .map((char) => char + char) .join(""); } if (!/^[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/.test(hex)) { throw new Error("Invalid hex color string"); } const r = Number.parseInt(hex.slice(0, 2), 16) / 255; const g = Number.parseInt(hex.slice(2, 4), 16) / 255; const b = Number.parseInt(hex.slice(4, 6), 16) / 255; return new Vec3(r, g, b); } /** * Parses RGB/RGBA string into RGB color * @param rgb - RGB/RGBA string (e.g., "rgb(255, 128, 0)" or "rgba(255, 128, 0, 0.5)") * @returns Vec3 containing RGB values * @throws Error if RGB string is invalid */ export function parseRGB(rgb) { const match = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*[\d.]+)?\)$/); if (!match) { throw new Error("Invalid RGB/RGBA string"); } return new Vec3(Number.parseInt(match[1], 10) / 255, Number.parseInt(match[2], 10) / 255, Number.parseInt(match[3], 10) / 255); } /** * Parses HSL/HSLA string into RGB color * @param hsl - HSL/HSLA string (e.g., "hsl(120, 100%, 50%)" or "hsla(120, 100%, 50%, 0.5)") * @returns Vec3 containing RGB values * @throws Error if HSL string is invalid */ export function parseHSL(hsl) { const match = hsl.match(/^hsla?\((\d+),\s*(\d+)%,\s*(\d+)%(?:,\s*[\d.]+)?\)$/); if (!match) { throw new Error("Invalid HSL/HSLA string"); } const h = Number.parseInt(match[1], 10) / 360; const s = Number.parseInt(match[2], 10) / 100; const l = Number.parseInt(match[3], 10) / 100; return hslToRGB(new Vec3(h, s, l)); } /** * Parses a color string in any supported format * @param color - Color string in hex, RGB, RGBA, HSL, or HSLA format * @returns Vec3 containing RGB values * @throws Error if color string is invalid or format is unsupported */ export function parseColor(color) { color = color.trim().toLowerCase(); if (color.startsWith("#")) { return parseHex(color); } if (color.startsWith("rgb")) { return parseRGB(color); } if (color.startsWith("hsl")) { return parseHSL(color); } throw new Error("Unsupported color format"); } /** * Converts RGB color to hex string * @param color - Vec3 containing RGB values * @param includeHash - Whether to include # prefix (default: true) * @returns Hex color string */ export function toHex(color, includeHash = true) { const r = Math.round(color.x * 255) .toString(16) .padStart(2, "0"); const g = Math.round(color.y * 255) .toString(16) .padStart(2, "0"); const b = Math.round(color.z * 255) .toString(16) .padStart(2, "0"); return `${includeHash ? "#" : ""}${r}${g}${b}`; } /** * Converts RGB color to RGB string * @param color - Vec3 containing RGB values * @param alpha - Optional alpha value (0 to 1) * @returns RGB or RGBA color string */ export function toRGB(color, alpha) { const r = Math.round(color.x * 255); const g = Math.round(color.y * 255); const b = Math.round(color.z * 255); return alpha !== undefined ? `rgba(${r}, ${g}, ${b}, ${alpha.toFixed(3)})` : `rgb(${r}, ${g}, ${b})`; } /** * Converts RGB color to HSL string * @param color - Vec3 containing RGB values * @param alpha - Optional alpha value (0 to 1) * @returns HSL or HSLA color string */ export function toHSL(color, alpha) { const hsl = rgbToHSL(color); const h = Math.round(hsl.x * 360); const s = Math.round(hsl.y * 100); const l = Math.round(hsl.z * 100); return alpha !== undefined ? `hsla(${h}, ${s}%, ${l}%, ${alpha.toFixed(3)})` : `hsl(${h}, ${s}%, ${l}%)`; } /** * Converts RGB color to string representation * @param color - Vec3 containing RGB values * @param options - Formatting options * @returns Color string in specified format */ export function colorToString(color, options) { switch (options.format) { case "hex": return toHex(color, options.includeHash); case "rgb": return toRGB(color, options.alpha); case "hsl": return toHSL(color, options.alpha); default: throw new Error("Unsupported color format"); } }