saturon 0.2.2 → 0.3.0

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/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2025 Ganemede Labs
1
+ Copyright © 2026 Ganemede Labs
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
4
 
package/README.md CHANGED
@@ -22,7 +22,7 @@ A runtime-extensible JavaScript library for parsing, converting, and manipulatin
22
22
  - Infinite nested color functions (e.g. `color-mix(...)` inside `light-dark(...)`)
23
23
  - Converts between all modern color spaces (OKLab, Display-P3, Rec.2020, etc.)
24
24
  - High-precision color math for serious colorimetry
25
- - Powerful plugin system for custom color spaces and functions
25
+ - Powerful plugin system for custom color spaces and syntaxes
26
26
  - Supports complex color syntaxes like `color(from hsl(240 none calc(-infinity) / 0.5) display-p3 r calc(g + b) 100 / alpha)`
27
27
 
28
28
  ## 🔧 Installation
@@ -77,14 +77,15 @@ console.log(hwb.toString()); // → hwb(100 7 20)
77
77
 
78
78
  ```js
79
79
  const red = Color.from("hsl(0, 100%, 50%)");
80
- const mixed = red.mix("hsl(120, 100%, 50%)");
80
+ const green = Color.from("hsl(120, 100%, 50%)");
81
+ const mixed = Color.mix({ in: "hsl", colors: [{ color: red }, { color: green }] });
81
82
  console.log(mixed.toString()); // → hsl(60 100 50)
82
83
  ```
83
84
 
84
85
  ### New Named Color Registration
85
86
 
86
87
  ```js
87
- registerNamedColor("sunsetblush", [255, 94, 77]);
88
+ register("named-color", [{ name: "sunsetblush", value: [255, 94, 77] }]);
88
89
  const rgb = Color.from("rgb(255, 94, 77)");
89
90
  console.log(rgb.to("named-color")); // → sunsetblush
90
91
  ```
@@ -103,7 +104,7 @@ const converter = {
103
104
  fromBridge: (rgb: number[]) => [/* i, ct, cp */],
104
105
  };
105
106
 
106
- registerColorFunction("ictcp", converter);
107
+ register("color-function", [{ name: "ictcp", value: converter }]);
107
108
  const ictcp = Color.from("ictcp(0.2 0.2 -0.1)");
108
109
  console.log(ictcp.to("rgb")); // → rgb(6 7 90)
109
110
  ```
package/dist/Color.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Component, MixOptions, ColorType, OutputType, FormattingOptions, NamedColor, ColorSpace, FitMethod, ColorModel, RandomOptions, GetOptions } from "./types.js";
1
+ import type { Component, MixOptions, OutputType, FormattingOptions, NamedColor, ColorSpace, FitMethod, ColorModel, RandomOptions, ComponentOptions, MixItem, IsValidOptions } from "./types.js";
2
2
  /**
3
3
  * The `Color` class represents a dynamic CSS color object, allowing for the manipulation
4
4
  * and retrieval of colors in various formats (e.g., RGB, HEX, HSL).
@@ -23,24 +23,25 @@ export declare class Color<M extends ColorModel = ColorModel> {
23
23
  static from(color: `lch(${string})`): Color<"lch">;
24
24
  static from(color: `oklab(${string})`): Color<"oklab">;
25
25
  static from(color: `oklch(${string})`): Color<"oklch">;
26
+ static from(color: `color(srgb ${string})`): Color<"srgb">;
27
+ static from(color: `color(srgb-linear ${string})`): Color<"srgb-linear">;
28
+ static from(color: `color(display-p3 ${string})`): Color<"display-p3">;
29
+ static from(color: `color(rec2020 ${string})`): Color<"rec2020">;
30
+ static from(color: `color(a98-rgb ${string})`): Color<"a98-rgb">;
31
+ static from(color: `color(prophoto-rgb ${string})`): Color<"prophoto-rgb">;
32
+ static from(color: `color(xyz-d65 ${string})`): Color<"xyz-d65">;
33
+ static from(color: `color(xyz-d50 ${string})`): Color<"xyz-d50">;
34
+ static from(color: `color(xyz ${string})`): Color<"xyz">;
26
35
  static from(color: string): Color<any>;
27
36
  static from<T extends ColorModel = ColorModel>(color: string): Color<T>;
28
37
  /**
29
- * Returns the detected color type, or `undefined` if unrecognized.
30
- *
31
- * @param color - Color string to analyze.
32
- * @param strict - Whether to validate full round-trip conversion.
33
- */
34
- static type(color: string, strict?: boolean): "hex-color" | "rgb" | "xyz-d65" | "xyz-d50" | "lab" | "oklab" | "srgb" | "srgb-linear" | "display-p3" | "rec2020" | "a98-rgb" | "prophoto-rgb" | "xyz" | "hsl" | "hwb" | "lch" | "oklch" | "named-color" | "color-mix" | "transparent" | "currentColor" | "system-color" | "contrast-color" | "device-cmyk" | "light-dark" | undefined;
35
- /**
36
- * Validates a color string, optionally for a specific type.
38
+ * Validates a color string.
37
39
  *
38
40
  * @param color - Color string to check.
39
- * @param type - Optional color type.
41
+ * @param options - Validation options.
40
42
  * @returns `true` if valid, otherwise `false`.
41
43
  */
42
- static isValid(color: string, type?: ColorType): boolean;
43
- static isValid(color: string, type?: string): boolean;
44
+ static isValid(color: string, options?: IsValidOptions): boolean;
44
45
  /**
45
46
  * Generates a random `Color` instance.
46
47
  *
@@ -50,6 +51,15 @@ export declare class Color<M extends ColorModel = ColorModel> {
50
51
  * @throws If an invalid component is specified.
51
52
  */
52
53
  static random<M extends ColorModel = ColorModel>(options?: RandomOptions<M>): Color<M>;
54
+ /**
55
+ * Statically mixes multiple colors together by specified percentages.
56
+ * Fully compliant with CSS Color Module Level 5 specification constraints.
57
+ *
58
+ * @param colors - Array of MixItems containing colors and optional percentages.
59
+ * @param options - Options containing the interpolation space and hue policy.
60
+ * @returns A new `Color` instance representing the mixed color.
61
+ */
62
+ static mix<M extends ColorModel = "oklab">(colors: MixItem[], options: MixOptions<M>): Color<M>;
53
63
  /**
54
64
  * Converts this color to a specified format.
55
65
  *
@@ -79,20 +89,22 @@ export declare class Color<M extends ColorModel = ColorModel> {
79
89
  * Returns the color as an object of component values.
80
90
  *
81
91
  * @param options - Optional retrieval options.
82
- * @returns An object mapping each component (and alpha) to its numeric value.
92
+ * @returns An object mapping each component to its numeric value.
83
93
  * @throws If the model has no defined components.
84
94
  */
85
- toObject(options?: GetOptions): { [key in Component<M>]: number; };
95
+ toObject(options?: ComponentOptions): {
96
+ [key in Component<M>]: number;
97
+ };
86
98
  /**
87
99
  * Returns the color as an array of component values, optionally normalized and fitted.
88
100
  *
89
101
  * @param options - Conversion configuration.
90
- * @returns An array of normalized color components and alpha.
102
+ * @returns An array of normalized color components.
91
103
  * @throws If the model has no defined components.
92
104
  */
93
- toArray(options?: GetOptions): number[];
105
+ toArray(options?: ComponentOptions): number[];
94
106
  /**
95
- * Returns a new `Color` instance with updated or replaced component values.
107
+ * Creates a new Color instance with modified component values.
96
108
  *
97
109
  * This method supports several flexible update styles:
98
110
  *
@@ -131,29 +143,29 @@ export declare class Color<M extends ColorModel = ColorModel> {
131
143
  * color.with(({ r, g, b }) => [r * 0.5, g * 0.5, b * 0.5, 1]);
132
144
  * ```
133
145
  *
134
- * @param values - Either:
135
- * - a partial object of component values,
136
- * - an updater function returning an object or array,
137
- * - or an array of new coordinates.
138
- * @returns A new `Color` instance with updated values.
139
- * @throws If the color model has no defined components.
146
+ * @template M - The color model type
147
+ * @param values - The new component values to apply. Can be:
148
+ * - A partial object mapping component names to numbers or update functions
149
+ * - A function that receives current components and returns partial updates or an array of values
150
+ * - An array of new values corresponding to component indices
151
+ * @param normalized - Whether to normalize component values to their valid ranges. Defaults to `true`.
152
+ * When `false`, values are not clamped or validated against their ranges.
153
+ * @returns A new Color instance with the updated component values
140
154
  */
141
155
  with(values: Partial<{
142
- [K in Component<M> | "alpha"]: number | ((prev: number) => number);
156
+ [K in Component<M>]: number | ((prev: number) => number);
143
157
  }> | ((components: {
144
- [K in Component<M> | "alpha"]: number;
158
+ [K in Component<M>]: number;
145
159
  }) => Partial<{
146
- [K in Component<M> | "alpha"]: number;
160
+ [K in Component<M>]: number;
147
161
  }> | (number | undefined)[]) | (number | undefined)[]): Color<M>;
148
162
  /**
149
- * Mixes this color with another by a specified amount.
163
+ * Creates a new Color instance with values fitted to the color model's gamut.
150
164
  *
151
- * @param other - The color to mix with. Can be a string or a `Color` instance.
152
- * @param options - Options for how the colors are mixed.
153
- * @returns A new `Color` instance representing the mixed color.
154
- * @throws If the color model does not have defined components.
165
+ * @param options - Configuration options for fitting
166
+ * @returns A new Color instance with fitted values
155
167
  */
156
- mix(other: Color<ColorModel> | string, options?: MixOptions): Color<M>;
168
+ fit(options?: ComponentOptions): Color<M>;
157
169
  /**
158
170
  * Fits this color within the specified gamut using a given method.
159
171
  *
@@ -166,18 +178,18 @@ export declare class Color<M extends ColorModel = ColorModel> {
166
178
  /**
167
179
  * Calculates the WCAG 2.1 contrast ratio between this color and another.
168
180
  *
169
- * @param other - The comparison color (instance or string).
181
+ * @param other - The comparison Color instance.
170
182
  * @returns Contrast ratio from 1 to 21.
171
183
  *
172
184
  * @remarks
173
185
  * - Ratios ≥ 4.5 are generally accessible for normal text.
174
186
  * - For perceptual accuracy, consider using APCA instead.
175
187
  */
176
- contrast(other: Color<ColorModel> | string): number;
188
+ contrast(other: Color<ColorModel>): number;
177
189
  /**
178
190
  * Calculates the color difference (ΔEOK) between the current color and another color using the OKLAB color space.
179
191
  *
180
- * @param other - The other color to compare against (as a Color instance or string).
192
+ * @param other - The other Color instance to compare against.
181
193
  * @returns A number in range (0-1) (smaller indicates more similar colors).
182
194
  *
183
195
  * @remarks
@@ -185,36 +197,36 @@ export declare class Color<M extends ColorModel = ColorModel> {
185
197
  * OKLAB's perceptual uniformity allows for a straightforward distance calculation without additional weighting.
186
198
  * The result is normalized by a factor of 100 to align with OKLAB's L range (0-1) and approximate the JND scale.
187
199
  */
188
- deltaEOK(other: Color<ColorModel> | string): number;
200
+ deltaEOK(other: Color<ColorModel>): number;
189
201
  /**
190
202
  * Calculates the color difference (ΔE) between two colors using the CIE76 formula.
191
203
  * This is a simple Euclidean distance in LAB color space.
192
204
  *
193
- * @param other - The other color to compare against (as a Color instance or string).
205
+ * @param other - The other Color instance to compare against.
194
206
  * @returns A number in range (0-1) (smaller indicates more similar colors).
195
207
  */
196
- deltaE76(other: Color<ColorModel> | string): number;
208
+ deltaE76(other: Color<ColorModel>): number;
197
209
  /**
198
210
  * Calculates the color difference (ΔE) between two colors using the CIE94 formula.
199
211
  * This method improves perceptual accuracy over CIE76 by applying weighting factors.
200
212
  *
201
- * @param other - The other color to compare against (as a Color instance or string).
213
+ * @param other - The other Color instance to compare against.
202
214
  * @returns A number in range (0-1) (smaller indicates more similar colors).
203
215
  */
204
- deltaE94(other: Color<ColorModel> | string): number;
216
+ deltaE94(other: Color<ColorModel>): number;
205
217
  /**
206
218
  * Calculates the color difference (ΔE) between two colors using the CIEDE2000 formula.
207
219
  * This is the most perceptually accurate method, accounting for interactions between hue, chroma, and lightness.
208
220
  *
209
- * @param other - The other color to compare against (as a Color instance or string).
221
+ * @param other - The other Color instance to compare against.
210
222
  * @returns A number in range (0-1) (smaller indicates more similar colors).
211
223
  */
212
- deltaE2000(other: Color<ColorModel> | string): number;
224
+ deltaE2000(other: Color<ColorModel>): number;
213
225
  /**
214
226
  * Checks numeric equality with another color within a tolerance.
215
227
  *
216
- * @param other - Color or string to compare.
217
- * @param epsilon - Allowed floating-point difference (default: 1e-5).
228
+ * @param other - Color instnace to compare.
229
+ * @param epsilon - Allowed floating-point difference (defaults to the value of `EPSILON` in `"saturon/math"`).
218
230
  * @returns `true` if equal within tolerance.
219
231
  *
220
232
  * @remarks
@@ -228,12 +240,12 @@ export declare class Color<M extends ColorModel = ColorModel> {
228
240
  * - {@link deltaE94} (weighted improvements over LAB)
229
241
  * - {@link deltaE2000} (most accurate, accounts for perceptual interactions)
230
242
  */
231
- equals(other: Color<ColorModel> | string, epsilon?: number): boolean;
243
+ equals(other: Color<ColorModel>, epsilon?: number): boolean;
232
244
  /**
233
245
  * Determines whether this color lies within a given gamut.
234
246
  *
235
247
  * @param gamut - Target color space.
236
- * @param epsilon - Floating-point tolerance (default: 1e-5).
248
+ * @param epsilon - Floating-point tolerance (defaults to the value of `EPSILON` in `"saturon/math"`).
237
249
  * @returns `true` if inside gamut, else `false`.
238
250
  */
239
251
  inGamut(gamut: ColorSpace | string, epsilon?: number): boolean;