Utilities
Documentation of utility functions in Saturon.
The "saturon/utils" module provides utility functions to configure and extend the Color class, enabling custom color types, spaces, plugins, and gamut mapping methods. These functions are essential for tailoring Saturon to specific use cases, such as registering new color formats, defining custom color spaces, or adding named colors. Import them as needed:
import {
configure,
use,
registerColorType,
registerColorBase,
registerColorFunction,
registerColorSpace,
registerNamedColor,
registerFitMethod,
} from "saturon/utils";Below are the detailed specifications for each utility function.
configure()
The configure() function merges user-provided configuration options into the global config object, allowing customization of Saturon's behavior, such as updating the current theme or changing the values of system colors.
Syntax
configure(options: Partial<Config>): voidoptions: A partial object containing configuration settings to merge into the globalconfig. Nested objects are merged recursively, while non-object values overwrite existing ones.- Returns:
void - Throws: None; invalid inputs are safely ignored.
Behavior
- Recursively merges the
optionsobject into the globalconfigusing a deep merge strategy. - For each key in
options:- If the value is a non-array object, creates a new object in
configif it doesn't exist and merges nested properties. - If the value is a non-object or array, overwrites the corresponding key in
config.
- If the value is a non-array object, creates a new object in
- Ignores
undefinedvalues to preserve existing configuration.
Example
import { configure } from "saturon/utils";
// Update theme to dark mode
configure({ theme: "dark" });
// Set default gamut mapping method
configure({ defaults: { fit: "css-gamut-map" } });
// Change system color values (case-sensitive)
configure({
systemColors: {
SelectedItem: [
[0, 120, 255], // For light theme
[0, 90, 255], // For dark theme
],
},
});
console.log(config); // Updated config with merged settingsuse()
The use() function registers one or more plugins to extend the Color class, enabling custom methods or behavior.
Syntax
use(...pluginFns: Plugin[]): voidpluginFns: One or more functions that receive theColorclass as an argument and enhance it (e.g., by adding methods to its prototype).- Returns:
void - Throws:
- If no plugins are provided.
- If a plugin is not a function.
Behavior
- Validates that at least one plugin is provided.
- Iterates through
pluginFns, checking each is a function. - Skips already registered plugins (tracked in
pluginsset) with a warning. - Executes each plugin, passing the
Colorclass, and adds it to thepluginsset. - Logs errors for failing plugins without interrupting the process.
Example
import { use } from "saturon/utils";
import { Color } from "saturon";
// Add a custom method to Color
const luminancePlugin = (ColorClass) => {
ColorClass.prototype.luminance = function () {
const [, luminance] = this.in("xyz-d65").toArray({ fit: "none", precision: null });
return luminance;
};
};
use(luminancePlugin);
const color = Color.from("rgb(255 87 51)");
console.log(color.luminance()); // ~0.28
// Register multiple plugins
const contrastPlugin = (ColorClass) => {
ColorClass.prototype.customContrast = function () {
/* ... */
};
};
use(luminancePlugin, contrastPlugin); // Skips duplicate luminancePlugin
// Invalid plugin
try {
use("not a function");
} catch (e) {
console.log(e.message); // Plugin at index 0 is not a function (received string)
}registerColorType()
The registerColorType() function registers a new <color> converter (e.g., device-cmyk, contrast-color) under a specified name, enabling support for custom color syntaxes in Color.from() and Color.to().
Syntax
registerColorType(name: string, converter: ColorConverter): voidname: A unique name for the<color>converter (e.g.,"color-at"). Whitespace is replaced with hyphens and lowercased.converter: An object implementingColorConverterwith:isValid: Function to validate the color string. It should be quick check to avoid performance issues, e.g., returningstring.startsWith("color-at(")for acolor-at()type.bridge: String specifying the bridge model (e.g.,"rgb","xyz-d65"). It should match a valid model incolorModels.toBridge: Function to convert parsed values to the bridge model. Never clip or fit values here; that should be handled by the engine using thecolorModelscomponent definitions.parse: Function to parse the color string into coordinates.fromBridge(optional): Function to convert bridge coordinates to the type's format. SincecolorTypesdon't have component definitions, you can clip or fit values here if needed.format(optional): Function to format coordinates as a string.
- Returns:
void - Throws:
- If
nameis already used. - If
converteris not a non-null object. - If required properties (
isValid,bridge,toBridge,parse) are missing or invalid. - If
fromBridgeorformatis provided but not a function. - If
fromBridgeandformatare not both provided or both omitted. - If
bridgedoes not match a valid model incolorModels.
- If
Note
If fromBridge and format are omitted, the converter is considered one-way (only supports Color.from()). This
is useful for non-functional syntaxes or when reverse conversion is not feasible, such as contrast-color().
Behavior
- Normalizes
nameby replacing whitespace with hyphens and lowercasing. - Validates
nameuniqueness againstcolorTypes. - Checks
converterfor required properties and types. - Ensures
fromBridgeandformatare either both present or both absent. - Registers the converter in
colorTypesand clears the conversion graph cache (cache.delete("graph")).
Example
import { registerColorType } from "saturon/utils";
import { Color } from "saturon";
// Register a custom color-at color type
registerColorType("color-at", {
isValid: (str) => str.startsWith("color-at(") && str.endsWith(")"),
bridge: "rgb",
toBridge: (coords) => coords,
parse: (str) => [],
});
const color = Color.from("color-at('06:00' skyblue, '12:00' gold, '18:00' orangered, '00:00' midnightblue)");
console.log(color.to("named-color")); // e.g., orangeredregisterColorBase()
The registerColorBase() function registers a new <color-base> converter (e.g., for non-functional color syntaxes) under a specified name, enabling support in Color.from() and Color.to().
Syntax
registerColorBase(name: string, converter: ColorConverter): voidname: A unique name for the<color-base>converter (e.g.,"custom-base"). Whitespace is replaced with hyphens and lowercased.converter: An object implementingColorConverterwith:isValid: Function to validate the color string. It should be quick check to avoid performance issues, e.g., returningstring.startsWith("wavelength(")for awavelength()type.bridge: String specifying the bridge model (e.g.,"rgb","xyz-d65"). It should match a valid model incolorModels.toBridge: Function to convert parsed values to the bridge model. Never clip or fit values here; that should be handled by the engine using thecolorModelscomponent definitions.parse: Function to parse the color string into coordinates.fromBridge(optional): Function to convert bridge coordinates to the type's format. SincecolorBasesdon't have component definitions, you can clip or fit values here if needed.format(optional): Function to format coordinates as a string.
- Returns:
void - Throws: Same as
registerColorType().
Behavior
- Normalizes
nameby replacing whitespace with hyphens and lowercasing. - Validates
nameuniqueness againstcolorTypes. - Checks
converterfor required properties. - Ensures
fromBridgeandformatare either both present or both absent. - Registers the converter in both
colorBasesandcolorTypes. - Clears the conversion graph cache (
cache.delete("graph")).
Example
import { registerColorBase } from "saturon/utils";
import { Color } from "saturon";
// Register a custom base color type
registerColorBase("wavelength", {
isValid: (str) => str.startsWith("wavelength("),
bridge: "xyz-d65",
toBridge: (coords) => coords,
parse: (str) => [],
fromBridge: (coords) => coords,
format: (coords) => `wavelength(${coords[0]})`,
});
const color = Color.from("wavelength(360)");
console.log(color.to("rgb")); // converted via xyz-d65 color space
console.log(color.to("wavelength")); // wavelength(360)registerColorFunction()
The registerColorFunction() function registers a new <color-function> converter (e.g., rgb(), hsl()) under a specified name, enabling support for functional color syntaxes with defined components.
Syntax
registerColorFunction(name: string, converter: ColorModelConverter): voidname: A unique name for the<color-function>converter (e.g.,"customfn"). Whitespace is removed and lowercased.converter: An object implementingColorModelConverterwith:components: Object mapping component names (e.g.,h,s,l) toComponentDefinitionobjects. Example forlch:{ l: { index: 0, value: "percentage", precision: 5 }, c: { index: 1, value: [0, 150], precision: 5 }, h: { index: 2, value: "angle", precision: 5 }, }bridge: String specifying the bridge model. It should match a valid model incolorModels.toBridge: Function to convert to the bridge model. Never clip or fit values here; that should be handled by the engine using the component definitions.fromBridge: Function to convert from the bridge model. Never clip or fit values here; that should be handled by the engine using the component definitions.targetGamut(optional): String ornullspecifying the target gamut.nullmeans the model has no limited gamut (e.g.,laborlch).supportsLegacy(optional): Boolean indicating legacy syntax support, e.g., allowing commas inrgb(). Defaults tofalse.alphaVariant(optional): String specifying the alpha variant (e.g.,"hsla"forhslin it's legacy syntax).
- Returns:
void - Throws:
- If
nameis already used. - If
converteris invalid. - If
componentsis not a non-null object. - If required properties are missing or invalid.
- If
targetGamutis not a string ornull. - If
supportsLegacyis not a boolean. - If
alphaVariantis not a string. - If
componentshas duplicate or invalid names.
- If
Behavior
- Normalizes
nameby removing whitespace and lowercasing. - Validates
nameuniqueness againstcolorTypes. - Normalizes
converter.componentskeys to lowercase. - Checks
converterfor required properties and optional properties. - Ensures
componentshas unique names and excludes"none". - Converts
converterto aColorConverterusingmodelConverterToColorConverter(). - Registers the converter in
colorModels,colorFunctions, andcolorTypes. - Clears the conversion graph cache (
cache.delete("graph")).
Example
import { registerColorFunction } from "saturon/utils";
import { Color } from "saturon";
// Register a custom color function
registerColorFunction("ictcp", {
components: {
i: { index: 0, value: [0, 1], precision: 5 },
ct: { index: 1, value: [-1, 1], precision: 5 },
cp: { index: 2, value: [-1, 1], precision: 5 },
},
bridge: "rec2020",
toBridge: (coords) => coords,
fromBridge: (coords) => coords,
});
const color = Color.from("ictcp(0.2 0.2 -0.1)");
console.log(color.to("rgb")); // converted via rec2020 color space
console.log(color.to("ictcp")); // ictcp(0.2 0.2 -0.1)registerColorSpace()
The registerColorSpace() function registers a new color space converter for the <color()> function (e.g., color(rec2100-linear 1 1 1)), enabling support for custom color spaces with matrix-based conversions.
Syntax
registerColorSpace(name: string, converter: ColorSpaceConverter): voidname: A unique name for the color space (e.g.,"rec2100-linear"). Whitespace is replaced with hyphens and lowercased.converter: An object implementingColorSpaceConverterwith:components: Array of component names (e.g.,["r", "g", "b"]).bridge: String specifying the bridge model (e.g.,"xyz-d65").toBridgeMatrix: 2D array of numbers for matrix conversion to the bridge model.fromBridgeMatrix: 2D array of numbers for matrix conversion from the bridge model.targetGamut(optional): Must benullif provided.nullmeans the model has no limited gamut (e.g.,xyz-d65orxyz-d50).toLinear(optional): Function for linearization.fromLinear(optional): Function for delinearization.
- Returns:
void - Throws:
- If
nameis already used. - If
converteris invalid. - If
componentsis not an array of strings. - If
bridgeis not a string. - If
toBridgeMatrixorfromBridgeMatrixis not a 2D array of numbers. - If
targetGamutis provided and notnull. - If
toLinearorfromLinearis provided but not a function.
- If
Behavior
- Normalizes
nameby replacing whitespace with hyphens and lowercasing. - Validates
nameuniqueness againstcolorTypes. - Checks
converterfor required properties and optional properties. - Converts
converterto aColorModelConverterusingspaceConverterToModelConverter()and then to aColorConverterusingmodelConverterToColorConverter(). - Registers the converter in
colorSpaces,colorModels,colorFunctions, andcolorTypes. - Clears the conversion graph cache (
cache.delete("graph")).
Example
import { registerColorSpace } from "saturon/utils";
import { MATRICES } from "saturon/math";
import { Color } from "saturon";
// Register a custom color space
registerColorSpace("rec2100-linear", {
components: ["r", "g", "b"],
bridge: "xyz-d65",
toBridgeMatrix: MATRICES.REC2020_to_XYZD65,
fromBridgeMatrix: MATRICES.XYZD65_to_REC2020,
});
const color = Color.from("color(rec2100-linear 0.7 0.3 0.1)");
console.log(color.to("rgb")); // Converted via xyz-d65 color space
console.log(color.to("rec2100-linear")); // color(rec2100-linear 0.7 0.3 0.1)Pro tip
You can use predefined matrices from MATRICES in saturon/math for common color spaces like Rec. 2020, Display
P3, etc.
registerNamedColor()
The registerNamedColor() function registers a new <named-color> with a specified RGB value, enabling its use in Color.from() and Color.to().
Syntax
registerNamedColor(name: string, rgb: [number, number, number]): voidname: A case-insensitive name for the color (letters only, e.g.,"brandblue").rgb: An array of exactly three numbers representing RGB values (e.g.,[255, 87, 51]).- Returns:
void - Throws:
- If
rgbis not an array of three numbers. - If
nameis already registered. - If
rgbis already registered under another name.
- If
Behavior
- Normalizes
nameby removing non-letters and lowercasing. - Validates
rgbas an array of three numbers. - Checks
nameandrgbuniqueness againstnamedColors. - Registers the
rgbvalue innamedColorsundername.
Example
import { registerNamedColor } from "saturon/utils";
import { Color } from "saturon";
// Register a custom named color
registerNamedColor("brandblue", [0, 128, 255]);
const color = Color.from("brandblue");
console.log(color.to("rgb")); // rgb(0 128 255)registerFitMethod()
The registerFitMethod() function registers a new gamut mapping method for use in Color.to(), Color.toString(), Color.toArray(), Color.toObject(), and Color.within().
Syntax
registerFitMethod(name: string, method: FitFunction): voidname: A unique name for the fit method (e.g.,"custom-fit"). Whitespace is replaced with hyphens and lowercased.method: A function implementing the gamut mapping logic, accepting coordinates, model, and options.- Returns:
void - Throws:
- If
nameis already used. - If
methodis not a function.
- If
Behavior
- Normalizes
nameby replacing whitespace with hyphens and lowercasing. - Validates
nameuniqueness againstfitMethods. - Checks that
methodis a function. - Registers the
methodinfitMethods.
Example
import { registerFitMethod } from "saturon/utils";
import { Color } from "saturon";
// Register a custom fit method
registerFitMethod("cam16-ucs", (coords, model, options) => {
/* ... */
});
const color = Color.from("color(display-p3 1.5 0 0)").in("rgb");
console.log(color.toArray({ fit: "cam16-ucs" })); // [255, 0, 0, 1]register()
The register() function bulk registers multiple converters of a specified type (e.g., color functions, named colors, fit methods) in a single call. It's ideal for plugins, design tokens, or theme systems that need to register many custom colors or spaces at once.
Syntax
register<T extends ConverterType>(type: T, entries: ConverterEntry<T>[]): voidtype: A string specifying the converter type to register. Must be one of:"color-type""color-base""color-function""color-space""named-color""fit-method"
entries: An array of objects with:name: The unique name for the converter.value: The converter configuration (type-safe based ontype).
- Returns:
void - Throws: Propagates any errors from the underlying registration function (e.g., duplicate name, invalid converter).
Behavior
- Looks up the appropriate registration function from
converterRegistrybased ontype. - Iterates through
entriesand calls the corresponding function (registerColorType,registerColorSpace, etc.) for each.
Example
import { register } from "saturon/utils";
import { Color } from "saturon";
// Bulk register named colors (e.g., brand palette)
register("named-color", [
{ name: "brand-primary", value: [0, 122, 255] },
{ name: "brand-secondary", value: [108, 117, 125] },
{ name: "success", value: [40, 167, 69] },
]);
// Bulk register fit methods
register("fit-method", [
{ name: "soft-clip", value: (coords) => coords.map((c) => Math.max(0, Math.min(255, c * 0.95))) },
{ name: "hard-clip", value: (coords) => coords.map((c) => Math.max(0, Math.min(255, c))) },
]);