@versatiles/style 5.8.4 → 5.9.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.
Files changed (54) hide show
  1. package/README.md +24 -18
  2. package/dist/index.d.ts +20 -14
  3. package/dist/index.js +151 -83
  4. package/dist/index.js.map +1 -1
  5. package/package.json +17 -18
  6. package/src/color/abstract.ts +0 -202
  7. package/src/color/hsl.test.ts +0 -177
  8. package/src/color/hsl.ts +0 -201
  9. package/src/color/hsv.test.ts +0 -169
  10. package/src/color/hsv.ts +0 -189
  11. package/src/color/index.test.ts +0 -99
  12. package/src/color/index.ts +0 -35
  13. package/src/color/random.test.ts +0 -57
  14. package/src/color/random.ts +0 -267
  15. package/src/color/rgb.test.ts +0 -215
  16. package/src/color/rgb.ts +0 -380
  17. package/src/color/utils.test.ts +0 -85
  18. package/src/color/utils.ts +0 -17
  19. package/src/guess_style/guess_style.test.ts +0 -140
  20. package/src/guess_style/guess_style.ts +0 -249
  21. package/src/guess_style/index.ts +0 -2
  22. package/src/index.test.ts +0 -131
  23. package/src/index.ts +0 -113
  24. package/src/lib/utils.test.ts +0 -198
  25. package/src/lib/utils.ts +0 -132
  26. package/src/shortbread/index.ts +0 -2
  27. package/src/shortbread/layers.test.ts +0 -81
  28. package/src/shortbread/layers.ts +0 -602
  29. package/src/shortbread/properties.test.ts +0 -44
  30. package/src/shortbread/properties.ts +0 -156
  31. package/src/shortbread/template.test.ts +0 -49
  32. package/src/shortbread/template.ts +0 -336
  33. package/src/style_builder/decorator.test.ts +0 -68
  34. package/src/style_builder/decorator.ts +0 -143
  35. package/src/style_builder/recolor.test.ts +0 -328
  36. package/src/style_builder/recolor.ts +0 -237
  37. package/src/style_builder/style_builder.test.ts +0 -148
  38. package/src/style_builder/style_builder.ts +0 -138
  39. package/src/style_builder/types.ts +0 -195
  40. package/src/styles/LICENSE.md +0 -41
  41. package/src/styles/colorful.test.ts +0 -91
  42. package/src/styles/colorful.ts +0 -1177
  43. package/src/styles/eclipse.ts +0 -11
  44. package/src/styles/empty.ts +0 -10
  45. package/src/styles/graybeard.ts +0 -11
  46. package/src/styles/index.ts +0 -32
  47. package/src/styles/neutrino.ts +0 -427
  48. package/src/styles/shadow.ts +0 -11
  49. package/src/types/index.ts +0 -5
  50. package/src/types/maplibre.ts +0 -25
  51. package/src/types/tilejson.test.ts +0 -96
  52. package/src/types/tilejson.ts +0 -125
  53. package/src/types/vector_layer.test.ts +0 -68
  54. package/src/types/vector_layer.ts +0 -69
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@versatiles/style",
3
- "version": "5.8.4",
3
+ "version": "5.9.1",
4
4
  "description": "Generate StyleJSON for MapLibre",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "devEngines": {
8
8
  "runtime": {
9
9
  "name": "node",
10
- "version": ">=20.0.0 <24.0.0"
10
+ "version": ">= 20.0.0"
11
11
  }
12
12
  },
13
13
  "scripts": {
@@ -44,12 +44,11 @@
44
44
  "brace-expansion": "^4.0.1"
45
45
  },
46
46
  "files": [
47
- "dist/*",
48
- "src/*"
47
+ "dist/*"
49
48
  ],
50
49
  "devDependencies": {
51
- "@maplibre/maplibre-gl-native": "^6.2.0",
52
- "@maplibre/maplibre-gl-style-spec": "^24.3.1",
50
+ "@maplibre/maplibre-gl-native": "^6.3.0",
51
+ "@maplibre/maplibre-gl-style-spec": "^24.4.1",
53
52
  "@rollup/plugin-commonjs": "^29.0.0",
54
53
  "@rollup/plugin-node-resolve": "^16.0.3",
55
54
  "@rollup/plugin-terser": "^0.4.4",
@@ -57,26 +56,26 @@
57
56
  "@types/bin-pack": "^1.0.3",
58
57
  "@types/brace-expansion": "^1.1.2",
59
58
  "@types/inquirer": "^9.0.9",
60
- "@types/node": "^24.10.2",
59
+ "@types/node": "^25.2.1",
61
60
  "@types/tar-stream": "^3.1.4",
62
- "@typescript-eslint/eslint-plugin": "^8.49.0",
63
- "@typescript-eslint/parser": "^8.49.0",
64
- "@versatiles/release-tool": "^2.5.0",
65
- "@vitest/coverage-v8": "^4.0.15",
61
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
62
+ "@typescript-eslint/parser": "^8.54.0",
63
+ "@versatiles/release-tool": "^2.7.0",
64
+ "@vitest/coverage-v8": "^4.0.18",
66
65
  "bin-pack": "^1.0.2",
67
- "esbuild": "^0.27.1",
68
- "eslint": "^9.39.1",
66
+ "esbuild": "^0.27.3",
67
+ "eslint": "^9.39.2",
69
68
  "husky": "^9.1.7",
70
- "inquirer": "^13.0.2",
71
- "prettier": "^3.7.4",
72
- "rollup": "^4.53.3",
69
+ "inquirer": "^13.2.2",
70
+ "prettier": "^3.8.1",
71
+ "rollup": "^4.57.1",
73
72
  "rollup-plugin-dts": "^6.3.0",
74
73
  "rollup-plugin-sourcemaps2": "^0.5.4",
75
74
  "sharp": "^0.34.5",
76
75
  "tar-stream": "^3.1.7",
77
76
  "tsx": "^4.21.0",
78
77
  "typescript": "^5.9.3",
79
- "typescript-eslint": "^8.49.0",
80
- "vitest": "^4.0.15"
78
+ "typescript-eslint": "^8.54.0",
79
+ "vitest": "^4.0.18"
81
80
  }
82
81
  }
@@ -1,202 +0,0 @@
1
- import type { HSL } from './hsl.js';
2
- import type { HSV } from './hsv.js';
3
- import type { RGB } from './rgb.js';
4
-
5
- /**
6
- * The abstract `Color` class provides a blueprint for color manipulation and conversion.
7
- * It includes methods for converting between different color models ({@link HSL}, {@link HSV}, {@link RGB}),
8
- * as well as various color transformations such as inversion, rotation, saturation, and blending.
9
- *
10
- * @abstract
11
- */
12
- /**
13
- * Abstract class representing a color.
14
- */
15
- export abstract class Color {
16
- /**
17
- * Parses a color from a string or another Color instance.
18
- * @param input - The input color as a string or Color instance.
19
- * @returns The parsed Color instance.
20
- */
21
- static parse: (input: Color | string) => Color;
22
-
23
- /**
24
- * The HSL color model.
25
- */
26
- static HSL: typeof HSL;
27
-
28
- /**
29
- * The HSV color model.
30
- */
31
- static HSV: typeof HSV;
32
-
33
- /**
34
- * The RGB color model.
35
- */
36
- static RGB: typeof RGB;
37
-
38
- /**
39
- * Creates a clone of the current color instance.
40
- * @returns A new Color instance that is a clone of the current instance.
41
- */
42
- abstract clone(): Color;
43
-
44
- /**
45
- * Converts the color to a hexadecimal string.
46
- * @returns The hexadecimal representation of the color.
47
- */
48
- asHex(): string {
49
- return this.asRGB().asHex();
50
- }
51
-
52
- /**
53
- * Converts the color to a string representation.
54
- * @returns The string representation of the color.
55
- */
56
- abstract asString(): string;
57
-
58
- /**
59
- * Rounds the color values.
60
- * @returns A new Color instance with rounded values.
61
- */
62
- abstract round(): Color;
63
-
64
- /**
65
- * Converts the color to an array of numbers.
66
- * @returns An array representing the color.
67
- */
68
- abstract asArray(): number[];
69
-
70
- /**
71
- * Converts the color to the HSL color model.
72
- * @returns The HSL representation of the color.
73
- */
74
- abstract asHSL(): HSL;
75
-
76
- /**
77
- * Converts the color to the HSV color model.
78
- * @returns The HSV representation of the color.
79
- */
80
- abstract asHSV(): HSV;
81
-
82
- /**
83
- * Converts the color to the RGB color model.
84
- * @returns The RGB representation of the color.
85
- */
86
- abstract asRGB(): RGB;
87
-
88
- /**
89
- * Inverts the luminosity of the color.
90
- * @returns A new HSL color with inverted luminosity.
91
- */
92
- invertLuminosity(): HSL {
93
- return this.asHSL().invertLuminosity();
94
- }
95
-
96
- /**
97
- * Rotates the hue of the color by a given offset.
98
- * @param offset - The amount to rotate the hue.
99
- * @returns A new HSL color with the hue rotated.
100
- */
101
- rotateHue(offset: number): HSL {
102
- return this.asHSL().rotateHue(offset);
103
- }
104
-
105
- /**
106
- * Saturates the color by a given ratio.
107
- * @param ratio - The ratio to saturate the color.
108
- * @returns A new HSL color with increased saturation.
109
- */
110
- saturate(ratio: number): HSL {
111
- return this.asHSL().saturate(ratio);
112
- }
113
-
114
- /**
115
- * Applies gamma correction to the color.
116
- * @param value - The gamma correction value.
117
- * @returns A new RGB color with gamma correction applied.
118
- */
119
- gamma(value: number): RGB {
120
- return this.asRGB().gamma(value);
121
- }
122
-
123
- /**
124
- * Inverts the color.
125
- * @returns A new RGB color with inverted values.
126
- */
127
- invert(): RGB {
128
- return this.asRGB().invert();
129
- }
130
-
131
- /**
132
- * Adjusts the contrast of the color.
133
- * @param value - The contrast adjustment value.
134
- * @returns A new RGB color with adjusted contrast.
135
- */
136
- contrast(value: number): RGB {
137
- return this.asRGB().contrast(value);
138
- }
139
-
140
- /**
141
- * Adjusts the brightness of the color.
142
- * @param value - The brightness adjustment value.
143
- * @returns A new RGB color with adjusted brightness.
144
- */
145
- brightness(value: number): RGB {
146
- return this.asRGB().brightness(value);
147
- }
148
-
149
- /**
150
- * Lightens the color by a given value.
151
- * @param value - The amount to lighten the color.
152
- * @returns A new RGB color that is lightened.
153
- */
154
- lighten(value: number): RGB {
155
- return this.asRGB().lighten(value);
156
- }
157
-
158
- /**
159
- * Darkens the color by a given value.
160
- * @param value - The amount to darken the color.
161
- * @returns A new RGB color that is darkened.
162
- */
163
- darken(value: number): RGB {
164
- return this.asRGB().darken(value);
165
- }
166
-
167
- /**
168
- * Tints the color by blending it with another color.
169
- * @param value - The blend ratio.
170
- * @param tintColor - The color to blend with.
171
- * @returns A new RGB color that is tinted.
172
- */
173
- tint(value: number, tintColor: Color): RGB {
174
- return this.asRGB().tint(value, tintColor);
175
- }
176
-
177
- /**
178
- * Blends the color with another color.
179
- * @param value - The blend ratio.
180
- * @param blendColor - The color to blend with.
181
- * @returns A new RGB color that is blended.
182
- */
183
- blend(value: number, blendColor: Color): RGB {
184
- return this.asRGB().blend(value, blendColor);
185
- }
186
-
187
- /**
188
- * Sets the hue of the color.
189
- * @param value - The new hue value.
190
- * @returns A new HSV color with the hue set.
191
- */
192
- setHue(value: number): HSV {
193
- return this.asHSV().setHue(value);
194
- }
195
-
196
- /**
197
- * Fades the color by a given value.
198
- * @param value - The fade value.
199
- * @returns A new Color instance that is faded.
200
- */
201
- abstract fade(value: number): Color;
202
- }
@@ -1,177 +0,0 @@
1
- import { describe, expect, it, beforeEach } from 'vitest';
2
- import { HSL } from './hsl.js';
3
- import { HSV } from './hsv.js';
4
- import { RGB } from './rgb.js';
5
-
6
- describe('HSL Class', () => {
7
- describe('constructor', () => {
8
- it('should initialize small HSL values correctly', () => {
9
- const color = new HSL(10, 20, 30, 0.4);
10
- expect(color.asArray()).toStrictEqual([10, 20, 30, 0.4]);
11
- });
12
-
13
- it('should initialize big HSL values correctly', () => {
14
- const color = new HSL(400, 120, 120, 2);
15
- expect(color.asArray()).toStrictEqual([40, 100, 100, 1]);
16
- });
17
-
18
- it('should initialize small HSL values correctly', () => {
19
- const color = new HSL(-60, -10, -10, -1);
20
- expect(color.asArray()).toStrictEqual([300, 0, 0, 0]);
21
- });
22
- });
23
-
24
- it('clone should return a new HSL instance with identical values', () => {
25
- const color = new HSL(120, 50, 50, 0.5);
26
- const clone = color.clone();
27
- expect(clone).toBeInstanceOf(HSL);
28
- expect(clone).toEqual(color);
29
- expect(clone).not.toBe(color);
30
- });
31
-
32
- describe('conversion', () => {
33
- it('asString should return correct HSL and HSLA strings', () => {
34
- const color1 = new HSL(120, 50, 50);
35
- expect(color1.asString()).toBe('hsl(120,50%,50%)');
36
-
37
- const color2 = new HSL(120, 50, 50, 0.5);
38
- expect(color2.asString()).toBe('hsla(120,50%,50%,0.5)');
39
- });
40
-
41
- it('asHSL and toHSL should return the same instance', () => {
42
- const color = new HSL(120, 50, 50);
43
- expect(color.asHSL()).toStrictEqual(color);
44
- expect(color.toHSL()).toStrictEqual(color);
45
- });
46
-
47
- it('asHSV should correctly convert HSL to HSV', () => {
48
- function check(input: [number, number, number], output: [number, number, number]) {
49
- const hsl = new HSL(...input);
50
- const hsv = hsl.asHSV();
51
- expect(hsv).toBeInstanceOf(HSV);
52
- expect(hsv.asArray().map(Math.round)).toStrictEqual([...output, 1]);
53
- }
54
-
55
- check([10, 0, 0], [10, 0, 0]);
56
- check([11, 0, 50], [11, 0, 50]);
57
- check([12, 0, 100], [12, 0, 100]);
58
- check([13, 50, 0], [13, 0, 0]);
59
- check([14, 50, 50], [14, 67, 75]);
60
- check([15, 50, 100], [15, 0, 100]);
61
- check([16, 100, 0], [16, 0, 0]);
62
- check([17, 100, 50], [17, 100, 100]);
63
- check([18, 100, 100], [18, 0, 100]);
64
- });
65
-
66
- it('asRGB should correctly convert HSL to RGB', () => {
67
- function check(input: [number, number, number], output: [number, number, number]) {
68
- const hsl = new HSL(...input);
69
- const rgb = hsl.asRGB();
70
- expect(rgb).toBeInstanceOf(RGB);
71
- expect(rgb.asArray().map(Math.round)).toStrictEqual([...output, 1]);
72
- }
73
-
74
- check([10, 0, 0], [0, 0, 0]);
75
- check([11, 0, 50], [128, 128, 128]);
76
- check([12, 0, 100], [255, 255, 255]);
77
- check([13, 50, 0], [0, 0, 0]);
78
- check([14, 50, 50], [191, 94, 64]);
79
- check([15, 50, 100], [255, 255, 255]);
80
- check([16, 100, 0], [0, 0, 0]);
81
- check([17, 100, 50], [255, 72, 0]);
82
- check([18, 100, 100], [255, 255, 255]);
83
- });
84
- });
85
-
86
- describe('should parse valid HSL and HSLA strings', () => {
87
- function check(str: string, result: number[]) {
88
- it(`parse "${str}"`, () => {
89
- const color = HSL.parse(str);
90
- expect(color).toBeInstanceOf(HSL);
91
- expect(color.asArray()).toStrictEqual(result);
92
- });
93
- }
94
-
95
- check('hsl(240,100%,50%)', [240, 100, 50, 1]);
96
- check('hsla(240,100%,50%,0.75)', [240, 100, 50, 0.75]);
97
- check('hsl(400,50%,50%)', [40, 50, 50, 1]);
98
-
99
- it('parse should throw an error for invalid strings', () => {
100
- expect(() => HSL.parse('invalid')).toThrow('Invalid HSL color string');
101
- });
102
- });
103
-
104
- describe('invertLuminosity', () => {
105
- let color: HSL;
106
- beforeEach(() => (color = new HSL(120, 50, 50, 0.8)));
107
-
108
- it('inverts luminosity correctly', () => {
109
- expect(color.invertLuminosity().asArray()).toStrictEqual([120, 50, 50, 0.8]); // Luminosity inverted to 50%
110
- });
111
-
112
- it('handles edge cases for luminosity inversion', () => {
113
- const black = new HSL(0, 0, 0, 1);
114
- expect(black.invertLuminosity().asArray()).toStrictEqual([0, 0, 100, 1]); // Black becomes white
115
-
116
- const white = new HSL(0, 0, 100, 1);
117
- expect(white.invertLuminosity().asArray()).toStrictEqual([0, 0, 0, 1]); // White becomes black
118
- });
119
- });
120
-
121
- describe('rotateHue', () => {
122
- let color: HSL;
123
- beforeEach(() => (color = new HSL(120, 50, 50, 0.8)));
124
-
125
- it('rotates hue correctly within the range of 0-360', () => {
126
- expect(color.rotateHue(180).asArray()).toStrictEqual([300, 50, 50, 0.8]); // Hue rotated by 180 degrees
127
- });
128
-
129
- it('handles negative rotation correctly', () => {
130
- expect(color.rotateHue(-270).asArray()).toStrictEqual([210, 50, 50, 0.8]); // Hue rotated negatively
131
- });
132
-
133
- it('handles rotations that exceed 360 degrees', () => {
134
- expect(color.rotateHue(540).asArray()).toStrictEqual([300, 50, 50, 0.8]); // Hue wrapped around to 300
135
- });
136
- });
137
-
138
- describe('saturate', () => {
139
- let color: HSL, grey: HSL;
140
- beforeEach(() => {
141
- color = new HSL(120, 50, 50, 0.8);
142
- grey = new HSL(120, 0, 50, 0.8);
143
- });
144
-
145
- it('increases saturation correctly', () => {
146
- expect(color.saturate(0.5).asArray()).toStrictEqual([120, 75, 50, 0.8]);
147
- expect(grey.saturate(0.5).asArray()).toStrictEqual([120, 0, 50, 0.8]);
148
- });
149
-
150
- it('decreases saturation correctly', () => {
151
- expect(color.saturate(-0.5).asArray()).toStrictEqual([120, 25, 50, 0.8]); // Saturation decreased by 50%
152
- });
153
-
154
- it('clamps saturation to the valid range', () => {
155
- expect(color.saturate(1.5).asArray()).toStrictEqual([120, 100, 50, 0.8]); // Saturation clamped to 100%
156
-
157
- expect(color.saturate(-2).asArray()).toStrictEqual([120, 0, 50, 0.8]); // Saturation clamped to 0%
158
- });
159
- });
160
-
161
- describe('fade', () => {
162
- let color: HSL;
163
- beforeEach(() => (color = new HSL(120, 50, 50, 0.8)));
164
-
165
- it('reduces alpha correctly', () => {
166
- expect(color.fade(0.5).asArray()).toStrictEqual([120, 50, 50, 0.4]); // Alpha reduced by 50%
167
- });
168
-
169
- it('handles edge cases for fading', () => {
170
- const opaque = new HSL(0, 50, 50, 1);
171
- expect(opaque.fade(1).asArray()).toStrictEqual([0, 50, 50, 0]); // Fully faded to transparent
172
-
173
- const transparent = new HSL(0, 50, 50, 0);
174
- expect(transparent.fade(0.5).asArray()).toStrictEqual([0, 50, 50, 0]); // Remains fully transparent
175
- });
176
- });
177
- });
package/src/color/hsl.ts DELETED
@@ -1,201 +0,0 @@
1
- import { Color } from './abstract.js';
2
- import { HSV } from './hsv.js';
3
- import { RGB } from './rgb.js';
4
- import { clamp, formatFloat, mod } from './utils.js';
5
-
6
- /**
7
- * Represents a color in the HSL (Hue, Saturation, Lightness) color space.
8
- * Extends the base `Color` class.
9
- */
10
- export class HSL extends Color {
11
- /**
12
- * The hue component of the color, in the range [0, 360].
13
- */
14
- readonly h: number;
15
-
16
- /**
17
- * The saturation component of the color, in the range [0, 100].
18
- */
19
- readonly s: number;
20
-
21
- /**
22
- * The lightness component of the color, in the range [0, 100].
23
- */
24
- readonly l: number;
25
-
26
- /**
27
- * The alpha (opacity) component of the color, in the range [0, 1].
28
- */
29
- readonly a: number;
30
-
31
- /**
32
- * Creates a new HSL color.
33
- * @param h - The hue component, in the range [0, 360].
34
- * @param s - The saturation component, in the range [0, 100].
35
- * @param l - The lightness component, in the range [0, 100].
36
- * @param a - The alpha (opacity) component, in the range [0, 1]. Defaults to 1.
37
- */
38
- constructor(h: number, s: number, l: number, a: number = 1) {
39
- super();
40
- this.h = mod(h, 360);
41
- this.s = clamp(s, 0, 100);
42
- this.l = clamp(l, 0, 100);
43
- this.a = clamp(a, 0, 1);
44
- }
45
-
46
- /**
47
- * Returns the HSL color as an array of numbers.
48
- * @returns An array containing the hue, saturation, lightness, and alpha components.
49
- */
50
- asArray(): [number, number, number, number] {
51
- return [this.h, this.s, this.l, this.a];
52
- }
53
-
54
- /**
55
- * Returns a new HSL color with rounded components.
56
- * @returns A new HSL color with rounded hue, saturation, lightness, and alpha components.
57
- */
58
- round(): HSL {
59
- return new HSL(Math.round(this.h), Math.round(this.s), Math.round(this.l), Math.round(this.a * 1000) / 1000);
60
- }
61
-
62
- /**
63
- * Creates a copy of the current HSL color.
64
- * @returns A new HSL color with the same components as the current color.
65
- */
66
- clone(): HSL {
67
- return new HSL(this.h, this.s, this.l, this.a);
68
- }
69
-
70
- /**
71
- * Returns the HSL color as a CSS-compatible string.
72
- * @returns A string representing the HSL color in CSS format.
73
- */
74
- asString(): string {
75
- if (this.a === 1) {
76
- return `hsl(${this.h.toFixed(0)},${this.s.toFixed(0)}%,${this.l.toFixed(0)}%)`;
77
- } else {
78
- return `hsla(${this.h.toFixed(0)},${this.s.toFixed(0)}%,${this.l.toFixed(0)}%,${formatFloat(this.a, 3)})`;
79
- }
80
- }
81
-
82
- /**
83
- * Returns the current HSL color.
84
- * @returns The current HSL color.
85
- */
86
- asHSL(): HSL {
87
- return this.clone();
88
- }
89
-
90
- /**
91
- * Returns the current HSL color.
92
- * @returns The current HSL color.
93
- */
94
- toHSL(): HSL {
95
- return this;
96
- }
97
-
98
- /**
99
- * Converts the HSL color to an HSV color.
100
- * @returns A new HSV color representing the same color.
101
- */
102
- asHSV(): HSV {
103
- const s = this.s / 100,
104
- l = this.l / 100;
105
- const v = l + s * Math.min(l, 1 - l);
106
- const sv = v === 0 ? 0 : 2 * (1 - l / v);
107
- return new HSV(this.h, sv * 100, v * 100, this.a);
108
- }
109
-
110
- /**
111
- * Converts the HSL color to an RGB color.
112
- * @returns A new RGB color representing the same color.
113
- */
114
- asRGB(): RGB {
115
- const h = this.h / 360;
116
- const s = this.s / 100;
117
- const l = this.l / 100;
118
-
119
- // Achromatic (grey)
120
- if (s === 0) return new RGB(l * 255, l * 255, l * 255, this.a);
121
-
122
- const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
123
- const p = 2 * l - q;
124
-
125
- const hueToRgb = (t: number): number => {
126
- if (t < 0) t += 1;
127
- if (t > 1) t -= 1;
128
- if (t < 1 / 6) return p + (q - p) * 6 * t;
129
- if (t < 1 / 2) return q;
130
- if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
131
- return p;
132
- };
133
-
134
- // Convert to RGB in the 0-255 range and return
135
- return new RGB(255 * hueToRgb(h + 1 / 3), 255 * hueToRgb(h), 255 * hueToRgb(h - 1 / 3), this.a);
136
- }
137
-
138
- /**
139
- * Parses a string or Color object into an HSL color.
140
- * @param input - The input string or Color object to parse.
141
- * @returns A new HSL color parsed from the input.
142
- * @throws Will throw an error if the input string is not a valid HSL color string.
143
- */
144
- static parse(input: string | Color): HSL {
145
- if (input instanceof Color) return input.asHSL();
146
-
147
- input = input.replace(/\s+/g, '').toLowerCase();
148
-
149
- let match = input.match(/^hsl\((?<h>[-+0-9.]+)(?:deg)?,(?<s>[-+0-9.]+)%,(?<l>[-+0-9.]+)%\)$/);
150
- if (match) {
151
- return new HSL(parseFloat(match.groups!.h), parseFloat(match.groups!.s), parseFloat(match.groups!.l));
152
- }
153
-
154
- match = input.match(/^hsla\((?<h>[-+0-9.]+)(?:deg)?,(?<s>[-+0-9.]+)%,(?<l>[-+0-9.]+)%,(?<a>[-+0-9.]+)\)$/);
155
- if (match) {
156
- return new HSL(
157
- parseFloat(match.groups!.h),
158
- parseFloat(match.groups!.s),
159
- parseFloat(match.groups!.l),
160
- parseFloat(match.groups!.a)
161
- );
162
- }
163
-
164
- throw new Error(`Invalid HSL color string: "${input}"`);
165
- }
166
-
167
- /**
168
- * Inverts the lightness component of the HSL color.
169
- * @returns A new HSL color with the lightness component inverted.
170
- */
171
- invertLuminosity(): HSL {
172
- return new HSL(this.h, this.s, 100 - this.l, this.a);
173
- }
174
-
175
- /**
176
- * Rotates the hue component of the HSL color by a given offset.
177
- * @param offset - The amount to rotate the hue by, in degrees.
178
- * @returns A new HSL color with the hue rotated by the given offset.
179
- */
180
- rotateHue(offset: number): HSL {
181
- return new HSL(mod(this.h + offset, 360), this.s, this.l, this.a);
182
- }
183
-
184
- /**
185
- * Increases the saturation of the HSL color by a given ratio.
186
- * @param ratio - The ratio by which to increase the saturation.
187
- * @returns A new HSL color with increased saturation.
188
- */
189
- saturate(ratio: number): HSL {
190
- return new HSL(this.h, clamp(this.s * (1 + ratio), 0, 100), this.l, this.a);
191
- }
192
-
193
- /**
194
- * Decreases the alpha (opacity) of the HSL color by a given value.
195
- * @param value - The value by which to decrease the alpha.
196
- * @returns A new HSL color with decreased alpha.
197
- */
198
- fade(value: number): HSL {
199
- return new HSL(this.h, this.s, this.l, this.a * (1 - value));
200
- }
201
- }