Socket
Socket
Sign inDemoInstall

colorjs.io

Package Overview
Dependencies
Maintainers
3
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

colorjs.io - npm Package Compare versions

Comparing version 0.4.5 to 0.5.0

dist/color-fn.cjs

80

package.json
{
"name": "colorjs.io",
"version": "0.4.5",
"version": "0.5.0",
"description": "Let’s get serious about color",
"files": [
"dist/color.cjs",
"dist/color.cjs.map",
"dist/color.js",
"dist/color.js.map",
"dist/color.legacy.cjs",
"dist/color.legacy.cjs.map",
"dist/color.legacy.js",
"dist/color.legacy.js.map",
"dist/",
"src/",
"types/dist/",
"types/src/",
"types/index.d.ts"
"types/index.d.ts",
"types/index.d.cts"
],
"exports": {
".": {
"types": "./types/index.d.ts",
"import": "./dist/color.js",
"require": "./dist/color.cjs"
"import": {
"types": "./types/index.d.ts",
"default": "./dist/color.js"
},
"require": {
"types": "./types/index.d.cts",
"default": "./dist/color.cjs"
}
},
"./fn": {
"types": "./types/src/index-fn.d.ts",
"import": "./src/index-fn.js"
"import": {
"types": "./types/src/index-fn.d.ts",
"default": "./src/index-fn.js"
},
"require": {
"types": "./types/src/index-fn.d.cts",
"default": "./dist/color-fn.cjs"
}
},

@@ -46,5 +50,7 @@ "./dist/*": "./dist/*"

"scripts": {
"test": "open tests/",
"dtslint": "dtslint types",
"lint": "eslint . --fix --ext .js --ext .ts --ext .js --ext .cjs",
"test": "npx htest ./test",
"dtslint": "dtslint --expectOnly types",
"eslint": "eslint . --ext .js --ext .ts --ext .cjs",
"lint": "run-s build:space-accessors \"eslint -- --fix\" dtslint",
"lint:ci": "run-s build:space-accessors \"eslint -- --max-warnings 0\" dtslint",
"build:css": "npx postcss \"**/*.postcss\" --base . --dir . --ext .css --config postcss.config.cjs",

@@ -54,8 +60,10 @@ "build:html": "npx @11ty/eleventy --config=.eleventy.cjs",

"build:js:legacy": "rollup -c rollup.legacy.config.js",
"build": "npm run build:html && npm run build:css && npm run build:js && npm run build:js:legacy",
"build:space-accessors": "node ./scripts/generate-space-accessor-types.js",
"build": "run-s build:html build:css build:js build:js:legacy build:space-accessors",
"watch:css": "npx postcss \"**/*.postcss\" --base . --dir . --ext .css --config postcss.config.cjs --watch",
"watch:html": "npx @11ty/eleventy --config=.eleventy.cjs --watch",
"watch:js": "rollup -c --watch",
"watch": "npm run watch:css & npm run watch:html & npm run watch:js",
"prepack": "npm run build"
"watch": "run-p watch:*",
"prepack": "npm run build",
"release": "release-it"
},

@@ -80,18 +88,24 @@ "repository": {

"@11ty/eleventy": "^2.0",
"@babel/core": "^7.21.4",
"@babel/preset-env": "^7.21.4",
"@definitelytyped/dtslint": "latest",
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^24.1.0",
"@rollup/plugin-node-resolve": "^15.0.2",
"@rollup/plugin-terser": "^0.4.1",
"@typescript-eslint/parser": "^5.59.1",
"@babel/core": "^7.24.0",
"@babel/preset-env": "^7.24.0",
"@definitelytyped/dtslint": "0.0.182",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"@stylistic/eslint-plugin": "latest",
"@typescript-eslint/eslint-plugin": "latest",
"@typescript-eslint/parser": "latest",
"acorn": "latest",
"core-js": "^3.30.1",
"core-js": "^3.36.0",
"eslint": "latest",
"htest.dev": "^0.0.9",
"mathjs": "^12.4.0",
"npm-run-all": "^4.1.5",
"postcss": "latest",
"postcss-cli": "latest",
"postcss-nesting": "latest",
"rollup": "^3.21",
"typescript": "^5.0.4"
"release-it": "^17.1.1",
"rollup": "^4.12.0",
"typescript": "^5.3.3"
},

@@ -98,0 +112,0 @@ "sideEffects": [

<header class="readme-only">
# Color.js: Let’s get serious about color
[![Netlify Status](https://api.netlify.com/api/v1/badges/a6208d72-3d48-43ab-9132-b9f31f828609/deploy-status)](https://app.netlify.com/sites/colorjs/deploys)
[![npm](https://img.shields.io/npm/dw/colorjs.io)](https://npmjs.com/package/colorjs.io)
- [Official website](https://colorjs.io)
- [Contribution guide](CONTRIBUTING.md)
[Official website](https://colorjs.io) • [Contribution guide](CONTRIBUTING.md)
Features:
Color.js is a color conversion and modification library originally created by two of the editors of the CSS Color specifications: Lea Verou and Chris Lilley.
They continue to work on it, but are also joined by an exceptional small grassroots team of co-maintainers.
## Features
- **Color space agnostic**: Each color object is basically a list of coords and a color space reference. Operations are color space agnostic.

@@ -23,3 +26,3 @@ Modules for <a href="https://colorjs.io/docs/spaces.html">a wide variety of color spaces</a>,

- **Readable, object-oriented API**: Color objects for multiple operations on the same color, and static `Color.something()` functions for one-off calculations
- **Modular & Extensible**: Use only what you need, or a bundle. Client-side or Node. Deep extensibility with <a href="https://colorjs.io/api/#Hooks-hooks.js">hooks</a>. </p>
- **Modular & Extensible**: Use only what you need, or a bundle. Client-side or Node. Deep extensibility with <a href="https://colorjs.io/api/#Hooks-hooks.js">hooks</a>.
- **Fast & efficient**: <a href="https://colorjs.io/docs/procedural.html">Procedural, tree-shakeable API</a> available for performance sensitive tasks and reduced bundle size

@@ -29,2 +32,14 @@

<section>
## Impact
- Has been used to create demos for several W3C specifications
- Has been used by browsers to test their CSS Color 4/5 implementations
- Over [2 million total npm downloads](https://limonte.dev/total-npm-downloads/?package=colorjs.io)!
- Used by several [high impact projects](https://www.npmjs.com/browse/depended/colorjs.io), including [Sass](https://sass-lang.com/), [Open Props](https://open-props.style/), [axe](https://www.deque.com/axe/) accessibility testing engine, and [OddContrast](https://www.oddcontrast.com/) and [CSS HD Gradients](https://gradient.style/) color tools
- Parts of Color.js’s API are used as a testing ground for the design of a [native `Color` object for the Web platform](https://github.com/wicg/color-api).
</section>
<section class="cn-ignore">

@@ -34,10 +49,6 @@

Install via npm:
Color.js is designed make simple things easy, and complex things possible, and that extends to installation as well.
```
npm install colorjs.io
```
For quick experiments, you can just import Color.js directly from the CDN (kindly provided by the awesome folks at [Netlify](https://netlify.com)) with all modules included:
For quick experiments, you can just import Color.js directly from the CDN with all modules included:
```js

@@ -47,4 +58,13 @@ import Color from "https://colorjs.io/dist/color.js";

You can also import specific modules:
You can also install via npm if you’d prefer:
```
npm install colorjs.io
```
Whether you’re using NPM, the CDN, or local files, Color.js allows you to also import specific modules by directly importing from `src`:
- `https://colorjs.io/src/` for the CDN
- `node_modules/colorjs.io/src/ for NPM
For example:
```js

@@ -59,3 +79,5 @@ import Color from "https://colorjs.io/src/color.js";

Or, if you'd rather just have `Color` as a global variable, the classic way, just include the following script in your HTML:
Are you old school and prefer to simply have a global `Color` variable?
We’ve got you covered!
Just include the following script in your HTML:

@@ -62,0 +84,0 @@ ```html

@@ -24,3 +24,3 @@ import hooks from "./hooks.js";

if (!W1 || !W2) {
throw new TypeError(`Missing white point to convert ${!W1? "from" : ""}${!W1&&!W2? "/" : ""}${!W2? "to" : ""}`);
throw new TypeError(`Missing white point to convert ${!W1 ? "from" : ""}${!W1 && !W2 ? "/" : ""}${!W2 ? "to" : ""}`);
}

@@ -40,5 +40,5 @@

env.M = [
[ 1.0479298208405488, 0.022946793341019088, -0.05019222954313557 ],
[ 0.029627815688159344, 0.990434484573249, -0.01707382502938514 ],
[ -0.009243058152591178, 0.015055144896577895, 0.7518742899580008 ]
[ 1.0479297925449969, 0.022946870601609652, -0.05019226628920524 ],
[ 0.02962780877005599, 0.9904344267538799, -0.017073799063418826 ],
[ -0.009243040646204504, 0.015055191490298152, 0.7518742814281371 ],
];

@@ -49,5 +49,5 @@ }

env.M = [
[ 0.9554734527042182, -0.023098536874261423, 0.0632593086610217 ],
[ -0.028369706963208136, 1.0099954580058226, 0.021041398966943008 ],
[ 0.012314001688319899, -0.020507696433477912, 1.3303659366080753 ]
[ 0.955473421488075, -0.02309845494876471, 0.06325924320057072 ],
[ -0.0283697093338637, 1.0099953980813041, 0.021041441191917323 ],
[ 0.012314014864481998, -0.020507649298898964, 1.330365926242124 ],
];

@@ -54,0 +54,0 @@ }

@@ -22,3 +22,3 @@ import hooks from "./hooks.js";

CATs[id] = arguments[0];
};
}

@@ -37,5 +37,5 @@ export function adapt (W1, W2, id = "Bradford") {

let scale = [
[ρd/ρs, 0, 0 ],
[0, γd/γs, 0 ],
[0, 0, βd/βs ]
[ρd / ρs, 0, 0 ],
[0, γd / γs, 0 ],
[0, 0, βd / βs],
];

@@ -48,3 +48,3 @@ // console.log({scale});

return adapt_M;
};
}

@@ -56,9 +56,9 @@ defineCAT({

[ -0.2263000, 1.1653200, 0.0457000 ],
[ 0.0000000, 0.0000000, 0.9182200 ]
[ 0.0000000, 0.0000000, 0.9182200 ],
],
fromCone_M: [
[ 1.8599364, -1.1293816, 0.2198974 ],
[ 0.3611914, 0.6388125, -0.0000064 ],
[ 0.0000000, 0.0000000, 1.0890636 ]
]
[ 1.8599363874558397, -1.1293816185800916, 0.21989740959619328 ],
[ 0.3611914362417676, 0.6388124632850422, -0.000006370596838649899 ],
[ 0, 0, 1.0890636230968613 ],
],
});

@@ -73,10 +73,10 @@

[ -0.7502000, 1.7135000, 0.0367000 ],
[ 0.0389000, -0.0685000, 1.0296000 ]
[ 0.0389000, -0.0685000, 1.0296000 ],
],
// and back
fromCone_M: [
[ 0.9869929, -0.1470543, 0.1599627 ],
[ 0.4323053, 0.5183603, 0.0492912 ],
[ -0.0085287, 0.0400428, 0.9684867 ]
]
[ 0.9869929054667121, -0.14705425642099013, 0.15996265166373122 ],
[ 0.4323052697233945, 0.5183602715367774, 0.049291228212855594 ],
[ -0.00852866457517732, 0.04004282165408486, 0.96848669578755 ],
],
});

@@ -90,9 +90,9 @@

[ -0.7036000, 1.6975000, 0.0061000 ],
[ 0.0030000, 0.0136000, 0.9834000 ]
[ 0.0030000, 0.0136000, 0.9834000 ],
],
fromCone_M: [
[ 1.0961238, -0.2788690, 0.1827452 ],
[ 0.4543690, 0.4735332, 0.0720978 ],
[ -0.0096276, -0.0056980, 1.0153256 ]
]
[ 1.0961238208355142, -0.27886900021828726, 0.18274517938277307 ],
[ 0.4543690419753592, 0.4735331543074117, 0.07209780371722911 ],
[ -0.009627608738429355, -0.00569803121611342, 1.0153256399545427 ],
],
});

@@ -105,10 +105,10 @@

[ -0.250268, 1.204414, 0.045854 ],
[ -0.002079, 0.048952, 0.953127 ]
[ -0.002079, 0.048952, 0.953127 ],
],
// the extra precision is needed to avoid roundtripping errors
fromCone_M: [
[ 1.862067855087233e+0, -1.011254630531685e+0, 1.491867754444518e-1 ],
[ 3.875265432361372e-1, 6.214474419314753e-1, -8.973985167612518e-3 ],
[ -1.584149884933386e-2, -3.412293802851557e-2, 1.049964436877850e+0 ]
]
[ 1.862067855087233, -1.0112546305316845, 0.14918677544445172 ],
[ 0.3875265432361372, 0.6214474419314753, -0.008973985167612521 ],
[ -0.01584149884933386, -0.03412293802851557, 1.0499644368778496 ],
],
});

@@ -120,3 +120,3 @@

// Illuminant A is a tungsten electric light, giving a very warm, orange light.
A: [1.09850, 1.00000, 0.35585],
A: [1.09850, 1.00000, 0.35585],

@@ -123,0 +123,0 @@ // Illuminant C was an early approximation to daylight: illuminant A with a blue filter.

@@ -6,2 +6,3 @@ import xyz_d65 from "./spaces/xyz-d65.js";

export function uv (color) {
// Assumes getAll() calls getColor() on color
let [X, Y, Z] = getAll(color, xyz_d65);

@@ -13,2 +14,3 @@ let denom = X + 15 * Y + 3 * Z;

export function xy (color) {
// Assumes getAll() calls getColor() on color
let [X, Y, Z] = getAll(color, xyz_d65);

@@ -25,3 +27,3 @@ let sum = X + Y + Z;

return uv(this);
}
},
});

@@ -32,4 +34,4 @@

return xy(this);
}
},
});
}

@@ -5,4 +5,4 @@ export default function clone (color) {

coords: color.coords.slice(),
alpha: color.alpha
alpha: color.alpha,
};
}

@@ -64,5 +64,8 @@ import * as util from "./util.js";

});
this.coords = coords? coords.slice() : [0, 0, 0];
this.alpha = alpha < 1? alpha : 1; // this also deals with NaN etc
this.coords = coords ? coords.slice() : [0, 0, 0];
// Clamp alpha to [0, 1]
this.alpha = alpha > 1 || alpha === undefined ? 1 : (alpha < 0 ? 0 : alpha);
// Convert "NaN" to NaN

@@ -79,3 +82,3 @@ for (let i = 0; i < this.coords.length; i++) {

get: () => this.get(id),
set: value => this.set(id, value)
set: value => this.set(id, value),
});

@@ -97,3 +100,3 @@ }

coords: this.coords,
alpha: this.alpha
alpha: this.alpha,
};

@@ -176,3 +179,3 @@ }

}
};
}

@@ -201,3 +204,3 @@ Color.defineFunctions({

// Global defaults one may want to configure
defaults
defaults,
});

@@ -28,2 +28,2 @@ import getColor from "./getColor.js";

throw new TypeError(`Unknown contrast algorithm: ${algorithm}`);
};
}

@@ -24,3 +24,3 @@ // APCA 0.0.98G

const loBoWoffset = 0.027;
const scaleWoB= 1.14;
const scaleWoB = 1.14;
const loWoBoffset = 0.027;

@@ -36,3 +36,3 @@

function linearize (val) {
let sign = val < 0? -1 : 1;
let sign = val < 0 ? -1 : 1;
let abs = Math.abs(val);

@@ -39,0 +39,0 @@ return sign * Math.pow(abs, 2.4);

@@ -25,2 +25,2 @@ // Delta Phi Star perceptual lightness contrast

return (contrast < 7.5) ? 0.0 : contrast ;
};
}

@@ -17,2 +17,2 @@ // CIE Lightness difference, as used by Google Material Design

return Math.abs(L1 - L2);
};
}

@@ -22,2 +22,2 @@ // Michelson luminance contrast

return denom === 0 ? 0 : (Y1 - Y2) / denom;
};
}

@@ -20,2 +20,2 @@ // WCAG 2.0 contrast https://www.w3.org/TR/WCAG20-TECHS/G18.html

return (Y1 + .05) / (Y2 + .05);
};
}

@@ -27,2 +27,2 @@ // Weber luminance contrast

return Y2 === 0 ? max : (Y1 - Y2) / Y2;
};
}
// Global defaults one may want to configure
const hasDOM = typeof document !== "undefined";
export default {
gamut_mapping: "lch.c",
gamut_mapping: "css",
precision: 5,
deltaE: "76", // Default deltaE method
verbose: globalThis?.process?.env?.NODE_ENV?.toLowerCase() !== "test",
warn: function warn (msg) {
if (this.verbose) {
globalThis?.console?.warn?.(msg);
}
},
};

@@ -1,2 +0,1 @@

import getColor from "./getColor.js";
import defaults from "./defaults.js";

@@ -13,5 +12,2 @@ import {isString} from "./util.js";

c1 = getColor(c1);
c2 = getColor(c2);
for (let m in deltaEMethods) {

@@ -24,2 +20,2 @@ if ("deltae" + method.toLowerCase() === m.toLowerCase()) {

throw new TypeError(`Unknown deltaE method: ${method}`);
};
}

@@ -0,3 +1,5 @@

import defaults from "../defaults.js";
import lab from "../spaces/lab.js";
import lch from "../spaces/lch.js";
import getColor from "../getColor.js";

@@ -17,3 +19,14 @@ // deltaE2000 is a statistically significant improvement

function pow7 (x) {
// Faster than x ** 7 or Math.pow(x, 7)
const x2 = x * x;
const x7 = x2 * x2 * x2 * x;
return x7;
}
export default function (color, sample, {kL = 1, kC = 1, kH = 1} = {}) {
[color, sample] = getColor([color, sample]);
// Given this color as the reference

@@ -46,9 +59,9 @@ // and the function parameter as the sample,

let Cbar = (C1 + C2)/2; // mean Chroma
let Cbar = (C1 + C2) / 2; // mean Chroma
// calculate a-axis asymmetry factor from mean Chroma
// this turns JND ellipses for near-neutral colors back into circles
let C7 = Cbar ** 7;
let C7 = pow7(Cbar);
let G = 0.5 * (1 - Math.sqrt(C7/(C7 + Gfactor)));
let G = 0.5 * (1 - Math.sqrt(C7 / (C7 + Gfactor)));

@@ -67,4 +80,4 @@ // scale a axes by asymmetry factor

let h1 = (adash1 === 0 && b1 === 0)? 0: Math.atan2(b1, adash1);
let h2 = (adash2 === 0 && b2 === 0)? 0: Math.atan2(b2, adash2);
let h1 = (adash1 === 0 && b1 === 0) ? 0 : Math.atan2(b1, adash1);
let h2 = (adash2 === 0 && b2 === 0) ? 0 : Math.atan2(b2, adash2);

@@ -104,3 +117,3 @@ if (h1 < 0) {

else {
console.log("the unthinkable has happened");
defaults.warn("the unthinkable has happened");
}

@@ -112,5 +125,5 @@

// calculate mean Lightness and Chroma
let Ldash = (L1 + L2)/2;
let Cdash = (Cdash1 + Cdash2)/2;
let Cdash7 = Math.pow(Cdash, 7);
let Ldash = (L1 + L2) / 2;
let Cdash = (Cdash1 + Cdash2) / 2;
let Cdash7 = pow7(Cdash);

@@ -160,4 +173,4 @@ // Compensate for non-linearity in the blue region of Lab.

// (Hue 225 to 315)
let Δθ = 30 * Math.exp(-1 * (((hdash - 275)/25) ** 2));
let RC = 2 * Math.sqrt(Cdash7/(Cdash7 + Gfactor));
let Δθ = 30 * Math.exp(-1 * (((hdash - 275) / 25) ** 2));
let RC = 2 * Math.sqrt(Cdash7 / (Cdash7 + Gfactor));
let RT = -1 * Math.sin(2 * Δθ * d2r) * RC;

@@ -172,2 +185,2 @@

// Yay!!!
};
}
import distance from "../distance.js";
import getColor from "../getColor.js";
export default function deltaE76 (color, sample) {
// Assume getColor() is called in the distance function
return distance(color, sample, "lab");
};
}
import lab from "../spaces/lab.js";
import lch from "../spaces/lch.js";
import getColor from "../getColor.js";

@@ -16,2 +17,4 @@ // More accurate color-difference formulae

export default function (color, sample, {l = 2, c = 1} = {}) {
[color, sample] = getColor([color, sample]);
// Given this color as the reference

@@ -88,3 +91,3 @@ // and a sample,

let T;
if ( Number.isNaN(H1)) {
if (Number.isNaN(H1)) {
H1 = 0;

@@ -113,2 +116,2 @@ }

// Yay!!!
};
}
import ictcp from "../spaces/ictcp.js";
import getColor from "../getColor.js";

@@ -8,2 +9,4 @@ // Delta E in ICtCp space,

export default function (color, sample) {
[color, sample] = getColor([color, sample]);
// Given this color as the reference

@@ -21,3 +24,3 @@ // and a sample,

return 720 * Math.sqrt((I1 - I2) ** 2 + (0.25 * (T1 -T2) ** 2) + (P1 - P2) ** 2);
};
return 720 * Math.sqrt((I1 - I2) ** 2 + (0.25 * (T1 - T2) ** 2) + (P1 - P2) ** 2);
}
import jzczhz from "../spaces/jzczhz.js";
import getColor from "../getColor.js";

@@ -11,2 +12,4 @@ // More accurate color-difference formulae

export default function (color, sample) {
[color, sample] = getColor([color, sample]);
// Given this color as the reference

@@ -41,2 +44,2 @@ // and a sample,

return Math.sqrt(ΔJ ** 2 + ΔC ** 2 + ΔH ** 2);
};
}

@@ -5,4 +5,7 @@ // More accurate color-difference formulae

import oklab from "../spaces/oklab.js";
import getColor from "../getColor.js";
export default function (color, sample) {
[color, sample] = getColor([color, sample]);
// Given this color as the reference

@@ -17,2 +20,2 @@ // and a sample,

return Math.sqrt(ΔL ** 2 + Δa ** 2 + Δb ** 2);
};
}

@@ -7,4 +7,13 @@ import deltaE76 from "./deltaE76.js";

import deltaEOK from "./deltaEOK.js";
import deltaEHCT from "./deltaEHCT.js";
export { deltaE76, deltaECMC, deltaE2000, deltaEJz, deltaEITP, deltaEOK };
export {
deltaE76,
deltaECMC,
deltaE2000,
deltaEJz,
deltaEITP,
deltaEOK,
deltaEHCT,
};

@@ -18,2 +27,3 @@ export default {

deltaEOK,
deltaEHCT,
};

@@ -1,10 +0,6 @@

import * as util from "./util.js";
import ColorSpace from "./space.js";
import { isNone, skipNone } from "./util.js";
import defaults from "./defaults.js";
import getColor from "./getColor.js";
import to from "./to.js";
import checkInGamut from "./inGamut.js";
import toGamut from "./toGamut.js";
import serialize from "./serialize.js";
import clone from "./clone.js";
import serialize from "./serialize.js";
import REC2020 from "./spaces/rec2020.js";

@@ -18,2 +14,4 @@ import P3 from "./spaces/p3.js";

let supportsNone;
if (typeof CSS !== "undefined" && CSS.supports) {

@@ -54,4 +52,29 @@ // Find widest supported color space for CSS

// If we're here, what we were about to output is not supported
let fallbackColor = color;
// First, check if the culprit is none values
let hasNone = color.coords.some(isNone) || isNone(color.alpha);
if (hasNone) {
// Does the browser support none values?
if (!(supportsNone ??= CSS.supports("color", "hsl(none 50% 50%)"))) {
// Nope, try again without none
fallbackColor = clone(color);
fallbackColor.coords = fallbackColor.coords.map(skipNone);
fallbackColor.alpha = skipNone(fallbackColor.alpha);
ret = serialize(fallbackColor, options);
if (CSS.supports("color", ret)) {
// We're done, now it's supported
ret = new String(ret);
ret.color = fallbackColor;
return ret;
}
}
}
// If we're here, the color function is not supported
// Fall back to fallback space
let fallbackColor = to(color, space);
fallbackColor = to(fallbackColor, space);
ret = new String(serialize(fallbackColor, options));

@@ -58,0 +81,0 @@ ret.color = fallbackColor;

@@ -9,2 +9,3 @@ import ColorSpace from "./space.js";

// Assume getColor() is called on color in space.from()
let coords1 = space.from(color1);

@@ -11,0 +12,0 @@ let coords2 = space.from(color2);

@@ -8,4 +8,4 @@ import getColor from "./getColor.js";

return color1.space === color2.space
&& color1.alpha === color2.alpha
&& color1.coords.every((c, i) => c === color2.coords[i]);
&& color1.alpha === color2.alpha
&& color1.coords.every((c, i) => c === color2.coords[i]);
}
import ColorSpace from "./space.js";
import getAll from "./getAll.js";
import getColor from "./getColor.js";
export default function get (color, prop) {
color = getColor(color);
let {space, index} = ColorSpace.resolveCoord(prop, color.space);

@@ -6,0 +9,0 @@ let coords = getAll(color, space);

import ColorSpace from "./space.js";
import getColor from "./getColor.js";
/**
* Get the coordinates of a color in another color space
*
* @param {string | ColorSpace} space
* @returns {number[]}
* Get the coordinates of a color in any color space
* @param {Color} color
* @param {string | ColorSpace} [space = color.space] The color space to convert to. Defaults to the color's current space
* @returns {number[]} The color coordinates in the given color space
*/
export default function getAll (color, space) {
color = getColor(color);
if (!space || color.space.equals(space)) {
// No conversion needed
return color.coords.slice();
}
space = ColorSpace.get(space);
return space.from(color);
}

@@ -7,6 +7,10 @@ import ColorSpace from "./space.js";

* Resolves a color reference (object or string) to a plain color object
* @param {Color | {space, coords, alpha} | string} color
* @returns {{space, coords, alpha}}
* @param {Color | {space, coords, alpha} | string | Array<Color | {space, coords, alpha} | string> } color
* @returns {{space, coords, alpha} | Array<{space, coords, alpha}}>
*/
export default function getColor (color) {
if (Array.isArray(color)) {
return color.map(getColor);
}
if (!color) {

@@ -13,0 +17,0 @@ throw new TypeError("Empty color reference");

@@ -15,7 +15,7 @@ /**

(Array.isArray(name)? name : [name]).forEach(function (name) {
(Array.isArray(name) ? name : [name]).forEach(function (name) {
this[name] = this[name] || [];
if (callback) {
this[name][first? "unshift" : "push"](callback);
this[name][first ? "unshift" : "push"](callback);
}

@@ -28,6 +28,6 @@ }, this);

this[name].forEach(function (callback) {
callback.call(env && env.context? env.context : env, env);
callback.call(env && env.context ? env.context : env, env);
});
}
};
}

@@ -34,0 +34,0 @@ /**

@@ -1,32 +0,28 @@

export {default as ColorSpace} from "./space.js";
export {default as RGBColorSpace} from "./rgbspace.js";
export {default as hooks, Hooks} from "./hooks.js";
export {default as defaults} from "./defaults.js";
export {default as getColor} from "./getColor.js";
export {default as get} from "./get.js";
export {default as getAll} from "./getAll.js";
export {default as set} from "./set.js";
export {default as setAll} from "./setAll.js";
export {default as parse} from "./parse.js";
export {default as to} from "./to.js";
export {default as serialize} from "./serialize.js";
export {default as display} from "./display.js";
export {default as inGamut} from "./inGamut.js";
export {default as toGamut} from "./toGamut.js";
export {default as distance} from "./distance.js";
export {default as equals} from "./equals.js";
export {default as contrast} from "./contrast.js";
export {default as clone} from "./clone.js";
export {
getLuminance, setLuminance
} from "./luminance.js";
export {uv, xy} from "./chromaticity.js";
export * from "./contrast/index.js";
export {default as deltaE} from "./deltaE.js";
export * from "./deltaE/index.js";
export {default as deltaEMethods} from "./deltaE/index.js";
export * from "./variations.js";
export {
mix, steps, range, isRange
} from "./interpolation.js";
export * from "./spaces/index-fn.js";
export {default as ColorSpace} from "./space.js";
export {default as RGBColorSpace} from "./rgbspace.js";
export {default as hooks, Hooks} from "./hooks.js";
export {default as defaults} from "./defaults.js";
export {default as getColor} from "./getColor.js";
export {default as get} from "./get.js";
export {default as getAll} from "./getAll.js";
export {default as set} from "./set.js";
export {default as setAll} from "./setAll.js";
export {default as parse} from "./parse.js";
export {default as to} from "./to.js";
export {default as serialize} from "./serialize.js";
export {default as display} from "./display.js";
export {default as inGamut} from "./inGamut.js";
export {default as toGamut, toGamutCSS} from "./toGamut.js";
export {default as distance} from "./distance.js";
export {default as equals} from "./equals.js";
export {default as contrast} from "./contrast.js";
export {default as clone} from "./clone.js";
export { getLuminance, setLuminance } from "./luminance.js";
export {uv, xy} from "./chromaticity.js";
export * from "./contrast/index.js";
export {default as deltaE} from "./deltaE.js";
export * from "./deltaE/index.js";
export {default as deltaEMethods} from "./deltaE/index.js";
export * from "./variations.js";
export { mix, steps, range, isRange } from "./interpolation.js";
export * from "./spaces/index-fn.js";

@@ -10,4 +10,9 @@ import ColorSpace from "./space.js";

*/
export default function inGamut (color, space = color.space, {epsilon = ε} = {}) {
export default function inGamut (color, space, {epsilon = ε} = {}) {
color = getColor(color);
if (!space) {
space = color.space;
}
space = ColorSpace.get(space);

@@ -14,0 +19,0 @@ let coords = color.coords;

/**
* Functions related to color interpolation
*/
import Color from "./color.js";
import ColorSpace from "./space.js";

@@ -35,5 +34,3 @@ import {type, interpolate} from "./util.js";

let {space, outputSpace, premultiplied} = o;
let r = range(c1, c2, {space, outputSpace, premultiplied});
let r = range(c1, c2, o);
return r(p);

@@ -70,3 +67,3 @@ }

let totalDelta = deltaE(c1, c2);
let actualSteps = maxDeltaE > 0? Math.max(steps, Math.ceil(totalDelta / maxDeltaE) + 1) : steps;
let actualSteps = maxDeltaE > 0 ? Math.max(steps, Math.ceil(totalDelta / maxDeltaE) + 1) : steps;
let ret = [];

@@ -121,3 +118,3 @@

return ret;
};
}

@@ -157,3 +154,3 @@ /**

outputSpace = outputSpace? ColorSpace.get(outputSpace) : space;
outputSpace = outputSpace ? ColorSpace.get(outputSpace) : space;

@@ -174,2 +171,11 @@ color1 = to(color1, space);

let [θ1, θ2] = [get(color1, hue), get(color2, hue)];
// Undefined hues must be evaluated before hue fix-up to properly
// calculate hue arcs between undefined and defined hues.
// See https://github.com/w3c/csswg-drafts/issues/9436#issuecomment-1746957545
if (isNaN(θ1) && !isNaN(θ2)) {
θ1 = θ2;
}
else if (isNaN(θ2) && !isNaN(θ1)) {
θ2 = θ1;
}
[θ1, θ2] = angles.adjust(arc, [θ1, θ2]);

@@ -187,3 +193,3 @@ set(color1, hue, θ1);

return Object.assign(p => {
p = progression? progression(p) : p;
p = progression ? progression(p) : p;
let coords = color1.coords.map((start, i) => {

@@ -208,9 +214,9 @@ let end = color2.coords[i];

}, {
rangeArgs
rangeArgs,
});
};
}
export function isRange (val) {
return type(val) === "function" && !!val.rangeArgs;
};
}

@@ -217,0 +223,0 @@ defaults.interpolationSpace = "lab";

@@ -157,3 +157,3 @@ /* List of CSS color keywords

"yellow": [1, 1, 0],
"yellowgreen": [154 / 255, 205 / 255, 50 / 255]
"yellowgreen": [154 / 255, 205 / 255, 50 / 255],
};

@@ -9,2 +9,3 @@ /**

export function getLuminance (color) {
// Assume getColor() is called on color in get()
return get(color, [xyz_d65, "y"]);

@@ -14,2 +15,3 @@ }

export function setLuminance (color, value) {
// Assume getColor() is called on color in set()
set(color, [xyz_d65, "y"], value);

@@ -25,4 +27,4 @@ }

setLuminance(this, value);
}
},
});
}

@@ -28,3 +28,3 @@ // A is m x n. B is n x p. product is m x p.

for (let i=0; i < row.length; i++) {
for (let i = 0; i < row.length; i++) {
ret += row[i] * (col[i] || 0);

@@ -31,0 +31,0 @@ }

import * as util from "./util.js";
import hooks from "./hooks.js";
import ColorSpace from "./space.js";
import defaults from "./defaults.js";
const noneTypes = new Set(["<number>", "<percentage>", "<angle>"]);
/**
* Validates the coordinates of a color against a format's coord grammar and
* maps the coordinates to the range or refRange of the coordinates.
* @param {ColorSpace} space - Colorspace the coords are in
* @param {object} format - the format object to validate against
* @param {string} name - the name of the color function. e.g. "oklab" or "color"
* @returns {object[]} - an array of type metadata for each coordinate
*/
function coerceCoords (space, format, name, coords) {
let types = Object.entries(space.coords).map(([id, coordMeta], i) => {
let coordGrammar = format.coordGrammar[i];
let arg = coords[i];
let providedType = arg?.type;
// Find grammar alternative that matches the provided type
// Non-strict equals is intentional because we are comparing w/ string objects
let type;
if (arg.none) {
type = coordGrammar.find(c => noneTypes.has(c));
}
else {
type = coordGrammar.find(c => c == providedType);
}
// Check that each coord conforms to its grammar
if (!type) {
// Type does not exist in the grammar, throw
let coordName = coordMeta.name || id;
throw new TypeError(`${providedType ?? arg.raw} not allowed for ${coordName} in ${name}()`);
}
let fromRange = type.range;
if (providedType === "<percentage>") {
fromRange ||= [0, 1];
}
let toRange = coordMeta.range || coordMeta.refRange;
if (fromRange && toRange) {
coords[i] = util.mapRange(fromRange, toRange, coords[i]);
}
return type;
});
return types;
}
/**
* Convert a CSS Color string to a color object

@@ -10,3 +63,3 @@ * @param {string} str

* @param {object} [options.meta] - Object for additional information about the parsing
* @returns { Color }
* @returns {Color}
*/

@@ -30,3 +83,6 @@ export default function parse (str, {meta} = {}) {

let id = env.parsed.args.shift();
let alpha = env.parsed.rawArgs.indexOf("/") > 0? env.parsed.args.pop() : 1;
// Check against both <dashed-ident> and <ident> versions
let alternateId = id.startsWith("--") ? id.substring(2) : `--${id}`;
let ids = [id, alternateId];
let alpha = env.parsed.rawArgs.indexOf("/") > 0 ? env.parsed.args.pop() : 1;

@@ -37,3 +93,3 @@ for (let space of ColorSpace.all) {

if (colorSpec) {
if (id === colorSpec.id || colorSpec.ids?.includes(id)) {
if (ids.includes(colorSpec.id) || colorSpec.ids?.filter((specId) => ids.includes(specId)).length) {
// From https://drafts.csswg.org/css-color-4/#color-function

@@ -44,6 +100,21 @@ // If more <number>s or <percentage>s are provided than parameters that the colorspace takes, the excess <number>s at the end are ignored.

let types;
if (colorSpec.coordGrammar) {
types = coerceCoords(space, colorSpec, "color", coords);
}
if (meta) {
meta.formatId = "color";
Object.assign(meta, {formatId: "color", types});
}
if (colorSpec.id.startsWith("--") && !id.startsWith("--")) {
defaults.warn(`${space.name} is a non-standard space and not currently supported in the CSS spec. ` +
`Use prefixed color(${colorSpec.id}) instead of color(${id}).`);
}
if (id.startsWith("--") && !colorSpec.id.startsWith("--")) {
defaults.warn(`${space.name} is a standard space and supported in the CSS spec. ` +
`Use color(${colorSpec.id}) instead of prefixed color(${id}).`);
}
return {spaceId: space.id, coords, alpha};

@@ -56,5 +127,6 @@ }

let didYouMean = "";
if (id in ColorSpace.registry) {
let registryId = id in ColorSpace.registry ? id : alternateId;
if (registryId in ColorSpace.registry) {
// Used color space id instead of color() id, these are often different
let cssId = ColorSpace.registry[id].formats?.functions?.color?.id;
let cssId = ColorSpace.registry[registryId].formats?.color?.id;

@@ -84,31 +156,3 @@ if (cssId) {

if (format.coordGrammar) {
types = Object.entries(space.coords).map(([id, coordMeta], i) => {
let coordGrammar = format.coordGrammar[i];
let providedType = coords[i]?.type;
// Find grammar alternative that matches the provided type
// Non-strict equals is intentional because we are comparing w/ string objects
let type = coordGrammar.find(c => c == providedType);
// Check that each coord conforms to its grammar
if (!type) {
// Type does not exist in the grammar, throw
let coordName = coordMeta.name || id;
throw new TypeError(`${providedType} not allowed for ${coordName} in ${name}()`);
}
let fromRange = type.range;
if (providedType === "<percentage>") {
fromRange ||= [0, 1];
}
let toRange = coordMeta.range || coordMeta.refRange;
if (fromRange && toRange) {
coords[i] = util.mapRange(fromRange, toRange, coords[i]);
}
return type;
});
types = coerceCoords(space, format, name, coords);
}

@@ -122,3 +166,3 @@

spaceId: space.id,
coords, alpha
coords, alpha,
};

@@ -125,0 +169,0 @@ }

@@ -25,12 +25,12 @@ import ColorSpace from "./space.js";

range: [0, 1],
name: "Red"
name: "Red",
},
g: {
range: [0, 1],
name: "Green"
name: "Green",
},
b: {
range: [0, 1],
name: "Blue"
}
name: "Blue",
},
};

@@ -37,0 +37,0 @@ }

@@ -5,3 +5,2 @@ import * as util from "./util.js";

import getColor from "./getColor.js";
import to from "./to.js";
import checkInGamut from "./inGamut.js";

@@ -29,16 +28,16 @@ import toGamut from "./toGamut.js";

format = color.space.getFormat(format)
?? color.space.getFormat("default")
?? ColorSpace.DEFAULT_FORMAT;
?? color.space.getFormat("default")
?? ColorSpace.DEFAULT_FORMAT;
inGamut ||= format.toGamut;
// The assignment to coords and inGamut needs to stay in the order they are now
// The order of the assignment was changed as a workaround for a bug in Next.js
// See this issue for details: https://github.com/color-js/color.js/issues/260
let coords = color.coords;
let coords = color.coords.slice(); // clone so we can manipulate it
// Convert NaN to zeros to have a chance at a valid CSS color
// Also convert -0 to 0
// This also clones it so we can manipulate it
coords = coords.map(c => c? c : 0);
inGamut ||= format.toGamut;
if (inGamut && !checkInGamut(color)) {
coords = toGamut(clone(color), inGamut === true? undefined : inGamut).coords;
// FIXME what happens if the color contains NaNs?
coords = toGamut(clone(color), inGamut === true ? undefined : inGamut).coords;
}

@@ -65,3 +64,5 @@

if (precision !== null) {
coords = coords.map(c => util.toPrecision(c, precision));
coords = coords.map(c => {
return util.serializeNumber(c, {precision});
});
}

@@ -80,7 +81,7 @@ }

if (precision !== null) {
alpha = util.toPrecision(alpha, precision);
alpha = util.serializeNumber(alpha, {precision});
}
let strAlpha = color.alpha < 1 && !format.noAlpha? `${format.commas? "," : " /"} ${alpha}` : "";
ret = `${name}(${args.join(format.commas? ", " : " ")}${strAlpha})`;
let strAlpha = color.alpha >= 1 || format.noAlpha ? "" : `${format.commas ? "," : " /"} ${alpha}`;
ret = `${name}(${args.join(format.commas ? ", " : " ")}${strAlpha})`;
}

@@ -87,0 +88,0 @@

@@ -32,1 +32,3 @@ import ColorSpace from "./space.js";

}
set.returns = "color";
import ColorSpace from "./space.js";
import getColor from "./getColor.js";
export default function setAll (color, space, coords) {
color = getColor(color);
space = ColorSpace.get(space);

@@ -8,1 +11,3 @@ color.coords = space.to(color.space, coords);

}
setAll.returns = "color";

@@ -23,7 +23,2 @@ /**

function addSpaceAccessors (id, space) {
// Coordinates can be looked up by both id and name
let coordIds = Object.keys(space.coords);
let coordNames = Object.values(space.coords).map(c => c.name);
let propId = id.replace(/-/g, "_");

@@ -90,4 +85,4 @@

configurable: true,
enumerable: true
enumerable: true,
});
}

@@ -1,4 +0,5 @@

import {type, parseCoordGrammar, toPrecision, mapRange} from "./util.js";
import {type, parseCoordGrammar, serializeNumber, mapRange} from "./util.js";
import {getWhite} from "./adapt.js";
import hooks from "./hooks.js";
import getColor from "./getColor.js";

@@ -48,10 +49,33 @@ const ε = .000075;

if (options.cssId && !this.formats.functions?.color) {
this.formats.color = { id: options.cssId };
Object.defineProperty(this, "cssId", {value: options.cssId});
if (!this.formats.color?.id) {
this.formats.color = {
...this.formats.color ?? {},
id: options.cssId || this.id,
};
}
else if (this.formats?.color && !this.formats?.color.id) {
this.formats.color.id = this.id;
// Gamut space
if (options.gamutSpace) {
// Gamut space explicitly specified
this.gamutSpace = options.gamutSpace === "self" ? this : ColorSpace.get(options.gamutSpace);
}
else {
// No gamut space specified, calculate a sensible default
if (this.isPolar) {
// Do not check gamut through polar coordinates
this.gamutSpace = this.base;
}
else {
this.gamutSpace = this;
}
}
// Optimize inGamut for unbounded spaces
if (this.gamutSpace.isUnbounded) {
this.inGamut = (coords, options) => {
return true;
};
}
// Other stuff

@@ -72,7 +96,5 @@ this.referred = options.referred;

inGamut (coords, {epsilon = ε} = {}) {
if (this.isPolar) {
// Do not check gamut through polar coordinates
coords = this.toBase(coords);
return this.base.inGamut(coords, {epsilon});
if (!this.equals(this.gamutSpace)) {
coords = this.to(this.gamutSpace, coords);
return this.gamutSpace.inGamut(coords, {epsilon});
}

@@ -100,4 +122,8 @@

get isUnbounded () {
return Object.values(this.coords).every(coord => !("range" in coord));
}
get cssId () {
return this.formats.functions?.color?.id || this.id;
return this.formats?.color?.id || this.id;
}

@@ -138,3 +164,8 @@

// We cannot rely on simple === because then ColorSpace objects cannot be proxied
/**
* Check if this color space is the same as another color space reference.
* Allows proxying color space objects and comparing color spaces with ids.
* @param {string | ColorSpace} space ColorSpace object or id to compare to
* @returns {boolean}
*/
equals (space) {

@@ -145,3 +176,3 @@ if (!space) {

return this === space || this.id === space.id;
return this === space || this.id === space || this.id === space.id;
}

@@ -151,3 +182,4 @@

if (arguments.length === 1) {
[space, coords] = [space.space, space.coords];
const color = getColor(space);
[space, coords] = [color.space, color.coords];
}

@@ -163,3 +195,3 @@

// Convert NaN to 0, which seems to be valid in every coordinate of every color space
coords = coords.map(c => Number.isNaN(c)? 0 : c);
coords = coords.map(c => Number.isNaN(c) ? 0 : c);

@@ -172,3 +204,3 @@ // Find connection space = lowest common ancestor in the base tree

for (let i=0; i < myPath.length; i++) {
for (let i = 0; i < myPath.length; i++) {
if (myPath[i].equals(otherPath[i])) {

@@ -203,3 +235,4 @@ connectionSpace = myPath[i];

if (arguments.length === 1) {
[space, coords] = [space.space, space.coords];
const color = getColor(space);
[space, coords] = [color.space, color.coords];
}

@@ -408,8 +441,4 @@

c = toPrecision(c, precision);
c = serializeNumber(c, {precision, unit: suffix});
if (suffix) {
c += suffix;
}
return c;

@@ -416,0 +445,0 @@ });

@@ -12,3 +12,3 @@ import RGBColorSpace from "../rgbspace.js";

[ 0.29734497525053605, 0.6273635662554661, 0.07529145849399788 ],
[ 0.02703136138641234, 0.07068885253582723, 0.9913375368376388 ]
[ 0.02703136138641234, 0.07068885253582723, 0.9913375368376388 ],
];

@@ -19,3 +19,3 @@

[ -0.9692436362808795, 1.8759675015077202, 0.04155505740717557 ],
[ 0.013444280632031142, -0.11836239223101838, 1.0151749943912054 ]
[ 0.013444280632031142, -0.11836239223101838, 1.0151749943912054 ],
];

@@ -25,6 +25,7 @@

id: "a98rgb-linear",
cssId: "--a98-rgb-linear",
name: "Linear Adobe® 98 RGB compatible",
white: "D65",
toXYZ_M,
fromXYZ_M
fromXYZ_M,
});

@@ -6,2 +6,3 @@ import RGBColorSpace from "../rgbspace.js";

id: "a98rgb",
cssId: "a98-rgb",
name: "Adobe® 98 RGB compatible",

@@ -11,7 +12,2 @@ base: A98Linear,

fromBase: RGB => RGB.map(val => Math.pow(Math.abs(val), 256 / 563) * Math.sign(val)),
formats: {
color: {
id: "a98-rgb"
}
},
});

@@ -16,2 +16,3 @@ import RGBColorSpace from "../rgbspace.js";

id: "acescc",
cssId: "--acescc",
name: "ACEScc",

@@ -29,12 +30,12 @@ // see S-2014-003 ACEScc – A Logarithmic Encoding of ACES Data

range: [ACES_min_nonzero, ACES_cc_max],
name: "Red"
name: "Red",
},
g: {
range: [ACES_min_nonzero, ACES_cc_max],
name: "Green"
name: "Green",
},
b: {
range: [ACES_min_nonzero, ACES_cc_max],
name: "Blue"
}
name: "Blue",
},
},

@@ -77,5 +78,2 @@ referred: "scene",

// encoded media black (rgb 0,0,0) => linear [ 0.0011857, 0.0011857, 0.0011857]
formats: {
color: {}
}
});

@@ -9,3 +9,3 @@ import RGBColorSpace from "../rgbspace.js";

// Similar to D60
WHITES.ACES = [0.32168/0.33767, 1.00000, (1.00000 - 0.32168 - 0.33767)/0.33767];
WHITES.ACES = [0.32168 / 0.33767, 1.00000, (1.00000 - 0.32168 - 0.33767) / 0.33767];

@@ -16,3 +16,3 @@ // convert an array of linear-light ACEScc values to CIE XYZ

[ 0.27222871678091454, 0.6740817658111484, 0.05368951740793705 ],
[ -0.005574649490394108, 0.004060733528982826, 1.0103391003129971 ]
[ -0.005574649490394108, 0.004060733528982826, 1.0103391003129971 ],
];

@@ -22,3 +22,3 @@ const fromXYZ_M = [

[ -0.6636628587229829, 1.6153315916573379, 0.016756347685530137 ],
[ 0.011721894328375376, -0.008284441996237409, 0.9883948585390215 ]
[ 0.011721894328375376, -0.008284441996237409, 0.9883948585390215 ],
];

@@ -28,2 +28,3 @@

id: "acescg",
cssId: "--acescg",
name: "ACEScg",

@@ -37,12 +38,12 @@

range: [0, 65504],
name: "Red"
name: "Red",
},
g: {
range: [0, 65504],
name: "Green"
name: "Green",
},
b: {
range: [0, 65504],
name: "Blue"
}
name: "Blue",
},
},

@@ -56,8 +57,4 @@

fromXYZ_M,
formats: {
color: {}
},
});
// export default Color;

@@ -11,12 +11,12 @@ import ColorSpace from "../space.js";

type: "angle",
name: "Hue"
name: "Hue",
},
s: {
range: [0, 100],
name: "Saturation"
name: "Saturation",
},
l: {
range: [0, 100],
name: "Lightness"
}
name: "Lightness",
},
},

@@ -26,3 +26,3 @@

// Adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
// Adapted from https://drafts.csswg.org/css-color-4/better-rgbToHsl.js
fromBase: rgb => {

@@ -32,3 +32,3 @@ let max = Math.max(...rgb);

let [r, g, b] = rgb;
let [h, s, l] = [NaN, 0, (min + max)/2];
let [h, s, l] = [NaN, 0, (min + max) / 2];
let d = max - min;

@@ -48,2 +48,14 @@

// Very out of gamut colors can produce negative saturation
// If so, just rotate the hue by 180 and use a positive saturation
// see https://github.com/w3c/csswg-drafts/issues/9222
if (s < 0) {
h += 180;
s = Math.abs(s);
}
if (h >= 360) {
h -= 360;
}
return [h, s * 100, l * 100];

@@ -65,3 +77,3 @@ },

function f (n) {
let k = (n + h/30) % 12;
let k = (n + h / 30) % 12;
let a = s * Math.min(l, 1 - l);

@@ -76,3 +88,2 @@ return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));

"hsl": {
toGamut: true,
coords: ["<number> | <angle>", "<percentage>", "<percentage>"],

@@ -84,4 +95,4 @@ },

lastAlpha: true,
}
},
},
});

@@ -16,12 +16,12 @@ import ColorSpace from "../space.js";

type: "angle",
name: "Hue"
name: "Hue",
},
s: {
range: [0, 100],
name: "Saturation"
name: "Saturation",
},
v: {
range: [0, 100],
name: "Value"
}
name: "Value",
},
},

@@ -40,4 +40,4 @@

h, // h is the same
v === 0? 0 : 200 * (1 - l / v), // s
100 * v
v === 0 ? 0 : 200 * (1 - l / v), // s
100 * v,
];

@@ -52,15 +52,17 @@ },

let l = v * (1 - s/2);
let l = v * (1 - s / 2);
return [
h, // h is the same
(l === 0 || l === 1)? 0 : ((v - l) / Math.min(l, 1 - l)) * 100,
l * 100
(l === 0 || l === 1) ? 0 : ((v - l) / Math.min(l, 1 - l)) * 100,
l * 100,
];
},
formats: {
color: {
toGamut: true,
}
}
id: "--hsv",
coords: ["<number> | <angle>", "<percentage> | <number>", "<percentage> | <number>"],
},
},
});

@@ -16,12 +16,12 @@ import ColorSpace from "../space.js";

type: "angle",
name: "Hue"
name: "Hue",
},
w: {
range: [0, 100],
name: "Whiteness"
name: "Whiteness",
},
b: {
range: [0, 100],
name: "Blackness"
}
name: "Blackness",
},
},

@@ -45,4 +45,4 @@

if (sum >= 1) {
let gray = w / sum;
return [h, 0, gray * 100];
let gray = w / sum;
return [h, 0, gray * 100];
}

@@ -57,6 +57,5 @@

"hwb": {
toGamut: true,
coords: ["<number> | <angle>", "<percentage>", "<percentage>"],
}
}
coords: ["<number> | <angle>", "<percentage> | <number>", "<percentage> | <number>"],
},
},
});

@@ -16,5 +16,5 @@ import ColorSpace from "../space.js";

const XYZtoLMS_M = [
[ 0.3592, 0.6976, -0.0358],
[-0.1922, 1.1004, 0.0755],
[ 0.0070, 0.0749, 0.8434]
[ 0.3592832590121217, 0.6976051147779502, -0.0358915932320290 ],
[ -0.1920808463704993, 1.1004767970374321, 0.0753748658519118 ],
[ 0.0070797844607479, 0.0748396662186362, 0.8433265453898765 ],
];

@@ -39,3 +39,3 @@ // linear-light Rec.2020 to LMS, again with crosstalk

[ 6610 / 4096, -13613 / 4096, 7003 / 4096 ],
[ 17933 / 4096, -17390 / 4096, -543 / 4096 ]
[ 17933 / 4096, -17390 / 4096, -543 / 4096 ],
];

@@ -45,5 +45,5 @@

const IPTtoLMS_M = [
[0.99998889656284013833, 0.00860505014728705821, 0.1110343715986164786 ],
[1.0000111034371598616, -0.00860505014728705821, -0.1110343715986164786 ],
[1.000032063391005412, 0.56004913547279000113, -0.32063391005412026469],
[ 0.9999999999999998, 0.0086090370379328, 0.1110296250030260 ],
[ 0.9999999999999998, -0.0086090370379328, -0.1110296250030259 ],
[ 0.9999999999999998, 0.5600313357106791, -0.3206271749873188 ],
];

@@ -58,5 +58,5 @@ /*

const LMStoXYZ_M = [
[ 2.0701800566956135096, -1.3264568761030210255, 0.20661600684785517081 ],
[ 0.36498825003265747974, 0.68046736285223514102, -0.045421753075853231409],
[-0.049595542238932107896, -0.049421161186757487412, 1.1879959417328034394 ]
[ 2.0701522183894223, -1.3263473389671563, 0.2066510476294053 ],
[ 0.3647385209748072, 0.6805660249472273, -0.0453045459220347 ],
[ -0.0497472075358123, -0.0492609666966131, 1.1880659249923042 ],
];

@@ -86,12 +86,12 @@

refRange: [0, 1], // Constant luminance,
name: "I"
name: "I",
},
ct: {
refRange: [-0.5, 0.5], // Full BT.2020 gamut in range [-0.5, 0.5]
name: "CT"
name: "CT",
},
cp: {
refRange: [-0.5, 0.5],
name: "CP"
}
name: "CP",
},
},

@@ -111,5 +111,2 @@

},
formats: {
color: {}
},
});

@@ -116,0 +113,0 @@

@@ -22,3 +22,9 @@ export {default as XYZ_D65} from "./xyz-d65.js";

export {default as OKLCH} from "./oklch.js";
export {default as CAM16_JMh} from "./cam16.js";
export {default as HCT} from "./hct.js";
export {default as Luv} from "./luv.js";
export {default as LCHuv} from "./lchuv.js";
export {default as HSLuv} from "./hsluv.js";
export {default as HPLuv} from "./hpluv.js";
export * from "./index-fn-hdr.js";

@@ -20,3 +20,3 @@ import ColorSpace from "../space.js";

[ -0.2015100, 1.120649, 0.0531008 ],
[ -0.0166008, 0.264800, 0.6684799 ]
[ -0.0166008, 0.264800, 0.6684799 ],
];

@@ -27,3 +27,3 @@ // XYZtoCone_M inverted

[ 0.35031676209499907, 0.7264811939316552, -0.06538442294808501 ],
[ -0.09098281098284752, -0.3127282905230739, 1.5227665613052603 ]
[ -0.09098281098284752, -0.3127282905230739, 1.5227665613052603 ],
];

@@ -33,3 +33,3 @@ const ConetoIab_M = [

[ 3.524000, -4.066708, 0.542708 ],
[ 0.199076, 1.096799, -1.295875 ]
[ 0.199076, 1.096799, -1.295875 ],
];

@@ -40,3 +40,3 @@ // ConetoIab_M inverted

[ 0.9999999999999999, -0.1386050432715393, -0.05804731615611886 ],
[ 0.9999999999999998, -0.09601924202631895, -0.8118918960560388 ]
[ 0.9999999999999998, -0.09601924202631895, -0.8118918960560388 ],
];

@@ -57,3 +57,3 @@

refRange: [-0.5, 0.5],
}
},
},

@@ -112,4 +112,4 @@

// restore standard D50 relative XYZ, relative to media white
let Xa = (Xm + ((b -1) * Za)) / b;
let Ya = (Ym + ((g -1) * Xa)) / g;
let Xa = (Xm + ((b - 1) * Za)) / b;
let Ya = (Ym + ((g - 1) * Xa)) / g;
return [ Xa, Ya, Za ];

@@ -120,4 +120,6 @@ },

// https://drafts.csswg.org/css-color-hdr/#Jzazbz
"color": {}
}
"color": {
coords: ["<number> | <percentage>", "<number> | <percentage>[-1,1]", "<number> | <percentage>[-1,1]"],
},
},
});

@@ -21,3 +21,3 @@ import ColorSpace from "../space.js";

name: "Hue",
}
},
},

@@ -42,3 +42,3 @@

Math.sqrt(az ** 2 + bz ** 2), // Chroma
constrainAngle(hue) // Hue, in degrees [0 to 360)
constrainAngle(hue), // Hue, in degrees [0 to 360)
];

@@ -52,8 +52,5 @@ },

jzczhz[1] * Math.cos(jzczhz[2] * Math.PI / 180), // az
jzczhz[1] * Math.sin(jzczhz[2] * Math.PI / 180) // bz
jzczhz[1] * Math.sin(jzczhz[2] * Math.PI / 180), // bz
];
},
formats: {
color: {}
},
});

@@ -6,5 +6,5 @@ import ColorSpace from "../space.js";

// κ * ε = 2^3 = 8
const ε = 216/24389; // 6^3/29^3 == (24/116)^3
const ε3 = 24/116;
const κ = 24389/27; // 29^3/3^3
const ε = 216 / 24389; // 6^3/29^3 == (24/116)^3
const ε3 = 24 / 116;
const κ = 24389 / 27; // 29^3/3^3

@@ -19,10 +19,10 @@ let white = WHITES.D65;

refRange: [0, 100],
name: "L"
name: "Lightness",
},
a: {
refRange: [-125, 125]
refRange: [-125, 125],
},
b: {
refRange: [-125, 125]
}
refRange: [-125, 125],
},
},

@@ -42,8 +42,8 @@

// now compute f
let f = xyz.map(value => value > ε ? Math.cbrt(value) : (κ * value + 16)/116);
let f = xyz.map(value => value > ε ? Math.cbrt(value) : (κ * value + 16) / 116);
return [
(116 * f[1]) - 16, // L
(116 * f[1]) - 16, // L
500 * (f[0] - f[1]), // a
200 * (f[1] - f[2]) // b
200 * (f[1] - f[2]), // b
];

@@ -57,11 +57,11 @@ },

let f = [];
f[1] = (Lab[0] + 16)/116;
f[0] = Lab[1]/500 + f[1];
f[2] = f[1] - Lab[2]/200;
f[1] = (Lab[0] + 16) / 116;
f[0] = Lab[1] / 500 + f[1];
f[2] = f[1] - Lab[2] / 200;
// compute xyz
let xyz = [
f[0] > ε3 ? Math.pow(f[0], 3) : (116*f[0]-16)/κ,
Lab[0] > 8 ? Math.pow((Lab[0]+16)/116, 3) : Lab[0]/κ,
f[2] > ε3 ? Math.pow(f[2], 3) : (116*f[2]-16)/κ
f[0] > ε3 ? Math.pow(f[0], 3) : (116 * f[0] - 16) / κ,
Lab[0] > 8 ? Math.pow((Lab[0] + 16) / 116, 3) : Lab[0] / κ,
f[2] > ε3 ? Math.pow(f[2], 3) : (116 * f[2] - 16) / κ,
];

@@ -76,4 +76,4 @@

coords: ["<number> | <percentage>", "<number> | <percentage>[-1,1]", "<number> | <percentage>[-1,1]"],
}
}
},
},
});

@@ -6,5 +6,5 @@ import ColorSpace from "../space.js";

// κ * ε = 2^3 = 8
const ε = 216/24389; // 6^3/29^3 == (24/116)^3
const ε3 = 24/116;
const κ = 24389/27; // 29^3/3^3
const ε = 216 / 24389; // 6^3/29^3 == (24/116)^3
const ε3 = 24 / 116;
const κ = 24389 / 27; // 29^3/3^3

@@ -19,10 +19,10 @@ let white = WHITES.D50;

refRange: [0, 100],
name: "L"
name: "Lightness",
},
a: {
refRange: [-125, 125]
refRange: [-125, 125],
},
b: {
refRange: [-125, 125]
}
refRange: [-125, 125],
},
},

@@ -42,8 +42,8 @@

// now compute f
let f = xyz.map(value => value > ε ? Math.cbrt(value) : (κ * value + 16)/116);
let f = xyz.map(value => value > ε ? Math.cbrt(value) : (κ * value + 16) / 116);
return [
(116 * f[1]) - 16, // L
(116 * f[1]) - 16, // L
500 * (f[0] - f[1]), // a
200 * (f[1] - f[2]) // b
200 * (f[1] - f[2]), // b
];

@@ -57,11 +57,11 @@ },

let f = [];
f[1] = (Lab[0] + 16)/116;
f[0] = Lab[1]/500 + f[1];
f[2] = f[1] - Lab[2]/200;
f[1] = (Lab[0] + 16) / 116;
f[0] = Lab[1] / 500 + f[1];
f[2] = f[1] - Lab[2] / 200;
// compute xyz
let xyz = [
f[0] > ε3 ? Math.pow(f[0], 3) : (116*f[0]-16)/κ,
Lab[0] > 8 ? Math.pow((Lab[0]+16)/116, 3) : Lab[0]/κ,
f[2] > ε3 ? Math.pow(f[2], 3) : (116*f[2]-16)/κ
f[0] > ε3 ? Math.pow(f[0], 3) : (116 * f[0] - 16) / κ,
Lab[0] > 8 ? Math.pow((Lab[0] + 16) / 116, 3) : Lab[0] / κ,
f[2] > ε3 ? Math.pow(f[2], 3) : (116 * f[2] - 16) / κ,
];

@@ -76,4 +76,4 @@

coords: ["<number> | <percentage>", "<number> | <percentage>[-1,1]", "<number> | <percentage>[-1,1]"],
}
}
},
},
});

@@ -11,7 +11,7 @@ import ColorSpace from "../space.js";

refRange: [0, 100],
name: "Lightness"
name: "Lightness",
},
c: {
refRange: [0, 150],
name: "Chroma"
name: "Chroma",
},

@@ -21,4 +21,4 @@ h: {

type: "angle",
name: "Hue"
}
name: "Hue",
},
},

@@ -43,3 +43,3 @@

Math.sqrt(a ** 2 + b ** 2), // Chroma
constrainAngle(hue) // Hue, in degrees [0 to 360)
constrainAngle(hue), // Hue, in degrees [0 to 360)
];

@@ -53,3 +53,3 @@ },

Chroma = 0;
};
}
// Deal with NaN Hue

@@ -62,3 +62,3 @@ if (isNaN(Hue)) {

Chroma * Math.cos(Hue * Math.PI / 180), // a
Chroma * Math.sin(Hue * Math.PI / 180) // b
Chroma * Math.sin(Hue * Math.PI / 180), // b
];

@@ -70,4 +70,4 @@ },

coords: ["<number> | <percentage>", "<number> | <percentage>", "<number> | <angle>"],
}
}
},
},
});

@@ -8,22 +8,22 @@ import ColorSpace from "../space.js";

const XYZtoLMS_M = [
[ 0.8190224432164319, 0.3619062562801221, -0.12887378261216414 ],
[ 0.0329836671980271, 0.9292868468965546, 0.03614466816999844 ],
[ 0.048177199566046255, 0.26423952494422764, 0.6335478258136937 ]
[ 0.8190224379967030, 0.3619062600528904, -0.1288737815209879 ],
[ 0.0329836539323885, 0.9292868615863434, 0.0361446663506424 ],
[ 0.0481771893596242, 0.2642395317527308, 0.6335478284694309 ],
];
// inverse of XYZtoLMS_M
const LMStoXYZ_M = [
[ 1.2268798733741557, -0.5578149965554813, 0.28139105017721583],
[ -0.04057576262431372, 1.1122868293970594, -0.07171106666151701],
[ -0.07637294974672142, -0.4214933239627914, 1.5869240244272418 ]
[ 1.2268798758459243, -0.5578149944602171, 0.2813910456659647 ],
[ -0.0405757452148008, 1.1122868032803170, -0.0717110580655164 ],
[ -0.0763729366746601, -0.4214933324022432, 1.5869240198367816 ],
];
const LMStoLab_M = [
[ 0.2104542553, 0.7936177850, -0.0040720468 ],
[ 1.9779984951, -2.4285922050, 0.4505937099 ],
[ 0.0259040371, 0.7827717662, -0.8086757660 ]
[ 0.2104542683093140, 0.7936177747023054, -0.0040720430116193 ],
[ 1.9779985324311684, -2.4285922420485799, 0.4505937096174110 ],
[ 0.0259040424655478, 0.7827717124575296, -0.8086757549230774 ],
];
// LMStoIab_M inverted
const LabtoLMS_M = [
[ 0.99999999845051981432, 0.39633779217376785678, 0.21580375806075880339 ],
[ 1.0000000088817607767, -0.1055613423236563494, -0.063854174771705903402 ],
[ 1.0000000546724109177, -0.089484182094965759684, -1.2914855378640917399 ]
[ 1.0000000000000000, 0.3963377773761749, 0.2158037573099136 ],
[ 1.0000000000000000, -0.1055613458156586, -0.0638541728258133 ],
[ 1.0000000000000000, -0.0894841775298119, -1.2914855480194092 ],
];

@@ -33,18 +33,18 @@

id: "oklab",
name: "Oklab",
coords: {
name: "Oklab",
coords: {
l: {
refRange: [0, 1],
name: "L"
name: "Lightness",
},
a: {
refRange: [-0.4, 0.4]
refRange: [-0.4, 0.4],
},
b: {
refRange: [-0.4, 0.4]
}
},
refRange: [-0.4, 0.4],
},
},
// Note that XYZ is relative to D65
white: "D65",
white: "D65",
base: XYZ_D65,

@@ -74,4 +74,4 @@ fromBase (XYZ) {

coords: ["<percentage> | <number>", "<number> | <percentage>[-1,1]", "<number> | <percentage>[-1,1]"],
}
}
},
},
});

@@ -11,7 +11,7 @@ import ColorSpace from "../space.js";

refRange: [0, 1],
name: "Lightness"
name: "Lightness",
},
c: {
refRange: [0, 0.4],
name: "Chroma"
name: "Chroma",
},

@@ -21,4 +21,4 @@ h: {

type: "angle",
name: "Hue"
}
name: "Hue",
},
},

@@ -44,3 +44,3 @@ white: "D65",

Math.sqrt(a ** 2 + b ** 2), // Chroma
constrainAngle(h) // Hue, in degrees [0 to 360)
constrainAngle(h), // Hue, in degrees [0 to 360)
];

@@ -68,5 +68,5 @@ },

"oklch": {
coords: ["<number> | <percentage>", "<number> | <percentage>[0,1]", "<number> | <angle>"],
}
}
coords: ["<percentage> | <number>", "<number> | <percentage>[0,1]", "<number> | <angle>"],
},
},
});

@@ -6,3 +6,3 @@ import RGBColorSpace from "../rgbspace.js";

[0.2289745640697488, 0.6917385218365064, 0.079286914093745],
[0.0000000000000000, 0.04511338185890264, 1.043944368900976]
[0.0000000000000000, 0.04511338185890264, 1.043944368900976],
];

@@ -13,3 +13,3 @@

[-0.8294889695615747, 1.7626640603183463, 0.023624685841943577],
[ 0.03584583024378447, -0.07617238926804182, 0.9568845240076872]
[ 0.03584583024378447, -0.07617238926804182, 0.9568845240076872],
];

@@ -19,6 +19,7 @@

id: "p3-linear",
cssId: "--display-p3-linear",
name: "Linear P3",
white: "D65",
toXYZ_M,
fromXYZ_M
fromXYZ_M,
});

@@ -7,2 +7,3 @@ import RGBColorSpace from "../rgbspace.js";

id: "p3",
cssId: "display-p3",
name: "P3",

@@ -13,7 +14,2 @@ base: P3Linear,

toBase: sRGB.toBase,
formats: {
color: {
id: "display-p3",
}
},
});

@@ -6,13 +6,14 @@ import RGBColorSpace from "../rgbspace.js";

// using D50 (so no chromatic adaptation needed afterwards)
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
// matrix cannot be expressed in rational form, but is calculated to 64 bit accuracy
// see https://github.com/w3c/csswg-drafts/issues/7675
const toXYZ_M = [
[ 0.7977604896723027, 0.13518583717574031, 0.0313493495815248 ],
[ 0.2880711282292934, 0.7118432178101014, 0.00008565396060525902 ],
[ 0.0, 0.0, 0.8251046025104601 ]
[ 0.79776664490064230, 0.13518129740053308, 0.03134773412839220 ],
[ 0.28807482881940130, 0.71183523424187300, 0.00008993693872564 ],
[ 0.00000000000000000, 0.00000000000000000, 0.82510460251046020 ],
];
const fromXYZ_M = [
[ 1.3457989731028281, -0.25558010007997534, -0.05110628506753401 ],
[ -0.5446224939028347, 1.5082327413132781, 0.02053603239147973 ],
[ 0.0, 0.0, 1.2119675456389454 ]
[ 1.34578688164715830, -0.25557208737979464, -0.05110186497554526 ],
[ -0.54463070512490190, 1.50824774284514680, 0.02052744743642139 ],
[ 0.00000000000000000, 0.00000000000000000, 1.21196754563894520 ],
];

@@ -22,2 +23,3 @@

id: "prophoto-linear",
cssId: "--prophoto-rgb-linear",
name: "Linear ProPhoto",

@@ -27,3 +29,3 @@ white: "D50",

toXYZ_M,
fromXYZ_M
fromXYZ_M,
});
import RGBColorSpace from "../rgbspace.js";
import ProPhotoLinear from "./prophoto-linear.js";
const Et = 1/512;
const Et2 = 16/512;
const Et = 1 / 512;
const Et2 = 16 / 512;
export default new RGBColorSpace({
id: "prophoto",
cssId: "prophoto-rgb",
name: "ProPhoto",

@@ -13,12 +14,7 @@ base: ProPhotoLinear,

// Transfer curve is gamma 1.8 with a small linear portion
return RGB.map(v => v < Et2? v / 16 : v ** 1.8);
return RGB.map(v => v < Et2 ? v / 16 : v ** 1.8);
},
fromBase (RGB) {
return RGB.map(v => v >= Et? v ** (1/1.8) : 16 * v);
return RGB.map(v => v >= Et ? v ** (1 / 1.8) : 16 * v);
},
formats: {
color: {
id: "prophoto-rgb"
}
},
});

@@ -10,3 +10,3 @@ import RGBColorSpace from "../rgbspace.js";

[ 0.2627002120112671, 0.6779980715188708, 0.05930171646986196 ],
[ 0.000000000000000, 0.028072693049087428, 1.060985057710791 ]
[ 0.000000000000000, 0.028072693049087428, 1.060985057710791 ],
];

@@ -18,3 +18,3 @@

[ -0.666684351832489, 1.616481236634939, 0.0157685458139111 ],
[ 0.017639857445311, -0.042770613257809, 0.942103121235474 ]
[ 0.017639857445311, -0.042770613257809, 0.942103121235474 ],
];

@@ -24,2 +24,3 @@

id: "rec2020-linear",
cssId: "--rec2020-linear",
name: "Linear REC.2020",

@@ -29,5 +30,2 @@ white: "D65",

fromXYZ_M,
formats: {
color: {},
}
});

@@ -15,7 +15,7 @@ import RGBColorSpace from "../rgbspace.js";

return RGB.map(function (val) {
if (val < β * 4.5 ) {
if (val < β * 4.5) {
return val / 4.5;
}
return Math.pow((val + α -1 ) / α, 1/0.45);
return Math.pow((val + α - 1) / α, 1 / 0.45);
});

@@ -25,3 +25,3 @@ },

return RGB.map(function (val) {
if (val >= β ) {
if (val >= β) {
return α * Math.pow(val, 0.45) - (α - 1);

@@ -33,5 +33,2 @@ }

},
formats: {
color: {},
}
});

@@ -14,3 +14,3 @@ import RGBColorSpace from "../rgbspace.js";

id: "rec2100hlg",
cssid: "rec2100-hlg",
cssId: "rec2100-hlg",
name: "REC.2100-HLG",

@@ -44,4 +44,4 @@ referred: "scene",

// 6.1 The hybrid log-gamma opto-electronic transfer function (OETF)
if (val <= 1/12) {
return Math.sqrt( 3 * val);
if (val <= 1 / 12) {
return Math.sqrt(3 * val);
}

@@ -51,7 +51,2 @@ return a * Math.log(12 * val - b) + c;

},
formats: {
color: {
id: "rec2100-hlg"
},
},
});

@@ -15,2 +15,3 @@ import RGBColorSpace from "../rgbspace.js";

id: "rec2100pq",
cssId: "rec2100-pq",
name: "REC.2100-PQ",

@@ -37,7 +38,2 @@ base: REC2020Linear,

},
formats: {
color: {
id: "rec2100-pq"
},
},
});

@@ -13,3 +13,3 @@ import RGBColorSpace from "../rgbspace.js";

[ 0.21263900587151027, 0.715168678767756, 0.07219231536073371 ],
[ 0.01933081871559182, 0.11919477979462598, 0.9505321522496607 ]
[ 0.01933081871559182, 0.11919477979462598, 0.9505321522496607 ],
];

@@ -19,6 +19,6 @@

// again it agrees with the official definition when rounded to 8 decimal places
const fromXYZ_M = [
export const fromXYZ_M = [
[ 3.2409699419045226, -1.537383177570094, -0.4986107602930034 ],
[ -0.9692436362808796, 1.8759675015077202, 0.04155505740717559 ],
[ 0.05563007969699366, -0.20397695888897652, 1.0569715142428786 ]
[ 0.05563007969699366, -0.20397695888897652, 1.0569715142428786 ],
];

@@ -32,5 +32,2 @@

fromXYZ_M,
formats: {
color: {}
},
});

@@ -17,7 +17,7 @@ import RGBColorSpace from "../rgbspace.js";

return rgb.map(val => {
let sign = val < 0? -1 : 1;
let sign = val < 0 ? -1 : 1;
let abs = val * sign;
if (abs > 0.0031308) {
return sign * (1.055 * (abs ** (1/2.4)) - 0.055);
return sign * (1.055 * (abs ** (1 / 2.4)) - 0.055);
}

@@ -33,6 +33,6 @@

return rgb.map(val => {
let sign = val < 0? -1 : 1;
let sign = val < 0 ? -1 : 1;
let abs = val * sign;
if (abs < 0.04045) {
if (abs <= 0.04045) {
return val / 12.92;

@@ -63,3 +63,3 @@ }

commas: true,
coords: coordGrammarNumber
coords: coordGrammarNumber,
},

@@ -84,7 +84,7 @@ "hex": {

coords: rgba.slice(0, 3),
alpha: rgba.slice(3)[0]
alpha: rgba.slice(3)[0],
};
},
serialize: (coords, alpha, {
collapse = true // collapse to 3-4 digit hex when possible?
collapse = true, // collapse to 3-4 digit hex when possible?
} = {}) => {

@@ -101,3 +101,3 @@ if (alpha < 1) {

if (collapsible) {
return (c/17).toString(16);
return (c / 17).toString(16);
}

@@ -109,3 +109,3 @@

return "#" + hex;
}
},
},

@@ -130,5 +130,5 @@ "keyword": {

}
}
},
},
}
},
});

@@ -12,2 +12,3 @@ import ColorSpace from "../space.js";

id: "xyz-abs-d65",
cssId: "--xyz-abs-d65",
name: "Absolute XYZ D65",

@@ -26,3 +27,3 @@ coords: {

name: "Za",
}
},
},

@@ -40,3 +41,3 @@

return AbsXYZ.map(v => Math.max(v / Yw, 0));
}
},
});

@@ -12,5 +12,2 @@ import ColorSpace from "../space.js";

toBase: coords => adapt("D50", XYZ_D65.white, coords),
formats: {
color: {}
},
});

@@ -15,5 +15,5 @@ import ColorSpace from "../space.js";

ids: ["xyz-d65", "xyz"],
}
},
},
aliases: ["xyz"],
});

@@ -20,3 +20,3 @@ import getColor from "./getColor.js";

if (inGamut) {
ret = toGamut(ret);
ret = toGamut(ret, inGamut === true ? undefined : inGamut);
}

@@ -23,0 +23,0 @@

@@ -5,15 +5,48 @@ import * as util from "./util.js";

import deltaE2000 from "./deltaE/deltaE2000.js";
import deltaEOK from "./deltaE/deltaEOK.js";
import inGamut from "./inGamut.js";
import to from "./to.js";
import get from "./get.js";
import oklab from "./spaces/oklab.js";
import set from "./set.js";
import clone from "./clone.js";
import getColor from "./getColor.js";
import deltaEMethods from "./deltaE/index.js";
import {WHITES} from "./adapt.js";
/**
* Calculate the epsilon to 2 degrees smaller than the specified JND.
* @param {Number} jnd - The target "just noticeable difference".
* @returns {Number}
*/
function calcEpsilon (jnd) {
// Calculate the epsilon to 2 degrees smaller than the specified JND.
const order = (!jnd) ? 0 : Math.floor(Math.log10(Math.abs(jnd)));
// Limit to an arbitrary value to ensure value is never too small and causes infinite loops.
return Math.max(parseFloat(`1e${order - 2}`), 1e-6);
}
const GMAPPRESET = {
"hct": {
method: "hct.c",
jnd: 2,
deltaEMethod: "hct",
blackWhiteClamp: {},
},
"hct-tonal": {
method: "hct.c",
jnd: 0,
deltaEMethod: "hct",
blackWhiteClamp: { channel: "hct.t", min: 0, max: 100 },
},
};
/**
* Force coordinates to be in gamut of a certain color space.
* Mutates the color it is passed.
* @param {Object} options
* @param {Object|string} options object or spaceId string
* @param {string} options.method - How to force into gamut.
* If "clip", coordinates are just clipped to their reference range.
* If "css", coordinates are reduced according to the CSS 4 Gamut Mapping Algorithm.
* If in the form [colorSpaceId].[coordName], that coordinate is reduced

@@ -23,14 +56,32 @@ * until the color is in gamut. Please note that this may produce nonsensical

* @param {ColorSpace|string} options.space - The space whose gamut we want to map to
* @param {string} options.deltaEMethod - The delta E method to use while performing gamut mapping.
* If no method is specified, delta E 2000 is used.
* @param {Number} options.jnd - The "just noticeable difference" to target.
* @param {Object} options.blackWhiteClamp - Used to configure SDR black and clamping.
* "channel" indicates the "space.channel" to use for determining when to clamp.
* "min" indicates the lower limit for black clamping and "max" indicates the upper
* limit for white clamping.
*/
export default function toGamut (color, {method = defaults.gamut_mapping, space = color.space} = {}) {
export default function toGamut (
color,
{
method = defaults.gamut_mapping,
space = undefined,
deltaEMethod = "",
jnd = 2,
blackWhiteClamp = {},
} = {},
) {
color = getColor(color);
if (util.isString(arguments[1])) {
space = arguments[1];
}
else if (!space) {
space = color.space;
}
space = ColorSpace.get(space);
if (inGamut(color, space, {epsilon: 0})) {
return getColor(color);
}
// 3 spaces:

@@ -40,60 +91,110 @@ // color.space: current color space

// mapSpace: space with the coord we're reducing
let spaceColor = to(color, space);
if (method !== "clip" && !inGamut(color, space)) {
let clipped = toGamut(clone(spaceColor), {method: "clip", space});
if (deltaE2000(color, clipped) > 2) {
// Reduce a coordinate of a certain color space until the color is in gamut
let coordMeta = ColorSpace.resolveCoord(method);
let mapSpace = coordMeta.space;
let coordId = coordMeta.id;
if (inGamut(color, space, { epsilon: 0 })) {
return color;
}
let mappedColor = to(spaceColor, mapSpace);
let bounds = coordMeta.range || coordMeta.refRange;
let min = bounds[0];
let ε = .01; // for deltaE
let low = min;
let high = get(mappedColor, coordId);
let spaceColor;
if (method === "css") {
spaceColor = toGamutCSS(color, { space });
}
else {
if (method !== "clip" && !inGamut(color, space)) {
while (high - low > ε) {
let clipped = clone(mappedColor);
clipped = toGamut(clipped, {space, method: "clip"});
let deltaE = deltaE2000(mappedColor, clipped);
if (Object.prototype.hasOwnProperty.call(GMAPPRESET, method)) {
({method, jnd, deltaEMethod, blackWhiteClamp} = GMAPPRESET[method]);
}
if (deltaE - 2 < ε) {
low = get(mappedColor, coordId);
// Get the correct delta E method
let de = deltaE2000;
if (deltaEMethod !== "") {
for (let m in deltaEMethods) {
if ("deltae" + deltaEMethod.toLowerCase() === m.toLowerCase()) {
de = deltaEMethods[m];
break;
}
}
else {
high = get(mappedColor, coordId);
}
let clipped = toGamut(to(color, space), { method: "clip", space });
if (de(color, clipped) > jnd) {
// Clamp to SDR white and black if required
if (Object.keys(blackWhiteClamp).length === 3) {
let channelMeta = ColorSpace.resolveCoord(blackWhiteClamp.channel);
let channel = get(to(color, channelMeta.space), channelMeta.id);
if (util.isNone(channel)) {
channel = 0;
}
if (channel >= blackWhiteClamp.max) {
return to({ space: "xyz-d65", coords: WHITES["D65"] }, color.space);
}
else if (channel <= blackWhiteClamp.min) {
return to({ space: "xyz-d65", coords: [0, 0, 0] }, color.space);
}
}
set(mappedColor, coordId, (low + high) / 2);
// Reduce a coordinate of a certain color space until the color is in gamut
let coordMeta = ColorSpace.resolveCoord(method);
let mapSpace = coordMeta.space;
let coordId = coordMeta.id;
let mappedColor = to(color, mapSpace);
// If we were already in the mapped color space, we need to resolve undefined channels
mappedColor.coords.forEach((c, i) => {
if (util.isNone(c)) {
mappedColor.coords[i] = 0;
}
});
let bounds = coordMeta.range || coordMeta.refRange;
let min = bounds[0];
let ε = calcEpsilon(jnd);
let low = min;
let high = get(mappedColor, coordId);
while (high - low > ε) {
let clipped = clone(mappedColor);
clipped = toGamut(clipped, { space, method: "clip" });
let deltaE = de(mappedColor, clipped);
if (deltaE - jnd < ε) {
low = get(mappedColor, coordId);
}
else {
high = get(mappedColor, coordId);
}
set(mappedColor, coordId, (low + high) / 2);
}
spaceColor = to(mappedColor, space);
}
spaceColor = to(mappedColor, space);
else {
spaceColor = clipped;
}
}
else {
spaceColor = clipped;
spaceColor = to(color, space);
}
}
if (method === "clip" // Dumb coord clipping
// finish off smarter gamut mapping with clip to get rid of ε, see #17
|| !inGamut(spaceColor, space, {epsilon: 0})
) {
let bounds = Object.values(space.coords).map(c => c.range || []);
if (method === "clip" // Dumb coord clipping
// finish off smarter gamut mapping with clip to get rid of ε, see #17
|| !inGamut(spaceColor, space, { epsilon: 0 })
) {
let bounds = Object.values(space.coords).map(c => c.range || []);
spaceColor.coords = spaceColor.coords.map((c, i) => {
let [min, max] = bounds[i];
spaceColor.coords = spaceColor.coords.map((c, i) => {
let [min, max] = bounds[i];
if (min !== undefined) {
c = Math.max(min, c);
}
if (min !== undefined) {
c = Math.max(min, c);
}
if (max !== undefined) {
c = Math.min(c, max);
}
if (max !== undefined) {
c = Math.min(c, max);
}
return c;
});
return c;
});
}
}

@@ -110,1 +211,104 @@

toGamut.returns = "color";
// The reference colors to be used if lightness is out of the range 0-1 in the
// `Oklch` space. These are created in the `Oklab` space, as it is used by the
// DeltaEOK calculation, so it is guaranteed to be imported.
const COLORS = {
WHITE: { space: oklab, coords: [1, 0, 0] },
BLACK: { space: oklab, coords: [0, 0, 0] },
};
/**
* Given a color `origin`, returns a new color that is in gamut using
* the CSS Gamut Mapping Algorithm. If `space` is specified, it will be in gamut
* in `space`, and returned in `space`. Otherwise, it will be in gamut and
* returned in the color space of `origin`.
* @param {Object} origin
* @param {Object} options
* @param {ColorSpace|string} options.space
* @returns {Color}
*/
export function toGamutCSS (origin, {space} = {}) {
const JND = 0.02;
const ε = 0.0001;
origin = getColor(origin);
if (!space) {
space = origin.space;
}
space = ColorSpace.get(space);
const oklchSpace = ColorSpace.get("oklch");
if (space.isUnbounded) {
return to(origin, space);
}
const origin_OKLCH = to(origin, oklchSpace);
let L = origin_OKLCH.coords[0];
// return media white or black, if lightness is out of range
if (L >= 1) {
const white = to(COLORS.WHITE, space);
white.alpha = origin.alpha;
return to(white, space);
}
if (L <= 0) {
const black = to(COLORS.BLACK, space);
black.alpha = origin.alpha;
return to(black, space);
}
if (inGamut(origin_OKLCH, space, {epsilon: 0})) {
return to(origin_OKLCH, space);
}
function clip (_color) {
const destColor = to(_color, space);
const spaceCoords = Object.values(space.coords);
destColor.coords = destColor.coords.map((coord, index) => {
if ("range" in spaceCoords[index]) {
const [min, max] = spaceCoords[index].range;
return util.clamp(min, coord, max);
}
return coord;
});
return destColor;
}
let min = 0;
let max = origin_OKLCH.coords[1];
let min_inGamut = true;
let current = clone(origin_OKLCH);
let clipped = clip(current);
let E = deltaEOK(clipped, current);
if (E < JND) {
return clipped;
}
while ((max - min) > ε) {
const chroma = (min + max) / 2;
current.coords[1] = chroma;
if (min_inGamut && inGamut(current, space, {epsilon: 0})) {
min = chroma;
}
else {
clipped = clip(current);
E = deltaEOK(clipped, current);
if (E < JND) {
if ((JND - E < ε)) {
break;
}
else {
min_inGamut = false;
min = chroma;
}
}
else {
max = chroma;
}
}
}
return clipped;
}

@@ -27,3 +27,27 @@ /**

export function serializeNumber (n, {precision, unit }) {
if (isNone(n)) {
return "none";
}
return toPrecision(n, precision) + (unit ?? "");
}
/**
* Check if a value corresponds to a none argument
* @param {*} n - Value to check
* @returns {boolean}
*/
export function isNone (n) {
return Number.isNaN(n) || (n instanceof Number && n?.none);
}
/**
* Replace none values with 0
*/
export function skipNone (n) {
return isNone(n) ? 0 : n;
}
/**
* Round a number to a certain number of significant digits

@@ -34,15 +58,21 @@ * @param {number} n - The number to round

export function toPrecision (n, precision) {
n = +n;
precision = +precision;
let integerLength = (Math.floor(n) + "").length;
if (precision > integerLength) {
return +n.toFixed(precision - integerLength);
if (n === 0) {
return 0;
}
else {
let p10 = 10 ** (integerLength - precision);
return Math.round(n / p10) * p10;
let integer = ~~n;
let digits = 0;
if (integer && precision) {
digits = ~~Math.log10(Math.abs(integer)) + 1;
}
const multiplier = 10.0 ** (precision - digits);
return Math.floor(n * multiplier + 0.5) / multiplier;
}
const angleFactor = {
deg: 1,
grad: 0.9,
rad: 180 / Math.PI,
turn: 360,
};
/**

@@ -62,2 +92,4 @@ * Parse a CSS function, regardless of its name and arguments

const isNumberRegex = /^-?[\d.]+$/;
const unitValueRegex = /%|deg|g?rad|turn$/;
const singleArgument = /\/?\s*(none|[-\w.]+(?:%|deg|g?rad|turn)?)/g;
let parts = str.match(isFunctionRegex);

@@ -68,15 +100,23 @@

let args = [];
parts[2].replace(/\/?\s*([-\w.]+(?:%|deg)?)/g, ($0, arg) => {
if (/%$/.test(arg)) {
// Convert percentages to 0-1 numbers
arg = new Number(arg.slice(0, -1) / 100);
arg.type = "<percentage>";
parts[2].replace(singleArgument, ($0, rawArg) => {
let match = rawArg.match(unitValueRegex);
let arg = rawArg;
if (match) {
let unit = match[0];
// Drop unit from value
let unitlessArg = arg.slice(0, -unit.length);
if (unit === "%") {
// Convert percentages to 0-1 numbers
arg = new Number(unitlessArg / 100);
arg.type = "<percentage>";
}
else {
// Multiply angle by appropriate factor for its unit
arg = new Number(unitlessArg * angleFactor[unit]);
arg.type = "<angle>";
arg.unit = unit;
}
}
else if (/deg$/.test(arg)) {
// Drop deg from degrees and convert to number
// TODO handle other units too
arg = new Number(+arg.slice(0, -3));
arg.type = "<angle>";
arg.unit = "deg";
}
else if (isNumberRegex.test(arg)) {

@@ -87,9 +127,17 @@ // Convert numerical args to numbers

}
else if (arg === "none") {
arg = new Number(NaN);
arg.none = true;
}
if ($0.startsWith("/")) {
// It's alpha
arg = arg instanceof Number? arg : new Number(arg);
arg = arg instanceof Number ? arg : new Number(arg);
arg.alpha = true;
}
if (typeof arg === "object" && arg instanceof Number) {
arg.raw = rawArg;
}
args.push(arg);

@@ -104,3 +152,3 @@ });

// a number, percentage, degrees (hue), ident (in color())
args
args,
};

@@ -150,1 +198,64 @@ }

}
/**
* Clamp value between the minimum and maximum
* @param {number} min minimum value to return
* @param {number} val the value to return if it is between min and max
* @param {number} max maximum value to return
* @returns number
*/
export function clamp (min, val, max) {
return Math.max(Math.min(max, val), min);
}
/**
* Copy sign of one value to another.
* @param {number} - to number to copy sign to
* @param {number} - from number to copy sign from
* @returns number
*/
export function copySign (to, from) {
return Math.sign(to) === Math.sign(from) ? to : -to;
}
/**
* Perform pow on a signed number and copy sign to result
* @param {number} - base the base number
* @param {number} - exp the exponent
* @returns number
*/
export function spow (base, exp) {
return copySign(Math.abs(base) ** exp, base);
}
/**
* Perform a divide, but return zero if the numerator is zero
* @param {number} n - the numerator
* @param {number} d - the denominator
* @returns number
*/
export function zdiv (n, d) {
return (d === 0) ? 0 : n / d;
}
/**
* Perform a bisect on a sorted list and locate the insertion point for
* a value in arr to maintain sorted order.
* @param {number[]} arr - array of sorted numbers
* @param {number} value - value to find insertion point for
* @param {number} lo - used to specify a the low end of a subset of the list
* @param {number} hi - used to specify a the high end of a subset of the list
* @returns number
*/
export function bisectLeft (arr, value, lo = 0, hi = arr.length) {
while (lo < hi) {
const mid = (lo + hi) >> 1;
if (arr[mid] < value) {
lo = mid + 1;
}
else {
hi = mid;
}
}
return lo;
}
// Definitions by: Adam Thompson-Sharpe <https://github.com/MysteryBlokHed>
// Minimum TypeScript Version: 4.1
export { default } from "./dist/color";
export { default } from "./src/index.js";
export type {
ColorConstructor,
ColorObject,
ColorTypes,
Coords,
DefineFunctionCode,
DefineFunctionOptions,
DefineFunctionHybrid,
PlainColorObject,
SpaceAccessor,
ToColorPrototype,
} from "./src/color.js";
export type { White } from "./src/adapt.js";
export type { CAT } from "./src/CATs.js";
export type { Display } from "./src/display.js";
export type {
Range,
RangeOptions,
MixOptions,
StepsOptions,
} from "./src/interpolation.js";
export type { Options as ParseOptions } from "./src/parse.js";
export type { RGBOptions } from "./src/rgbspace.js";
export type { Options as SerializeOptions } from "./src/serialize.js";
export type {
Format as SpaceFormat,
CoordMeta,
Ref,
Options as SpaceOptions,
} from "./src/space.js";

@@ -5,5 +5,5 @@ export type White = [number, number, number];

export function getWhite(name: string | White): White;
export function getWhite (name: string | White): White;
export default function adapt(
export default function adapt (
w1: White,

@@ -10,0 +10,0 @@ w2: White,

/** Constrain an angle to 360 degrees */
export function constrain(angle: number): number;
export function constrain (angle: number): number;
export function adjust(
export function adjust (
arc: "raw" | "increasing" | "decreasing" | "longer" | "shorter",
angles: [number, number]
): [number, number];

@@ -1,2 +0,2 @@

import { White } from "./adapt";
import { White } from "./adapt.js";

@@ -11,4 +11,4 @@ export interface CAT {

export function defineCAT(cat: CAT): void;
export function defineCAT (cat: CAT): void;
export function adapt(W1: White, W2: White, id?: string): number[];
export function adapt (W1: White, W2: White, id?: string): number[];

@@ -1,7 +0,7 @@

import Color, { ColorObject } from "./color";
import Color, { ColorTypes } from "./color.js";
export function uv(color: Color | ColorObject): [number, number];
export function uv (color: ColorTypes): [number, number];
export function xy(color: Color | ColorObject): [number, number];
export function xy (color: ColorTypes): [number, number];
export function register(color: typeof Color): void;
export function register (color: typeof Color): void;

@@ -1,3 +0,3 @@

import { PlainColorObject } from "./color";
import { PlainColorObject } from "./color.js";
export default function clone(color: PlainColorObject): PlainColorObject;
export default function clone (color: PlainColorObject): PlainColorObject;

@@ -1,22 +0,24 @@

import { WHITES } from "./adapt";
import defaults from "./defaults";
import hooks from "./hooks";
import * as util from "./util";
import ColorSpace from "./space";
import { WHITES } from "./adapt.js";
import defaults from "./defaults.js";
import hooks from "./hooks.js";
import * as util from "./util.js";
import ColorSpace, { Ref } from "./space.js";
import SpaceAccessors from "./space-coord-accessors.js";
import {
to,
to as toFn,
parse,
serialize,
inGamut,
toGamut,
distance,
equals,
inGamut as inGamutFn,
toGamut as toGamutFn,
distance as distanceFn,
equals as equalsFn,
get,
getAll,
set,
setAll,
getAll as getAllFn,
setAll as setAllFn,
display,
} from "./index-fn";
} from "./index-fn.js";
export type { SpaceAccessor } from "./space-coord-accessors.js";
export type Coords = [number, number, number];

@@ -57,3 +59,3 @@

? R
: Array<T[number]>;
: T[number][];

@@ -70,28 +72,39 @@ /** Convert a function to a prototype for Color */

/** Proxy used for space accessors */
export type SpaceAccessor = Record<string, number> & number[];
/** Convert a function to a Color namespace property (returning a Color) */
export type ToColorNamespace<T extends (...args: any[]) => any> = T extends (
...args: infer A
) => infer R
? T extends { returns: "color" }
? (...args: A) => Color
: (...args: A) => R
: never;
declare namespace Color {
export {
getAll,
set,
setAll,
to,
equals,
inGamut,
toGamut,
distance,
serialize as toString,
};
// Functions defined using Color.defineFunctions
export const getAll: ToColorNamespace<typeof getAllFn>;
export const setAll: ToColorNamespace<typeof setAllFn>;
export const to: ToColorNamespace<typeof toFn>;
export const equals: ToColorNamespace<typeof equalsFn>;
export const inGamut: ToColorNamespace<typeof inGamutFn>;
export const toGamut: ToColorNamespace<typeof toGamutFn>;
export const distance: ToColorNamespace<typeof distanceFn>;
// `get` is defined below as a static method on the Class,
// and `toString` is intentionally not overridden for the namespace
export { util, hooks, WHITES, ColorSpace as Space, parse, defaults };
export const spaces: typeof ColorSpace["registry"];
// Must be manually defined due to overloads
// These should always match the signature of the original function
export function set (color: ColorTypes, prop: Ref, value: number | ((coord: number) => number)): Color;
export function set (color: ColorTypes, props: Record<string, number | ((coord: number) => number)>): Color;
}
declare class Color implements PlainColorObject {
constructor(color: ColorTypes);
constructor(space: string | ColorSpace, coords: Coords, alpha?: number);
declare class Color extends SpaceAccessors implements PlainColorObject {
constructor (color: ColorTypes);
constructor (space: string | ColorSpace, coords: Coords, alpha?: number);
// These signatures should always be the same as the constructor
static get(color: ColorTypes): Color;
static get(
static get (color: ColorTypes): Color;
static get (
space: string | ColorSpace,

@@ -102,4 +115,4 @@ coords: Coords,

static defineFunction(name: string, code: DefineFunctionHybrid): void;
static defineFunction(
static defineFunction (name: string, code: DefineFunctionHybrid): void;
static defineFunction (
name: string,

@@ -110,12 +123,12 @@ code: DefineFunctionCode,

static defineFunctions(objects: Record<string, DefineFunctionHybrid>): void;
static defineFunctions (objects: Record<string, DefineFunctionHybrid>): void;
static extend(
static extend (
exports:
| { register: (color: typeof Color) => void }
| Record<string, DefineFunctionHybrid>
| { register: (color: typeof Color) => void }
| Record<string, DefineFunctionHybrid>
): void;
get space(): ColorSpace;
get spaceId(): string;
get space (): ColorSpace;
get spaceId (): string;

@@ -125,57 +138,28 @@ alpha: number;

clone(): this;
clone (): this;
// Copy parameter types from display function, except for the first one
display(
display (
...args: RemoveFirstElement<Parameters<typeof display>>
): string & { color: Color };
toJSON(): ColorConstructor;
toJSON (): ColorConstructor;
// Functions defined using Color.defineFunctions
get: ToColorPrototype<typeof get>;
getAll: ToColorPrototype<typeof getAll>;
set: ToColorPrototype<typeof set>;
setAll: ToColorPrototype<typeof setAll>;
to: ToColorPrototype<typeof to>;
equals: ToColorPrototype<typeof equals>;
inGamut: ToColorPrototype<typeof inGamut>;
toGamut: ToColorPrototype<typeof toGamut>;
distance: ToColorPrototype<typeof distance>;
getAll: ToColorPrototype<typeof getAllFn>;
setAll: ToColorPrototype<typeof setAllFn>;
to: ToColorPrototype<typeof toFn>;
equals: ToColorPrototype<typeof equalsFn>;
inGamut: ToColorPrototype<typeof inGamutFn>;
toGamut: ToColorPrototype<typeof toGamutFn>;
distance: ToColorPrototype<typeof distanceFn>;
toString: ToColorPrototype<typeof serialize>;
// Space accessors
// A property should technically be added every time a new ColorSpace is initialized,
// but I don't know that there's any good way to do that with TypeScript
a98rgb: SpaceAccessor;
a98rgb_linear: SpaceAccessor;
acescc: SpaceAccessor;
acescg: SpaceAccessor;
hsl: SpaceAccessor;
hsv: SpaceAccessor;
hwb: SpaceAccessor;
ictcp: SpaceAccessor;
jzazbz: SpaceAccessor;
jzczhz: SpaceAccessor;
lab: SpaceAccessor;
lab_d65: SpaceAccessor;
lch: SpaceAccessor;
oklab: SpaceAccessor;
oklch: SpaceAccessor;
p3: SpaceAccessor;
p3_linear: SpaceAccessor;
prophoto: SpaceAccessor;
prophoto_linear: SpaceAccessor;
rec2020: SpaceAccessor;
rec2020_linear: SpaceAccessor;
rec2100hlg: SpaceAccessor;
rec2100pq: SpaceAccessor;
srgb: SpaceAccessor;
srgb_linear: SpaceAccessor;
xyz: SpaceAccessor;
xyz_abs_d65: SpaceAccessor;
xyz_d50: SpaceAccessor;
xyz_d65: SpaceAccessor;
// Must be manually defined due to overloads
// These should always match the signature of the original function
set (prop: Ref, value: number | ((coord: number) => number)): Color;
set (props: Record<string, number | ((coord: number) => number)>): Color;
}
export default Color;

@@ -1,3 +0,3 @@

import { ColorTypes } from "./color";
import { Algorithms } from "./contrast/index";
import { ColorTypes } from "./color.js";
import { Algorithms } from "./contrast/index.js";

@@ -8,3 +8,3 @@ /**

*/
export default function contrast(
export default function contrast (
background: ColorTypes,

@@ -11,0 +11,0 @@ foreground: ColorTypes,

@@ -1,2 +0,2 @@

import { ColorTypes } from "../color";
import { ColorTypes } from "../color.js";
export default function (

@@ -3,0 +3,0 @@ background: ColorTypes,

@@ -1,2 +0,2 @@

import { ColorTypes } from "../color";
import { ColorTypes } from "../color.js";
export default function (

@@ -3,0 +3,0 @@ background: ColorTypes,

@@ -1,10 +0,11 @@

export type Algorithms = keyof typeof import(".") extends `contrast${infer Alg}`
? Alg
: string;
export type Algorithms =
keyof typeof import("./index.js") extends `contrast${infer Alg}`
? Alg
: string;
export { default as contrastWCAG21 } from "./WCAG21";
export { default as contrastAPCA } from "./APCA";
export { default as contrastMichelson } from "./Michelson";
export { default as contrastWeber } from "./Weber";
export { default as contrastLstar } from "./Lstar";
export { default as contrastDeltaPhi } from "./deltaPhi";
export { default as contrastWCAG21 } from "./WCAG21.js";
export { default as contrastAPCA } from "./APCA.js";
export { default as contrastMichelson } from "./Michelson.js";
export { default as contrastWeber } from "./Weber.js";
export { default as contrastLstar } from "./Lstar.js";
export { default as contrastDeltaPhi } from "./deltaPhi.js";

@@ -1,2 +0,2 @@

import { ColorTypes } from "../color";
import { ColorTypes } from "../color.js";
export default function (

@@ -3,0 +3,0 @@ background: ColorTypes,

@@ -1,2 +0,2 @@

import { ColorTypes } from "../color";
import { ColorTypes } from "../color.js";
export default function (

@@ -3,0 +3,0 @@ background: ColorTypes,

@@ -1,2 +0,2 @@

import { ColorTypes } from "../color";
import { ColorTypes } from "../color.js";
export default function (

@@ -3,0 +3,0 @@ background: ColorTypes,

@@ -1,2 +0,2 @@

import { ColorTypes } from "../color";
import { ColorTypes } from "../color.js";
export default function (

@@ -3,0 +3,0 @@ background: ColorTypes,

@@ -1,3 +0,3 @@

import { ColorTypes } from "./color";
import { Methods } from "./deltaE/index";
import { ColorTypes } from "./color.js";
import { Methods } from "./deltaE/index.js";

@@ -8,3 +8,3 @@ /**

*/
export default function deltaE(
export default function deltaE (
color1: ColorTypes,

@@ -11,0 +11,0 @@ color2: ColorTypes,

@@ -1,6 +0,6 @@

import Color, { ColorObject } from "../color";
import { ColorTypes } from "../color.js";
export default function (
color: Color | ColorObject,
sample: Color | ColorObject,
color: ColorTypes,
sample: ColorTypes,
options?: {

@@ -7,0 +7,0 @@ kL?: number | undefined;

@@ -1,5 +0,5 @@

import Color, { ColorObject } from "../color";
import { ColorTypes } from "../color.js";
export default function (
color: Color | ColorObject,
sample: Color | ColorObject
color: ColorTypes,
sample: ColorTypes
): number;

@@ -1,5 +0,5 @@

import Color, { ColorObject } from "../color";
import { ColorTypes } from "../color.js";
export default function (
color: Color | ColorObject,
sample: Color | ColorObject,
color: ColorTypes,
sample: ColorTypes,
options?: {

@@ -6,0 +6,0 @@ l?: number | undefined;

@@ -1,5 +0,5 @@

import Color, { ColorObject } from "../color";
import { ColorTypes } from "../color.js";
export default function (
color: Color | ColorObject,
sample: Color | ColorObject
color: ColorTypes,
sample: ColorTypes
): number;

@@ -1,5 +0,5 @@

import Color, { ColorObject } from "../color";
import { ColorTypes } from "../color.js";
export default function (
color: Color | ColorObject,
sample: Color | ColorObject
color: ColorTypes,
sample: ColorTypes
): number;

@@ -1,5 +0,5 @@

import Color, { ColorObject } from "../color";
import { ColorTypes } from "../color.js";
export default function (
color: Color | ColorObject,
sample: Color | ColorObject
color: ColorTypes,
sample: ColorTypes
): number;

@@ -1,9 +0,10 @@

export { default as deltaE76 } from "./deltaE76";
export { default as deltaECMC } from "./deltaECMC";
export { default as deltaE2000 } from "./deltaE2000";
export { default as deltaEJz } from "./deltaEJz";
export { default as deltaEITP } from "./deltaEITP";
export { default as deltaEOK } from "./deltaEOK";
export { default as deltaE76 } from "./deltaE76.js";
export { default as deltaECMC } from "./deltaECMC.js";
export { default as deltaE2000 } from "./deltaE2000.js";
export { default as deltaEJz } from "./deltaEJz.js";
export { default as deltaEITP } from "./deltaEITP.js";
export { default as deltaEOK } from "./deltaEOK.js";
export { default as deltaEHCT } from "./deltaEHCT.js";
declare const deltaEMethods: Omit<typeof import("./index"), "default">;
declare const deltaEMethods: Omit<typeof import("./index.js"), "default">;
export default deltaEMethods;

@@ -10,0 +11,0 @@

@@ -1,7 +0,13 @@

import { PlainColorObject, ColorTypes } from "./color";
import ColorSpace from "./space";
import { PlainColorObject, ColorTypes } from "./color.js";
import ColorSpace from "./space.js";
export type Display = string & { color: PlainColorObject };
export default function display(
/**
* Returns a serialization of the color that can actually be displayed in the browser.
* If the default serialization can be displayed, it is returned.
* Otherwise, the color is converted to Lab, REC2020, or P3, whichever is the widest supported.
* In Node.js, this is basically equivalent to `serialize()` but returns a `String` object instead
*/
export default function display (
color: ColorTypes,

@@ -8,0 +14,0 @@ options?: {

@@ -1,8 +0,8 @@

import Color, { ColorObject } from "./color";
import ColorSpace from "./space";
import { ColorTypes } from "./color.js";
import ColorSpace from "./space.js";
export default function distance(
color1: Color | ColorObject,
color2: Color | ColorObject,
export default function distance (
color1: ColorTypes,
color2: ColorTypes,
space?: string | ColorSpace
): number;

@@ -1,3 +0,3 @@

import { ColorTypes } from "./color";
import { ColorTypes } from "./color.js";
export default function equals(color1: ColorTypes, color2: ColorTypes): boolean;
export default function equals (color1: ColorTypes, color2: ColorTypes): boolean;

@@ -1,4 +0,4 @@

import Color, { ColorObject } from "./color";
import { Ref } from "./space";
import { ColorTypes } from "./color.js";
import { Ref } from "./space.js";
export default function get(color: Color | ColorObject, prop: Ref): number;
export default function get (color: ColorTypes, prop: Ref): number;

@@ -1,7 +0,7 @@

import Color, { ColorObject } from "./color";
import ColorSpace from "./space";
import { ColorTypes, Coords } from "./color.js";
import ColorSpace from "./space.js";
export default function getAll(
color: Color | ColorObject,
space: string | ColorSpace
): [number, number, number];
export default function getAll (
color: ColorTypes,
space?: string | ColorSpace
): Coords;

@@ -1,3 +0,4 @@

import { PlainColorObject, ColorTypes } from "./color";
import { PlainColorObject, ColorTypes } from "./color.js";
export default function getColor(color: ColorTypes): PlainColorObject;
export default function getColor (color: ColorTypes): PlainColorObject;
export default function getColor (color: ColorTypes[]): PlainColorObject[];

@@ -0,1 +1,16 @@

/**
* This is for plugin authors.
* If you're not interested in writing plugins for Color.js, you can skip this.
*
* Hooks afford extensibility far beyond what can be achieved
* by overriding properties and methods, or using functions.
* Hooks allow plugin authors to change how Color.js’ internal code works,
* by adding custom callbacks to predefined points in the execution.
*
* You can find available hooks by searching the source code for `hooks.run(` in color.js.
* If you need a hook that is not present, we typically accept pull requests for new hooks pretty easily!
*
* The Hooks module exports both a hooks object that is used throughout Color.js (as a default export),
* as well as a Hooks class (as a named export) that can be used to create new sets of hooks.
*/
export class Hooks {

@@ -6,3 +21,13 @@ // Can't find a way to type this more specifically

add(
/**
* Schedule a callback to be executed at a certain point in the source code
* @param name The name of the hook to add the callback to
* @param callback The code to run at the given hook.
* The callback will be callewd with (typically) the same context as the calling code,
* and a single object as its only argument (typically called `env`)
* with writeable properties for various aspects of the calling environment
* @param [first=false] Whether to prepend instead of append this callback to any existing callbacks
* on the same hook. Defaults to `false`
*/
add (
name: string | string[],

@@ -12,3 +37,14 @@ callback: (env: Record<string, any>) => void,

): void;
run(name: string, env?: { context?: Record<string, any> }): void;
/**
* Creates a hook for plugin authors to add code to
* @param name The name of the hook to create.
* By convention, it's in the form `[class-name]-[function name]-[location in function body]`.
* Class name can be omitted if it's in `color.js`.
* Location in function body is typically something like `"start"`, `"end'`,
* `"before-conversion"`, `"after-init"`, etc.
* @param env Object with properties to be passed to the hook's callback.
* This will also be used as the function context, unless it has a `context` property,
* in which case that is used as the function context
*/
run (name: string, env?: { context?: Record<string, any> }): void;
}

@@ -15,0 +51,0 @@

@@ -1,29 +0,63 @@

export { default as ColorSpace } from "./space";
export { default as RGBColorSpace } from "./rgbspace";
export { default as hooks, Hooks } from "./hooks";
export { default as defaults } from "./defaults";
export { default as getColor } from "./getColor";
export { default as get } from "./get";
export { default as getAll } from "./getAll";
export { default as set } from "./set";
export { default as setAll } from "./setAll";
export { default as parse } from "./parse";
export { default as to } from "./to";
export { default as serialize } from "./serialize";
export { default as display } from "./display";
export { default as inGamut } from "./inGamut";
export { default as toGamut } from "./toGamut";
export { default as distance } from "./distance";
export { default as equals } from "./equals";
export { default as contrast } from "./contrast";
export { default as clone } from "./clone";
export { getLuminance, setLuminance } from "./luminance";
export { uv, xy } from "./chromaticity";
export { default as deltaE } from "./deltaE";
export { mix, steps, range, isRange } from "./interpolation";
export { default as ColorSpace } from "./space.js";
export { default as RGBColorSpace } from "./rgbspace.js";
export { default as hooks, Hooks } from "./hooks.js";
export { default as defaults } from "./defaults.js";
export { default as getColor } from "./getColor.js";
export { default as get } from "./get.js";
export { default as getAll } from "./getAll.js";
export { default as set } from "./set.js";
export { default as setAll } from "./setAll.js";
export { default as parse } from "./parse.js";
export { default as to } from "./to.js";
export { default as serialize } from "./serialize.js";
export { default as display } from "./display.js";
export { default as inGamut } from "./inGamut.js";
export { default as toGamut, toGamutCSS } from "./toGamut.js";
export { default as distance } from "./distance.js";
export { default as equals } from "./equals.js";
export { default as contrast } from "./contrast.js";
export { default as clone } from "./clone.js";
export { getLuminance, setLuminance } from "./luminance.js";
export { uv, xy } from "./chromaticity.js";
export { default as deltaE } from "./deltaE.js";
export { mix, steps, range, isRange } from "./interpolation.js";
export * from "./contrast/index";
export * from "./deltaE/index";
export { default as deltaEMethods } from "./deltaE/index";
export * from "./variations";
export * from "./spaces/index-fn";
export * from "./contrast/index.js";
export * from "./deltaE/index.js";
export { default as deltaEMethods } from "./deltaE/index.js";
export * from "./variations.js";
export * from "./spaces/index-fn.js";
export type {
ColorConstructor,
ColorObject,
ColorTypes,
Coords,
PlainColorObject,
} from "./color.js";
export type { White } from "./adapt.js";
export type { CAT } from "./CATs.js";
export type { Display } from "./display.js";
export type {
Range,
RangeOptions,
MixOptions,
StepsOptions,
} from "./interpolation.js";
export type { Options as ParseOptions } from "./parse.js";
export type { RGBOptions } from "./rgbspace.js";
export type { Options as SerializeOptions } from "./serialize.js";
export type {
Format as SpaceFormat,
CoordMeta,
Ref,
Options as SpaceOptions,
} from "./space.js";

@@ -1,4 +0,4 @@

import { uv, xy } from "./chromaticity";
import Color from "./color";
import contrast from "./contrast";
import { uv, xy } from "./chromaticity.js";
import Color, { ColorTypes, ToColorPrototype } from "./color.js";
import contrast from "./contrast.js";
import {

@@ -11,4 +11,4 @@ contrastWCAG21,

contrastDeltaPhi,
} from "./contrast/index";
import deltaE from "./deltaE";
} from "./contrast/index.js";
import deltaE from "./deltaE.js";
import deltaEMethods, {

@@ -21,6 +21,6 @@ deltaE76,

deltaEOK,
} from "./deltaE/index";
import { mix, range, steps } from "./interpolation";
import { getLuminance } from "./luminance";
import { lighten, darken } from "./variations";
} from "./deltaE/index.js";
import { range, Range, MixOptions, StepsOptions } from "./interpolation.js";
import { getLuminance } from "./luminance.js";
import { lighten, darken } from "./variations.js";

@@ -72,13 +72,48 @@ // Augment existing Color object

// interpolation
mix: ToColorPrototype<typeof mix>;
// These signatures should always match those in interpolation.d.ts,
// including the static versions
/** Create color mixtures in any desired proportion between two colors */
mix (color2: ColorTypes, options?: MixOptions): Color;
mix (color2: ColorTypes, p: number, options?: MixOptions): Color;
/**
* Creates a function that accepts a number and returns a color.
* For numbers in the range 0 to 1, the function interpolates;
* for numbers outside that range, the function extrapolates
* (and thus may not return the results you expect)
*/
range: ToColorPrototype<typeof range>;
steps: ToColorPrototype<typeof steps>;
static mix: typeof mix;
/** Get an array of discrete steps */
steps (color2: ColorTypes, options?: StepsOptions): Color[];
/** Create color mixtures in any desired proportion between two colors */
static mix (
color1: ColorTypes,
color2: ColorTypes,
options?: MixOptions
): Color;
static mix (
color1: ColorTypes,
color2: ColorTypes,
p: number,
options?: MixOptions
): Color;
/**
* Creates a function that accepts a number and returns a color.
* For numbers in the range 0 to 1, the function interpolates;
* for numbers outside that range, the function extrapolates
* (and thus may not return the results you expect)
*/
static range: typeof range;
static steps: typeof steps;
/** Get an array of discrete steps */
static steps (
color1: ColorTypes,
color2: ColorTypes,
options?: StepsOptions
): Color[];
static steps (range: Range, options?: StepsOptions): Color[];
// luminance
get luminance(): ReturnType<typeof getLuminance>;
get luminance (): ReturnType<typeof getLuminance>;
// the definition for this set in the orignial code like it doesn't actually use the parameter?
set luminance(_: number);
set luminance (_: number);

@@ -85,0 +120,0 @@ // variations

@@ -1,5 +0,5 @@

import { ColorTypes } from "./color";
import ColorSpace from "./space";
import { ColorTypes } from "./color.js";
import ColorSpace from "./space.js";
export default function inGamut(
export default function inGamut (
color: ColorTypes,

@@ -6,0 +6,0 @@ space?: string | ColorSpace,

@@ -1,4 +0,4 @@

import Color, { ColorTypes, PlainColorObject } from "./color";
import ColorSpace from "./space";
import { Methods } from "./deltaE/index";
import Color, { ColorTypes, PlainColorObject } from "./color.js";
import ColorSpace from "./space.js";
import { Methods } from "./deltaE/index.js";

@@ -9,14 +9,35 @@ export type Range = ((percentage: number) => Color) & {

export function isRange(val: any): val is Range;
export function isRange (val: any): val is Range;
export interface RangeOptions {
/**
* The interpolation space.
* Colors do not need to be in this space; they will be converted for interpolation
* @see {@link <https://colorjs.io/docs/interpolation#ranges>}
*/
space?: string | ColorSpace | undefined;
outputSpace?: string | ColorSpace | undefined;
/**
* Used to customize the progression and make in nonlinear
* @example
* let r = new Color("lch(50 50 0)").range("lch(90 50 20)");
* Color.range(r, { progression: p => p ** 3 });
*/
progression?: ((percentage: number) => number) | undefined;
premultiplied?: boolean | undefined;
/**
* Inspired by the
* {@link https://drafts.csswg.org/css-color-5/#hue-adjuster hue-adjuster in CSS Color 5}.
*/
hue?: "longer" | "shorter" | "increasing" | "decreasing" | "raw" | undefined;
}
export function range(range: Range, options?: RangeOptions): Range;
export function range(
/**
* Creates a function that accepts a number and returns a color.
* For numbers in the range 0 to 1, the function interpolates;
* for numbers outside that range, the function extrapolates
* (and thus may not return the results you expect)
*/
export function range (range: Range, options?: RangeOptions): Range;
export function range (
color1: ColorTypes,

@@ -27,9 +48,6 @@ color2: ColorTypes,

export interface MixOptions {
space?: string | ColorSpace | undefined;
outputSpace?: string | ColorSpace | undefined;
premultiplied?: boolean | undefined;
}
export type MixOptions = RangeOptions;
export function mix(
/** Create color mixtures in any desired proportion between two colors */
export function mix (
color1: ColorTypes,

@@ -39,3 +57,3 @@ color2: ColorTypes,

): PlainColorObject;
export function mix(
export function mix (
color1: ColorTypes,

@@ -48,11 +66,16 @@ color2: ColorTypes,

export interface StepsOptions extends RangeOptions {
/** max deltaE between consecutive steps */
maxDeltaE?: number | undefined;
/** @see {@link Methods} */
deltaEMethod?: Methods | undefined;
/** The minimum number of steps */
steps?: number | undefined;
/** The maximum number of steps */
maxSteps?: number | undefined;
}
export function steps(color1: ColorTypes, color2: ColorTypes, options?: StepsOptions): PlainColorObject[];
export function steps(range: Range, options?: StepsOptions): PlainColorObject[];
/** Get an array of discrete steps */
export function steps (color1: ColorTypes, color2: ColorTypes, options?: StepsOptions): PlainColorObject[];
export function steps (range: Range, options?: StepsOptions): PlainColorObject[];
export function register(color: typeof Color): void;
export function register (color: typeof Color): void;

@@ -1,10 +0,10 @@

import Color, { ColorObject } from "./color";
import Color, { ColorTypes } from "./color.js";
export function getLuminance(color: Color | ColorObject): number;
export function getLuminance (color: ColorTypes): number;
export function setLuminance(
color: Color | ColorObject,
value: number | ((coord: number) => number),
export function setLuminance (
color: ColorTypes,
value: number | ((coord: number) => number),
): void;
export function register(color: typeof Color): void;
export function register (color: typeof Color): void;

@@ -6,5 +6,5 @@ /**

*/
export default function multiplyMatrices(
export default function multiplyMatrices (
a: number[] | number[][],
b: number[] | number[][]
): number[];

@@ -1,2 +0,2 @@

import { ColorConstructor } from "./color";
import { ColorConstructor } from "./color.js";

@@ -7,5 +7,11 @@ export interface Options {

export default function parse(
/**
* Parse a string as a color.
* Understands all {@link https://www.w3.org/TR/css-color-4/ CSS Color 4} functions.
* Uses the DOM if present to parse hex colors and color names,
* so that will not available in non-DOM environments such as Node.js
*/
export default function parse (
str: string,
options?: Options & Record<string, any>
): ColorConstructor;

@@ -1,2 +0,2 @@

import ColorSpace, { Options } from "./space";
import ColorSpace, { Options } from "./space.js";

@@ -9,3 +9,3 @@ export interface RGBOptions extends Options {

export default class RGBColorSpace extends ColorSpace {
constructor(options: RGBOptions);
constructor (options: RGBOptions);
}

@@ -1,3 +0,3 @@

import { ColorTypes } from "./color";
import { Format } from "./space";
import { ColorTypes } from "./color.js";
import { Format } from "./space.js";

@@ -10,5 +10,5 @@ export interface Options {

export default function serialize(
export default function serialize (
color: ColorTypes,
options?: Options & Record<string, any>
): string;

@@ -1,8 +0,18 @@

import Color, { ColorTypes } from "./color";
import { Ref } from "./space";
import { ColorTypes, PlainColorObject } from "./color.js";
import { Ref } from "./space.js";
export default function set(
declare namespace set {
let returns: "color";
}
declare function set (
color: ColorTypes,
prop: Ref,
value: number | ((coord: number) => number)
): Color;
): PlainColorObject;
declare function set (
color: ColorTypes,
props: Record<string, number | ((coord: number) => number)>
): PlainColorObject;
export default set;

@@ -1,8 +0,14 @@

import Color, { ColorObject } from "./color";
import ColorSpace from "./space";
import { ColorTypes, PlainColorObject } from "./color.js";
import ColorSpace from "./space.js";
export default function setAll<T extends Color | ColorObject>(
color: T,
declare namespace setAll {
let returns: "color";
}
declare function setAll (
color: ColorTypes,
space: string | ColorSpace,
coords: [number, number, number]
): T;
): PlainColorObject;
export default setAll;

@@ -1,19 +0,30 @@

import { White } from "./adapt";
import Color, { ColorConstructor, ColorObject, Coords } from "./color";
import { White } from "./adapt.js";
import { ColorConstructor, Coords, ColorTypes } from "./color.js";
export interface Format {
/** @default "function" */
type?: string | undefined;
/** @default "color" */
name?: string | undefined;
id?: string | undefined;
coords?: string[] | undefined;
coordGrammar?: Array<string & { range?: [number, number] }> | undefined;
coordGrammar?: (string & { range?: [number, number] })[] | undefined;
serializeCoords?:
| ((coords: Coords, precision: number) => [string, string, string])
| undefined;
| ((coords: Coords, precision: number) => [string, string, string])
| undefined;
/** Whether to adjust the coordinates to fit in the gamut */
toGamut?: boolean | undefined;
/** Whether commas should separate arguments for a format */
commas?: boolean | undefined;
/** Whether the last coordinate is the alpha coordinate */
lastAlpha?: boolean | undefined;
/** Whether the format has an alpha channel */
noAlpha?: boolean | undefined;
test?: ((str: string) => boolean) | undefined;
/** Function to parse a string into a color */
parse?: ((str: string) => ColorConstructor) | undefined;
/**
* Serialize coordinates and an alpha channel into a string.
* Must be defined for a format to support serialization
*/
serialize?: ((coords: Coords, alpha: number, opts?: Record<string, any>) => string) | undefined;

@@ -30,12 +41,33 @@ }

export interface Options {
/** Id of this space, used in things such as conversions */
id: string;
/** The readable name of the space, used in user-facing UI */
name: string;
/** The base color space */
base?: string | ColorSpace | null | undefined;
/**
* Function that converts coords in the base color space to coords in this color space.
* Must perform chromatic adaptation if needed
*/
fromBase?: ((coords: Coords) => number[]) | undefined;
/**
* Function that converts coords in this color space to coords in the base color space.
* Must perform chromatic adaptation if needed
*/
toBase?: ((coords: Coords) => number[]) | undefined;
/**
* Object mapping coord ids to coord metadata
* @see {@link CoordMeta}
*/
coords?: Record<string, CoordMeta> | undefined;
white?: string | White | undefined;
/** The ID used by CSS, such as `display-p3` or `--cam16-jmh` */
cssId?: string | undefined;
referred?: string | undefined;
/**
* Details about string formats to parse from / serialize to
* @see {@link Format}
*/
formats?: Record<string, Format> | undefined;
gamutSpace?: "self" | string | ColorSpace | null | undefined;
}

@@ -48,4 +80,5 @@

/** Class for color spaces. Each color space corresponds to a `ColorSpace` instance */
export default class ColorSpace {
constructor(options: Options);
constructor (options: Options);

@@ -57,5 +90,5 @@ static DEFAULT_FORMAT: { type: "functions"; name: "color" };

*/
static get(
static get (
space: ColorSpace | string,
...alternatives: Array<ColorSpace | string>
...alternatives: (ColorSpace | string)[]
): ColorSpace;

@@ -66,3 +99,3 @@

*/
static resolveCoord(
static resolveCoord (
ref: Ref,

@@ -79,10 +112,11 @@ workingSpace?: string | ColorSpace

*/
static register(space: ColorSpace): ColorSpace;
static register(id: string, space: ColorSpace): ColorSpace;
static register (space: ColorSpace): ColorSpace;
static register (id: string, space: ColorSpace): ColorSpace;
static registry: Record<string, ColorSpace>;
get all(): Set<ColorSpace>;
get cssId(): string;
get isPolar(): boolean;
get all (): Set<ColorSpace>;
/** The ID used by CSS, such as `display-p3` or `--cam16-jmh` */
get cssId (): string;
get isPolar (): boolean;

@@ -99,16 +133,17 @@ name: string;

white: White;
gamutSpace: ColorSpace;
from(color: Color | ColorObject): Coords;
from(space: string | ColorSpace, coords: Coords): Coords;
from (color: ColorTypes): Coords;
from (space: string | ColorSpace, coords: Coords): Coords;
getFormat(format?: string | Format): Format | null;
getFormat (format?: string | Format): Format | null;
getMinCoords(): Coords;
getMinCoords (): Coords;
inGamut(coords: Coords, options?: { epsilon?: number }): boolean;
inGamut (coords: Coords, options?: { epsilon?: number }): boolean;
to(color: Color | ColorObject): Coords;
to(space: string | ColorSpace, coords: Coords): Coords;
to (color: ColorTypes): Coords;
to (space: string | ColorSpace, coords: Coords): Coords;
toString(): string;
toString (): string;
}

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,9 +0,9 @@

export type HDRSpaces = keyof typeof import("./index-fn-hdr");
export type HDRSpaces = keyof typeof import("./index-fn-hdr.js");
export { default as Jzazbz } from "./jzazbz";
export { default as JzCzHz } from "./jzczhz";
export { default as ICTCP } from "./ictcp";
export { default as REC_2100_PQ } from "./rec2100-pq";
export { default as REC_2100_HLG } from "./rec2100-hlg";
export { default as ACEScg } from "./acescg";
export { default as ACEScc } from "./acescc";
export { default as Jzazbz } from "./jzazbz.js";
export { default as JzCzHz } from "./jzczhz.js";
export { default as ICTCP } from "./ictcp.js";
export { default as REC_2100_PQ } from "./rec2100-pq.js";
export { default as REC_2100_HLG } from "./rec2100-hlg.js";
export { default as ACEScg } from "./acescg.js";
export { default as ACEScc } from "./acescc.js";

@@ -1,25 +0,29 @@

export type Spaces = keyof typeof import("./index-fn");
export type Spaces = keyof typeof import("./index-fn.js");
export { default as XYZ_D65 } from "./xyz-d65";
export { default as XYZ_D50 } from "./xyz-d50";
export { default as XYZ_ABS_D65 } from "./xyz-abs-d65";
export { default as Lab } from "./lab";
export { default as Lab_D65 } from "./lab-d65";
export { default as LCH } from "./lch";
export { default as sRGB_Linear } from "./srgb-linear";
export { default as sRGB } from "./srgb";
export { default as HSL } from "./hsl";
export { default as HWB } from "./hwb";
export { default as HSV } from "./hsv";
export { default as P3_Linear } from "./p3-linear";
export { default as P3 } from "./p3";
export { default as A98RGB_Linear } from "./a98rgb-linear";
export { default as A98RGB } from "./a98rgb";
export { default as ProPhoto_Linear } from "./prophoto-linear";
export { default as ProPhoto } from "./prophoto";
export { default as REC_2020_Linear } from "./rec2020-linear";
export { default as REC_2020 } from "./rec2020";
export { default as OKLab } from "./oklab";
export { default as OKLCH } from "./oklch";
export { default as XYZ_D65 } from "./xyz-d65.js";
export { default as XYZ_D50 } from "./xyz-d50.js";
export { default as XYZ_ABS_D65 } from "./xyz-abs-d65.js";
export { default as Lab } from "./lab.js";
export { default as Lab_D65 } from "./lab-d65.js";
export { default as LCH } from "./lch.js";
export { default as sRGB_Linear } from "./srgb-linear.js";
export { default as sRGB } from "./srgb.js";
export { default as HSL } from "./hsl.js";
export { default as HWB } from "./hwb.js";
export { default as HSV } from "./hsv.js";
export { default as P3_Linear } from "./p3-linear.js";
export { default as P3 } from "./p3.js";
export { default as A98RGB_Linear } from "./a98rgb-linear.js";
export { default as A98RGB } from "./a98rgb.js";
export { default as ProPhoto_Linear } from "./prophoto-linear.js";
export { default as ProPhoto } from "./prophoto.js";
export { default as REC_2020_Linear } from "./rec2020-linear.js";
export { default as REC_2020 } from "./rec2020.js";
export { default as OKLab } from "./oklab.js";
export { default as OKLCH } from "./oklch.js";
export { default as Luv } from "./luv.js";
export { default as LCHuv } from "./lchuv.js";
export { default as HSLuv } from "./hsluv.js";
export { default as HPLuv } from "./hpluv.js";
export * from "./index-fn-hdr";
export * from "./index-fn-hdr.js";

@@ -1,4 +0,4 @@

import * as spaces from "./index-fn";
import * as spaces from "./index-fn.js";
export { Spaces } from "./index-fn";
export { Spaces } from "./index-fn.js";
export { spaces };

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import RGBColorSpace from "../rgbspace";
import RGBColorSpace from "../rgbspace.js";
declare const _default: RGBColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import ColorSpace from "../space";
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

@@ -1,3 +0,3 @@

import { PlainColorObject, ColorTypes } from "./color";
import ColorSpace from "./space";
import { PlainColorObject, ColorTypes } from "./color.js";
import ColorSpace from "./space.js";

@@ -8,3 +8,3 @@ declare namespace to {

declare function to(
declare function to (
color: ColorTypes,

@@ -11,0 +11,0 @@ space: string | ColorSpace,

@@ -1,4 +0,32 @@

import { ColorTypes, PlainColorObject } from "./color";
import ColorSpace from "./space";
import { ColorTypes, PlainColorObject } from "./color.js";
import { Methods } from "./deltaE/index.js";
import ColorSpace, { Ref } from "./space.js";
export interface Options {
/**
* How to force into gamut.
*
* If `"clip"`, coordinates are just clipped to their reference range.\
* If `"css"`, coordinates are reduced according to the CSS 4 Gamut Mapping Algorithm.\
* If in the form `[colorSpaceId].[coordName]`, that coordinate is reduced
* until the color is in gamut. Please note that this may produce nonsensical
* results for certain coordinates (e.g. hue) or infinite loops
* if reducing the coordinate never brings the color in gamut
* @default "css"
*/
method?: "css" | "clip" | (string & {}) | undefined;
/** The color whose space is being mapped to. Defaults to the current space */
space?: string | ColorSpace | undefined;
deltaEMethod?: Methods | undefined;
/** The "just noticeable difference" to target */
jnd?: number | undefined;
/**
* Used to configure SDR black and clamping.
* `channel` indicates the `space.channel` to use for determining when to clamp.
* `min` indicates the lower limit for black clamping and `max` indicates the upper
* limit for white clamping
*/
blackWhiteClamp?: { channel: Ref; min: number; max: number } | undefined;
}
declare namespace toGamut {

@@ -8,10 +36,11 @@ let returns: "color";

declare function toGamut(
declare function toGamut (color: ColorTypes, options?: Options | string): PlainColorObject;
export default toGamut;
export function toGamutCSS (
color: ColorTypes,
options?: {
method?: string | undefined;
space?: string | ColorSpace | undefined;
}
): PlainColorObject;
export default toGamut;

@@ -1,2 +0,2 @@

export { default as multiplyMatrices } from "./multiply-matrices";
export { default as multiplyMatrices } from "./multiply-matrices.js";

@@ -7,3 +7,3 @@ /**

*/
export function isString(str: any): str is string;
export function isString (str: any): str is string;

@@ -14,3 +14,3 @@ /**

*/
export function type(o: any): string;
export function type (o: any): string;

@@ -22,3 +22,3 @@ /**

*/
export function toPrecision(n: number, precision: number): number;
export function toPrecision (n: number, precision: number): number;

@@ -29,14 +29,12 @@ /**

*/
export function parseFunction(str: string): {
export function parseFunction (str: string): {
name: string;
rawName: string;
rawArgs: string;
args: Array<
| string
| (number & {
type?: "<angle>" | "<number>" | "<percentage>" | undefined;
unit?: "deg" | undefined;
alpha?: true | undefined;
})
>;
args: (string
| (number & {
type?: "<angle>" | "<number>" | "<percentage>" | undefined;
unit?: "deg" | undefined;
alpha?: true | undefined;
}))[];
};

@@ -48,7 +46,7 @@

*/
export function last<T extends readonly any[]>(arr: T): T[number];
export function last<T extends readonly any[]> (arr: T): T[number];
export function interpolate(start: number, end: number, p: number): number;
export function interpolate (start: number, end: number, p: number): number;
export function interpolateInv(
export function interpolateInv (
start: number,

@@ -59,3 +57,3 @@ end: number,

export function mapRange(
export function mapRange (
from: [number, number],

@@ -66,2 +64,2 @@ to: [number, number],

export function parseCoordGrammar(coordGrammars: string[]): string[];
export function parseCoordGrammar (coordGrammars: string[]): string[];

@@ -1,5 +0,5 @@

import { PlainColorObject, ColorTypes } from "./color";
import { PlainColorObject, ColorTypes } from "./color.js";
export function lighten(color: ColorTypes, amount?: number): PlainColorObject;
export function lighten (color: ColorTypes, amount?: number): PlainColorObject;
export function darken(color: ColorTypes, amount?: number): PlainColorObject;
export function darken (color: ColorTypes, amount?: number): PlainColorObject;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc