diff --git a/src/distance.js b/src/distance.js index 6f8c92653..788772482 100644 --- a/src/distance.js +++ b/src/distance.js @@ -1,14 +1,12 @@ import ColorSpace from "./space.js"; -import getColor from "./getColor.js"; /** * Euclidean distance of colors in an arbitrary color space */ export default function distance (color1, color2, space = "lab") { - [color1, color2] = getColor([color1, color2]); - space = ColorSpace.get(space); + // Assume getColor() is called on color in space.from() let coords1 = space.from(color1); let coords2 = space.from(color2); diff --git a/src/set.js b/src/set.js index 17fc3682d..1463b8462 100644 --- a/src/set.js +++ b/src/set.js @@ -29,3 +29,5 @@ export default function set (color, prop, value) { return color; } + +set.returns = "color"; diff --git a/src/setAll.js b/src/setAll.js index ac56a2da9..54afeeba1 100644 --- a/src/setAll.js +++ b/src/setAll.js @@ -8,3 +8,5 @@ export default function setAll (color, space, coords) { color.coords = space.to(color.space, coords); return color; } + +setAll.returns = "color"; diff --git a/src/space.js b/src/space.js index dccf1a73f..9f32602bb 100644 --- a/src/space.js +++ b/src/space.js @@ -1,6 +1,7 @@ import {type, parseCoordGrammar, serializeNumber, mapRange} from "./util.js"; import {getWhite} from "./adapt.js"; import hooks from "./hooks.js"; +import getColor from "./getColor.js"; const ε = .000075; @@ -173,7 +174,8 @@ export default class ColorSpace { to (space, coords) { if (arguments.length === 1) { - [space, coords] = [space.space, space.coords]; + const color = getColor(space); + [space, coords] = [color.space, color.coords]; } space = ColorSpace.get(space); @@ -222,7 +224,8 @@ export default class ColorSpace { from (space, coords) { if (arguments.length === 1) { - [space, coords] = [space.space, space.coords]; + const color = getColor(space); + [space, coords] = [color.space, color.coords]; } space = ColorSpace.get(space); diff --git a/types/src/color.d.ts b/types/src/color.d.ts index 0477ddaff..6853dd240 100644 --- a/types/src/color.d.ts +++ b/types/src/color.d.ts @@ -6,17 +6,16 @@ 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.js"; @@ -69,20 +68,34 @@ export type ToColorPrototype any> = T extends ( : (...args: A) => R : never; +/** Convert a function to a Color namespace property (returning a Color) */ +export type ToColorNamespace 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; + export const setAll: ToColorNamespace; + export const to: ToColorNamespace; + export const equals: ToColorNamespace; + export const inGamut: ToColorNamespace; + export const toGamut: ToColorNamespace; + export const distance: ToColorNamespace; + // `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 number)>): Color; } declare class Color extends SpaceAccessors implements PlainColorObject { @@ -129,13 +142,13 @@ declare class Color extends SpaceAccessors implements PlainColorObject { // Functions defined using Color.defineFunctions get: ToColorPrototype; - getAll: ToColorPrototype; - setAll: ToColorPrototype; - to: ToColorPrototype; - equals: ToColorPrototype; - inGamut: ToColorPrototype; - toGamut: ToColorPrototype; - distance: ToColorPrototype; + getAll: ToColorPrototype; + setAll: ToColorPrototype; + to: ToColorPrototype; + equals: ToColorPrototype; + inGamut: ToColorPrototype; + toGamut: ToColorPrototype; + distance: ToColorPrototype; toString: ToColorPrototype; // Must be manually defined due to overloads diff --git a/types/src/set.d.ts b/types/src/set.d.ts index 2f9665bff..6aea210fe 100644 --- a/types/src/set.d.ts +++ b/types/src/set.d.ts @@ -1,12 +1,18 @@ 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) ): PlainColorObject; -export default function set ( +declare function set ( color: ColorTypes, props: Record number)> ): PlainColorObject; + +export default set; diff --git a/types/src/setAll.d.ts b/types/src/setAll.d.ts index ba2fce3c7..9959fa55a 100644 --- a/types/src/setAll.d.ts +++ b/types/src/setAll.d.ts @@ -1,4 +1,4 @@ -import Color, { ColorTypes, PlainColorObject } from "./color.js"; +import { ColorTypes, PlainColorObject } from "./color.js"; import ColorSpace from "./space.js"; declare namespace setAll { diff --git a/types/src/space.d.ts b/types/src/space.d.ts index 9e8f01442..33facad8e 100644 --- a/types/src/space.d.ts +++ b/types/src/space.d.ts @@ -1,5 +1,5 @@ import { White } from "./adapt.js"; -import Color, { ColorConstructor, ColorObject, Coords, PlainColorObject } from "./color.js"; +import { ColorConstructor, Coords, ColorTypes } from "./color.js"; export interface Format { /** @default "function" */ @@ -127,7 +127,7 @@ export default class ColorSpace { white: White; gamutSpace: ColorSpace; - from (color: {space: ColorSpace, coords: Coords, alpha?: number | undefined}): Coords; + from (color: ColorTypes): Coords; from (space: string | ColorSpace, coords: Coords): Coords; getFormat (format?: string | Format): Format | null; @@ -136,7 +136,7 @@ export default class ColorSpace { inGamut (coords: Coords, options?: { epsilon?: number }): boolean; - to (color: {space: ColorSpace, coords: Coords, alpha?: number | undefined}): Coords; + to (color: ColorTypes): Coords; to (space: string | ColorSpace, coords: Coords): Coords; toString (): string; diff --git a/types/test/set.ts b/types/test/set.ts index 2a84f4ca4..f9056daaf 100644 --- a/types/test/set.ts +++ b/types/test/set.ts @@ -18,3 +18,5 @@ set("red", { }); new Color("red").set("foo", 123); // $ExpectType Color +Color.set("red", "foo", 123); // $ExpectType Color +Color.set(new Color("red"), "foo", 123); // $ExpectType Color diff --git a/types/test/setAll.ts b/types/test/setAll.ts index f3d5719dd..040e667da 100644 --- a/types/test/setAll.ts +++ b/types/test/setAll.ts @@ -26,3 +26,5 @@ setAll( new Color("red").setAll("srgb", [1, 2, 3]); // $ExpectType Color new Color("red").setAll(sRGB, [1, 2, 3]); // $ExpectType Color +Color.setAll("red", "srgb", [1, 2, 3]); // $ExpectType Color +Color.setAll(new Color("red"), "srgb", [1, 2, 3]); // $ExpectType Color diff --git a/types/test/spaces.ts b/types/test/spaces.ts index 86fa8fd84..cbb233098 100644 --- a/types/test/spaces.ts +++ b/types/test/spaces.ts @@ -50,14 +50,15 @@ ColorSpace.resolveCoord("p3.0", "p3"); ColorSpace.resolveCoord(["p3", "r"], "p3"); space.to(new Color("red")); // $ExpectType Coords +space.to("red"); // $ExpectType Coords space.to({space: space, coords: [1, 2, 3], alpha: 1}); // $ExpectType Coords space.to({space: space, coords: [1, 2, 3]}); // $ExpectType Coords space.to(space, [1, 2, 3]); // $ExpectType Coords space.to("srgb", [1, 2, 3]); // $ExpectType Coords space.from(new Color("red")); // $ExpectType Coords +space.from("red"); // $ExpectType Coords space.from({space: space, coords: [1, 2, 3], alpha: 1}); // $ExpectType Coords space.from({space: space, coords: [1, 2, 3]}); // $ExpectType Coords space.from(space, [1, 2, 3]); // $ExpectType Coords space.from("srgb", [1, 2, 3]); // $ExpectType Coords - diff --git a/types/test/to.ts b/types/test/to.ts index 286d6996b..759e55eed 100644 --- a/types/test/to.ts +++ b/types/test/to.ts @@ -1,3 +1,4 @@ +import Color from "colorjs.io/src"; import to from "colorjs.io/src/to"; // @ts-expect-error @@ -8,3 +9,7 @@ to("red"); to("red", "srgb"); // $ExpectType PlainColorObject to("red", "srgb", { inGamut: false }); // $ExpectType PlainColorObject + +new Color("red").to("srgb"); // $ExpectType Color +Color.to("red", "srgb"); // $ExpectType Color +Color.to(new Color("red"), "srgb"); // $ExpectType Color diff --git a/types/test/toGamut.ts b/types/test/toGamut.ts index 4bb02c16f..3b64e5e32 100644 --- a/types/test/toGamut.ts +++ b/types/test/toGamut.ts @@ -17,3 +17,5 @@ new Color("red").toGamut(); // $ExpectType Color new Color("red").toGamut({ method: "clip", space: "srgb" }); // $ExpectType Color new Color("red").toGamut({ method: "clip", space: sRGB }); // $ExpectType Color new Color("red").toGamut("srgb"); // $ExpectType Color +Color.toGamut("red"); // $ExpectType Color +Color.toGamut(new Color("red")); // $ExpectType Color