From 9c3c65b4b79e15aff9fa804a4f843623a64c5847 Mon Sep 17 00:00:00 2001 From: Adam Thompson-Sharpe Date: Sun, 18 Feb 2024 18:29:05 -0500 Subject: [PATCH] [types] Add JSDoc based on website docs (#436) --- .eslintrc.cjs | 8 +++++- types/src/display.d.ts | 6 +++++ types/src/hooks.d.ts | 36 ++++++++++++++++++++++++++ types/src/index.d.ts | 16 ++++++++++++ types/src/interpolation.d.ts | 27 ++++++++++++++++++++ types/src/parse.d.ts | 6 +++++ types/src/space.d.ts | 33 ++++++++++++++++++++++++ types/src/toGamut.d.ts | 49 +++++++++++++++++++++++++----------- 8 files changed, 166 insertions(+), 15 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 8e5677af5..1027f7e07 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -252,7 +252,13 @@ module.exports = { "@typescript-eslint/ban-ts-comment": 1, // Disallow certain built-in types // https://typescript-eslint.io/rules/ban-types - "@typescript-eslint/ban-types": 1, + "@typescript-eslint/ban-types": [ + 1, + { + extendDefaults: true, + types: { "{}": false }, + }, + ], // Disallow generic `Array` constructors // https://typescript-eslint.io/rules/no-array-constructor "@typescript-eslint/no-array-constructor": 1, diff --git a/types/src/display.d.ts b/types/src/display.d.ts index 47539ce3d..2c99ada92 100644 --- a/types/src/display.d.ts +++ b/types/src/display.d.ts @@ -3,6 +3,12 @@ import ColorSpace from "./space.js"; export type Display = string & { color: PlainColorObject }; +/** + * 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, options?: { diff --git a/types/src/hooks.d.ts b/types/src/hooks.d.ts index eef88c901..bfe08e459 100644 --- a/types/src/hooks.d.ts +++ b/types/src/hooks.d.ts @@ -1,13 +1,49 @@ +/** + * 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 { // Can't find a way to type this more specifically // without conflicting with the types of add and run [name: string]: any; + /** + * 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[], callback: (env: Record) => void, first?: boolean ): 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 }): void; } diff --git a/types/src/index.d.ts b/types/src/index.d.ts index 26e389614..73bc03a39 100644 --- a/types/src/index.d.ts +++ b/types/src/index.d.ts @@ -69,11 +69,20 @@ declare module "./color" { // interpolation // 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; + /** 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, @@ -85,7 +94,14 @@ declare module "./color" { 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; + /** Get an array of discrete steps */ static steps ( color1: ColorTypes, color2: ColorTypes, diff --git a/types/src/interpolation.d.ts b/types/src/interpolation.d.ts index bb289114e..48cc7ffd9 100644 --- a/types/src/interpolation.d.ts +++ b/types/src/interpolation.d.ts @@ -9,13 +9,34 @@ export type Range = ((percentage: number) => Color) & { 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 } + */ 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; } +/** + * 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, @@ -25,6 +46,7 @@ export function range ( export type MixOptions = RangeOptions; +/** Create color mixtures in any desired proportion between two colors */ export function mix ( color1: ColorTypes, color2: ColorTypes, @@ -38,12 +60,17 @@ export function mix ( ): PlainColorObject; 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; } +/** Get an array of discrete steps */ export function steps (color1: ColorTypes, color2: ColorTypes, options?: StepsOptions): PlainColorObject[]; export function steps (range: Range, options?: StepsOptions): PlainColorObject[]; diff --git a/types/src/parse.d.ts b/types/src/parse.d.ts index 8ea7e1206..51b0cd013 100644 --- a/types/src/parse.d.ts +++ b/types/src/parse.d.ts @@ -4,6 +4,12 @@ export interface Options { meta?: object | undefined; } +/** + * 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 diff --git a/types/src/space.d.ts b/types/src/space.d.ts index cd9477bb7..03312ca16 100644 --- a/types/src/space.d.ts +++ b/types/src/space.d.ts @@ -2,7 +2,9 @@ import { White } from "./adapt.js"; import Color, { ColorConstructor, ColorObject, Coords } from "./color.js"; export interface Format { + /** @default "function" */ type?: string | undefined; + /** @default "color" */ name?: string | undefined; id?: string | undefined; coords?: string[] | undefined; @@ -10,12 +12,21 @@ export interface Format { serializeCoords?: | ((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) | undefined; } @@ -27,15 +38,35 @@ export interface CoordMeta { } 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 | 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 | undefined; gamutSpace?: "self" | string | ColorSpace | null | undefined; } @@ -45,6 +76,7 @@ export type Ref = | [string | ColorSpace, string] | { space: string | ColorSpace; coordId: string }; +/** Class for color spaces. Each color space corresponds to a `ColorSpace` instance */ export default class ColorSpace { constructor (options: Options); @@ -79,6 +111,7 @@ export default class ColorSpace { static registry: Record; get all (): Set; + /** The ID used by CSS, such as `display-p3` or `--cam16-jmh` */ get cssId (): string; get isPolar (): boolean; diff --git a/types/src/toGamut.d.ts b/types/src/toGamut.d.ts index c5131a10e..ff3e7fb41 100644 --- a/types/src/toGamut.d.ts +++ b/types/src/toGamut.d.ts @@ -1,24 +1,45 @@ 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 { let returns: "color"; } -declare function toGamut ( - color: ColorTypes, - options?: { - method?: string | undefined; - space?: string | ColorSpace | undefined; - deltaEMethod?: string | undefined; - jnd?: number | undefined; - blackWhiteClamp?: { - channel: Ref; - min: number; - max: number; - } | undefined; - } | string -): PlainColorObject; +declare function toGamut (color: ColorTypes, options?: Options | string): PlainColorObject; export default toGamut;