colorizr 5.0.1 → 5.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +80 -10
- package/dist/index.d.ts +80 -10
- package/dist/index.js +165 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +165 -46
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -14
- package/src/extract-color-parts.ts +3 -3
- package/src/index.ts +2 -1
- package/src/modules/validators.ts +2 -2
- package/src/random.ts +1 -1
- package/src/scale.ts +415 -74
- package/src/types/index.ts +0 -2
package/dist/index.d.mts
CHANGED
|
@@ -9,7 +9,6 @@ type ColorTypeInput = ColorType | 'named';
|
|
|
9
9
|
type ColorValue = ColorModel | HEX;
|
|
10
10
|
type ConverterParameters<TModel extends ColorModel> = TModel | ColorTuple;
|
|
11
11
|
type HEX = `#${string}`;
|
|
12
|
-
type PlainObject<T = any> = Record<string, T>;
|
|
13
12
|
interface Analysis {
|
|
14
13
|
brightnessDifference: number;
|
|
15
14
|
colorDifference: number;
|
|
@@ -524,7 +523,7 @@ declare function desaturate(input: string, amount: number, format?: ColorType):
|
|
|
524
523
|
type ExtractColorPartsReturn = {
|
|
525
524
|
alpha?: number;
|
|
526
525
|
model: ColorModelKey;
|
|
527
|
-
} &
|
|
526
|
+
} & Record<string, number>;
|
|
528
527
|
/**
|
|
529
528
|
* Extract the color parts from a CSS color string.
|
|
530
529
|
* Hex colors are supported via conversion.
|
|
@@ -919,8 +918,20 @@ declare function rotate(input: string, degrees: number, format?: ColorType): str
|
|
|
919
918
|
*/
|
|
920
919
|
declare function saturate(input: string, amount: number, format?: ColorType): string;
|
|
921
920
|
|
|
922
|
-
type ScaleMode = 'light' | 'dark';
|
|
921
|
+
type ScaleMode = 'light' | 'dark' | 'reversed';
|
|
923
922
|
type ScaleVariant = 'deep' | 'neutral' | 'pastel' | 'subtle' | 'vibrant';
|
|
923
|
+
/**
|
|
924
|
+
* Parabolic chroma curve with a movable center.
|
|
925
|
+
*/
|
|
926
|
+
interface ScaleChromaPeak {
|
|
927
|
+
/** Blend between constant chroma (0) and the full parabola (1). */
|
|
928
|
+
amount: number;
|
|
929
|
+
/**
|
|
930
|
+
* Lightness (exclusive 0-1) where chroma stays at full base.
|
|
931
|
+
* @default 0.5
|
|
932
|
+
*/
|
|
933
|
+
peak?: number;
|
|
934
|
+
}
|
|
924
935
|
/**
|
|
925
936
|
* Options for generating a color scale.
|
|
926
937
|
*
|
|
@@ -931,14 +942,29 @@ type ScaleVariant = 'deep' | 'neutral' | 'pastel' | 'subtle' | 'vibrant';
|
|
|
931
942
|
*/
|
|
932
943
|
interface ScaleOptions {
|
|
933
944
|
/**
|
|
934
|
-
* Controls chroma
|
|
945
|
+
* Controls how chroma flows across the scale. Three forms:
|
|
946
|
+
*
|
|
947
|
+
* Scalar (0-1) — parabolic blend centered at mid-lightness:
|
|
935
948
|
* - 0: Constant chroma across all steps (default).
|
|
936
|
-
* - 1:
|
|
937
|
-
*
|
|
949
|
+
* - 1: Full parabola — peak chroma at mid-lightness, reduced toward extremes.
|
|
950
|
+
* Shorthand for `{ amount: x }`.
|
|
951
|
+
*
|
|
952
|
+
* `{ amount, peak }` — the same parabola with a movable center.
|
|
953
|
+
* `peak` is the lightness (exclusive 0-1) that keeps full base chroma;
|
|
954
|
+
* sides away from it are reduced. Defaults to 0.5.
|
|
955
|
+
*
|
|
956
|
+
* `{ low, high }` — fractions (0-1) of the maximum P3 chroma at each step,
|
|
957
|
+
* blended from `low` (50-end) through the input color's own fraction at the
|
|
958
|
+
* lock/middle step to `high` (950-end). NOT equivalent to the scalar form —
|
|
959
|
+
* it is a different model: values set chroma relative to the gamut ceiling
|
|
960
|
+
* instead of bending the input's chroma. Being gamut-relative, the input's
|
|
961
|
+
* chroma matters only at the anchor step; an achromatic input collapses the
|
|
962
|
+
* anchor fraction to 0, yielding a V-shaped, colored scale (full at the ends,
|
|
963
|
+
* gray at the anchor).
|
|
938
964
|
*
|
|
939
965
|
* @default 0
|
|
940
966
|
*/
|
|
941
|
-
chromaCurve?: number;
|
|
967
|
+
chromaCurve?: number | ScaleChromaPeak | ScaleRange;
|
|
942
968
|
/**
|
|
943
969
|
* Output color format.
|
|
944
970
|
*
|
|
@@ -947,14 +973,36 @@ interface ScaleOptions {
|
|
|
947
973
|
* If not specified, the output will match the format of the input color.
|
|
948
974
|
*/
|
|
949
975
|
format?: ColorType;
|
|
976
|
+
/**
|
|
977
|
+
* Hue rotation across the scale, in degrees.
|
|
978
|
+
*
|
|
979
|
+
* A scalar `x` is shorthand for `{ low: -x, high: x }`.
|
|
980
|
+
* `low` shifts the low-key end (50), `high` the high-key end (950); shifts
|
|
981
|
+
* blend to 0° at the lock step (or the middle step when not locked), so the
|
|
982
|
+
* input hue is preserved there. The per-step gamut clamp follows the
|
|
983
|
+
* shifted hue.
|
|
984
|
+
*
|
|
985
|
+
* Values must be within [-180, 180].
|
|
986
|
+
*
|
|
987
|
+
* @default 0
|
|
988
|
+
*/
|
|
989
|
+
hueShift?: number | ScaleRange;
|
|
950
990
|
/**
|
|
951
991
|
* The lightness tuning factor for the scale.
|
|
952
992
|
* - 1: Linear lightness distribution.
|
|
953
993
|
* - >1: Lighter tones are emphasized.
|
|
954
994
|
* - <1: Darker tones are emphasized.
|
|
995
|
+
*
|
|
996
|
+
* A scalar `x` is shorthand for `{ low: x, high: x }`. With `{ low, high }`
|
|
997
|
+
* each half of the scale gets its own exponent: `low` shapes the low-key
|
|
998
|
+
* half (toward 50), `high` the high-key half (toward 950), split at the
|
|
999
|
+
* lock step when locked or blended continuously when not.
|
|
1000
|
+
* Reference palettes typically fit `{ low: 1.5, high: 1 }`.
|
|
1001
|
+
*
|
|
1002
|
+
* Values must be greater than 0.
|
|
955
1003
|
* @default 1.5
|
|
956
1004
|
*/
|
|
957
|
-
lightnessCurve?: number;
|
|
1005
|
+
lightnessCurve?: number | ScaleRange;
|
|
958
1006
|
/**
|
|
959
1007
|
* Lock input color's lightness at specific step position.
|
|
960
1008
|
*
|
|
@@ -965,6 +1013,11 @@ interface ScaleOptions {
|
|
|
965
1013
|
* Must be a valid step key for the current step count.
|
|
966
1014
|
* Default step keys (11 steps): 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950.
|
|
967
1015
|
* Step keys vary based on the `steps` option (3-20 steps supported).
|
|
1016
|
+
*
|
|
1017
|
+
* When locked at the first or last step, only one side of the scale remains,
|
|
1018
|
+
* so the unused-side value (`low`/`high`) of asymmetric options
|
|
1019
|
+
* (`hueShift`, `lightnessCurve`, endpoint `chromaCurve`) has no effect and
|
|
1020
|
+
* emits a warning.
|
|
968
1021
|
*/
|
|
969
1022
|
lock?: number;
|
|
970
1023
|
/**
|
|
@@ -990,7 +1043,14 @@ interface ScaleOptions {
|
|
|
990
1043
|
* Theme-aware lightness direction.
|
|
991
1044
|
*
|
|
992
1045
|
* - 'light': Low keys (50) are lightest, high keys (950) are darkest
|
|
993
|
-
* - 'dark': Low keys (50) are darkest, high keys (950) are lightest
|
|
1046
|
+
* - 'dark': Low keys (50) are darkest, high keys (950) are lightest, re-derived
|
|
1047
|
+
* with the lightness ramp running in the dark direction
|
|
1048
|
+
* - 'reversed': the 'light' palette with its keys reversed — identical colors in
|
|
1049
|
+
* mirrored order (50↔950, 100↔900, …)
|
|
1050
|
+
*
|
|
1051
|
+
* `dark` re-derives the scale, so its intermediate steps are not a reversal of
|
|
1052
|
+
* `light` (they coincide only when `lightnessCurve` is linear). `reversed`
|
|
1053
|
+
* re-labels the `light` palette, so it mirrors exactly at any curve.
|
|
994
1054
|
*
|
|
995
1055
|
* @default 'light'
|
|
996
1056
|
*/
|
|
@@ -1022,6 +1082,16 @@ interface ScaleOptions {
|
|
|
1022
1082
|
*/
|
|
1023
1083
|
variant?: ScaleVariant;
|
|
1024
1084
|
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Endpoint values for an asymmetric scale option.
|
|
1087
|
+
*
|
|
1088
|
+
* `low` applies at the low-key end (50), `high` at the high-key end (950),
|
|
1089
|
+
* regardless of `mode` — keys, not lightness, define the ends.
|
|
1090
|
+
*/
|
|
1091
|
+
interface ScaleRange {
|
|
1092
|
+
high: number;
|
|
1093
|
+
low: number;
|
|
1094
|
+
}
|
|
1025
1095
|
/**
|
|
1026
1096
|
* Generate a scale of colors based on the input color.
|
|
1027
1097
|
*
|
|
@@ -1078,4 +1148,4 @@ declare function toGamut(input: string, format?: ColorType): string;
|
|
|
1078
1148
|
*/
|
|
1079
1149
|
declare function transparentize(input: string, alpha: number, format?: ColorType): string;
|
|
1080
1150
|
|
|
1081
|
-
export { APCA_VERSION, type Analysis, CLMS_TO_OKLAB, type ColorKeysTuple, type ColorModel, type ColorModelKey, type ColorModelKeys, type ColorReturn, type ColorTuple, type ColorType, type ColorTypeInput, type ColorValue, type ColorizrOptions, type ConverterParameters, DEG2RAD, DELTA_E_JND, type FormatCSSOptions, GAMUT_EPSILON, type HEX, type HSL, type HueMode, type LAB, type LCH, LMS_TO_LRGB, LRGB_TO_LMS, type MixOptions, OKLAB_TO_CLMS, P3_TO_SRGB, P3_TO_XYZ, PRECISION, type PaletteOptions,
|
|
1151
|
+
export { APCA_VERSION, type Analysis, CLMS_TO_OKLAB, type ColorKeysTuple, type ColorModel, type ColorModelKey, type ColorModelKeys, type ColorReturn, type ColorTuple, type ColorType, type ColorTypeInput, type ColorValue, type ColorizrOptions, type ConverterParameters, DEG2RAD, DELTA_E_JND, type FormatCSSOptions, GAMUT_EPSILON, type HEX, type HSL, type HueMode, type LAB, type LCH, LMS_TO_LRGB, LRGB_TO_LMS, type MixOptions, OKLAB_TO_CLMS, P3_TO_SRGB, P3_TO_XYZ, PRECISION, type PaletteOptions, RAD2DEG, type RGB, type RandomOptions, type ReadableColorMethod, type ReadableColorOptions, SRGB_TO_P3, type ScaleChromaPeak, type ScaleMode, type ScaleOptions, type ScaleRange, type ScaleVariant, type Scheme, type SchemeOptions, XYZ_TO_SRGB, addAlphaToHex, apcaContrast, brightnessDifference, chroma, colorDifference, compare, contrast, convertAlphaToHex, convertCSS, darken, Colorizr as default, deltaE, desaturate, extractAlphaFromHex, extractColorParts, formatCSS, formatHex, getColorType, getP3MaxChroma, getP3MaxColor, getScaleStepKeys, grayscale, hex2hsl, hex2oklab, hex2oklch, hex2rgb, hsl2hex, hsl2oklab, hsl2oklch, hsl2rgb, invert, isHSL, isHex, isInGamut, isLAB, isLCH, isRGB, isValidColor, lighten, luminance, mix, name, oklab2hex, oklab2hsl, oklab2oklch, oklab2rgb, oklabToLinearP3, oklabToLinearSRGB, oklch2hex, oklch2hsl, oklch2oklab, oklch2rgb, opacify, opacity, palette, parseCSS, random, readableColor, removeAlphaFromHex, rgb2hex, rgb2hsl, rgb2oklab, rgb2oklch, rotate, saturate, scale, scheme, srgbGammaDecode, srgbGammaEncode, toGamut, transparentize };
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ type ColorTypeInput = ColorType | 'named';
|
|
|
9
9
|
type ColorValue = ColorModel | HEX;
|
|
10
10
|
type ConverterParameters<TModel extends ColorModel> = TModel | ColorTuple;
|
|
11
11
|
type HEX = `#${string}`;
|
|
12
|
-
type PlainObject<T = any> = Record<string, T>;
|
|
13
12
|
interface Analysis {
|
|
14
13
|
brightnessDifference: number;
|
|
15
14
|
colorDifference: number;
|
|
@@ -524,7 +523,7 @@ declare function desaturate(input: string, amount: number, format?: ColorType):
|
|
|
524
523
|
type ExtractColorPartsReturn = {
|
|
525
524
|
alpha?: number;
|
|
526
525
|
model: ColorModelKey;
|
|
527
|
-
} &
|
|
526
|
+
} & Record<string, number>;
|
|
528
527
|
/**
|
|
529
528
|
* Extract the color parts from a CSS color string.
|
|
530
529
|
* Hex colors are supported via conversion.
|
|
@@ -919,8 +918,20 @@ declare function rotate(input: string, degrees: number, format?: ColorType): str
|
|
|
919
918
|
*/
|
|
920
919
|
declare function saturate(input: string, amount: number, format?: ColorType): string;
|
|
921
920
|
|
|
922
|
-
type ScaleMode = 'light' | 'dark';
|
|
921
|
+
type ScaleMode = 'light' | 'dark' | 'reversed';
|
|
923
922
|
type ScaleVariant = 'deep' | 'neutral' | 'pastel' | 'subtle' | 'vibrant';
|
|
923
|
+
/**
|
|
924
|
+
* Parabolic chroma curve with a movable center.
|
|
925
|
+
*/
|
|
926
|
+
interface ScaleChromaPeak {
|
|
927
|
+
/** Blend between constant chroma (0) and the full parabola (1). */
|
|
928
|
+
amount: number;
|
|
929
|
+
/**
|
|
930
|
+
* Lightness (exclusive 0-1) where chroma stays at full base.
|
|
931
|
+
* @default 0.5
|
|
932
|
+
*/
|
|
933
|
+
peak?: number;
|
|
934
|
+
}
|
|
924
935
|
/**
|
|
925
936
|
* Options for generating a color scale.
|
|
926
937
|
*
|
|
@@ -931,14 +942,29 @@ type ScaleVariant = 'deep' | 'neutral' | 'pastel' | 'subtle' | 'vibrant';
|
|
|
931
942
|
*/
|
|
932
943
|
interface ScaleOptions {
|
|
933
944
|
/**
|
|
934
|
-
* Controls chroma
|
|
945
|
+
* Controls how chroma flows across the scale. Three forms:
|
|
946
|
+
*
|
|
947
|
+
* Scalar (0-1) — parabolic blend centered at mid-lightness:
|
|
935
948
|
* - 0: Constant chroma across all steps (default).
|
|
936
|
-
* - 1:
|
|
937
|
-
*
|
|
949
|
+
* - 1: Full parabola — peak chroma at mid-lightness, reduced toward extremes.
|
|
950
|
+
* Shorthand for `{ amount: x }`.
|
|
951
|
+
*
|
|
952
|
+
* `{ amount, peak }` — the same parabola with a movable center.
|
|
953
|
+
* `peak` is the lightness (exclusive 0-1) that keeps full base chroma;
|
|
954
|
+
* sides away from it are reduced. Defaults to 0.5.
|
|
955
|
+
*
|
|
956
|
+
* `{ low, high }` — fractions (0-1) of the maximum P3 chroma at each step,
|
|
957
|
+
* blended from `low` (50-end) through the input color's own fraction at the
|
|
958
|
+
* lock/middle step to `high` (950-end). NOT equivalent to the scalar form —
|
|
959
|
+
* it is a different model: values set chroma relative to the gamut ceiling
|
|
960
|
+
* instead of bending the input's chroma. Being gamut-relative, the input's
|
|
961
|
+
* chroma matters only at the anchor step; an achromatic input collapses the
|
|
962
|
+
* anchor fraction to 0, yielding a V-shaped, colored scale (full at the ends,
|
|
963
|
+
* gray at the anchor).
|
|
938
964
|
*
|
|
939
965
|
* @default 0
|
|
940
966
|
*/
|
|
941
|
-
chromaCurve?: number;
|
|
967
|
+
chromaCurve?: number | ScaleChromaPeak | ScaleRange;
|
|
942
968
|
/**
|
|
943
969
|
* Output color format.
|
|
944
970
|
*
|
|
@@ -947,14 +973,36 @@ interface ScaleOptions {
|
|
|
947
973
|
* If not specified, the output will match the format of the input color.
|
|
948
974
|
*/
|
|
949
975
|
format?: ColorType;
|
|
976
|
+
/**
|
|
977
|
+
* Hue rotation across the scale, in degrees.
|
|
978
|
+
*
|
|
979
|
+
* A scalar `x` is shorthand for `{ low: -x, high: x }`.
|
|
980
|
+
* `low` shifts the low-key end (50), `high` the high-key end (950); shifts
|
|
981
|
+
* blend to 0° at the lock step (or the middle step when not locked), so the
|
|
982
|
+
* input hue is preserved there. The per-step gamut clamp follows the
|
|
983
|
+
* shifted hue.
|
|
984
|
+
*
|
|
985
|
+
* Values must be within [-180, 180].
|
|
986
|
+
*
|
|
987
|
+
* @default 0
|
|
988
|
+
*/
|
|
989
|
+
hueShift?: number | ScaleRange;
|
|
950
990
|
/**
|
|
951
991
|
* The lightness tuning factor for the scale.
|
|
952
992
|
* - 1: Linear lightness distribution.
|
|
953
993
|
* - >1: Lighter tones are emphasized.
|
|
954
994
|
* - <1: Darker tones are emphasized.
|
|
995
|
+
*
|
|
996
|
+
* A scalar `x` is shorthand for `{ low: x, high: x }`. With `{ low, high }`
|
|
997
|
+
* each half of the scale gets its own exponent: `low` shapes the low-key
|
|
998
|
+
* half (toward 50), `high` the high-key half (toward 950), split at the
|
|
999
|
+
* lock step when locked or blended continuously when not.
|
|
1000
|
+
* Reference palettes typically fit `{ low: 1.5, high: 1 }`.
|
|
1001
|
+
*
|
|
1002
|
+
* Values must be greater than 0.
|
|
955
1003
|
* @default 1.5
|
|
956
1004
|
*/
|
|
957
|
-
lightnessCurve?: number;
|
|
1005
|
+
lightnessCurve?: number | ScaleRange;
|
|
958
1006
|
/**
|
|
959
1007
|
* Lock input color's lightness at specific step position.
|
|
960
1008
|
*
|
|
@@ -965,6 +1013,11 @@ interface ScaleOptions {
|
|
|
965
1013
|
* Must be a valid step key for the current step count.
|
|
966
1014
|
* Default step keys (11 steps): 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950.
|
|
967
1015
|
* Step keys vary based on the `steps` option (3-20 steps supported).
|
|
1016
|
+
*
|
|
1017
|
+
* When locked at the first or last step, only one side of the scale remains,
|
|
1018
|
+
* so the unused-side value (`low`/`high`) of asymmetric options
|
|
1019
|
+
* (`hueShift`, `lightnessCurve`, endpoint `chromaCurve`) has no effect and
|
|
1020
|
+
* emits a warning.
|
|
968
1021
|
*/
|
|
969
1022
|
lock?: number;
|
|
970
1023
|
/**
|
|
@@ -990,7 +1043,14 @@ interface ScaleOptions {
|
|
|
990
1043
|
* Theme-aware lightness direction.
|
|
991
1044
|
*
|
|
992
1045
|
* - 'light': Low keys (50) are lightest, high keys (950) are darkest
|
|
993
|
-
* - 'dark': Low keys (50) are darkest, high keys (950) are lightest
|
|
1046
|
+
* - 'dark': Low keys (50) are darkest, high keys (950) are lightest, re-derived
|
|
1047
|
+
* with the lightness ramp running in the dark direction
|
|
1048
|
+
* - 'reversed': the 'light' palette with its keys reversed — identical colors in
|
|
1049
|
+
* mirrored order (50↔950, 100↔900, …)
|
|
1050
|
+
*
|
|
1051
|
+
* `dark` re-derives the scale, so its intermediate steps are not a reversal of
|
|
1052
|
+
* `light` (they coincide only when `lightnessCurve` is linear). `reversed`
|
|
1053
|
+
* re-labels the `light` palette, so it mirrors exactly at any curve.
|
|
994
1054
|
*
|
|
995
1055
|
* @default 'light'
|
|
996
1056
|
*/
|
|
@@ -1022,6 +1082,16 @@ interface ScaleOptions {
|
|
|
1022
1082
|
*/
|
|
1023
1083
|
variant?: ScaleVariant;
|
|
1024
1084
|
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Endpoint values for an asymmetric scale option.
|
|
1087
|
+
*
|
|
1088
|
+
* `low` applies at the low-key end (50), `high` at the high-key end (950),
|
|
1089
|
+
* regardless of `mode` — keys, not lightness, define the ends.
|
|
1090
|
+
*/
|
|
1091
|
+
interface ScaleRange {
|
|
1092
|
+
high: number;
|
|
1093
|
+
low: number;
|
|
1094
|
+
}
|
|
1025
1095
|
/**
|
|
1026
1096
|
* Generate a scale of colors based on the input color.
|
|
1027
1097
|
*
|
|
@@ -1078,4 +1148,4 @@ declare function toGamut(input: string, format?: ColorType): string;
|
|
|
1078
1148
|
*/
|
|
1079
1149
|
declare function transparentize(input: string, alpha: number, format?: ColorType): string;
|
|
1080
1150
|
|
|
1081
|
-
export { APCA_VERSION, type Analysis, CLMS_TO_OKLAB, type ColorKeysTuple, type ColorModel, type ColorModelKey, type ColorModelKeys, type ColorReturn, type ColorTuple, type ColorType, type ColorTypeInput, type ColorValue, type ColorizrOptions, type ConverterParameters, DEG2RAD, DELTA_E_JND, type FormatCSSOptions, GAMUT_EPSILON, type HEX, type HSL, type HueMode, type LAB, type LCH, LMS_TO_LRGB, LRGB_TO_LMS, type MixOptions, OKLAB_TO_CLMS, P3_TO_SRGB, P3_TO_XYZ, PRECISION, type PaletteOptions,
|
|
1151
|
+
export { APCA_VERSION, type Analysis, CLMS_TO_OKLAB, type ColorKeysTuple, type ColorModel, type ColorModelKey, type ColorModelKeys, type ColorReturn, type ColorTuple, type ColorType, type ColorTypeInput, type ColorValue, type ColorizrOptions, type ConverterParameters, DEG2RAD, DELTA_E_JND, type FormatCSSOptions, GAMUT_EPSILON, type HEX, type HSL, type HueMode, type LAB, type LCH, LMS_TO_LRGB, LRGB_TO_LMS, type MixOptions, OKLAB_TO_CLMS, P3_TO_SRGB, P3_TO_XYZ, PRECISION, type PaletteOptions, RAD2DEG, type RGB, type RandomOptions, type ReadableColorMethod, type ReadableColorOptions, SRGB_TO_P3, type ScaleChromaPeak, type ScaleMode, type ScaleOptions, type ScaleRange, type ScaleVariant, type Scheme, type SchemeOptions, XYZ_TO_SRGB, addAlphaToHex, apcaContrast, brightnessDifference, chroma, colorDifference, compare, contrast, convertAlphaToHex, convertCSS, darken, Colorizr as default, deltaE, desaturate, extractAlphaFromHex, extractColorParts, formatCSS, formatHex, getColorType, getP3MaxChroma, getP3MaxColor, getScaleStepKeys, grayscale, hex2hsl, hex2oklab, hex2oklch, hex2rgb, hsl2hex, hsl2oklab, hsl2oklch, hsl2rgb, invert, isHSL, isHex, isInGamut, isLAB, isLCH, isRGB, isValidColor, lighten, luminance, mix, name, oklab2hex, oklab2hsl, oklab2oklch, oklab2rgb, oklabToLinearP3, oklabToLinearSRGB, oklch2hex, oklch2hsl, oklch2oklab, oklch2rgb, opacify, opacity, palette, parseCSS, random, readableColor, removeAlphaFromHex, rgb2hex, rgb2hsl, rgb2oklab, rgb2oklch, rotate, saturate, scale, scheme, srgbGammaDecode, srgbGammaEncode, toGamut, transparentize };
|
package/dist/index.js
CHANGED
|
@@ -2177,11 +2177,53 @@ var chromaScale = {
|
|
|
2177
2177
|
subtle: 0.2,
|
|
2178
2178
|
vibrant: 1.25
|
|
2179
2179
|
};
|
|
2180
|
+
function assertScaleObject(value, label) {
|
|
2181
|
+
invariant(isPlainObject(value), `${label} must be a number or an object.`);
|
|
2182
|
+
}
|
|
2183
|
+
function computeLightnessMapWithLock(lock, inputLightness, keys, lightnessCurve, maxLightness, minLightness, mode) {
|
|
2184
|
+
const lightnessMap = {};
|
|
2185
|
+
const lockIndex = keys.indexOf(lock);
|
|
2186
|
+
lightnessMap[lock] = inputLightness;
|
|
2187
|
+
if (lockIndex > 0) {
|
|
2188
|
+
const target = mode === "light" ? maxLightness : minLightness;
|
|
2189
|
+
for (let index = 0; index < lockIndex; index++) {
|
|
2190
|
+
const t = index / lockIndex;
|
|
2191
|
+
lightnessMap[keys[index]] = target + (inputLightness - target) * t ** lightnessCurve.low;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
const remaining = keys.length - 1 - lockIndex;
|
|
2195
|
+
if (remaining > 0) {
|
|
2196
|
+
const target = mode === "light" ? minLightness : maxLightness;
|
|
2197
|
+
for (let index = lockIndex + 1; index < keys.length; index++) {
|
|
2198
|
+
const t = (index - lockIndex) / remaining;
|
|
2199
|
+
lightnessMap[keys[index]] = inputLightness + (target - inputLightness) * t ** lightnessCurve.high;
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
return lightnessMap;
|
|
2203
|
+
}
|
|
2204
|
+
function computeLightnessMapWithoutLock(keys, lightnessCurve, maxLightness, minLightness, mode) {
|
|
2205
|
+
const lightnessMap = {};
|
|
2206
|
+
for (let index = 0; index < keys.length; index++) {
|
|
2207
|
+
const tBase = index / (keys.length - 1);
|
|
2208
|
+
const exponent = lightnessCurve.low + (lightnessCurve.high - lightnessCurve.low) * tBase;
|
|
2209
|
+
const t = tBase ** exponent;
|
|
2210
|
+
lightnessMap[keys[index]] = mode === "light" ? maxLightness - (maxLightness - minLightness) * t : minLightness + (maxLightness - minLightness) * t;
|
|
2211
|
+
}
|
|
2212
|
+
return lightnessMap;
|
|
2213
|
+
}
|
|
2214
|
+
function computeStepHue(hue, hueShift, index, anchorIndex, keysLength) {
|
|
2215
|
+
if (hueShift.low === 0 && hueShift.high === 0 || index === anchorIndex) {
|
|
2216
|
+
return hue;
|
|
2217
|
+
}
|
|
2218
|
+
const shift = index < anchorIndex ? hueShift.low * (1 - index / anchorIndex) : hueShift.high * ((index - anchorIndex) / (keysLength - 1 - anchorIndex));
|
|
2219
|
+
return (hue + shift + 360) % 360;
|
|
2220
|
+
}
|
|
2180
2221
|
function generatePalette(options) {
|
|
2181
2222
|
const {
|
|
2182
2223
|
baseChroma,
|
|
2183
2224
|
chromaCurve,
|
|
2184
2225
|
hue,
|
|
2226
|
+
hueShift,
|
|
2185
2227
|
inputLightness,
|
|
2186
2228
|
keys,
|
|
2187
2229
|
lightnessCurve,
|
|
@@ -2191,52 +2233,113 @@ function generatePalette(options) {
|
|
|
2191
2233
|
mode
|
|
2192
2234
|
} = options;
|
|
2193
2235
|
const palette2 = {};
|
|
2194
|
-
const lightnessMap =
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
const
|
|
2206
|
-
if (remaining > 0) {
|
|
2207
|
-
const target = mode === "light" ? minLightness : maxLightness;
|
|
2208
|
-
for (let index = lockIndex + 1; index < keys.length; index++) {
|
|
2209
|
-
const t = (index - lockIndex) / remaining;
|
|
2210
|
-
lightnessMap[keys[index]] = inputLightness + (target - inputLightness) * t ** lightnessCurve;
|
|
2211
|
-
}
|
|
2212
|
-
}
|
|
2213
|
-
} else {
|
|
2214
|
-
for (let index = 0; index < keys.length; index++) {
|
|
2215
|
-
const t = (index / (keys.length - 1)) ** lightnessCurve;
|
|
2216
|
-
lightnessMap[keys[index]] = mode === "light" ? maxLightness - (maxLightness - minLightness) * t : minLightness + (maxLightness - minLightness) * t;
|
|
2217
|
-
}
|
|
2218
|
-
}
|
|
2219
|
-
for (const key of keys) {
|
|
2236
|
+
const lightnessMap = lock !== void 0 && inputLightness !== void 0 ? computeLightnessMapWithLock(
|
|
2237
|
+
lock,
|
|
2238
|
+
inputLightness,
|
|
2239
|
+
keys,
|
|
2240
|
+
lightnessCurve,
|
|
2241
|
+
maxLightness,
|
|
2242
|
+
minLightness,
|
|
2243
|
+
mode
|
|
2244
|
+
) : computeLightnessMapWithoutLock(keys, lightnessCurve, maxLightness, minLightness, mode);
|
|
2245
|
+
const anchorIndex = lock !== void 0 ? keys.indexOf(lock) : Math.floor((keys.length - 1) / 2);
|
|
2246
|
+
for (let index = 0; index < keys.length; index++) {
|
|
2247
|
+
const key = keys[index];
|
|
2220
2248
|
const lightness = lightnessMap[key];
|
|
2221
|
-
const
|
|
2222
|
-
const maxChroma = getP3MaxChroma({ l: lightness, c: 0, h:
|
|
2223
|
-
|
|
2249
|
+
const stepHue = computeStepHue(hue, hueShift, index, anchorIndex, keys.length);
|
|
2250
|
+
const maxChroma = getP3MaxChroma({ l: lightness, c: 0, h: stepHue });
|
|
2251
|
+
const chroma2 = chromaCurve.type === "endpoints" ? getStepRelativeChroma(chromaCurve, index, anchorIndex, keys.length) * maxChroma : getStepChroma(lightness, baseChroma, chromaCurve.amount, chromaCurve.peak);
|
|
2252
|
+
palette2[key] = { l: lightness, c: Math.min(chroma2, maxChroma), h: stepHue };
|
|
2224
2253
|
}
|
|
2225
2254
|
return palette2;
|
|
2226
2255
|
}
|
|
2227
|
-
function getStepChroma(lightness, baseChroma,
|
|
2228
|
-
if (
|
|
2256
|
+
function getStepChroma(lightness, baseChroma, amount, peak) {
|
|
2257
|
+
if (amount === 0) {
|
|
2229
2258
|
return baseChroma;
|
|
2230
2259
|
}
|
|
2231
|
-
const parabolic = 4 * lightness * (1 - lightness);
|
|
2232
|
-
const curveScale = 1 -
|
|
2260
|
+
const parabolic = peak === 0.5 ? 4 * lightness * (1 - lightness) : Math.max(0, 1 - ((lightness - peak) / Math.max(peak, 1 - peak)) ** 2);
|
|
2261
|
+
const curveScale = 1 - amount * (1 - parabolic);
|
|
2233
2262
|
return Math.max(0, baseChroma * curveScale);
|
|
2234
2263
|
}
|
|
2264
|
+
function getStepRelativeChroma(curve, index, anchorIndex, total) {
|
|
2265
|
+
const { high, low, mid } = curve;
|
|
2266
|
+
if (index === anchorIndex) {
|
|
2267
|
+
return mid;
|
|
2268
|
+
}
|
|
2269
|
+
if (index < anchorIndex) {
|
|
2270
|
+
return low + (mid - low) * (index / anchorIndex);
|
|
2271
|
+
}
|
|
2272
|
+
return mid + (high - mid) * ((index - anchorIndex) / (total - 1 - anchorIndex));
|
|
2273
|
+
}
|
|
2274
|
+
function normalizeChromaCurve(chromaCurve, lch, baseChroma) {
|
|
2275
|
+
if (isNumber(chromaCurve)) {
|
|
2276
|
+
invariant(isNumberInRange(chromaCurve, 0, 1), "chromaCurve must be within the range [0, 1].");
|
|
2277
|
+
return { amount: chromaCurve, peak: 0.5, type: "parabola" };
|
|
2278
|
+
}
|
|
2279
|
+
assertScaleObject(chromaCurve, "chromaCurve");
|
|
2280
|
+
if ("amount" in chromaCurve) {
|
|
2281
|
+
const { amount, peak = 0.5 } = chromaCurve;
|
|
2282
|
+
invariant(isNumberInRange(amount, 0, 1), "chromaCurve amount must be within the range [0, 1].");
|
|
2283
|
+
invariant(
|
|
2284
|
+
isNumber(peak) && peak > 0 && peak < 1,
|
|
2285
|
+
"chromaCurve peak must be within the range (0, 1)."
|
|
2286
|
+
);
|
|
2287
|
+
return { amount, peak, type: "parabola" };
|
|
2288
|
+
}
|
|
2289
|
+
const { high, low } = chromaCurve;
|
|
2290
|
+
invariant(
|
|
2291
|
+
isNumberInRange(low, 0, 1) && isNumberInRange(high, 0, 1),
|
|
2292
|
+
"chromaCurve low/high must be within the range [0, 1]."
|
|
2293
|
+
);
|
|
2294
|
+
const maxChromaAtInput = getP3MaxChroma(lch);
|
|
2295
|
+
return {
|
|
2296
|
+
high,
|
|
2297
|
+
low,
|
|
2298
|
+
mid: maxChromaAtInput > 0 ? clamp(baseChroma / maxChromaAtInput, 0, 1) : 0,
|
|
2299
|
+
type: "endpoints"
|
|
2300
|
+
};
|
|
2301
|
+
}
|
|
2302
|
+
function resolveBaseChroma(saturation, variant, lch) {
|
|
2303
|
+
if (saturation !== void 0) {
|
|
2304
|
+
return clamp(saturation, 0, 100) / 100 * getP3MaxChroma(lch);
|
|
2305
|
+
}
|
|
2306
|
+
if (variant && chromaScale[variant]) {
|
|
2307
|
+
return lch.c * chromaScale[variant];
|
|
2308
|
+
}
|
|
2309
|
+
if (variant) {
|
|
2310
|
+
warn(`variant: ${variant} is not valid, ignoring`);
|
|
2311
|
+
}
|
|
2312
|
+
return lch.c;
|
|
2313
|
+
}
|
|
2314
|
+
function warnIgnoredLockEndpoints(lock, keys, options) {
|
|
2315
|
+
if (lock === void 0) {
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
const lockIndex = keys.indexOf(lock);
|
|
2319
|
+
if (lockIndex !== 0 && lockIndex !== keys.length - 1) {
|
|
2320
|
+
return;
|
|
2321
|
+
}
|
|
2322
|
+
const { chromaCurve, hueShift, lightnessCurve } = options;
|
|
2323
|
+
const ignored = lockIndex === 0 ? "low" : "high";
|
|
2324
|
+
const ranges = [
|
|
2325
|
+
["hueShift", hueShift],
|
|
2326
|
+
["lightnessCurve", lightnessCurve]
|
|
2327
|
+
];
|
|
2328
|
+
if (chromaCurve.type === "endpoints") {
|
|
2329
|
+
ranges.push(["chromaCurve", { high: chromaCurve.high, low: chromaCurve.low }]);
|
|
2330
|
+
}
|
|
2331
|
+
for (const [name2, range] of ranges) {
|
|
2332
|
+
if (range.low !== range.high) {
|
|
2333
|
+
warn(`lock at ${lock} ignores ${name2}.${ignored} (${range[ignored]})`);
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2235
2337
|
function scale(input, options = {}) {
|
|
2236
2338
|
invariant(isString(input), MESSAGES.inputString);
|
|
2237
2339
|
const {
|
|
2238
2340
|
chromaCurve = 0,
|
|
2239
2341
|
format,
|
|
2342
|
+
hueShift = 0,
|
|
2240
2343
|
lightnessCurve = 1.5,
|
|
2241
2344
|
lock: lockOption,
|
|
2242
2345
|
maxLightness = 0.97,
|
|
@@ -2250,6 +2353,22 @@ function scale(input, options = {}) {
|
|
|
2250
2353
|
maxLightness > minLightness && maxLightness <= 1 && minLightness >= 0,
|
|
2251
2354
|
"maxLightness must be greater than minLightness and within the range [0, 1]."
|
|
2252
2355
|
);
|
|
2356
|
+
if (!isNumber(hueShift)) {
|
|
2357
|
+
assertScaleObject(hueShift, "hueShift");
|
|
2358
|
+
}
|
|
2359
|
+
const hueShiftRange = isNumber(hueShift) ? { low: -hueShift, high: hueShift } : hueShift;
|
|
2360
|
+
invariant(
|
|
2361
|
+
isNumberInRange(hueShiftRange.low, -180, 180) && isNumberInRange(hueShiftRange.high, -180, 180),
|
|
2362
|
+
"hueShift values must be within the range [-180, 180]."
|
|
2363
|
+
);
|
|
2364
|
+
if (!isNumber(lightnessCurve)) {
|
|
2365
|
+
assertScaleObject(lightnessCurve, "lightnessCurve");
|
|
2366
|
+
}
|
|
2367
|
+
const lightnessCurveRange = isNumber(lightnessCurve) ? { low: lightnessCurve, high: lightnessCurve } : lightnessCurve;
|
|
2368
|
+
invariant(
|
|
2369
|
+
isNumber(lightnessCurveRange.low) && lightnessCurveRange.low > 0 && isNumber(lightnessCurveRange.high) && lightnessCurveRange.high > 0,
|
|
2370
|
+
"lightnessCurve values must be greater than 0."
|
|
2371
|
+
);
|
|
2253
2372
|
const steps = stepsOption !== void 0 ? Math.round(stepsOption) : 11;
|
|
2254
2373
|
const keys = getScaleStepKeys(steps);
|
|
2255
2374
|
let lock = lockOption;
|
|
@@ -2259,30 +2378,30 @@ function scale(input, options = {}) {
|
|
|
2259
2378
|
}
|
|
2260
2379
|
const parsed = resolveColor(input);
|
|
2261
2380
|
const lch = parsed.oklch;
|
|
2262
|
-
|
|
2263
|
-
if (saturation !== void 0) {
|
|
2264
|
-
const maxChroma = getP3MaxChroma(lch);
|
|
2265
|
-
baseChroma = clamp(saturation, 0, 100) / 100 * maxChroma;
|
|
2266
|
-
} else if (variant && chromaScale[variant]) {
|
|
2267
|
-
baseChroma = lch.c * chromaScale[variant];
|
|
2268
|
-
} else {
|
|
2269
|
-
baseChroma = lch.c;
|
|
2270
|
-
}
|
|
2381
|
+
const baseChroma = resolveBaseChroma(saturation, variant, lch);
|
|
2271
2382
|
const colorFormat = format ?? parsed.type;
|
|
2383
|
+
const chromaCurveConfig = normalizeChromaCurve(chromaCurve, lch, baseChroma);
|
|
2384
|
+
warnIgnoredLockEndpoints(lock, keys, {
|
|
2385
|
+
chromaCurve: chromaCurveConfig,
|
|
2386
|
+
hueShift: hueShiftRange,
|
|
2387
|
+
lightnessCurve: lightnessCurveRange
|
|
2388
|
+
});
|
|
2272
2389
|
const palette2 = generatePalette({
|
|
2273
2390
|
baseChroma,
|
|
2274
|
-
chromaCurve,
|
|
2391
|
+
chromaCurve: chromaCurveConfig,
|
|
2275
2392
|
hue: lch.h,
|
|
2393
|
+
hueShift: hueShiftRange,
|
|
2276
2394
|
inputLightness: lock !== void 0 ? lch.l : void 0,
|
|
2277
2395
|
keys,
|
|
2278
|
-
lightnessCurve,
|
|
2396
|
+
lightnessCurve: lightnessCurveRange,
|
|
2279
2397
|
lock,
|
|
2280
2398
|
maxLightness,
|
|
2281
2399
|
minLightness,
|
|
2282
|
-
mode
|
|
2400
|
+
mode: mode === "reversed" ? "light" : mode
|
|
2283
2401
|
});
|
|
2402
|
+
const ordered = mode === "reversed" ? Object.fromEntries(keys.map((key, index) => [key, palette2[keys[keys.length - 1 - index]]])) : palette2;
|
|
2284
2403
|
return Object.fromEntries(
|
|
2285
|
-
Object.entries(
|
|
2404
|
+
Object.entries(ordered).map(([key, value]) => [key, formatCSS(value, { format: colorFormat })])
|
|
2286
2405
|
);
|
|
2287
2406
|
}
|
|
2288
2407
|
|