Merge pull request #81 from microsoft/cleanup-color-compute

Cleanup color compute
This commit is contained in:
Nathan Evans 2022-11-16 16:29:45 -08:00 коммит произвёл GitHub
Родитель 3bd5f802f0 64756445dc
Коммит cd2c001643
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
134 изменённых файлов: 3951 добавлений и 1373 удалений

8
.yarn/versions/f8f31d29.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
releases:
"@thematic/color": major
"@thematic/core": major
"@thematic/d3": patch
"@thematic/fluent": major
"@thematic/react": patch
"@thematic/vega": major
"@thematic/webapp": major

Просмотреть файл

@ -7,13 +7,9 @@
<b>Signature:</b>
```typescript
hsl(): {
h: number;
s: number;
l: number;
};
hsl(): Hsl;
```
<b>Returns:</b>
{ h: number; s: number; l: number; }
[Hsl](./color.hsl.md)

Просмотреть файл

@ -7,9 +7,9 @@
<b>Signature:</b>
```typescript
hsluv(): [number, number, number];
hsluv(): HslVector;
```
<b>Returns:</b>
\[number, number, number\]
[HslVector](./color.hslvector.md)

Просмотреть файл

@ -7,7 +7,7 @@
<b>Signature:</b>
```typescript
rgbav(alpha?: number): [number, number, number, number];
rgbav(alpha?: number): RGBAV;
```
## Parameters
@ -18,5 +18,5 @@ rgbav(alpha?: number): [number, number, number, number];
<b>Returns:</b>
\[number, number, number, number\]
[RGBAV](./color.rgbav.md)

Просмотреть файл

@ -18,6 +18,8 @@ export declare enum ColorSpace
| --- | --- | --- |
| CSS | <code>&quot;css&quot;</code> | Encode the color using any CSS-compatible color string. The default due to its wide applicability, and the format colors use in theme JSON. https://www.w3.org/TR/css-color-3/\#colorunits |
| HEX | <code>&quot;hex&quot;</code> | Encode as a standard hexadecimal color. |
| HSL | <code>&quot;hsl&quot;</code> | HSL color space, { h, s, l }<!-- -->. |
| HSLUV | <code>&quot;hsluv&quot;</code> | HSLuv, which is a perceptually balanced space. \[h, s, l\]. https://www.hsluv.org/ |
| RGB | <code>&quot;rgb&quot;</code> | Encode as an object with r, g, b properies, scaled 0-255 each. |
| RGBA | <code>&quot;rgba&quot;</code> | Encode as an object with r, g, b properies, scaled 0-255 each, along with an alpha prop scaled 0-1 |
| RGBA\_NUMBER | <code>&quot;rgbaint&quot;</code> | This is raw JavaScript number representing the RGBA color. It is calculated by bitshifting R, G, B, and A values into a 32-bit space. (i.e., r, g &lt;<!-- -->&lt; 8, b &lt;<!-- -->&lt; 16, a &lt;<!-- -->&lt; 24) |

Просмотреть файл

@ -9,7 +9,7 @@ Convert a standard CSS-compatible string to \[h, s, l\] array
<b>Signature:</b>
```typescript
export declare function css2hsluv(css: string): [number, number, number];
export declare function css2hsluv(css: string): HslVector;
```
## Parameters
@ -20,5 +20,5 @@ export declare function css2hsluv(css: string): [number, number, number];
<b>Returns:</b>
\[number, number, number\]
[HslVector](./color.hslvector.md)

Просмотреть файл

@ -9,7 +9,7 @@ Convert a standard CSS-compatible string to \[l, c, h\] array
<b>Signature:</b>
```typescript
export declare function css2lch(css: string): [number, number, number];
export declare function css2lch(css: string): HslVector;
```
## Parameters
@ -20,5 +20,5 @@ export declare function css2lch(css: string): [number, number, number];
<b>Returns:</b>
\[number, number, number\]
[HslVector](./color.hslvector.md)

Просмотреть файл

@ -1,15 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [css2rgbaNumber](./color.css2rgbanumber.md)
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [css2rgbaint](./color.css2rgbaint.md)
## css2rgbaNumber() function
## css2rgbaint() function
Convert a standard CSS string to an integer number. This is commonly used in GL code.
<b>Signature:</b>
```typescript
export declare function css2rgbaNumber(css: string, alpha?: number): number;
export declare function css2rgbaint(css: string, alpha?: number): number;
```
## Parameters

Просмотреть файл

@ -1,15 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [css2rgbaVector](./color.css2rgbavector.md)
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [css2rgbav](./color.css2rgbav.md)
## css2rgbaVector() function
## css2rgbav() function
Convert a standard CSS string to vector of \[r, g, b, a\] values scaled from 0-1. This is typically used in WebGl.
<b>Signature:</b>
```typescript
export declare function css2rgbaVector(css: string, alpha?: number): [number, number, number, number];
export declare function css2rgbav(css: string, alpha?: number): [number, number, number, number];
```
## Parameters

Просмотреть файл

@ -4,15 +4,18 @@
## defaultParams variable
Default set of params useful for initializing new themes with our "standard look".
<b>Signature:</b>
```typescript
defaultParams: {
accentHue: number;
accentSaturation: number;
accentLuminance: number;
backgroundHueShift: number;
backgroundLevel: number;
nominalHueStep: number;
accentLightness: number;
scaleSaturation: number;
scaleLightness: number;
greyHue: number;
greySaturation: number;
}
```

Просмотреть файл

@ -4,22 +4,26 @@
## getScheme() function
Takes a set of core params and generates all of the scale computes required for a Schema, using HSLuv color space for even perceptual qualities.
<b>Signature:</b>
```typescript
export declare function getScheme(params: Params, nominalItemCount: number, sequentialItemCount: number, light: boolean): Scheme;
export declare function getScheme(params: SchemeParams, nominalItemCount: number, sequentialItemCount: number, light: boolean, tuning?: Partial<TuningParameters>): Scheme;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| params | [Params](./color.params.md) | |
| params | [SchemeParams](./color.schemeparams.md) | |
| nominalItemCount | number | |
| sequentialItemCount | number | |
| light | boolean | |
| tuning | Partial&lt;[TuningParameters](./color.tuningparameters.md)<!-- -->&gt; | <i>(Optional)</i> |
<b>Returns:</b>
[Scheme](./color.scheme.md)

Просмотреть файл

@ -7,16 +7,14 @@
<b>Signature:</b>
```typescript
export declare function hsluv2hex(h: number, s: number, l: number): string;
export declare function hsluv2hex(hsluv: HslVector): string;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| h | number | |
| s | number | |
| l | number | |
| hsluv | [HslVector](./color.hslvector.md) | |
<b>Returns:</b>

Просмотреть файл

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [hsluv2hsl](./color.hsluv2hsl.md)
## hsluv2hsl() function
<b>Signature:</b>
```typescript
export declare function hsluv2hsl(hsluv: HslVector): HslVector;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| hsluv | [HslVector](./color.hslvector.md) | |
<b>Returns:</b>
[HslVector](./color.hslvector.md)

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [HslVector](./color.hslvector.md)
## HslVector type
<b>Signature:</b>
```typescript
export declare type HslVector = [number, number, number];
```

Просмотреть файл

@ -32,12 +32,13 @@
| [css2lch(css)](./color.css2lch.md) | Convert a standard CSS-compatible string to \[l, c, h\] array |
| [css2rgb(css, \_alpha)](./color.css2rgb.md) | Converts a standard CSS color to an {<!-- -->r, g, b<!-- -->} object |
| [css2rgba(css, alpha)](./color.css2rgba.md) | Converts a standard CSS color to an { r, g, b, a } object. |
| [css2rgbaNumber(css, alpha)](./color.css2rgbanumber.md) | Convert a standard CSS string to an integer number. This is commonly used in GL code. |
| [css2rgbaVector(css, alpha)](./color.css2rgbavector.md) | Convert a standard CSS string to vector of \[r, g, b, a\] values scaled from 0-1. This is typically used in WebGl. |
| [css2rgbaint(css, alpha)](./color.css2rgbaint.md) | Convert a standard CSS string to an integer number. This is commonly used in GL code. |
| [css2rgbav(css, alpha)](./color.css2rgbav.md) | Convert a standard CSS string to vector of \[r, g, b, a\] values scaled from 0-1. This is typically used in WebGl. |
| [darken(css, value)](./color.darken.md) | Darken a standard CSS color |
| [getNamedSchemeColor(scheme, path)](./color.getnamedschemecolor.md) | Extracts a thematic Color using its scheme "path". |
| [getScheme(params, nominalItemCount, sequentialItemCount, light)](./color.getscheme.md) | |
| [hsluv2hex(h, s, l)](./color.hsluv2hex.md) | |
| [getScheme(params, nominalItemCount, sequentialItemCount, light, tuning)](./color.getscheme.md) | Takes a set of core params and generates all of the scale computes required for a Schema, using HSLuv color space for even perceptual qualities. |
| [hsluv2hex(hsluv)](./color.hsluv2hex.md) | |
| [hsluv2hsl(hsluv)](./color.hsluv2hsl.md) | |
| [isNominal(name)](./color.isnominal.md) | |
| [lch2hex(l, c, h)](./color.lch2hex.md) | Convert a set of l, c, and h values to a standard CSS-comptible hex string |
| [lighten(css, value)](./color.lighten.md) | Lighten a standard CSS color |
@ -52,14 +53,22 @@
| [ColorBlindnessMeta](./color.colorblindnessmeta.md) | Interface for meta container about color blindness. Note that incidence is the reported number for males, as female color blindness is very rare in comparison (overall 1 in 12 males, 1 in 200 females) |
| [Hsl](./color.hsl.md) | |
| [Hsv](./color.hsv.md) | |
| [Params](./color.params.md) | This is the core set of parameters for generating schemes using the ColorPicker |
| [Rgb](./color.rgb.md) | |
| [Rgba](./color.rgba.md) | |
| [Scheme](./color.scheme.md) | Core color properties for a computed color scheme. Note the values are all strings - our color default representation uses hex codes. |
| [SchemeParams](./color.schemeparams.md) | This is the core set of parameters for generating schemes using the ColorPicker |
| [TuningParameters](./color.tuningparameters.md) | Detailed tuning for the scale generation algorithms. |
## Variables
| Variable | Description |
| --- | --- |
| [defaultParams](./color.defaultparams.md) | |
| [defaultParams](./color.defaultparams.md) | Default set of params useful for initializing new themes with our "standard look". |
## Type Aliases
| Type Alias | Description |
| --- | --- |
| [HslVector](./color.hslvector.md) | |
| [RGBAV](./color.rgbav.md) | |

Просмотреть файл

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Params](./color.params.md) &gt; [accentHue](./color.params.accenthue.md)
## Params.accentHue property
<b>Signature:</b>
```typescript
accentHue: number;
```

Просмотреть файл

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Params](./color.params.md) &gt; [accentLuminance](./color.params.accentluminance.md)
## Params.accentLuminance property
<b>Signature:</b>
```typescript
accentLuminance: number;
```

Просмотреть файл

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Params](./color.params.md) &gt; [accentSaturation](./color.params.accentsaturation.md)
## Params.accentSaturation property
<b>Signature:</b>
```typescript
accentSaturation: number;
```

Просмотреть файл

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Params](./color.params.md) &gt; [backgroundHueShift](./color.params.backgroundhueshift.md)
## Params.backgroundHueShift property
<b>Signature:</b>
```typescript
backgroundHueShift: number;
```

Просмотреть файл

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Params](./color.params.md) &gt; [backgroundLevel](./color.params.backgroundlevel.md)
## Params.backgroundLevel property
<b>Signature:</b>
```typescript
backgroundLevel: number;
```

Просмотреть файл

@ -1,25 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Params](./color.params.md)
## Params interface
This is the core set of parameters for generating schemes using the ColorPicker
<b>Signature:</b>
```typescript
export interface Params
```
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [accentHue](./color.params.accenthue.md) | | number | |
| [accentLuminance](./color.params.accentluminance.md) | | number | |
| [accentSaturation](./color.params.accentsaturation.md) | | number | |
| [backgroundHueShift](./color.params.backgroundhueshift.md) | | number | |
| [backgroundLevel](./color.params.backgroundlevel.md) | | number | |
| [nominalHueStep](./color.params.nominalhuestep.md) | | number | |

Просмотреть файл

@ -1,11 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Params](./color.params.md) &gt; [nominalHueStep](./color.params.nominalhuestep.md)
## Params.nominalHueStep property
<b>Signature:</b>
```typescript
nominalHueStep: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [RGBAV](./color.rgbav.md)
## RGBAV type
<b>Signature:</b>
```typescript
export declare type RGBAV = [number, number, number, number];
```

Просмотреть файл

@ -7,14 +7,14 @@
<b>Signature:</b>
```typescript
export declare function rgbav2hex(rgbav: [number, number, number, number]): string;
export declare function rgbav2hex(rgbav: RGBAV): string;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| rgbav | \[number, number, number, number\] | |
| rgbav | [RGBAV](./color.rgbav.md) | |
<b>Returns:</b>

Просмотреть файл

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Scheme](./color.scheme.md) &gt; [dataPrimary](./color.scheme.dataprimary.md)
## Scheme.dataPrimary property
Primary data color, derived from the accent.
<b>Signature:</b>
```typescript
dataPrimary: string;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Scheme](./color.scheme.md) &gt; [dataPrimaryBold](./color.scheme.dataprimarybold.md)
## Scheme.dataPrimaryBold property
<b>Signature:</b>
```typescript
dataPrimaryBold: string;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Scheme](./color.scheme.md) &gt; [dataPrimaryMuted](./color.scheme.dataprimarymuted.md)
## Scheme.dataPrimaryMuted property
<b>Signature:</b>
```typescript
dataPrimaryMuted: string;
```

Просмотреть файл

@ -18,6 +18,9 @@ export interface Scheme
| --- | --- | --- | --- |
| [accent](./color.scheme.accent.md) | | string | |
| [background](./color.scheme.background.md) | | string | |
| [dataPrimary](./color.scheme.dataprimary.md) | | string | Primary data color, derived from the accent. |
| [dataPrimaryBold](./color.scheme.dataprimarybold.md) | | string | |
| [dataPrimaryMuted](./color.scheme.dataprimarymuted.md) | | string | |
| [diverging](./color.scheme.diverging.md) | | string\[\] | |
| [diverging2](./color.scheme.diverging2.md) | | string\[\] | |
| [error](./color.scheme.error.md) | | string | |
@ -33,6 +36,7 @@ export interface Scheme
| [nominalBold](./color.scheme.nominalbold.md) | | string\[\] | |
| [nominalMuted](./color.scheme.nominalmuted.md) | | string\[\] | |
| [offsetBackground](./color.scheme.offsetbackground.md) | | string | |
| [rainbow](./color.scheme.rainbow.md) | | string\[\] | |
| [sequential](./color.scheme.sequential.md) | | string\[\] | |
| [sequential2](./color.scheme.sequential2.md) | | string\[\] | |
| [warning](./color.scheme.warning.md) | | string | |

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [Scheme](./color.scheme.md) &gt; [rainbow](./color.scheme.rainbow.md)
## Scheme.rainbow property
<b>Signature:</b>
```typescript
rainbow: string[];
```

Просмотреть файл

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [SchemeParams](./color.schemeparams.md) &gt; [accentHue](./color.schemeparams.accenthue.md)
## SchemeParams.accentHue property
HSL hue component for the accent. Valid range is 0-360 (degrees).
<b>Signature:</b>
```typescript
accentHue: number;
```

Просмотреть файл

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [SchemeParams](./color.schemeparams.md) &gt; [accentLightness](./color.schemeparams.accentlightness.md)
## SchemeParams.accentLightness property
HSL lightness component for the accent. Valid range is 0-100.
<b>Signature:</b>
```typescript
accentLightness: number;
```

Просмотреть файл

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [SchemeParams](./color.schemeparams.md) &gt; [accentSaturation](./color.schemeparams.accentsaturation.md)
## SchemeParams.accentSaturation property
HSL saturation component for the accent. Valid range is 0-100.
<b>Signature:</b>
```typescript
accentSaturation: number;
```

Просмотреть файл

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [SchemeParams](./color.schemeparams.md) &gt; [greyHue](./color.schemeparams.greyhue.md)
## SchemeParams.greyHue property
Optional hue to mix some of warm or cool into grey scales.
<b>Signature:</b>
```typescript
greyHue?: number;
```

Просмотреть файл

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [SchemeParams](./color.schemeparams.md) &gt; [greySaturation](./color.schemeparams.greysaturation.md)
## SchemeParams.greySaturation property
Optional saturation to mix some of warm or cool into grey scales.
<b>Signature:</b>
```typescript
greySaturation?: number;
```

Просмотреть файл

@ -0,0 +1,26 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [SchemeParams](./color.schemeparams.md)
## SchemeParams interface
This is the core set of parameters for generating schemes using the ColorPicker
<b>Signature:</b>
```typescript
export interface SchemeParams
```
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [accentHue](./color.schemeparams.accenthue.md) | | number | HSL hue component for the accent. Valid range is 0-360 (degrees). |
| [accentLightness](./color.schemeparams.accentlightness.md) | | number | HSL lightness component for the accent. Valid range is 0-100. |
| [accentSaturation](./color.schemeparams.accentsaturation.md) | | number | HSL saturation component for the accent. Valid range is 0-100. |
| [greyHue?](./color.schemeparams.greyhue.md) | | number | <i>(Optional)</i> Optional hue to mix some of warm or cool into grey scales. |
| [greySaturation?](./color.schemeparams.greysaturation.md) | | number | <i>(Optional)</i> Optional saturation to mix some of warm or cool into grey scales. |
| [scaleLightness?](./color.schemeparams.scalelightness.md) | | number | <i>(Optional)</i> Sets the default lightness for nominal scales. Muted and bold scales are a fixed lightness +- |
| [scaleSaturation?](./color.schemeparams.scalesaturation.md) | | number | <i>(Optional)</i> Sets the default saturation for nominal scales. Muted and bold scales are a fixed saturation +- |

Просмотреть файл

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [SchemeParams](./color.schemeparams.md) &gt; [scaleLightness](./color.schemeparams.scalelightness.md)
## SchemeParams.scaleLightness property
Sets the default lightness for nominal scales. Muted and bold scales are a fixed lightness +-
<b>Signature:</b>
```typescript
scaleLightness?: number;
```

Просмотреть файл

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [SchemeParams](./color.schemeparams.md) &gt; [scaleSaturation](./color.schemeparams.scalesaturation.md)
## SchemeParams.scaleSaturation property
Sets the default saturation for nominal scales. Muted and bold scales are a fixed saturation +-
<b>Signature:</b>
```typescript
scaleSaturation?: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [analogousRange](./color.tuningparameters.analogousrange.md)
## TuningParameters.analogousRange property
<b>Signature:</b>
```typescript
analogousRange: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [backgroundHueShift](./color.tuningparameters.backgroundhueshift.md)
## TuningParameters.backgroundHueShift property
<b>Signature:</b>
```typescript
backgroundHueShift: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [backgroundLevel](./color.tuningparameters.backgroundlevel.md)
## TuningParameters.backgroundLevel property
<b>Signature:</b>
```typescript
backgroundLevel: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [complementaryRange](./color.tuningparameters.complementaryrange.md)
## TuningParameters.complementaryRange property
<b>Signature:</b>
```typescript
complementaryRange: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [darkBackgroundLightnessShift](./color.tuningparameters.darkbackgroundlightnessshift.md)
## TuningParameters.darkBackgroundLightnessShift property
<b>Signature:</b>
```typescript
darkBackgroundLightnessShift: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [darkestGrey](./color.tuningparameters.darkestgrey.md)
## TuningParameters.darkestGrey property
<b>Signature:</b>
```typescript
darkestGrey: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [darkMaxLightnessOffet](./color.tuningparameters.darkmaxlightnessoffet.md)
## TuningParameters.darkMaxLightnessOffet property
<b>Signature:</b>
```typescript
darkMaxLightnessOffet: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [darkTextLightness](./color.tuningparameters.darktextlightness.md)
## TuningParameters.darkTextLightness property
<b>Signature:</b>
```typescript
darkTextLightness: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [lightBackgroundLightnessShift](./color.tuningparameters.lightbackgroundlightnessshift.md)
## TuningParameters.lightBackgroundLightnessShift property
<b>Signature:</b>
```typescript
lightBackgroundLightnessShift: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [lightestGrey](./color.tuningparameters.lightestgrey.md)
## TuningParameters.lightestGrey property
<b>Signature:</b>
```typescript
lightestGrey: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [lightMaxLightnessOffset](./color.tuningparameters.lightmaxlightnessoffset.md)
## TuningParameters.lightMaxLightnessOffset property
<b>Signature:</b>
```typescript
lightMaxLightnessOffset: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [lightTextLightness](./color.tuningparameters.lighttextlightness.md)
## TuningParameters.lightTextLightness property
<b>Signature:</b>
```typescript
lightTextLightness: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [lowContrastBackgroundShift](./color.tuningparameters.lowcontrastbackgroundshift.md)
## TuningParameters.lowContrastBackgroundShift property
<b>Signature:</b>
```typescript
lowContrastBackgroundShift: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [maxBackgroundChroma](./color.tuningparameters.maxbackgroundchroma.md)
## TuningParameters.maxBackgroundChroma property
<b>Signature:</b>
```typescript
maxBackgroundChroma: number;
```

Просмотреть файл

@ -0,0 +1,43 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md)
## TuningParameters interface
Detailed tuning for the scale generation algorithms.
<b>Signature:</b>
```typescript
export interface TuningParameters
```
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [analogousRange](./color.tuningparameters.analogousrange.md) | | number | |
| [backgroundHueShift](./color.tuningparameters.backgroundhueshift.md) | | number | |
| [backgroundLevel](./color.tuningparameters.backgroundlevel.md) | | number | |
| [complementaryRange](./color.tuningparameters.complementaryrange.md) | | number | |
| [darkBackgroundLightnessShift](./color.tuningparameters.darkbackgroundlightnessshift.md) | | number | |
| [darkestGrey](./color.tuningparameters.darkestgrey.md) | | number | |
| [darkMaxLightnessOffet](./color.tuningparameters.darkmaxlightnessoffet.md) | | number | |
| [darkTextLightness](./color.tuningparameters.darktextlightness.md) | | number | |
| [lightBackgroundLightnessShift](./color.tuningparameters.lightbackgroundlightnessshift.md) | | number | |
| [lightestGrey](./color.tuningparameters.lightestgrey.md) | | number | |
| [lightMaxLightnessOffset](./color.tuningparameters.lightmaxlightnessoffset.md) | | number | |
| [lightTextLightness](./color.tuningparameters.lighttextlightness.md) | | number | |
| [lowContrastBackgroundShift](./color.tuningparameters.lowcontrastbackgroundshift.md) | | number | |
| [maxBackgroundChroma](./color.tuningparameters.maxbackgroundchroma.md) | | number | |
| [minNominalLightness](./color.tuningparameters.minnominallightness.md) | | number | |
| [minNominalSaturation](./color.tuningparameters.minnominalsaturation.md) | | number | |
| [nominalBoldLightnessShift](./color.tuningparameters.nominalboldlightnessshift.md) | | number | |
| [nominalBoldSaturationShift](./color.tuningparameters.nominalboldsaturationshift.md) | | number | |
| [nominalHueStep](./color.tuningparameters.nominalhuestep.md) | | number | |
| [nominalMutedLightnessShift](./color.tuningparameters.nominalmutedlightnessshift.md) | | number | |
| [nominalMutedSaturationShift](./color.tuningparameters.nominalmutedsaturationshift.md) | | number | |
| [offsetBackgroundLightnessShift](./color.tuningparameters.offsetbackgroundlightnessshift.md) | | number | |
| [polynomialExponent](./color.tuningparameters.polynomialexponent.md) | | number | |
| [reservedDataColors](./color.tuningparameters.reserveddatacolors.md) | | number | |

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [minNominalLightness](./color.tuningparameters.minnominallightness.md)
## TuningParameters.minNominalLightness property
<b>Signature:</b>
```typescript
minNominalLightness: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [minNominalSaturation](./color.tuningparameters.minnominalsaturation.md)
## TuningParameters.minNominalSaturation property
<b>Signature:</b>
```typescript
minNominalSaturation: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [nominalBoldLightnessShift](./color.tuningparameters.nominalboldlightnessshift.md)
## TuningParameters.nominalBoldLightnessShift property
<b>Signature:</b>
```typescript
nominalBoldLightnessShift: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [nominalBoldSaturationShift](./color.tuningparameters.nominalboldsaturationshift.md)
## TuningParameters.nominalBoldSaturationShift property
<b>Signature:</b>
```typescript
nominalBoldSaturationShift: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [nominalHueStep](./color.tuningparameters.nominalhuestep.md)
## TuningParameters.nominalHueStep property
<b>Signature:</b>
```typescript
nominalHueStep: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [nominalMutedLightnessShift](./color.tuningparameters.nominalmutedlightnessshift.md)
## TuningParameters.nominalMutedLightnessShift property
<b>Signature:</b>
```typescript
nominalMutedLightnessShift: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [nominalMutedSaturationShift](./color.tuningparameters.nominalmutedsaturationshift.md)
## TuningParameters.nominalMutedSaturationShift property
<b>Signature:</b>
```typescript
nominalMutedSaturationShift: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [offsetBackgroundLightnessShift](./color.tuningparameters.offsetbackgroundlightnessshift.md)
## TuningParameters.offsetBackgroundLightnessShift property
<b>Signature:</b>
```typescript
offsetBackgroundLightnessShift: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [polynomialExponent](./color.tuningparameters.polynomialexponent.md)
## TuningParameters.polynomialExponent property
<b>Signature:</b>
```typescript
polynomialExponent: number;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/color](./color.md) &gt; [TuningParameters](./color.tuningparameters.md) &gt; [reservedDataColors](./color.tuningparameters.reserveddatacolors.md)
## TuningParameters.reservedDataColors property
<b>Signature:</b>
```typescript
reservedDataColors: number;
```

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -14,20 +14,16 @@ export class Color {
// (undocumented)
hex(alpha?: number): string;
// (undocumented)
hsl(): {
h: number;
s: number;
l: number;
};
hsl(): Hsl;
// (undocumented)
hsluv(): [number, number, number];
hsluv(): HslVector;
get raw(): string;
// (undocumented)
rgba(alpha?: number): Rgba;
// (undocumented)
rgbaint(alpha?: number): number;
// (undocumented)
rgbav(alpha?: number): [number, number, number, number];
rgbav(alpha?: number): RGBAV;
// (undocumented)
toString(): string;
}
@ -72,6 +68,8 @@ export enum ColorBlindnessMode {
export enum ColorSpace {
CSS = "css",
HEX = "hex",
HSL = "hsl",
HSLUV = "hsluv",
RGB = "rgb",
RGBA = "rgba",
RGBA_NUMBER = "rgbaint",
@ -101,7 +99,7 @@ export function css2hsl(css: string, _alpha?: number): Hsl;
// Warning: (ae-missing-release-tag) "css2hsluv" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function css2hsluv(css: string): [number, number, number];
export function css2hsluv(css: string): HslVector;
// Warning: (ae-missing-release-tag) "css2hsv" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@ -111,7 +109,7 @@ export function css2hsv(css: string, _alpha?: number): Hsv;
// Warning: (ae-missing-release-tag) "css2lch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function css2lch(css: string): [number, number, number];
export function css2lch(css: string): HslVector;
// Warning: (ae-missing-release-tag) "css2rgb" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@ -123,15 +121,15 @@ export function css2rgb(css: string, _alpha?: number): Rgb;
// @public
export function css2rgba(css: string, alpha?: number): Rgba;
// Warning: (ae-missing-release-tag) "css2rgbaNumber" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "css2rgbaint" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function css2rgbaNumber(css: string, alpha?: number): number;
export function css2rgbaint(css: string, alpha?: number): number;
// Warning: (ae-missing-release-tag) "css2rgbaVector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-missing-release-tag) "css2rgbav" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function css2rgbaVector(css: string, alpha?: number): [number, number, number, number];
export function css2rgbav(css: string, alpha?: number): [number, number, number, number];
// Warning: (ae-missing-release-tag) "darken" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@ -140,14 +138,15 @@ export function darken(css: string, value?: number): string;
// Warning: (ae-missing-release-tag) "defaultParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
// @public
export const defaultParams: {
accentHue: number;
accentSaturation: number;
accentLuminance: number;
backgroundHueShift: number;
backgroundLevel: number;
nominalHueStep: number;
accentLightness: number;
scaleSaturation: number;
scaleLightness: number;
greyHue: number;
greySaturation: number;
};
// Warning: (ae-missing-release-tag) "getNamedSchemeColor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@ -157,8 +156,8 @@ export function getNamedSchemeColor(scheme: Scheme, path?: string): Color;
// Warning: (ae-missing-release-tag) "getScheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function getScheme(params: Params, nominalItemCount: number, sequentialItemCount: number, light: boolean): Scheme;
// @public
export function getScheme(params: SchemeParams, nominalItemCount: number, sequentialItemCount: number, light: boolean, tuning?: Partial<TuningParameters>): Scheme;
// Warning: (ae-missing-release-tag) "Hsl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@ -175,7 +174,17 @@ export interface Hsl {
// Warning: (ae-missing-release-tag) "hsluv2hex" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function hsluv2hex(h: number, s: number, l: number): string;
export function hsluv2hex(hsluv: HslVector): string;
// Warning: (ae-missing-release-tag) "hsluv2hsl" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function hsluv2hsl(hsluv: HslVector): HslVector;
// Warning: (ae-missing-release-tag) "HslVector" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type HslVector = [number, number, number];
// Warning: (ae-missing-release-tag) "Hsv" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@ -209,24 +218,6 @@ export function lighten(css: string, value?: number): string;
// @public
export function nearest(input: Color, list: Color[]): Color;
// Warning: (ae-missing-release-tag) "Params" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export interface Params {
// (undocumented)
accentHue: number;
// (undocumented)
accentLuminance: number;
// (undocumented)
accentSaturation: number;
// (undocumented)
backgroundHueShift: number;
// (undocumented)
backgroundLevel: number;
// (undocumented)
nominalHueStep: number;
}
// Warning: (ae-missing-release-tag) "Rgb" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@ -252,10 +243,15 @@ export interface Rgba extends Rgb {
// @public (undocumented)
export function rgba2hex(rgba: Rgba): string;
// Warning: (ae-missing-release-tag) "RGBAV" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type RGBAV = [number, number, number, number];
// Warning: (ae-missing-release-tag) "rgbav2hex" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function rgbav2hex(rgbav: [number, number, number, number]): string;
export function rgbav2hex(rgbav: RGBAV): string;
// Warning: (ae-missing-release-tag) "Scheme" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@ -265,6 +261,11 @@ export interface Scheme {
accent: string;
// (undocumented)
background: string;
dataPrimary: string;
// (undocumented)
dataPrimaryBold: string;
// (undocumented)
dataPrimaryMuted: string;
// (undocumented)
diverging: string[];
// (undocumented)
@ -296,6 +297,8 @@ export interface Scheme {
// (undocumented)
offsetBackground: string;
// (undocumented)
rainbow: string[];
// (undocumented)
sequential: string[];
// (undocumented)
sequential2: string[];
@ -303,6 +306,73 @@ export interface Scheme {
warning: string;
}
// Warning: (ae-missing-release-tag) "SchemeParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export interface SchemeParams {
accentHue: number;
accentLightness: number;
accentSaturation: number;
greyHue?: number;
greySaturation?: number;
scaleLightness?: number;
scaleSaturation?: number;
}
// Warning: (ae-missing-release-tag) "TuningParameters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export interface TuningParameters {
// (undocumented)
analogousRange: number;
// (undocumented)
backgroundHueShift: number;
// (undocumented)
backgroundLevel: number;
// (undocumented)
complementaryRange: number;
// (undocumented)
darkBackgroundLightnessShift: number;
// (undocumented)
darkestGrey: number;
// (undocumented)
darkMaxLightnessOffet: number;
// (undocumented)
darkTextLightness: number;
// (undocumented)
lightBackgroundLightnessShift: number;
// (undocumented)
lightestGrey: number;
// (undocumented)
lightMaxLightnessOffset: number;
// (undocumented)
lightTextLightness: number;
// (undocumented)
lowContrastBackgroundShift: number;
// (undocumented)
maxBackgroundChroma: number;
// (undocumented)
minNominalLightness: number;
// (undocumented)
minNominalSaturation: number;
// (undocumented)
nominalBoldLightnessShift: number;
// (undocumented)
nominalBoldSaturationShift: number;
// (undocumented)
nominalHueStep: number;
// (undocumented)
nominalMutedLightnessShift: number;
// (undocumented)
nominalMutedSaturationShift: number;
// (undocumented)
offsetBackgroundLightnessShift: number;
// (undocumented)
polynomialExponent: number;
// (undocumented)
reservedDataColors: number;
}
// (No @packageDocumentation comment for this package)
```

Просмотреть файл

@ -69,11 +69,12 @@
"css2lch": "function",
"css2rgb": "function",
"css2rgba": "function",
"css2rgbaNumber": "function",
"css2rgbaVector": "function",
"css2rgbaint": "function",
"css2rgbav": "function",
"rgba2hex": "function",
"rgbav2hex": "function",
"hsluv2hex": "function",
"hsluv2hsl": "function",
"lch2hex": "function",
"nearest": "function"
},

Просмотреть файл

@ -8,10 +8,10 @@ import {
css2hsl,
css2hsluv,
css2rgba,
css2rgbaNumber,
css2rgbaVector,
css2rgbaint,
css2rgbav,
} from './chroma.js'
import type { Rgba } from './types.js'
import type { Hsl, HslVector, Rgba, RGBAV } from './types.js'
/**
* This class represents an instance of a color.
@ -41,19 +41,19 @@ export class Color {
css(alpha?: number): string {
return css2css(this._raw, alpha || this._alpha)
}
rgbav(alpha?: number): [number, number, number, number] {
return css2rgbaVector(this._raw, alpha || this._alpha)
rgbav(alpha?: number): RGBAV {
return css2rgbav(this._raw, alpha || this._alpha)
}
rgbaint(alpha?: number): number {
return css2rgbaNumber(this._raw, alpha || this._alpha)
return css2rgbaint(this._raw, alpha || this._alpha)
}
rgba(alpha?: number): Rgba {
return css2rgba(this._raw, alpha)
}
hsluv(): [number, number, number] {
hsluv(): HslVector {
return css2hsluv(this._raw)
}
hsl(): { h: number; s: number; l: number } {
hsl(): Hsl {
return css2hsl(this._raw)
}
toString(): string {

Просмотреть файл

@ -2,81 +2,82 @@
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
import { ColorMaker, polynomial_scale } from '../scheme/HsluvColorLogic.js'
import { defaultParams } from '../index.js'
import { getScheme, validateParams } from '../scheme/HsluvColorLogic.js'
const GREYS = [
[50, 0, 92],
[50, 0, 84],
[50, 0, 76],
[50, 0, 68],
[50, 0, 60],
[50, 0, 52],
[50, 0, 44],
[50, 0, 36.000000000000007],
[50, 0, 28],
[50, 0, 20],
const NEUTRAL_GREYS = [
'#f5f5f5',
'#dddddd',
'#c5c5c5',
'#aeaeae',
'#979797',
'#818181',
'#6c6c6c',
'#575757',
'#434343',
'#303030',
]
const SEQUENTIAL1 = [
[50, 0, 92],
[50, 25, 81.5],
[50, 50, 71],
[50, 75, 60.5],
[50, 100, 50],
const TINTED_GREYS = [
'#f6f5f3',
'#e0ddd5',
'#c8c5be',
'#b0aea7',
'#999791',
'#83817c',
'#6d6c67',
'#585754',
'#444340',
'#31302e',
]
const SEQUENTIAL2 = [
[58.57142857142857, 0, 92],
[58.57142857142857, 25, 81.5],
[58.57142857142857, 50, 71],
[58.57142857142857, 75, 60.5],
[58.57142857142857, 100, 50],
]
const SEQUENTIAL1 = ['#f5f5f5', '#dfd2c6', '#d4ad85', '#ba8c54', '#9d6e22']
const SEQUENTIAL2 = ['#f5f5f5', '#d9d1de', '#c5aad7', '#ba7cdd', '#b92fec']
const DIVERGING = [
[140, 100, 50],
[140, 71.55417527999329, 61.947246382402824],
[140, 46.47580015448901, 72.48016393511462],
[140, 25.29822128134704, 81.37474706183424],
[140, 8.944271909999161, 88.24340579780035],
[50, 8.944271909999161, 88.24340579780035],
[50, 25.29822128134704, 81.37474706183424],
[50, 46.47580015448901, 72.48016393511462],
[50, 71.55417527999329, 61.947246382402824],
[50, 100, 50],
'#238850',
'#5ba978',
'#8dc59f',
'#badcc4',
'#e3ebe5',
'#ebe9e7',
'#dfd1c6',
'#d7b28c',
'#be915a',
'#9d6e22',
]
describe('ColorMaker', () => {
test('can be instantiated', () => {
expect(() => new ColorMaker([50, 50, 50], 50, 50, 50, true)).not.toThrow()
// TODO: test light v dark
describe('getScheme', () => {
test('creates neutral grey scales (no saturation)', () => {
const scheme = getScheme(
{
accentHue: 50,
accentSaturation: 50,
accentLightness: 50,
greySaturation: 0,
},
10,
10,
true,
)
expect(scheme.greys).toEqual(NEUTRAL_GREYS)
})
test('can create grey scales', () => {
const colorMaker = new ColorMaker([50, 50, 50], 50, 50, 50, true)
const greys = colorMaker.grey(10)
expect(greys).toEqual(GREYS)
})
test('can create sequential scales', () => {
const colorMaker = new ColorMaker([50, 50, 50], 50, 50, 50, true)
const sequential1 = colorMaker.sequential(5)
const sequential2 = colorMaker.sequential(5, 1)
expect(sequential1).toEqual(SEQUENTIAL1)
expect(sequential2).toEqual(SEQUENTIAL2)
})
test('can create diverging scales', () => {
const colorMaker = new ColorMaker([50, 50, 50], 50, 50, 50, true)
const diverging = colorMaker.diverging(10)
expect(diverging).toEqual(DIVERGING)
})
test('has polynomial scales', () => {
const scale1 = polynomial_scale(1, 0, 10, 11).map(x => Math.round(x))
expect(scale1).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
const scale2 = polynomial_scale(2, 0, 64, 8).map(x => Math.round(x))
expect(scale2).toEqual([0, 1, 5, 12, 21, 33, 47, 64])
test('creates tinted grey scales (default)', () => {
const scheme = getScheme(
{
accentHue: 50,
accentSaturation: 50,
accentLightness: 50,
},
10,
10,
true,
)
expect(scheme.greys).toEqual(TINTED_GREYS)
})
describe('nominal count matches requested size', () => {
@ -84,21 +85,96 @@ describe('ColorMaker', () => {
// but this can result in mismatched final counts
// ensure that the resulting nominal scales are trimmed correctly
test('default hue step (10)', () => {
const colorMaker = new ColorMaker([50, 50, 50], 50, 50, 10, true)
const scale = colorMaker.nominal(1)
expect(scale.size).toBe(1)
const scheme = getScheme(
{
accentHue: 50,
accentSaturation: 50,
accentLightness: 50,
},
1,
10,
true,
)
expect(scheme.nominal).toHaveLength(1)
})
test('hue step < 10 (3)', () => {
const colorMaker = new ColorMaker([50, 50, 50], 50, 50, 3, true)
const scale = colorMaker.nominal(1)
expect(scale.size).toBe(1)
const scheme = getScheme(
{
accentHue: 50,
accentSaturation: 50,
accentLightness: 50,
},
1,
10,
true,
{
nominalHueStep: 3,
},
)
expect(scheme.nominal).toHaveLength(1)
})
test('hue step > 10 (14)', () => {
const colorMaker = new ColorMaker([50, 50, 50], 50, 50, 14, true)
const scale = colorMaker.nominal(2)
expect(scale.size).toBe(2)
const scheme = getScheme(
{
accentHue: 50,
accentSaturation: 50,
accentLightness: 50,
},
2,
10,
true,
{
nominalHueStep: 14,
},
)
expect(scheme.nominal).toHaveLength(2)
})
})
describe('sequential scales', () => {
test('creates sequential scales', () => {
const scheme = getScheme(
{
accentHue: 50,
accentSaturation: 50,
accentLightness: 50,
},
10,
5,
true,
)
expect(scheme.sequential).toEqual(SEQUENTIAL1)
expect(scheme.sequential2).toEqual(SEQUENTIAL2)
})
})
describe('diverging scales', () => {
test('creates diverging scales', () => {
const scheme = getScheme(
{
accentHue: 50,
accentSaturation: 50,
accentLightness: 50,
},
10,
10,
true,
)
expect(scheme.diverging).toEqual(DIVERGING)
})
})
})
describe('validateParams', () => {
test('fill in defaults', () => {
const params = validateParams({
accentHue: 100,
accentLightness: 100,
accentSaturation: 100,
})
expect(params.greyHue).toBe(defaultParams.greyHue)
expect(params.greySaturation).toBe(defaultParams.greySaturation)
})
})

Просмотреть файл

@ -2,7 +2,7 @@
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
import { css2css, css2rgbaNumber, css2rgbaVector } from '../chroma.js'
import { css2css, css2rgbaint, css2rgbav } from '../chroma.js'
describe('color conversion functions', () => {
describe('css2css', () => {
@ -14,48 +14,48 @@ describe('color conversion functions', () => {
describe('css => rgba vector', () => {
test('default opacity in hex string', () => {
const value = css2rgbaVector('#1f77b4')
const value = css2rgbav('#1f77b4')
expect(value).toEqual([
0.12156862745098039, 0.4666666666666667, 0.7058823529411765, 1,
])
})
test('override opacity with alpha param', () => {
const value = css2rgbaVector('#1f77b4', 0.5)
const value = css2rgbav('#1f77b4', 0.5)
expect(value).toEqual([
0.12156862745098039, 0.4666666666666667, 0.7058823529411765, 0.5,
])
})
test('css "none" value', () => {
const value = css2rgbaVector('none')
const value = css2rgbav('none')
expect(value).toEqual([0, 0, 0, 0])
})
})
describe('css => rgba number', () => {
test('full opacity black', () => {
const value = css2rgbaNumber('black')
const value = css2rgbaint('black')
expect(value).toBe(-16777216)
})
test('zero opacity black', () => {
const value = css2rgbaNumber('black', 0)
const value = css2rgbaint('black', 0)
expect(value).toBe(0)
})
test('full opacity red', () => {
const value = css2rgbaNumber('red', 1)
const value = css2rgbaint('red', 1)
expect(value).toBe(-16776961)
})
test('zero opacity red', () => {
const value = css2rgbaNumber('red', 0)
const value = css2rgbaint('red', 0)
expect(value).toBe(255)
})
test('css "none" value', () => {
const value = css2rgbaNumber('none')
const value = css2rgbaint('none')
expect(value).toBe(0)
})
})

Просмотреть файл

@ -35,7 +35,7 @@ describe('nearest', () => {
test('orange', () => {
const color = new Color('orange')
const match = nearest(color, colors)
expect(match.hex()).toBe('#ce9e3f')
expect(match.hex()).toBe('#e7973c')
})
test('yellow', () => {
@ -127,7 +127,7 @@ describe('nearest', () => {
test('indigo', () => {
const color = new Color('indigo')
const match = nearest(color, colors)
expect(match.hex()).toBe('#d291f7')
expect(match.hex()).toBe('#b197f3')
})
test('violet', () => {

Просмотреть файл

@ -0,0 +1,15 @@
import { polynomialSequence } from '../scheme/utils.js'
describe('schema compute utils', () => {
describe('polynomialSequence', () => {
test('default linear', () => {
const scale1 = polynomialSequence(0, 10, 11).map(x => Math.round(x))
expect(scale1).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
})
test('squared', () => {
const scale2 = polynomialSequence(0, 64, 8, 2).map(x => Math.round(x))
expect(scale2).toEqual([0, 1, 5, 12, 21, 33, 47, 64])
})
})
})

Просмотреть файл

@ -6,7 +6,7 @@
import chroma from 'chroma-js'
import { Hsluv } from 'hsluv'
import type { Hsl, Hsv, Rgb, Rgba } from './types.js'
import type { Hsl, HslVector, Hsv, Rgb, Rgba, RGBAV } from './types.js'
/**
* This is a variety of color utilities to minimize additional direct dependencies
@ -18,34 +18,36 @@ import type { Hsl, Hsv, Rgb, Rgba } from './types.js'
*
* @param css - the css color hex string
*/
export function css2hsluv(css: string): [number, number, number] {
export function css2hsluv(css: string): HslVector {
const conv = new Hsluv()
conv.hex = chroma(css).hex()
conv.hexToHsluv()
return [conv.hsluv_h, conv.hsluv_s, conv.hsluv_l].map((v: number) =>
Math.round(v),
) as [number, number, number]
) as HslVector
}
export function hsluv2hex(h: number, s: number, l: number): string {
export function hsluv2hex(hsluv: HslVector): string {
const conv = new Hsluv()
conv.hsluv_h = h
conv.hsluv_s = s
conv.hsluv_l = l
conv.hsluv_h = hsluv[0]
conv.hsluv_s = hsluv[1]
conv.hsluv_l = hsluv[2]
conv.hsluvToHex()
return conv.hex
}
export function hsluv2hsl(hsluv: HslVector): HslVector {
return chroma(hsluv2hex(hsluv)).hsl()
}
/**
* Convert a standard CSS-compatible string to [l, c, h] array
*
* @param css - the css color hex string
*/
export function css2lch(css: string): [number, number, number] {
export function css2lch(css: string): HslVector {
return chroma(css)
.lch()
.map((v: number) => Math.round(v)) as [number, number, number]
.map((v: number) => Math.round(v)) as HslVector
}
/**
@ -227,7 +229,7 @@ export function css2hex(css: string, alpha?: number): string {
* @param css - the css color hex string
* @param alpha - optional alpha override from 0-1. Not all CSS strings include alpha, so you can provide it if needed.
*/
export function css2rgbaVector(
export function css2rgbav(
css: string,
alpha?: number,
): [number, number, number, number] {
@ -246,7 +248,7 @@ export function css2rgbaVector(
* @param css - the css color hex string
* @param alpha - the alpha value to use [0-1]
*/
export function css2rgbaNumber(css: string, alpha?: number): number {
export function css2rgbaint(css: string, alpha?: number): number {
if (css === 'none') {
return 0
}
@ -260,6 +262,6 @@ export function css2rgbaNumber(css: string, alpha?: number): number {
return color
}
export function rgbav2hex(rgbav: [number, number, number, number]): string {
export function rgbav2hex(rgbav: RGBAV): string {
return chroma(rgbav).hex()
}

Просмотреть файл

@ -9,12 +9,15 @@ export * from './nearest.js'
export * from './scheme.js'
export * from './types.js'
// TODO: best would be to update the scheme compute to accept undefined or baseline params and handle an "empty" case, which is maybe grayscale
/**
* Default set of params useful for initializing new themes with our "standard look".
*/
export const defaultParams = {
accentHue: 252,
accentSaturation: 89,
accentLuminance: 50,
backgroundHueShift: 50,
backgroundLevel: 95,
nominalHueStep: 10,
accentLightness: 50,
scaleSaturation: 90,
scaleLightness: 67,
greyHue: 72,
greySaturation: 7,
}

Просмотреть файл

@ -15,11 +15,11 @@ import type { Color } from './Color.js'
* @param list
*/
export function nearest(input: Color, list: Color[]): Color {
const hsl = input.hsl()
const hsl = input.hsluv()
const distances = list.map(color => {
const hsl2 = color.hsl()
const left = hsl.h
const right = hsl2.h
const hsl2 = color.hsluv()
const left = hsl[0]
const right = hsl2[0]
let delta1 = Math.abs(left - right)
if (delta1 > 180) {
delta1 = 360 - delta1

Просмотреть файл

@ -2,449 +2,365 @@
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
import chroma from 'chroma-js'
import { hsluv2hex } from '../chroma.js'
import type { Params, Scheme } from '../types'
import { defaultParams } from '../index.js'
import type {
HslVector,
Scheme,
SchemeParams,
TuningParameters,
} from '../types'
import {
getAnnotations,
getBackgroundHsl,
getDivergingSequence,
getForegroundHsl,
getGreyLightness,
getNominalHues,
getNominalRainbowSequence,
getNominalSequence,
getNominalShiftedSequence,
getOffsetBackgroundHsl,
getSequentialSequence,
greySequence,
} from './functions.js'
const lightTextLuminance = 95
const darkTextLuminance = 20
const lightScaleLuminance = 70
const darkScaleLuminance = 70
const maxSaturation = 100
const maxLightLuminanceOffset = 5
const maxDarkLuminanceOffset = 10
const maxBackgroundChroma = 4 // absolute
const lightScaleBackgroundLuminanceShift = 10
const darkScaleBackgroundLuminanceShift = 3
const analogousRange = 60
const complementaryRange = 60
const nominalSaturation = 90
const nominalLighterShift = 15
const nominalDarkerShift = 30
const boldSaturationShift = 10
const mutedSaturationShift = 55
const minNominalSaturation = 10
const minNominalLuminance = 50
const linearExponent = 1
const polynomialExponent = 1.5
const lowContrastBackgroundShift = 20
const darkestGrey = 20
const lightestGrey = 90
const offsetBackgroundLuminanceShift = 1
function getDefaultTuning(
tuning?: Partial<TuningParameters>,
): Required<TuningParameters> {
return {
analogousRange: 60,
complementaryRange: 60,
export interface NominalHueSequence {
bold: [number, number, number][]
std: [number, number, number][]
muted: [number, number, number][]
hues: number[]
size: number
}
lightTextLightness: 95,
lightMaxLightnessOffset: 5,
lightBackgroundLightnessShift: 10,
export function polynomial_scale(
exp: number,
start: number,
end: number,
size: number,
): number[] {
const base = 1 / (size - 1)
const interval = end - start
const result: number[] = []
for (let i = 0; i < size; i++) {
result.push(start + interval * (i * base) ** exp)
}
return result
}
darkTextLightness: 20,
darkMaxLightnessOffet: 10,
darkBackgroundLightnessShift: 3,
export type HSLVector = [number, number, number]
backgroundLevel: 95,
backgroundHueShift: 50,
export function polynomial_hsl_scale(
exp: number,
[sh, ss, sl]: HSLVector,
[eh, es, el]: HSLVector,
size: number,
): HSLVector[] {
const hues = polynomial_scale(exp, sh, eh, size)
const saturations = polynomial_scale(exp, ss, es, size)
const luminances = polynomial_scale(exp, sl, el, size)
const hexvalues: HSLVector[] = []
for (let i = 0; i < size; i++) {
hexvalues.push([
hues[i] as number,
saturations[i] as number,
luminances[i] as number,
])
}
return hexvalues
}
nominalHueStep: 10,
minNominalSaturation: 10,
minNominalLightness: 50,
// Based on a maximum hue shift of 100 (from the slider)
function getOffsetHue([h]: HSLVector, hueShift: number) {
if (hueShift >= 25 && hueShift <= 75) {
// analogous range
const delta = (analogousRange * (hueShift - 50)) / 25
return (h + delta) % 360
} else if (hueShift > 75) {
// clockwise complementary range
const delta = 180 - (complementaryRange * (100 - hueShift)) / 25
return (h + delta) % 360
} else {
// anticlockwise complementary range
const delta = 180 + (complementaryRange * hueShift) / 25
return (h + delta) % 360
nominalMutedSaturationShift: -55,
nominalMutedLightnessShift: 15,
nominalBoldSaturationShift: 10,
nominalBoldLightnessShift: -30,
maxBackgroundChroma: 4,
lowContrastBackgroundShift: 20,
offsetBackgroundLightnessShift: 1,
lightestGrey: 90,
darkestGrey: 20,
polynomialExponent: 1.5,
reservedDataColors: 1,
...tuning,
}
}
function getBackgroundSaturationaAndLuminance(
hue: number,
backgroundLevel: number,
light: boolean,
): [number, number] {
function normalizeSaturation(_h: number, l: number) {
let satGivingMaxChroma = 100
let c = chroma.hex(hsluv2hex(hue, 100, l)).hcl()[1]
while (c > maxBackgroundChroma && satGivingMaxChroma >= 0) {
satGivingMaxChroma -= 1
c = chroma.hex(hsluv2hex(hue, satGivingMaxChroma, l)).hcl()[1]
}
return satGivingMaxChroma
}
if (light) {
if (backgroundLevel < 50) {
const l = 100 - maxLightLuminanceOffset
return [(backgroundLevel * normalizeSaturation(hue, l)) / 50, l]
} else {
const l =
100 - maxLightLuminanceOffset * (1 - (backgroundLevel - 50) / 50)
return [normalizeSaturation(hue, l), l]
}
} else {
if (backgroundLevel < 50) {
const l = maxDarkLuminanceOffset
return [(backgroundLevel * normalizeSaturation(hue, l)) / 50, l]
} else {
const l = maxDarkLuminanceOffset * (1 - (backgroundLevel - 50) / 50)
return [normalizeSaturation(hue, l), l]
}
}
}
export class ColorMaker {
public readonly textLuminance: number
public readonly scaleLuminance: number
public readonly backgroundHsl: [number, number, number]
public readonly offsetbackgroundHsl: [number, number, number]
public readonly foregroundHsl: [number, number, number]
public readonly faintAnnotationHsl: [number, number, number]
public readonly lowContrastAnnotationHsl: [number, number, number]
public readonly lowMidContrastAnnotationHsl: [number, number, number]
public readonly midContrastAnnotationHsl: [number, number, number]
public readonly midHighContrastAnnotationHsl: [number, number, number]
public readonly highContrastAnnotationHsl: [number, number, number]
public readonly greyLuminance: number
private cachedNominalSequence: NominalHueSequence | undefined
public constructor(
public readonly accentHsl: [number, number, number],
public readonly backgroundLevel: number,
public readonly backgroundHueShift: number,
public readonly nominalHueStep: number,
public readonly light: boolean,
) {
this.textLuminance = light ? darkTextLuminance : lightTextLuminance
this.scaleLuminance = light ? darkScaleLuminance : lightScaleLuminance
const h = getOffsetHue(this.accentHsl, this.backgroundHueShift)
const [s, l] = getBackgroundSaturationaAndLuminance(
h,
this.backgroundLevel,
this.light,
)
this.backgroundHsl = [h, s, l]
const offsetBackgroundLuminance = light
? Math.min(100, l + offsetBackgroundLuminanceShift)
: Math.max(0, l - offsetBackgroundLuminanceShift)
this.offsetbackgroundHsl = [h, s, offsetBackgroundLuminance]
this.foregroundHsl = [0, 0, this.textLuminance]
this.greyLuminance = this.light
? this.backgroundHsl[2] - darkScaleBackgroundLuminanceShift
: this.backgroundHsl[2] + lightScaleBackgroundLuminanceShift
const mutedGreyLuminance = this.light
? this.backgroundHsl[2] - lowContrastBackgroundShift
: this.backgroundHsl[2] + lowContrastBackgroundShift
const boldGreyLuminance = this.light ? darkestGrey : lightestGrey
const greys = this.explicitGrey(5, mutedGreyLuminance, boldGreyLuminance)
this.lowContrastAnnotationHsl = greys[0] as HSLVector
this.lowMidContrastAnnotationHsl = greys[1] as HSLVector
this.midContrastAnnotationHsl = greys[2] as HSLVector
this.midHighContrastAnnotationHsl = greys[3] as HSLVector
this.highContrastAnnotationHsl = greys[4] as HSLVector
// halfway to the background from the darkest/lightest
const faintLuminance = this.light
? (100 - lightestGrey) / 2 + lightestGrey
: darkestGrey / 2
this.faintAnnotationHsl = [this.accentHsl[0], 0, faintLuminance]
}
public grey(size: number): HSLVector[] {
const boldGreyLuminance = this.light ? darkestGrey : lightestGrey
return this.explicitGrey(size, this.greyLuminance, boldGreyLuminance)
}
public nominal(size: number): NominalHueSequence {
if (
!this.cachedNominalSequence ||
this.cachedNominalSequence.size !== size
) {
const { nominalBold, nominal, nominalMuted, nominalHues } =
this.getNominalHueSequences(size)
this.cachedNominalSequence = {
bold: nominalBold,
std: nominal,
muted: nominalMuted,
hues: nominalHues,
size: nominal.length,
}
}
return this.cachedNominalSequence
}
private explicitGrey(
size: number,
startLuminance: number,
endLuminance: number,
) {
const greyFrom: HSLVector = [this.accentHsl[0], 0, startLuminance]
const greyTo: HSLVector = [this.accentHsl[0], 0, endLuminance]
return polynomial_hsl_scale(linearExponent, greyFrom, greyTo, size)
}
private getAccentsAndComplements(
size: number,
offset: number,
): {
greyAccent: HSLVector
greyComplement: HSLVector
maxSaturationAccent: HSLVector
maxSaturationComplement: HSLVector
} {
const { hues: nominalHues } = this.nominal(size)
const accentHue = nominalHues[offset % nominalHues.length] as number
const colorLuminance = this.accentHsl[2]
const greyLuminance = this.greyLuminance
const complementHue = (accentHue + 90) % 360
const greyAccent: HSLVector = [accentHue, 0, greyLuminance]
const greyComplement: HSLVector = [complementHue, 0, greyLuminance]
const maxSaturationAccent: HSLVector = [
accentHue,
maxSaturation,
colorLuminance,
]
const maxSaturationComplement: HSLVector = [
complementHue,
maxSaturation,
colorLuminance,
]
return {
greyAccent,
greyComplement,
maxSaturationAccent,
maxSaturationComplement,
}
}
public sequential(size: number, offset = 0): HSLVector[] {
const { greyAccent, maxSaturationAccent } = this.getAccentsAndComplements(
size,
offset,
)
return polynomial_hsl_scale(
linearExponent,
greyAccent,
maxSaturationAccent,
size,
)
}
public sequentialComplement(size: number, offset = 0): HSLVector[] {
const { greyAccent, maxSaturationComplement } =
this.getAccentsAndComplements(size, offset)
return polynomial_hsl_scale(
linearExponent,
greyAccent,
maxSaturationComplement,
size,
)
}
public diverging(size: number, offset = 0): HSLVector[] {
const {
greyAccent,
greyComplement,
maxSaturationAccent,
maxSaturationComplement,
} = this.getAccentsAndComplements(size, offset)
const half = Math.round(size / 2)
const cut = size % 2 === 0 ? half + 1 : half
let diverging = polynomial_hsl_scale(
polynomialExponent,
greyComplement,
maxSaturationComplement,
cut,
)
.slice(1)
.reverse()
let toAdd = polynomial_hsl_scale(
polynomialExponent,
greyAccent,
maxSaturationAccent,
cut,
)
if (size % 2 === 0) {
toAdd = toAdd.slice(1, cut)
}
diverging = diverging.concat(toAdd)
return diverging
}
private getNominalHueSequences(size: number) {
const nominal: HSLVector[] = []
const nominalBold: HSLVector[] = []
const nominalMuted: HSLVector[] = []
const nominalHues: number[] = []
let hues: number[] = []
const h = this.accentHsl[0]
const initialHues =
this.nominalHueStep <= 10
? 13 - this.nominalHueStep
: this.nominalHueStep - 8
const hueDirection = this.nominalHueStep <= 10 ? -1 : 1
let hueStep = 360.0 / initialHues
for (let i = 0; i < initialHues; i += 1) {
hues.push((h + i * hueDirection * hueStep) % 360)
}
while (hues.length < size) {
hueStep = hueStep / 2
const newHues: number[] = []
for (const existingHue of hues) {
newHues.push((existingHue + hueDirection * hueStep) % 360)
if (hues.length + newHues.length === size) {
break
}
}
hues = hues.concat(newHues)
}
// trim the core hues to match requested size
// this acounts for initialHues calculation
// which can result in minimum counts higher than requested
hues = hues.slice(0, size)
let baseSaturation = nominalSaturation
let baseLuminance = this.scaleLuminance
const addHue = (hue: number) => {
nominal.push([hue, baseSaturation, baseLuminance])
nominalBold.push([
hue,
0.5 * (nominalSaturation + baseSaturation) + boldSaturationShift,
0.5 * (this.scaleLuminance + baseLuminance) - nominalDarkerShift,
])
nominalMuted.push([
hue,
0.5 * (nominalSaturation + baseSaturation) - mutedSaturationShift,
0.5 * (this.scaleLuminance + baseLuminance) + nominalLighterShift,
])
nominalHues.push(hue)
if (nominal.length % 3 === 0) {
baseSaturation = Math.max(baseSaturation - 1, minNominalSaturation)
}
if (nominal.length % 6 === 0) {
baseLuminance = Math.max(baseLuminance - 1, minNominalLuminance)
}
}
for (const finalHue of hues) {
addHue(finalHue)
}
return {
nominal,
nominalBold,
nominalMuted,
nominalHues,
}
}
}
export function hsluv_to_hex(values: HSLVector[]): string[] {
return values.map(([h, s, l]) => hsluv2hex(h, s, l))
}
// TODO: this should probably throw errors if out-of-bounds values are submitted OR, wrap around the geometry if that's always valid
/**
* Takes a set of core params and generates all of the scale computes required for a Schema,
* using HSLuv color space for even perceptual qualities.
* @param params
* @param nominalItemCount
* @param sequentialItemCount
* @param light
* @returns
*/
export function getScheme(
params: Params,
params: SchemeParams,
nominalItemCount: number,
sequentialItemCount: number,
light: boolean,
tuning?: Partial<TuningParameters>,
): Scheme {
const {
accentHue,
accentSaturation,
accentLuminance,
backgroundLevel,
backgroundHueShift,
nominalHueStep,
} = params
accentLightness,
scaleSaturation,
scaleLightness,
greyHue,
greySaturation,
} = validateParams(params)
const colorMaker = new ColorMaker(
[accentHue, accentSaturation, accentLuminance],
const {
analogousRange,
complementaryRange,
nominalHueStep,
maxBackgroundChroma,
lightMaxLightnessOffset,
darkMaxLightnessOffet,
lightTextLightness,
darkTextLightness,
lightBackgroundLightnessShift,
darkBackgroundLightnessShift,
backgroundLevel,
backgroundHueShift,
nominalHueStep,
nominalMutedLightnessShift,
nominalBoldLightnessShift,
nominalMutedSaturationShift,
nominalBoldSaturationShift,
minNominalSaturation,
minNominalLightness,
lowContrastBackgroundShift,
offsetBackgroundLightnessShift,
lightestGrey,
darkestGrey,
reservedDataColors,
polynomialExponent,
} = getDefaultTuning(tuning)
const foregroundHsl = getForegroundHsl(
lightTextLightness,
darkTextLightness,
light,
)
const nominalSequences = colorMaker.nominal(nominalItemCount)
const backgroundHsl = getBackgroundHsl(
accentHue,
backgroundLevel,
backgroundHueShift,
lightMaxLightnessOffset,
darkMaxLightnessOffet,
maxBackgroundChroma,
analogousRange,
complementaryRange,
light,
)
const backgroundLightness = backgroundHsl[2]
const offsetbackgroundHsl = getOffsetBackgroundHsl(
backgroundHsl,
offsetBackgroundLightnessShift,
light,
)
const boldGreyLightness = light ? darkestGrey : lightestGrey
const greyLightness = getGreyLightness(
backgroundLightness,
lightBackgroundLightnessShift,
darkBackgroundLightnessShift,
light,
)
const greys = greySequence(
greyHue,
greySaturation,
greyLightness,
boldGreyLightness,
sequentialItemCount,
)
const {
faintAnnotationHsl,
lowContrastAnnotationHsl,
lowMidContrastAnnotationHsl,
midContrastAnnotationHsl,
midHighContrastAnnotationHsl,
highContrastAnnotationHsl,
} = getAnnotations(
greyHue,
backgroundLightness,
boldGreyLightness,
lowContrastBackgroundShift,
lightestGrey,
darkestGrey,
greySaturation,
light,
)
const nominalHues = getNominalHues(
accentHue,
nominalHueStep,
nominalItemCount + reservedDataColors,
)
const nominal = getNominalSequence(
nominalHues,
scaleSaturation,
minNominalSaturation,
scaleLightness,
minNominalLightness,
)
const nominalMuted = getNominalShiftedSequence(
nominalHues,
scaleSaturation,
minNominalSaturation,
scaleLightness,
minNominalLightness,
nominalMutedSaturationShift,
nominalMutedLightnessShift,
)
const nominalBold = getNominalShiftedSequence(
nominalHues,
scaleSaturation,
minNominalSaturation,
scaleLightness,
minNominalLightness,
nominalBoldSaturationShift,
nominalBoldLightnessShift,
)
const sequential1 = getSequentialSequence(
nominalHues,
scaleSaturation,
accentLightness,
greyLightness,
sequentialItemCount,
0,
)
const sequential2 = getSequentialSequence(
nominalHues,
scaleSaturation,
accentLightness,
greyLightness,
sequentialItemCount,
1,
)
const diverging1 = getDivergingSequence(
nominalHues,
scaleSaturation,
accentLightness,
greyLightness,
polynomialExponent,
sequentialItemCount,
0,
)
const diverging2 = getDivergingSequence(
nominalHues,
scaleSaturation,
accentLightness,
greyLightness,
polynomialExponent,
sequentialItemCount,
1,
)
const rainbow = getNominalRainbowSequence(
accentHue,
scaleSaturation,
scaleLightness,
)
return {
background: hsluv2hex(...colorMaker.backgroundHsl),
offsetBackground: hsluv2hex(...colorMaker.offsetbackgroundHsl),
foreground: hsluv2hex(...colorMaker.foregroundHsl),
accent: hsluv2hex(...colorMaker.accentHsl),
lowContrastAnnotation: hsluv2hex(...colorMaker.lowContrastAnnotationHsl),
lowMidContrastAnnotation: hsluv2hex(
...colorMaker.lowMidContrastAnnotationHsl,
),
midContrastAnnotation: hsluv2hex(...colorMaker.midContrastAnnotationHsl),
midHighContrastAnnotation: hsluv2hex(
...colorMaker.midHighContrastAnnotationHsl,
),
highContrastAnnotation: hsluv2hex(...colorMaker.highContrastAnnotationHsl),
faintAnnotation: hsluv2hex(...colorMaker.faintAnnotationHsl),
sequential: hsluv_to_hex(colorMaker.sequential(sequentialItemCount, 0)),
sequential2: hsluv_to_hex(colorMaker.sequential(sequentialItemCount, 1)),
diverging: hsluv_to_hex(colorMaker.diverging(sequentialItemCount, 0)),
diverging2: hsluv_to_hex(colorMaker.diverging(sequentialItemCount, 1)),
nominalBold: hsluv_to_hex(nominalSequences.bold),
nominal: hsluv_to_hex(nominalSequences.std),
nominalMuted: hsluv_to_hex(nominalSequences.muted),
greys: hsluv_to_hex(colorMaker.grey(sequentialItemCount)),
background: hsluv2hex(backgroundHsl),
offsetBackground: hsluv2hex(offsetbackgroundHsl),
foreground: hsluv2hex(foregroundHsl),
accent: hsluv2hex([accentHue, accentSaturation, accentLightness]),
dataPrimary: hsluv2hex(nominal[0]!),
dataPrimaryMuted: hsluv2hex(nominalMuted[0]!),
dataPrimaryBold: hsluv2hex(nominalBold[0]!),
lowContrastAnnotation: hsluv2hex(lowContrastAnnotationHsl),
lowMidContrastAnnotation: hsluv2hex(lowMidContrastAnnotationHsl),
midContrastAnnotation: hsluv2hex(midContrastAnnotationHsl),
midHighContrastAnnotation: hsluv2hex(midHighContrastAnnotationHsl),
highContrastAnnotation: hsluv2hex(highContrastAnnotationHsl),
faintAnnotation: hsluv2hex(faintAnnotationHsl),
sequential: hsluvList2hexList(sequential1),
sequential2: hsluvList2hexList(sequential2),
diverging: hsluvList2hexList(diverging1),
diverging2: hsluvList2hexList(diverging2),
nominalBold: hsluvList2hexList(nominalBold.slice(reservedDataColors)),
nominal: hsluvList2hexList(nominal.slice(reservedDataColors)),
nominalMuted: hsluvList2hexList(nominalMuted.slice(reservedDataColors)),
greys: hsluvList2hexList(greys),
rainbow: hsluvList2hexList(rainbow),
warning: '#ff8c00',
error: '#d13438',
}
}
/**
* Transforms a list of HSLuv vectors to hex strings.
* @param values
* @returns
*/
function hsluvList2hexList(hsluvs: HslVector[]): string[] {
return hsluvs.map(hsluv2hex)
}
/**
* Validates the param limits, and returns a clean set or throws if unadjustable.
* @param params
*/
export function validateParams(params: SchemeParams): Required<SchemeParams> {
const {
accentHue,
accentSaturation,
accentLightness,
scaleSaturation,
scaleLightness,
greyHue,
greySaturation,
} = params
const scaleSat =
scaleSaturation === undefined
? defaultParams.scaleSaturation
: scaleSaturation
const scaleLt =
scaleLightness === undefined ? defaultParams.scaleLightness : scaleLightness
const grey = greyHue === undefined ? defaultParams.greyHue : greyHue
const greySat =
greySaturation === undefined ? defaultParams.greySaturation : greySaturation
if (accentHue === undefined) {
throw new Error(
'Must supply an accent hue from 0-360. <undefined> was supplied.',
)
}
if (accentLightness === undefined) {
throw new Error(
'Must supply an accent lightness from 0-100. <undefined> was supplied.',
)
}
if (accentSaturation === undefined) {
throw new Error(
'Must supply an accent saturation from 0-100. <undefined> was supplied.',
)
}
if (accentLightness < 0 || accentLightness > 100) {
throw new Error(
`accentLightness ${accentLightness} is out of valid range: 0-100`,
)
}
if (accentSaturation < 0 || accentSaturation > 100) {
throw new Error(
`accentSaturation ${accentSaturation} is out of valid range: 0-100`,
)
}
if (scaleSat < 0 || scaleSat > 100) {
throw new Error(`scaleSaturation ${scaleSat} is out of valid range: 0-100`)
}
if (scaleLt < 0 || scaleLt > 100) {
throw new Error(`scaleLightness ${scaleLt} is out of valid range: 0-100`)
}
if (greySat < 0 || greySat > 100) {
throw new Error(`greySaturation ${greySat} is out of valid range: 0-100`)
}
return {
accentHue,
accentLightness,
accentSaturation,
scaleSaturation: scaleSat,
scaleLightness: scaleLt,
greyHue: grey,
greySaturation: greySat,
}
}

Просмотреть файл

@ -0,0 +1,508 @@
/*!
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
import { hsluv2hsl } from '../chroma.js'
import type { HslVector } from '../types.js'
import { polynomialHslSequence } from './utils.js'
/**
* Gets an offset hue based on the hue shift param.
* This is used to tint the background color slightly.
* Note that the shift parameter is arbitrarily binned using the 0-100 range:
* 0-25 counterclockwise complementary, 25-75 analogous, 75+ clockwise complementary.
* @param hue
* @param shift
* @param analagousRange
* @param complementaryRange
* @returns
*/
function getOffsetHue(
hue: number,
shift: number,
analogousRange: number,
complementaryRange: number,
) {
if (shift >= 25 && shift <= 75) {
// analogous range
const delta = (analogousRange * (shift - 50)) / 25
return (hue + delta) % 360
} else if (shift > 75) {
// clockwise complementary range
const delta = 180 - (complementaryRange * (100 - shift)) / 25
return (hue + delta) % 360
} else {
// anticlockwise complementary range
const delta = 180 + (complementaryRange * shift) / 25
return (hue + delta) % 360
}
}
/**
* Choose a background lightness based on the "level" and light/dark mode.
* @param level
* @param lightMaxOffset
* @param darkMaxOffset
* @param light
* @returns
*/
function getBackgroundLightness(
level: number,
lightMaxOffset: number,
darkMaxOffset: number,
light: boolean,
) {
if (light) {
if (level < 50) {
return 100 - lightMaxOffset
}
return 100 - lightMaxOffset * (1 - (level - 50) / 50)
} else {
if (level < 50) {
return darkMaxOffset
} else {
return darkMaxOffset * (1 - (level - 50) / 50)
}
}
}
/**
* Find a saturation value that maximizes chroma for a given hue.
* HSLuv has relative saturation, so we find this using HSL and map it back.
* @param hue
* @param lightness
* @param maxBackgroundChroma
* @returns
*/
function normalizeSaturation(
hue: number,
lightness: number,
maxChroma: number,
) {
let satGivingMaxChroma = 100
let c = hsluv2hsl([hue, 100, lightness])[1]
while (c > maxChroma && satGivingMaxChroma >= 0) {
satGivingMaxChroma -= 1
c = hsluv2hsl([hue, satGivingMaxChroma, lightness])[1]
}
return satGivingMaxChroma
}
/**
* Finds the ideal saturation for a given background config.
* @param hue
* @param lightness
* @param level
* @param maxChroma
* @returns
*/
function getBackgroundSaturation(
hue: number,
lightness: number,
level: number,
maxChroma: number,
): number {
if (level < 50) {
return (level * normalizeSaturation(hue, lightness, maxChroma)) / 50
} else {
return normalizeSaturation(hue, lightness, maxChroma)
}
}
/**
* Gets the background HSL color based on our hue params and shifts.
* @param hue
* @param level
* @param shift
* @param lightMaxLightnessOffset
* @param darkMaxLightnessOffet
* @param maxChroma
* @param analogousRange
* @param complementaryRange
* @param light
* @returns
*/
export function getBackgroundHsl(
hue: number,
level: number,
shift: number,
lightMaxLightnessOffset: number,
darkMaxLightnessOffet: number,
maxChroma: number,
analogousRange: number,
complementaryRange: number,
light: boolean,
): HslVector {
const h = getOffsetHue(hue, shift, analogousRange, complementaryRange)
const l = getBackgroundLightness(
level,
lightMaxLightnessOffset,
darkMaxLightnessOffet,
light,
)
const s = getBackgroundSaturation(h, l, level, maxChroma)
return [h, s, l]
}
/**
* For a given set of nominal hues, find the accents and complement set.
* Accent is established by configuring an offset within the hues array,
* complement is 90deg from that in the hue space.
* @param hues
* @param accentHsl
* @param greyLightness
* @param offset
* @returns
*/
export function getAccentsAndComplements(
hues: number[],
saturation: number,
lightness: number,
greyLightness: number,
offset: number,
): {
greyAccent: HslVector
greyComplement: HslVector
accent: HslVector
complement: HslVector
} {
const accentHue = hues[offset % hues.length] as number
const complementHue = (accentHue + 90) % 360
const greyAccent: HslVector = [accentHue, 0, greyLightness]
const greyComplement: HslVector = [complementHue, 0, greyLightness]
const accent: HslVector = [accentHue, saturation, lightness]
const complement: HslVector = [complementHue, saturation, lightness]
return {
greyAccent,
greyComplement,
accent,
complement,
}
}
/**
* Returns a sequence of hue components using the specified step starting from an initial hue.
* Attempts to cycle in a way that is predictable but does not result in similar neighbor colors.
* Note that there is a standard cycle for the most common 10 hue scales, and then it randomizes more.
* @param start
* @param step
* @param size
* @returns
*/
export function getNominalHues(start: number, step: number, size: number) {
const initialHues = step <= 11 ? 13 - step : step - 8
const hueDirection = step <= 11 ? -1 : 1
let hues: number[] = []
let hueStep = 360.0 / initialHues
for (let i = 0; i < initialHues; i += 1) {
hues.push((start + i * hueDirection * hueStep) % 360)
}
while (hues.length < size) {
hueStep = hueStep / 2
const newHues: number[] = []
for (const existingHue of hues) {
newHues.push((existingHue + hueDirection * hueStep) % 360)
if (hues.length + newHues.length === size) {
break
}
}
hues = hues.concat(newHues)
}
// trim the core hues to match requested size
// this accounts for initialHues calculation
// which can result in minimum counts higher than requested
return hues.slice(0, size)
}
/**
* Gets a nominal sequence with even perception based on a core hue set.
* In order to maintain some differentiation, at greater quantities
* the colors are shifted in saturation and lightness.
* @param hues
* @param saturation
* @param minSaturation
* @param lightness
* @param minLightness
* @returns
*/
export function getNominalSequence(
hues: number[],
saturation: number,
minSaturation: number,
lightness: number,
minLightness: number,
) {
const minS = Math.min(saturation, minSaturation)
const minL = Math.min(lightness, minLightness)
let baseSaturation = saturation
let baseLightness = lightness
return hues.map((hue, idx) => {
const hsl = [hue, baseSaturation, baseLightness] as HslVector
if (idx > 9 && (idx + 1) % 3 === 0) {
baseSaturation = Math.max(baseSaturation - 1, minS)
}
if (idx > 9 && (idx + 1) % 6 === 0) {
baseLightness = Math.max(baseLightness - 1, minL)
}
return hsl
})
}
/**
* Gets the muted/bold nominal sequence by shifting the saturation and lightness
* @param hues
* @param saturation
* @param minSaturation
* @param lightness
* @param minLightness
* @param saturationShift
* @param nominalShift
* @returns
*/
export function getNominalShiftedSequence(
hues: number[],
saturation: number,
minSaturation: number,
lightness: number,
minLightness: number,
saturationShift: number,
lightnessShift: number,
) {
let baseSaturation = saturation
let baseLightness = lightness
return hues.map((hue, idx) => {
const shiftedS = 0.5 * (saturation + baseSaturation) + saturationShift
const shiftedL = 0.5 * (lightness + baseLightness) + lightnessShift
// correct for valid bounds
const correctedS = Math.min(Math.max(0, shiftedS), 100)
const correctedL = Math.min(Math.max(0, shiftedL), 100)
const hsl = [hue, correctedS, correctedL] as HslVector
if (idx > 9 && (idx + 1) % 3 === 0) {
baseSaturation = Math.max(baseSaturation - 1, minSaturation)
}
if (idx > 9 && (idx + 1) % 6 === 0) {
baseLightness = Math.max(baseLightness - 1, minLightness)
}
return hsl
})
}
/**
* Just gets every hue, with consistent saturation and lightness.
* @param start
* @param saturation
* @param lightness
* @returns
*/
export function getNominalRainbowSequence(
start: number,
saturation: number,
lightness: number,
) {
return new Array(360)
.fill(1)
.map((_a, i) => [i + start, saturation, lightness] as HslVector)
}
/**
* Creates a sequence of greys from a {start} to {end} lightness.
* Note the optional saturation - by default this is 0 for pure greys,
* but if you want some of the hue mixed in to warm or cool the sequence
* you can bump this and the hue will emerge.
* @param hue
* @param size
* @param startLightness
* @param endLightness
* @param saturation
* @returns
*/
export function greySequence(
hue: number,
saturation: number,
startLightness: number,
endLightness: number,
size: number,
) {
const greyFrom: HslVector = [hue, saturation, startLightness]
const greyTo: HslVector = [hue, saturation, endLightness]
return polynomialHslSequence(greyFrom, greyTo, size)
}
/**
* Gets the sequential scale sequence from grey to the offset hue color.
* @param hues
* @param saturation
* @param lightness
* @param greyLightness
* @param size
* @param offset
* @returns
*/
export function getSequentialSequence(
hues: number[],
saturation: number,
lightness: number,
greyLightness: number,
size: number,
offset: number,
) {
const { greyAccent, accent } = getAccentsAndComplements(
hues,
saturation,
lightness,
greyLightness,
offset,
)
return polynomialHslSequence(greyAccent, accent, size)
}
/**
* Gets the diverging scale sequence from a complement on one end to the offset hue on the other, with near-white in the middle.
* @param hues
* @param saturation
* @param lightness
* @param greyLightness
* @param polynomialExponent
* @param size
* @param offset
* @returns
*/
export function getDivergingSequence(
hues: number[],
saturation: number,
lightness: number,
greyLightness: number,
polynomialExponent: number,
size: number,
offset: number,
) {
const { greyAccent, greyComplement, accent, complement } =
getAccentsAndComplements(hues, saturation, lightness, greyLightness, offset)
const half = Math.round(size / 2)
const cut = size % 2 === 0 ? half + 1 : half
const diverging = polynomialHslSequence(
greyComplement,
complement,
cut,
polynomialExponent,
)
.slice(1)
.reverse()
let toAdd = polynomialHslSequence(greyAccent, accent, cut, polynomialExponent)
if (size % 2 === 0) {
toAdd = toAdd.slice(1, cut)
}
return diverging.concat(toAdd)
}
/**
* Gets the collection of greyscale annotations for text colors.
* @param accentHue
* @param backgroundLightness
* @param boldGreyLightness
* @param lowContrastbackgroundShift
* @param lightestGrey
* @param darkestGrey
* @param greySaturation
* @param light
* @returns
*/
export function getAnnotations(
accentHue: number,
backgroundLightness: number,
boldGreyLightness: number,
lowContrastbackgroundShift: number,
lightestGrey: number,
darkestGrey: number,
greySaturation: number,
light: boolean,
) {
const mutedGreyLightness = light
? backgroundLightness - lowContrastbackgroundShift
: backgroundLightness + lowContrastbackgroundShift
const annotations = greySequence(
accentHue,
greySaturation,
mutedGreyLightness,
boldGreyLightness,
5,
)
const lowContrastAnnotationHsl = annotations[0] as HslVector
const lowMidContrastAnnotationHsl = annotations[1] as HslVector
const midContrastAnnotationHsl = annotations[2] as HslVector
const midHighContrastAnnotationHsl = annotations[3] as HslVector
const highContrastAnnotationHsl = annotations[4] as HslVector
// halfway to the background from the darkest/lightest
const faintLightness = light
? (100 - lightestGrey) / 2 + lightestGrey
: darkestGrey / 2
const faintAnnotationHsl: HslVector = [accentHue, 0, faintLightness]
return {
faintAnnotationHsl,
lowContrastAnnotationHsl,
lowMidContrastAnnotationHsl,
midContrastAnnotationHsl,
midHighContrastAnnotationHsl,
highContrastAnnotationHsl,
}
}
/**
* Gets the primary foreground (text) color.
* @param lightTextLightness
* @param darkTextLightness
* @param light
* @returns
*/
export function getForegroundHsl(
lightTextLightness: number,
darkTextLightness: number,
light: boolean,
): HslVector {
const textLightness = light ? darkTextLightness : lightTextLightness
return [0, 0, textLightness]
}
/**
* Gets the offset background - this is used for data plot area for example,
* so it stands out slightly from the regular application background.
* @param backgroundHsl
* @param lightnessShift
* @param light
* @returns
*/
export function getOffsetBackgroundHsl(
backgroundHsl: HslVector,
lightnessShift: number,
light: boolean,
): HslVector {
const [hue, saturation, lightness] = backgroundHsl
const offsetLightness = light
? Math.min(100, lightness + lightnessShift)
: Math.max(0, lightness - lightnessShift)
return [hue, saturation, offsetLightness]
}
export function getGreyLightness(
backgroundLightness: number,
lightBackgroundLightnessShift: number,
darkBackgroundLightnessShift: number,
light: boolean,
) {
return light
? backgroundLightness - darkBackgroundLightnessShift
: backgroundLightness + lightBackgroundLightnessShift
}

Просмотреть файл

@ -2,4 +2,4 @@
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
export * from './HsluvColorLogic.js'
export { getScheme } from './HsluvColorLogic.js'

Просмотреть файл

@ -0,0 +1,58 @@
/*!
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
import type { HslVector } from '../types.js'
/**
* Creates a polynomial number sequence of {size} entries from {start} to {end}.
* @param start
* @param end
* @param size
* @param exponent
* @returns
*/
export function polynomialSequence(
start: number,
end: number,
size: number,
exponent = 1,
): number[] {
const base = 1 / (size - 1)
const interval = end - start
const result: number[] = []
for (let i = 0; i < size; i++) {
result.push(start + interval * (i * base) ** exponent)
}
return result
}
/**
* Creates a sequence of HSL values interpolated from {start} to {end}
* @param start
* @param end
* @param size
* @param exp
* @returns
*/
export function polynomialHslSequence(
start: HslVector,
end: HslVector,
size: number,
exp = 1,
): HslVector[] {
const [sh, ss, sl] = start
const [eh, es, el] = end
const hues = polynomialSequence(sh, eh, size, exp)
const saturations = polynomialSequence(ss, es, size, exp)
const luminances = polynomialSequence(sl, el, size, exp)
const hexvalues: HslVector[] = []
for (let i = 0; i < size; i++) {
hexvalues.push([
hues[i] as number,
saturations[i] as number,
luminances[i] as number,
])
}
return hexvalues
}

Просмотреть файл

@ -6,13 +6,81 @@
/**
* This is the core set of parameters for generating schemes using the ColorPicker
*/
export interface Params {
export interface SchemeParams {
/**
* HSL hue component for the accent.
* Valid range is 0-360 (degrees).
*/
accentHue: number
/**
* HSL saturation component for the accent.
* Valid range is 0-100.
*/
accentSaturation: number
accentLuminance: number
backgroundHueShift: number
backgroundLevel: number
/**
* HSL lightness component for the accent.
* Valid range is 0-100.
*/
accentLightness: number
/**
* Sets the default saturation for nominal scales.
* Muted and bold scales are a fixed saturation +-
*/
scaleSaturation?: number
/**
* Sets the default lightness for nominal scales.
* Muted and bold scales are a fixed lightness +-
*/
scaleLightness?: number
/**
* Optional hue to mix some of warm or cool into grey scales.
*/
greyHue?: number
/**
* Optional saturation to mix some of warm or cool into grey scales.
*/
greySaturation?: number
}
/**
* Detailed tuning for the scale generation algorithms.
*/
export interface TuningParameters {
analogousRange: number
complementaryRange: number
nominalHueStep: number
lightTextLightness: number
lightMaxLightnessOffset: number
lightBackgroundLightnessShift: number
darkTextLightness: number
darkMaxLightnessOffet: number
darkBackgroundLightnessShift: number
backgroundLevel: number
backgroundHueShift: number
minNominalSaturation: number
minNominalLightness: number
nominalMutedSaturationShift: number
nominalMutedLightnessShift: number
nominalBoldLightnessShift: number
nominalBoldSaturationShift: number
maxBackgroundChroma: number
lowContrastBackgroundShift: number
offsetBackgroundLightnessShift: number
lightestGrey: number
darkestGrey: number
reservedDataColors: number
polynomialExponent: number
}
/**
@ -26,6 +94,12 @@ export interface Scheme {
accent: string
warning: string
error: string
/**
* Primary data color, derived from the accent.
*/
dataPrimary: string
dataPrimaryMuted: string
dataPrimaryBold: string
faintAnnotation: string
lowContrastAnnotation: string
lowMidContrastAnnotation: string
@ -40,6 +114,7 @@ export interface Scheme {
nominal: string[]
nominalMuted: string[]
greys: string[]
rainbow: string[]
}
/**
@ -129,6 +204,15 @@ export enum ColorSpace {
* (i.e., r, g \<\< 8, b \<\< 16, a \<\< 24)
*/
RGBA_NUMBER = 'rgbaint',
/**
* HSL color space, { h, s, l }.
*/
HSL = 'hsl',
/**
* HSLuv, which is a perceptually balanced space. [h, s, l].
* https://www.hsluv.org/
*/
HSLUV = 'hsluv',
}
export interface Rgb {
@ -152,3 +236,7 @@ export interface Hsl {
s: number
l: number
}
export type RGBAV = [number, number, number, number]
export type HslVector = [number, number, number]

Просмотреть файл

@ -20,6 +20,7 @@ export interface ColorScales
| [nominal](./core.colorscales.nominal.md) | | (sizeOrDomain?: number \| string\[\] \| number\[\]) =&gt; [NominalColorScaleFunction](./core.nominalcolorscalefunction.md) | |
| [nominalBold](./core.colorscales.nominalbold.md) | | (sizeOrDomain?: number \| string\[\] \| number\[\]) =&gt; [NominalColorScaleFunction](./core.nominalcolorscalefunction.md) | |
| [nominalMuted](./core.colorscales.nominalmuted.md) | | (sizeOrDomain?: number \| string\[\] \| number\[\]) =&gt; [NominalColorScaleFunction](./core.nominalcolorscalefunction.md) | |
| [rainbow](./core.colorscales.rainbow.md) | | (domain?: number\[\], scaleType?: [ScaleType](./core.scaletype.md)<!-- -->, quantiles?: number) =&gt; [ContinuousColorScaleFunction](./core.continuouscolorscalefunction.md) | |
| [sequential](./core.colorscales.sequential.md) | | (domain?: number\[\], scaleType?: [ScaleType](./core.scaletype.md)<!-- -->, quantiles?: number) =&gt; [ContinuousColorScaleFunction](./core.continuouscolorscalefunction.md) | Constructs a sequential numeric scale based on the input domain and specified ScaleType The input domain should be an array of values. For linear or log scales, the behavior mimics d3-scale. For quantile scales, the domain values are used to construct a quantile division using the requested number of quantile bins |
| [sequential2](./core.colorscales.sequential2.md) | | (domain?: number\[\], scaleType?: [ScaleType](./core.scaletype.md)<!-- -->, quantiles?: number) =&gt; [ContinuousColorScaleFunction](./core.continuouscolorscalefunction.md) | |

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/core](./core.md) &gt; [ColorScales](./core.colorscales.md) &gt; [rainbow](./core.colorscales.rainbow.md)
## ColorScales.rainbow property
<b>Signature:</b>
```typescript
rainbow: (domain?: number[], scaleType?: ScaleType, quantiles?: number) => ContinuousColorScaleFunction;
```

Просмотреть файл

@ -36,7 +36,7 @@ export interface Theme
| [name](./core.theme.name.md) | | string | |
| [nearest](./core.theme.nearest.md) | | (color: string, scale?: [NominalColorScaleFunction](./core.nominalcolorscalefunction.md)<!-- -->) =&gt; Color | Returns a theme color that's the closest to a CSS color string we can find. Note that by default this uses the standard nominal scale with 20 entries so there is plenty of variety to choose from. Pass in a different scale instance if you want something else to choose from. |
| [node](./core.theme.node.md) | | [MarkFunction](./core.markfunction.md)<!-- -->&lt;[Node](./core.node.md)<!-- -->&gt; | |
| [params](./core.theme.params.md) | | Params | |
| [params](./core.theme.params.md) | | SchemeParams | |
| [plotArea](./core.theme.plotarea.md) | | [ChromeFunction](./core.chromefunction.md)<!-- -->&lt;[PlotArea](./core.plotarea.md)<!-- -->&gt; | |
| [process](./core.theme.process.md) | | [MarkFunction](./core.markfunction.md)<!-- -->&lt;[Process](./core.process.md)<!-- -->&gt; | |
| [rect](./core.theme.rect.md) | | [MarkFunction](./core.markfunction.md)<!-- -->&lt;[Rect](./core.rect.md)<!-- -->&gt; | |

Просмотреть файл

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
params: Params;
params: SchemeParams;
```

Просмотреть файл

@ -41,7 +41,7 @@ export declare class Theme implements ITheme
| [link](./core.themeimpl.link.md) | | (markConfig?: [MarkConfig](./core.markconfig.md)<!-- -->) =&gt; [Link](./core.link.md) | |
| [name](./core.themeimpl.name.md) | <code>readonly</code> | string | |
| [node](./core.themeimpl.node.md) | | (markConfig?: [MarkConfig](./core.markconfig.md)<!-- -->) =&gt; [Node](./core.node.md) | |
| [params](./core.themeimpl.params.md) | <code>readonly</code> | Params | |
| [params](./core.themeimpl.params.md) | <code>readonly</code> | SchemeParams | |
| [plotArea](./core.themeimpl.plotarea.md) | | () =&gt; [PlotArea](./core.plotarea.md) | |
| [process](./core.themeimpl.process.md) | | (markConfig?: [MarkConfig](./core.markconfig.md)<!-- -->) =&gt; [Process](./core.process.md) | |
| [rect](./core.themeimpl.rect.md) | | (markConfig?: [MarkConfig](./core.markconfig.md)<!-- -->) =&gt; [Rect](./core.rect.md) | |

Просмотреть файл

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
get params(): Params;
get params(): SchemeParams;
```

Просмотреть файл

@ -19,5 +19,6 @@ export interface ThemeSpec
| [dark?](./core.themespec.dark.md) | | Scheme | <i>(Optional)</i> |
| [light?](./core.themespec.light.md) | | Scheme | <i>(Optional)</i> |
| [name?](./core.themespec.name.md) | | string | <i>(Optional)</i> |
| [params?](./core.themespec.params.md) | | Params | <i>(Optional)</i> |
| [params?](./core.themespec.params.md) | | SchemeParams | <i>(Optional)</i> |
| [tuning?](./core.themespec.tuning.md) | | TuningParameters | <i>(Optional)</i> |

Просмотреть файл

@ -7,5 +7,5 @@
<b>Signature:</b>
```typescript
params?: Params;
params?: SchemeParams;
```

Просмотреть файл

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@thematic/core](./core.md) &gt; [ThemeSpec](./core.themespec.md) &gt; [tuning](./core.themespec.tuning.md)
## ThemeSpec.tuning property
<b>Signature:</b>
```typescript
tuning?: TuningParameters;
```

Просмотреть файл

@ -2620,6 +2620,47 @@
"endIndex": 3
}
},
{
"kind": "PropertySignature",
"canonicalReference": "@thematic/core!ColorScales#rainbow:member",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "rainbow: "
},
{
"kind": "Content",
"text": "(domain?: number[], scaleType?: "
},
{
"kind": "Reference",
"text": "ScaleType",
"canonicalReference": "@thematic/core!ScaleType:enum"
},
{
"kind": "Content",
"text": ", quantiles?: number) => "
},
{
"kind": "Reference",
"text": "ContinuousColorScaleFunction",
"canonicalReference": "@thematic/core!ContinuousColorScaleFunction:interface"
},
{
"kind": "Content",
"text": ";"
}
],
"isReadonly": false,
"isOptional": false,
"releaseTag": "Public",
"name": "rainbow",
"propertyTypeTokenRange": {
"startIndex": 1,
"endIndex": 5
}
},
{
"kind": "PropertySignature",
"canonicalReference": "@thematic/core!ColorScales#sequential:member",
@ -6367,8 +6408,8 @@
},
{
"kind": "Reference",
"text": "Params",
"canonicalReference": "@thematic/color!Params:interface"
"text": "SchemeParams",
"canonicalReference": "@thematic/color!SchemeParams:interface"
},
{
"kind": "Content",
@ -8509,8 +8550,8 @@
},
{
"kind": "Reference",
"text": "Params",
"canonicalReference": "@thematic/color!Params:interface"
"text": "SchemeParams",
"canonicalReference": "@thematic/color!SchemeParams:interface"
},
{
"kind": "Content",
@ -9255,8 +9296,8 @@
},
{
"kind": "Reference",
"text": "Params",
"canonicalReference": "@thematic/color!Params:interface"
"text": "SchemeParams",
"canonicalReference": "@thematic/color!SchemeParams:interface"
},
{
"kind": "Content",
@ -9271,6 +9312,34 @@
"startIndex": 1,
"endIndex": 2
}
},
{
"kind": "PropertySignature",
"canonicalReference": "@thematic/core!ThemeSpec#tuning:member",
"docComment": "",
"excerptTokens": [
{
"kind": "Content",
"text": "tuning?: "
},
{
"kind": "Reference",
"text": "TuningParameters",
"canonicalReference": "@thematic/color!TuningParameters:interface"
},
{
"kind": "Content",
"text": ";"
}
],
"isReadonly": false,
"isOptional": true,
"releaseTag": "Public",
"name": "tuning",
"propertyTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
}
}
],
"extendsTokenRanges": []

Просмотреть файл

@ -6,8 +6,9 @@
import { Color } from '@thematic/color';
import { ColorBlindnessMode } from '@thematic/color';
import type { Params } from '@thematic/color';
import type { Scheme } from '@thematic/color';
import type { SchemeParams } from '@thematic/color';
import type { TuningParameters } from '@thematic/color';
// Warning: (ae-missing-release-tag) "Application" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@ -248,6 +249,8 @@ export interface ColorScales {
nominalBold: (sizeOrDomain?: number | string[] | number[]) => NominalColorScaleFunction;
// (undocumented)
nominalMuted: (sizeOrDomain?: number | string[] | number[]) => NominalColorScaleFunction;
// (undocumented)
rainbow: (domain?: number[], scaleType?: ScaleType, quantiles?: number) => ContinuousColorScaleFunction;
sequential: (domain?: number[], scaleType?: ScaleType, quantiles?: number) => ContinuousColorScaleFunction;
// (undocumented)
sequential2: (domain?: number[], scaleType?: ScaleType, quantiles?: number) => ContinuousColorScaleFunction;
@ -662,7 +665,7 @@ export interface Theme {
// (undocumented)
node: MarkFunction<Node>;
// (undocumented)
params: Params;
params: SchemeParams;
// (undocumented)
plotArea: ChromeFunction<PlotArea>;
// (undocumented)
@ -797,7 +800,7 @@ export class ThemeImpl implements Theme {
// (undocumented)
node: (markConfig?: MarkConfig) => Node;
// (undocumented)
get params(): Params;
get params(): SchemeParams;
// (undocumented)
plotArea: () => PlotArea;
// (undocumented)
@ -848,7 +851,9 @@ export interface ThemeSpec {
// (undocumented)
name?: string;
// (undocumented)
params?: Params;
params?: SchemeParams;
// (undocumented)
tuning?: TuningParameters;
}
// Warning: (ae-missing-release-tag) "ThemeVariant" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)

Просмотреть файл

@ -2,7 +2,7 @@
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
import type { Params, Scheme } from '@thematic/color'
import type { Scheme, SchemeParams } from '@thematic/color'
import { Color, ColorBlindnessMode, nearest } from '@thematic/color'
import merge from 'lodash-es/merge.js'
@ -80,9 +80,8 @@ export class Theme implements ITheme {
private _spec: ThemeSpec
private _themeDefinition: ThemeDefinition
private _config: ThemeConfig
private _params: Params
private _params: SchemeParams
private _scheme: Scheme
private _schemeCache: { [size: number]: Scheme }
/**
* Creates a new Theme instance using the params defined in the spec.
@ -92,7 +91,6 @@ export class Theme implements ITheme {
*/
public constructor(spec: ThemeSpec, config?: ThemeConfig) {
const conf = merge({}, defaultConfig, config)
this._schemeCache = {}
const scheme = createScheme(spec, conf.dark, conf.colorBlindnessMode)
this._scheme = scheme
this._spec = applyScheme(spec)
@ -152,7 +150,7 @@ export class Theme implements ITheme {
public get config(): ThemeConfig {
return this._config
}
public get params(): Params {
public get params(): SchemeParams {
return this._params
}
public get scheme(): Scheme {
@ -238,6 +236,14 @@ export class Theme implements ITheme {
const scheme = this.getScheme(100)
return continuous(scheme.greys, domain, scaleType, quantiles)
},
rainbow: (
domain: number[] = [0, 1],
scaleType?: ScaleType,
quantiles?: number,
) => {
const scheme = this.getScheme(360)
return continuous(scheme.rainbow, domain, scaleType, quantiles)
},
}
}
public application = (): Application => {
@ -304,28 +310,20 @@ export class Theme implements ITheme {
const c = new Color(color)
const colors = scale
? scale.toColors()
: this.scales().nominal().toColors(20)
: this.scales().nominal(30).toColors()
return nearest(c, colors)
}
/**
* Gets the scheme with the appropriate size
* @param size - The number of elements in the scheme
*/
// TODO: this cache overcomes slow scale computes, but they shouldn't be slow
private getScheme(size = 0) {
if (!this._schemeCache[size]) {
this._schemeCache[size] = createScheme(
this._spec,
this._config.dark,
this._config.colorBlindnessMode,
size,
size,
)
}
const result = this._schemeCache[size]
if (!result) {
throw new Error(`could not locate schema with size ${size}`)
}
return result
return createScheme(
this._spec,
this._config.dark,
this._config.colorBlindnessMode,
size,
size,
)
}
}

Просмотреть файл

@ -30,9 +30,9 @@ const lightConfig = {
// TODO: mock this out better so it isn't unstable
const SCALE_VECTOR = [
0.9725490196078431, 0.5490196078431373, 0.5529411764705883, 1.0,
0.21568627450980393, 0.7058823529411765, 0.7058823529411765, 1.0,
]
const SCALE_NUMBER = -7500552
const SCALE_NUMBER = -4934601
// these are variants from the mock theme config above
const STROKE_VECTOR = [

Просмотреть файл

@ -6,17 +6,14 @@ import { load } from '../loader.js'
import { ThemeVariant } from '../types/index.js'
describe('load', () => {
// these are variants from the theme json for arc.stroke - they could change if we change the json!
const STROKE_CSS = '#c5c5c5'
test('zero-config load (light theme)', () => {
const theme = load()
expect(theme.name).toBe('Default')
expect(theme.variant).toBe(ThemeVariant.Light)
expect(theme.dark).toBe(false)
expect(theme.chart().backgroundColor().hex()).toBe('none')
expect(theme.arc().stroke().hex()).toBe(STROKE_CSS)
expect(theme.text().fill().hex()).toBe('#303030')
expect(theme.arc().stroke().hex()).toBe('#c8c5be')
expect(theme.text().fill().hex()).toBe('#31302e')
})
test('load dark theme', () => {
@ -27,7 +24,7 @@ describe('load', () => {
expect(theme.variant).toBe(ThemeVariant.Dark)
expect(theme.dark).toBe(true)
expect(theme.chart().backgroundColor().hex()).toBe('none')
expect(theme.arc().stroke().hex()).toBe('#323232')
expect(theme.text().fill().hex()).toBe('#e2e2e2')
expect(theme.arc().stroke().hex()).toBe('#333230')
expect(theme.text().fill().hex()).toBe('#e5e2db')
})
})

Просмотреть файл

@ -2,11 +2,13 @@
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
import type { Scheme } from '@thematic/color'
import { computeDefinition } from '../scheme.js'
const definition = {}
const scheme = {
const scheme: Scheme = {
background: '#111111',
offsetBackground: '#222222',
foreground: '#333333',
@ -25,6 +27,9 @@ const scheme = {
greys: ['lightgrey', 'darkgrey'],
warning: 'orange',
error: 'red',
dataPrimary: '#999999',
dataPrimaryMuted: '#99999e',
dataPrimaryBold: '#99999f',
}
describe('scheme overlays', () => {
describe('computeDefinition', () => {
@ -35,13 +40,13 @@ describe('scheme overlays', () => {
})
test('scale-based props', () => {
expect(def.rect!.fill).toBe(scheme.nominal[0])
expect(def.rect!.fill).toBe(scheme.dataPrimary)
})
test('signal props', () => {
expect(def.rect!.hovered!.fill).toBe(scheme.nominalBold[0])
expect(def.rect!.selected!.fill).toBe(scheme.nominalBold[0])
expect(def.rect!.suppressed!.fill).toBe(scheme.nominalMuted[0])
expect(def.rect!.suppressed!.fill).toBe(scheme.dataPrimaryMuted)
expect(def.rect!.hovered!.fill).toBe(scheme.dataPrimaryBold)
expect(def.rect!.selected!.fill).toBe(scheme.dataPrimaryBold)
})
})
})

Просмотреть файл

@ -30,11 +30,11 @@ const themes = {
export const defaultThemes: ThemeListing[] = Object.entries(themes).map(
entry => {
const [key, value] = entry
const { accentHue, accentSaturation, accentLuminance } = value.params
const { accentHue, accentSaturation, accentLightness } = value.params
return {
id: key,
name: value.name,
accent: hsluv2hex(accentHue, accentSaturation, accentLuminance),
accent: hsluv2hex([accentHue, accentSaturation, accentLightness]),
}
},
)

Просмотреть файл

@ -2,7 +2,7 @@
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
import type { ColorBlindnessMode, Params, Scheme } from '@thematic/color'
import type { ColorBlindnessMode, Scheme, SchemeParams } from '@thematic/color'
import { colorBlindness, defaultParams, getScheme } from '@thematic/color'
import merge from 'lodash-es/merge.js'
import set from 'lodash-es/set.js'
@ -20,23 +20,19 @@ type Config = {
}
/**
* Creates a completed Params block from a ThemeDefinition, making sure missing optional fields are populated.
* Creates a completed SchemeParams block from a ThemeDefinition, making sure missing optional fields are populated.
* @param themeDefinition
*/
export function applyParams(spec: ThemeSpec): Params {
const { params = defaultParams } = spec
export function applyParams(spec: ThemeSpec): SchemeParams {
const { params } = spec
return {
accentHue: params.accentHue,
accentSaturation: params.accentSaturation,
accentLuminance: params.accentLuminance,
backgroundHueShift: params.backgroundHueShift,
backgroundLevel: params.backgroundLevel,
nominalHueStep: params.nominalHueStep,
...defaultParams,
...params,
}
}
/**
* Creates a computed scheme from a ThemeDefinition (specifically, the Params in the definition).
* Creates a computed scheme from a ThemeDefinition (specifically, the SchemeParams in the definition).
* Note that this creates scales with 10 items as a default, useful for saving to file, etc.
* If more gradations are desired, a new scheme should be created at point-of-use.
* TODO: separate the scale bisection using Scheme functions that allow request of different
@ -51,7 +47,13 @@ export function createScheme(
sequentialItemCount: number = DEFAULT_SEQUENTIAL_ITEMS,
): Scheme {
const params = applyParams(spec)
const scheme = getScheme(params, nominalItemCount, sequentialItemCount, !dark)
const scheme = getScheme(
params,
nominalItemCount,
sequentialItemCount,
!dark,
spec.tuning,
)
return colorBlindness(scheme, colorBlindnessMode)
}
@ -120,7 +122,7 @@ export function computeDefinition(
paths: ['application.error'],
},
{
value: scheme.nominal[0] as string,
value: scheme.dataPrimary,
paths: [
'rect.fill',
'area.fill',
@ -133,7 +135,7 @@ export function computeDefinition(
{
// very light grey, for subtle borders and backgrounds
value: scheme.faintAnnotation,
paths: ['application.faint'],
paths: ['application.faint', 'gridLines.stroke'],
},
{
// low contrast grey, so they don't occupy lots of visual attention
@ -143,7 +145,6 @@ export function computeDefinition(
'plotArea.stroke',
'axisLine.stroke',
'axisTicks.stroke',
'gridLines.stroke',
'arc.stroke',
'application.border',
'application.lowContrast',
@ -191,7 +192,7 @@ export function computeDefinition(
const signalConfigs: Config[] = [
{
value: scheme.nominalBold[0] as string,
value: scheme.dataPrimaryBold,
paths: [
'rect.hovered.fill',
'area.hovered.fill',
@ -208,7 +209,7 @@ export function computeDefinition(
],
},
{
value: scheme.nominalMuted[0] as string,
value: scheme.dataPrimaryMuted,
paths: [
'rect.suppressed.fill',
'area.suppressed.fill',

Просмотреть файл

@ -7,10 +7,11 @@ const autumnTheme = {
params: {
accentHue: 50,
accentSaturation: 86,
accentLuminance: 67,
backgroundLevel: 95,
backgroundHueShift: 50,
nominalHueStep: 10,
accentLightness: 67,
scaleSaturation: 90,
scaleLightness: 67,
greyHue: 50,
greySaturation: 10,
},
}
export default autumnTheme

Просмотреть файл

@ -7,10 +7,11 @@ const defaultTheme = {
params: {
accentHue: 252,
accentSaturation: 78,
accentLuminance: 49,
backgroundLevel: 95,
backgroundHueShift: 50,
nominalHueStep: 10,
accentLightness: 49,
scaleSaturation: 90,
scaleLightness: 67,
greyHue: 72,
greySaturation: 7,
},
}
export default defaultTheme

Просмотреть файл

@ -7,10 +7,11 @@ const metalTheme = {
params: {
accentHue: 242,
accentSaturation: 46,
accentLuminance: 45,
backgroundLevel: 98,
backgroundHueShift: 100,
nominalHueStep: 21,
accentLightness: 45,
scaleSaturation: 90,
scaleLightness: 67,
greyHue: 242,
greySaturation: 20,
},
}
export default metalTheme

Просмотреть файл

@ -7,10 +7,11 @@ const oceanTheme = {
params: {
accentHue: 215,
accentSaturation: 95,
accentLuminance: 61,
backgroundLevel: 90,
backgroundHueShift: 40,
nominalHueStep: 0,
accentLightness: 61,
scaleSaturation: 90,
scaleLightness: 67,
greyHue: 100,
greySaturation: 7,
},
}
export default oceanTheme

Просмотреть файл

@ -2,7 +2,12 @@
* Copyright (c) Microsoft. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project.
*/
import type { Color, ColorBlindnessMode, Params, Scheme } from '@thematic/color'
import type {
Color,
ColorBlindnessMode,
Scheme,
SchemeParams,
} from '@thematic/color'
import type { ScaleType, SelectionState, ThemeVariant } from './enums.js'
import type { ThemeConfig } from './ThemeConfig.js'
@ -192,6 +197,11 @@ export interface ColorScales {
scaleType?: ScaleType,
quantiles?: number,
) => ContinuousColorScaleFunction
rainbow: (
domain?: number[],
scaleType?: ScaleType,
quantiles?: number,
) => ContinuousColorScaleFunction
}
/**
@ -263,7 +273,7 @@ export interface Theme {
name: string
dark: boolean
variant: ThemeVariant
params: Params
params: SchemeParams
scheme: Scheme
spec: ThemeSpec
config: ThemeConfig

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше