@electrovir/color 1.0.0 → 1.2.0
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/color-class/color-formats.d.ts +51 -21
- package/dist/color-class/color-formats.js +66 -7
- package/dist/color-class/color.d.ts +18 -7
- package/dist/color-class/color.js +41 -26
- package/dist/elements/vir-all-color-space-sliders.element.d.ts +11 -0
- package/dist/elements/vir-all-color-space-sliders.element.js +52 -0
- package/dist/elements/vir-color-format-sliders.element.d.ts +13 -0
- package/dist/elements/vir-color-format-sliders.element.js +54 -0
- package/dist/elements/vir-color-slider.element.d.ts +14 -0
- package/dist/elements/vir-color-slider.element.js +101 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/package.json +3 -2
|
@@ -28,16 +28,6 @@ export type ColorCoordinateDefinition = {
|
|
|
28
28
|
factor?: number | undefined;
|
|
29
29
|
suffix?: string;
|
|
30
30
|
}>;
|
|
31
|
-
/**
|
|
32
|
-
* A single color format definition.
|
|
33
|
-
*
|
|
34
|
-
* @category Internal
|
|
35
|
-
*/
|
|
36
|
-
export type ColorFormatDefinition<ColorSpace extends string = string> = {
|
|
37
|
-
coords: Record<string, ColorCoordinateDefinition>;
|
|
38
|
-
/** This name for this color to be used in `Colorjs.to()`. Defaults to the color format key. */
|
|
39
|
-
colorSpace: ColorSpace;
|
|
40
|
-
};
|
|
41
31
|
/**
|
|
42
32
|
* All raw supported color formats.
|
|
43
33
|
*
|
|
@@ -184,15 +174,35 @@ export declare const rawColorFormats: {
|
|
|
184
174
|
};
|
|
185
175
|
};
|
|
186
176
|
/**
|
|
187
|
-
* All supported color format names.
|
|
177
|
+
* All supported color format names.
|
|
178
|
+
*
|
|
179
|
+
* @category Internal
|
|
180
|
+
* @enum
|
|
181
|
+
*/
|
|
182
|
+
export declare const ColorFormatName: { [Key in ColorFormatName]: Key; };
|
|
183
|
+
/**
|
|
184
|
+
* {@link ColorFormatName} combined with hex and named CSS color representation.
|
|
188
185
|
*
|
|
189
186
|
* @category Internal
|
|
187
|
+
* @enum
|
|
190
188
|
*/
|
|
191
|
-
export declare const
|
|
189
|
+
export declare const ColorSyntaxName: {
|
|
190
|
+
readonly hex: "hex";
|
|
191
|
+
readonly name: "name";
|
|
192
|
+
readonly rgb: "rgb";
|
|
193
|
+
readonly hsl: "hsl";
|
|
194
|
+
readonly hwb: "hwb";
|
|
195
|
+
readonly lab: "lab";
|
|
196
|
+
readonly lch: "lch";
|
|
197
|
+
readonly oklab: "oklab";
|
|
198
|
+
readonly oklch: "oklch";
|
|
199
|
+
};
|
|
200
|
+
export type ColorSyntaxName = Values<typeof ColorSyntaxName>;
|
|
192
201
|
/**
|
|
193
|
-
* All supported color format names.
|
|
202
|
+
* All supported color format names.
|
|
194
203
|
*
|
|
195
204
|
* @category Internal
|
|
205
|
+
* @enum
|
|
196
206
|
*/
|
|
197
207
|
export type ColorFormatName = keyof typeof rawColorFormats;
|
|
198
208
|
/**
|
|
@@ -210,9 +220,9 @@ export type ColorCoordsByFormat = {
|
|
|
210
220
|
* @category Internal
|
|
211
221
|
*/
|
|
212
222
|
export type ColorFormats = Readonly<{
|
|
213
|
-
[FormatName in ColorFormatName]: ColorFormatDefinition<
|
|
223
|
+
[FormatName in ColorFormatName]: ColorFormatDefinition<Extract<(typeof rawColorFormats)[FormatName], {
|
|
214
224
|
colorSpace: any;
|
|
215
|
-
}>['colorSpace']
|
|
225
|
+
}>['colorSpace'], FormatName>;
|
|
216
226
|
}>;
|
|
217
227
|
/**
|
|
218
228
|
* All supported color formats.
|
|
@@ -221,17 +231,25 @@ export type ColorFormats = Readonly<{
|
|
|
221
231
|
*/
|
|
222
232
|
export declare const colorFormats: ColorFormats;
|
|
223
233
|
/**
|
|
224
|
-
* All
|
|
234
|
+
* All supported color space names.
|
|
225
235
|
*
|
|
226
236
|
* @category Internal
|
|
237
|
+
* @enum
|
|
227
238
|
*/
|
|
228
239
|
export type ColorSpaceName = Values<typeof rawColorFormats>['colorSpace'];
|
|
240
|
+
/**
|
|
241
|
+
* All supported color space names.
|
|
242
|
+
*
|
|
243
|
+
* @category Internal
|
|
244
|
+
* @enum
|
|
245
|
+
*/
|
|
246
|
+
export declare const ColorSpaceName: { [Key in ColorSpaceName]: Key; };
|
|
229
247
|
/**
|
|
230
248
|
* All value types for all supported color formats.
|
|
231
249
|
*
|
|
232
250
|
* @category Internal
|
|
233
251
|
*/
|
|
234
|
-
export type
|
|
252
|
+
export type ColorValue = {
|
|
235
253
|
[FormatName in ColorFormatName]: Record<keyof (typeof rawColorFormats)[FormatName]['coords'], number>;
|
|
236
254
|
};
|
|
237
255
|
/**
|
|
@@ -239,16 +257,28 @@ export type ColorValues = {
|
|
|
239
257
|
*
|
|
240
258
|
* @category Color Format
|
|
241
259
|
*/
|
|
242
|
-
export declare const
|
|
260
|
+
export declare const colorFormatsBySpace: { [ColorSpace in ColorSpaceName]: { [ColorFormat in ColorFormatName]: ColorFormatDefinition<ColorSpace, ColorFormat>; }; };
|
|
243
261
|
/**
|
|
244
|
-
*
|
|
262
|
+
* Determines the color syntax / format in use based on the given CSS color string.
|
|
245
263
|
*
|
|
246
|
-
* @category
|
|
264
|
+
* @category Util
|
|
247
265
|
*/
|
|
248
|
-
export declare
|
|
266
|
+
export declare function getColorSyntaxFromCssString(cssString: string): ColorSyntaxName;
|
|
249
267
|
/**
|
|
250
268
|
* All possible coordinate names for all supported color formats in a union.
|
|
251
269
|
*
|
|
252
270
|
* @category Internal
|
|
253
271
|
*/
|
|
254
272
|
export type ColorCoordinateName = keyof UnionToIntersection<Values<typeof rawColorFormats>['coords']>;
|
|
273
|
+
/**
|
|
274
|
+
* A single color format definition.
|
|
275
|
+
*
|
|
276
|
+
* @category Internal
|
|
277
|
+
*/
|
|
278
|
+
export type ColorFormatDefinition<ColorSpace extends ColorSpaceName = any, ColorFormat extends ColorFormatName = any> = {
|
|
279
|
+
/** Which exact color coordinates exist in here depends on the set color space. */
|
|
280
|
+
coords: Record<ColorCoordsByFormat[ColorFormat], ColorCoordinateDefinition>;
|
|
281
|
+
/** This name for this color to be used in `Colorjs.to()`. Defaults to the color format key. */
|
|
282
|
+
colorSpace: ColorSpace;
|
|
283
|
+
colorFormat: ColorFormat;
|
|
284
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getObjectTypedEntries,
|
|
1
|
+
import { arrayToObject, getObjectTypedEntries, getObjectTypedValues, getOrSet, mapObjectValues, } from '@augment-vir/common';
|
|
2
2
|
/**
|
|
3
3
|
* All raw supported color formats.
|
|
4
4
|
*
|
|
@@ -145,31 +145,90 @@ export const rawColorFormats = {
|
|
|
145
145
|
},
|
|
146
146
|
};
|
|
147
147
|
/**
|
|
148
|
-
* All supported color format names.
|
|
148
|
+
* All supported color format names.
|
|
149
149
|
*
|
|
150
150
|
* @category Internal
|
|
151
|
+
* @enum
|
|
151
152
|
*/
|
|
152
153
|
export const ColorFormatName = mapObjectValues(rawColorFormats, (colorName) => colorName);
|
|
154
|
+
/**
|
|
155
|
+
* {@link ColorFormatName} combined with hex and named CSS color representation.
|
|
156
|
+
*
|
|
157
|
+
* @category Internal
|
|
158
|
+
* @enum
|
|
159
|
+
*/
|
|
160
|
+
export const ColorSyntaxName = {
|
|
161
|
+
...ColorFormatName,
|
|
162
|
+
hex: 'hex',
|
|
163
|
+
name: 'name',
|
|
164
|
+
};
|
|
153
165
|
/**
|
|
154
166
|
* All supported color formats.
|
|
155
167
|
*
|
|
156
168
|
* @category Color Format
|
|
157
169
|
*/
|
|
158
|
-
export const colorFormats = rawColorFormats
|
|
170
|
+
export const colorFormats = mapObjectValues(rawColorFormats, (colorFormatName, colorFormatValue) => {
|
|
171
|
+
return {
|
|
172
|
+
...colorFormatValue,
|
|
173
|
+
colorFormat: colorFormatName,
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
/**
|
|
177
|
+
* All supported color space names.
|
|
178
|
+
*
|
|
179
|
+
* @category Internal
|
|
180
|
+
* @enum
|
|
181
|
+
*/
|
|
182
|
+
export const ColorSpaceName = arrayToObject(getObjectTypedValues(rawColorFormats), (format) => {
|
|
183
|
+
return {
|
|
184
|
+
key: format.colorSpace,
|
|
185
|
+
value: format.colorSpace,
|
|
186
|
+
};
|
|
187
|
+
}, {
|
|
188
|
+
useRequired: true,
|
|
189
|
+
});
|
|
159
190
|
/**
|
|
160
191
|
* All color formats grouped by their color space.
|
|
161
192
|
*
|
|
162
193
|
* @category Color Format
|
|
163
194
|
*/
|
|
164
|
-
export const
|
|
195
|
+
export const colorFormatsBySpace = getObjectTypedEntries(colorFormats).reduce((accum, [colorFormatName, colorFormatDefinition,]) => {
|
|
165
196
|
getOrSet(accum, colorFormatDefinition.colorSpace, () => {
|
|
166
197
|
return {};
|
|
167
198
|
})[colorFormatName] = colorFormatDefinition;
|
|
168
199
|
return accum;
|
|
169
200
|
}, {});
|
|
170
201
|
/**
|
|
171
|
-
*
|
|
202
|
+
* Determines the color syntax / format in use based on the given CSS color string.
|
|
172
203
|
*
|
|
173
|
-
* @category
|
|
204
|
+
* @category Util
|
|
174
205
|
*/
|
|
175
|
-
export
|
|
206
|
+
export function getColorSyntaxFromCssString(cssString) {
|
|
207
|
+
if (cssString.startsWith('rgb')) {
|
|
208
|
+
return ColorSyntaxName.rgb;
|
|
209
|
+
}
|
|
210
|
+
else if (cssString.startsWith('hsl')) {
|
|
211
|
+
return ColorSyntaxName.hsl;
|
|
212
|
+
}
|
|
213
|
+
else if (cssString.startsWith('hwb')) {
|
|
214
|
+
return ColorSyntaxName.hwb;
|
|
215
|
+
}
|
|
216
|
+
else if (cssString.startsWith('oklab')) {
|
|
217
|
+
return ColorSyntaxName.oklab;
|
|
218
|
+
}
|
|
219
|
+
else if (cssString.startsWith('oklch')) {
|
|
220
|
+
return ColorSyntaxName.oklch;
|
|
221
|
+
}
|
|
222
|
+
else if (cssString.startsWith('lab')) {
|
|
223
|
+
return ColorSyntaxName.lab;
|
|
224
|
+
}
|
|
225
|
+
else if (cssString.startsWith('lch')) {
|
|
226
|
+
return ColorSyntaxName.lch;
|
|
227
|
+
}
|
|
228
|
+
else if (cssString.startsWith('#')) {
|
|
229
|
+
return ColorSyntaxName.hex;
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
return ColorSyntaxName.name;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type PartialWithUndefined } from '@augment-vir/common';
|
|
2
2
|
import { type RequireExactlyOne } from 'type-fest';
|
|
3
|
-
import {
|
|
3
|
+
import { ColorFormatName, ColorSyntaxName, type ColorCoordsByFormat, type ColorValue, type HexColor } from './color-formats.js';
|
|
4
4
|
/**
|
|
5
5
|
* An update to an existing {@link Color} instance. Used in {@link Color.set}.
|
|
6
6
|
*
|
|
@@ -9,8 +9,8 @@ import { type ColorCoordsByFormat, type ColorFormatName, type ColorValues, type
|
|
|
9
9
|
export type ColorUpdate = RequireExactlyOne<{
|
|
10
10
|
[FormatName in ColorFormatName]: PartialWithUndefined<Record<ColorCoordsByFormat[FormatName], number>>;
|
|
11
11
|
} & {
|
|
12
|
-
hex: HexColor;
|
|
13
|
-
name: string;
|
|
12
|
+
[ColorSyntaxName.hex]: HexColor;
|
|
13
|
+
[ColorSyntaxName.name]: string;
|
|
14
14
|
}>;
|
|
15
15
|
/**
|
|
16
16
|
* The values of all supported color formats for a given {@link Color} instance. Accessed via
|
|
@@ -18,8 +18,9 @@ export type ColorUpdate = RequireExactlyOne<{
|
|
|
18
18
|
*
|
|
19
19
|
* @category Internal
|
|
20
20
|
*/
|
|
21
|
-
export type AllColorsValues =
|
|
22
|
-
hex: HexColor;
|
|
21
|
+
export type AllColorsValues = ColorValue & {
|
|
22
|
+
[ColorSyntaxName.hex]: HexColor;
|
|
23
|
+
[ColorSyntaxName.name]: string;
|
|
23
24
|
names: string[];
|
|
24
25
|
};
|
|
25
26
|
/**
|
|
@@ -46,6 +47,7 @@ export declare class Color {
|
|
|
46
47
|
/** All current color values. These are updated whenever {@link Color.set} is called. */
|
|
47
48
|
protected readonly _allColors: {
|
|
48
49
|
names: string[];
|
|
50
|
+
name: string;
|
|
49
51
|
hex: HexColor;
|
|
50
52
|
rgb: {
|
|
51
53
|
r: number;
|
|
@@ -112,18 +114,27 @@ export declare class Color {
|
|
|
112
114
|
/**
|
|
113
115
|
* Converts the values for each supported color format into a padded string for easy display
|
|
114
116
|
* purposes.
|
|
117
|
+
*
|
|
118
|
+
* @see `.toCss()`
|
|
115
119
|
*/
|
|
116
|
-
toFormattedStrings(): Record<
|
|
120
|
+
toFormattedStrings(): Record<ColorSyntaxName | 'names', string>;
|
|
117
121
|
/**
|
|
118
122
|
* Converts the values for each supported color format in a CSS string that can be directly used
|
|
119
123
|
* in any modern CSS code.
|
|
124
|
+
*
|
|
125
|
+
* @see `.toFormattedStrings()`
|
|
120
126
|
*/
|
|
121
|
-
toCss(): Record<
|
|
127
|
+
toCss(): Record<ColorSyntaxName, string>;
|
|
122
128
|
/**
|
|
123
129
|
* The current color expressed as hardcoded CSS color keywords. If no CSS color keywords match
|
|
124
130
|
* the current color, this array will be empty.
|
|
125
131
|
*/
|
|
126
132
|
get names(): string[];
|
|
133
|
+
/**
|
|
134
|
+
* The current color expressed as a single CSS color name string. If there is no color name that
|
|
135
|
+
* matches the current color, this will be an empty string.
|
|
136
|
+
*/
|
|
137
|
+
get name(): string;
|
|
127
138
|
/** The current color expressed as an RGB hex string. */
|
|
128
139
|
get hex(): HexColor;
|
|
129
140
|
/** The current color expressed as its RGB coordinate values. */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { assert, assertWrap, check } from '@augment-vir/assert';
|
|
2
|
-
import { copyThroughJson, filterMap, getObjectTypedEntries, joinWithFinalConjunction, mapObjectValues, round, } from '@augment-vir/common';
|
|
2
|
+
import { copyThroughJson, filterMap, getEnumValues, getObjectTypedEntries, getObjectTypedKeys, joinWithFinalConjunction, mapObjectValues, round, } from '@augment-vir/common';
|
|
3
3
|
import colorNames from 'color-name';
|
|
4
4
|
import { clampGamut, converter, formatHex, parse } from 'culori';
|
|
5
|
-
import {
|
|
5
|
+
import { ColorFormatName, colorFormats, ColorSyntaxName, } from './color-formats.js';
|
|
6
6
|
import { maxColorNameLength } from './color-name-length.js';
|
|
7
7
|
/**
|
|
8
8
|
* A `Color` class with state and the following features:
|
|
@@ -37,38 +37,39 @@ export class Color {
|
|
|
37
37
|
/** All current color values. These are updated whenever {@link Color.set} is called. */
|
|
38
38
|
_allColors = {
|
|
39
39
|
names: ['black'],
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
[ColorSyntaxName.name]: 'black',
|
|
41
|
+
[ColorSyntaxName.hex]: '#000000',
|
|
42
|
+
[ColorSyntaxName.rgb]: {
|
|
42
43
|
r: 0,
|
|
43
44
|
g: 0,
|
|
44
45
|
b: 0,
|
|
45
46
|
},
|
|
46
|
-
hsl: {
|
|
47
|
+
[ColorSyntaxName.hsl]: {
|
|
47
48
|
h: 0,
|
|
48
49
|
s: 0,
|
|
49
50
|
l: 0,
|
|
50
51
|
},
|
|
51
|
-
hwb: {
|
|
52
|
+
[ColorSyntaxName.hwb]: {
|
|
52
53
|
h: 0,
|
|
53
54
|
w: 0,
|
|
54
55
|
b: 0,
|
|
55
56
|
},
|
|
56
|
-
lab: {
|
|
57
|
+
[ColorSyntaxName.lab]: {
|
|
57
58
|
l: 0,
|
|
58
59
|
a: 0,
|
|
59
60
|
b: 0,
|
|
60
61
|
},
|
|
61
|
-
lch: {
|
|
62
|
+
[ColorSyntaxName.lch]: {
|
|
62
63
|
l: 0,
|
|
63
64
|
c: 0,
|
|
64
65
|
h: 0,
|
|
65
66
|
},
|
|
66
|
-
oklab: {
|
|
67
|
+
[ColorSyntaxName.oklab]: {
|
|
67
68
|
l: 0,
|
|
68
69
|
a: 0,
|
|
69
70
|
b: 0,
|
|
70
71
|
},
|
|
71
|
-
oklch: {
|
|
72
|
+
[ColorSyntaxName.oklch]: {
|
|
72
73
|
l: 0,
|
|
73
74
|
c: 0,
|
|
74
75
|
h: 0,
|
|
@@ -109,7 +110,7 @@ export class Color {
|
|
|
109
110
|
const colorFormatDefinition = colorFormats[colorFormatName];
|
|
110
111
|
const orderedColorCoords = Object.values(mapObjectValues(colorFormatDefinition.coords, (coordName) => {
|
|
111
112
|
const coordValue = colorValues[coordName];
|
|
112
|
-
const coordDefinition = assertWrap.
|
|
113
|
+
const coordDefinition = colorFormatDefinition.coords[assertWrap.isKeyOf(coordName, colorFormatDefinition.coords)];
|
|
113
114
|
const rawCoordValue = coordValue != undefined &&
|
|
114
115
|
coordValue >= coordDefinition.min &&
|
|
115
116
|
coordValue <= coordDefinition.max
|
|
@@ -125,7 +126,7 @@ export class Color {
|
|
|
125
126
|
* internal color object.
|
|
126
127
|
*/
|
|
127
128
|
pullFromInternalColor() {
|
|
128
|
-
|
|
129
|
+
getEnumValues(ColorFormatName).forEach((colorFormatName) => {
|
|
129
130
|
const colorFormatDefinition = colorFormats[colorFormatName];
|
|
130
131
|
const originalColorDefinition = check.isKeyOf(this.#internalColor.mode, colorFormats)
|
|
131
132
|
? colorFormats[this.#internalColor.mode]
|
|
@@ -137,17 +138,19 @@ export class Color {
|
|
|
137
138
|
if (!converted) {
|
|
138
139
|
assert.never(`Failed to convert color '${JSON.stringify(this.#internalColor)}' to '${colorFormatName}'.`);
|
|
139
140
|
}
|
|
140
|
-
|
|
141
|
+
getObjectTypedKeys(this[colorFormatName]).forEach((coordName) => {
|
|
141
142
|
const coordValue = converted[coordName];
|
|
143
|
+
const coordinateDefinition = colorFormatDefinition.coords[assertWrap.isKeyOf(coordName, colorFormatDefinition.coords)];
|
|
142
144
|
if (coordValue != undefined) {
|
|
143
|
-
this._allColors[colorFormatName][coordName] = round((coordValue || 0) * (
|
|
144
|
-
digits:
|
|
145
|
+
this._allColors[colorFormatName][coordName] = round((coordValue || 0) * (coordinateDefinition.factor || 1), {
|
|
146
|
+
digits: coordinateDefinition.digits || 0,
|
|
145
147
|
});
|
|
146
148
|
}
|
|
147
149
|
});
|
|
148
150
|
});
|
|
149
|
-
this._allColors.hex = formatHex(this.#internalColor);
|
|
151
|
+
this._allColors[ColorSyntaxName.hex] = formatHex(this.#internalColor);
|
|
150
152
|
this._allColors.names = findMatchingColorNames(this.rgb);
|
|
153
|
+
this._allColors[ColorSyntaxName.name] = this._allColors.names[0] || '';
|
|
151
154
|
}
|
|
152
155
|
/**
|
|
153
156
|
* Create a string that can be serialized into a new {@link Color} instance which will exactly
|
|
@@ -163,6 +166,8 @@ export class Color {
|
|
|
163
166
|
/**
|
|
164
167
|
* Converts the values for each supported color format into a padded string for easy display
|
|
165
168
|
* purposes.
|
|
169
|
+
*
|
|
170
|
+
* @see `.toCss()`
|
|
166
171
|
*/
|
|
167
172
|
toFormattedStrings() {
|
|
168
173
|
const colorFormatStrings = mapObjectValues(colorFormats, (colorFormatName) => {
|
|
@@ -170,14 +175,17 @@ export class Color {
|
|
|
170
175
|
return coordValues.map((coordValue) => String(coordValue).padStart(6, ' ')).join(' ');
|
|
171
176
|
});
|
|
172
177
|
return {
|
|
173
|
-
hex: this.hex,
|
|
178
|
+
[ColorSyntaxName.hex]: this.hex,
|
|
174
179
|
...colorFormatStrings,
|
|
175
180
|
names: this.names.join(', ').padEnd(maxColorNameLength, ' '),
|
|
181
|
+
name: (this.names[0] || '').padEnd(maxColorNameLength, ' '),
|
|
176
182
|
};
|
|
177
183
|
}
|
|
178
184
|
/**
|
|
179
185
|
* Converts the values for each supported color format in a CSS string that can be directly used
|
|
180
186
|
* in any modern CSS code.
|
|
187
|
+
*
|
|
188
|
+
* @see `.toFormattedStrings()`
|
|
181
189
|
*/
|
|
182
190
|
toCss() {
|
|
183
191
|
const colorFormatStrings = mapObjectValues(colorFormats, (colorFormatName) => {
|
|
@@ -185,7 +193,7 @@ export class Color {
|
|
|
185
193
|
return `${colorFormatName}(${coordValues.join(' ')})`;
|
|
186
194
|
});
|
|
187
195
|
return {
|
|
188
|
-
hex: this.hex,
|
|
196
|
+
[ColorSyntaxName.hex]: this.hex,
|
|
189
197
|
...colorFormatStrings,
|
|
190
198
|
name: this.names[0] || '',
|
|
191
199
|
};
|
|
@@ -197,37 +205,44 @@ export class Color {
|
|
|
197
205
|
get names() {
|
|
198
206
|
return copyThroughJson(this._allColors.names);
|
|
199
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* The current color expressed as a single CSS color name string. If there is no color name that
|
|
210
|
+
* matches the current color, this will be an empty string.
|
|
211
|
+
*/
|
|
212
|
+
get name() {
|
|
213
|
+
return this._allColors.names[0] || '';
|
|
214
|
+
}
|
|
200
215
|
/** The current color expressed as an RGB hex string. */
|
|
201
216
|
get hex() {
|
|
202
|
-
return copyThroughJson(this._allColors.hex);
|
|
217
|
+
return copyThroughJson(this._allColors[ColorSyntaxName.hex]);
|
|
203
218
|
}
|
|
204
219
|
/** The current color expressed as its RGB coordinate values. */
|
|
205
220
|
get rgb() {
|
|
206
|
-
return copyThroughJson(this._allColors.rgb);
|
|
221
|
+
return copyThroughJson(this._allColors[ColorSyntaxName.rgb]);
|
|
207
222
|
}
|
|
208
223
|
/** The current color expressed as its HSL coordinate values. */
|
|
209
224
|
get hsl() {
|
|
210
|
-
return copyThroughJson(this._allColors.hsl);
|
|
225
|
+
return copyThroughJson(this._allColors[ColorSyntaxName.hsl]);
|
|
211
226
|
}
|
|
212
227
|
/** The current color expressed as its HWB coordinate values. */
|
|
213
228
|
get hwb() {
|
|
214
|
-
return copyThroughJson(this._allColors.hwb);
|
|
229
|
+
return copyThroughJson(this._allColors[ColorSyntaxName.hwb]);
|
|
215
230
|
}
|
|
216
231
|
/** The current color expressed as its LAB coordinate values. */
|
|
217
232
|
get lab() {
|
|
218
|
-
return copyThroughJson(this._allColors.lab);
|
|
233
|
+
return copyThroughJson(this._allColors[ColorSyntaxName.lab]);
|
|
219
234
|
}
|
|
220
235
|
/** The current color expressed as its LCH coordinate values. */
|
|
221
236
|
get lch() {
|
|
222
|
-
return copyThroughJson(this._allColors.lch);
|
|
237
|
+
return copyThroughJson(this._allColors[ColorSyntaxName.lch]);
|
|
223
238
|
}
|
|
224
239
|
/** The current color expressed as its Oklab coordinate values. */
|
|
225
240
|
get oklab() {
|
|
226
|
-
return copyThroughJson(this._allColors.oklab);
|
|
241
|
+
return copyThroughJson(this._allColors[ColorSyntaxName.oklab]);
|
|
227
242
|
}
|
|
228
243
|
/** The current color expressed as its Oklch coordinate values. */
|
|
229
244
|
get oklch() {
|
|
230
|
-
return copyThroughJson(this._allColors.oklch);
|
|
245
|
+
return copyThroughJson(this._allColors[ColorSyntaxName.oklch]);
|
|
231
246
|
}
|
|
232
247
|
}
|
|
233
248
|
function findMatchingColorNames(rgb) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Color } from '../color-class/color.js';
|
|
2
|
+
/**
|
|
3
|
+
* Color sliders for all color spaces.
|
|
4
|
+
*
|
|
5
|
+
* @category Elements
|
|
6
|
+
*/
|
|
7
|
+
export declare const VirAllColorSpaceSliders: import("element-vir").DeclarativeElementDefinition<"vir-all-color-space-sliders", {
|
|
8
|
+
color: Readonly<Color>;
|
|
9
|
+
}, {}, {
|
|
10
|
+
colorChange: import("element-vir").DefineEvent<string>;
|
|
11
|
+
}, "vir-all-color-space-sliders-", "vir-all-color-space-sliders-", readonly [], readonly []>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/* node:coverage disable */
|
|
2
|
+
import { getObjectTypedKeys, getObjectTypedValues } from '@augment-vir/common';
|
|
3
|
+
import { css, defineElement, defineElementEvent, html, listen } from 'element-vir';
|
|
4
|
+
import { colorFormatsBySpace } from '../color-class/color-formats.js';
|
|
5
|
+
import { VirColorFormatSliders } from './vir-color-format-sliders.element.js';
|
|
6
|
+
/**
|
|
7
|
+
* Color sliders for all color spaces.
|
|
8
|
+
*
|
|
9
|
+
* @category Elements
|
|
10
|
+
*/
|
|
11
|
+
export const VirAllColorSpaceSliders = defineElement()({
|
|
12
|
+
tagName: 'vir-all-color-space-sliders',
|
|
13
|
+
styles: css `
|
|
14
|
+
:host {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
gap: 16px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.color-space {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-wrap: wrap;
|
|
23
|
+
column-gap: 32px;
|
|
24
|
+
row-gap: 8px;
|
|
25
|
+
}
|
|
26
|
+
`,
|
|
27
|
+
events: {
|
|
28
|
+
colorChange: defineElementEvent(),
|
|
29
|
+
},
|
|
30
|
+
render({ inputs, dispatch, events }) {
|
|
31
|
+
const colorSpaceTemplates = getObjectTypedValues(colorFormatsBySpace).map((colorSpaceFormats) => {
|
|
32
|
+
const formatTemplates = getObjectTypedKeys(colorSpaceFormats).map((colorFormatName) => {
|
|
33
|
+
return html `
|
|
34
|
+
<${VirColorFormatSliders.assign({
|
|
35
|
+
color: inputs.color,
|
|
36
|
+
colorFormatName,
|
|
37
|
+
})}
|
|
38
|
+
${listen(VirColorFormatSliders.events.colorChange, (event) => {
|
|
39
|
+
dispatch(new events.colorChange(event.detail));
|
|
40
|
+
})}
|
|
41
|
+
></${VirColorFormatSliders}>
|
|
42
|
+
`;
|
|
43
|
+
});
|
|
44
|
+
return html `
|
|
45
|
+
<section class="color-space">${formatTemplates}</section>
|
|
46
|
+
`;
|
|
47
|
+
});
|
|
48
|
+
return html `
|
|
49
|
+
${colorSpaceTemplates}
|
|
50
|
+
`;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ColorFormatName } from '../color-class/color-formats.js';
|
|
2
|
+
import { type Color } from '../color-class/color.js';
|
|
3
|
+
/**
|
|
4
|
+
* Color sliders for all coordinates within a specific color format.
|
|
5
|
+
*
|
|
6
|
+
* @category Elements
|
|
7
|
+
*/
|
|
8
|
+
export declare const VirColorFormatSliders: import("element-vir").DeclarativeElementDefinition<"vir-color-format-sliders", {
|
|
9
|
+
color: Readonly<Color>;
|
|
10
|
+
colorFormatName: ColorFormatName;
|
|
11
|
+
}, {}, {
|
|
12
|
+
colorChange: import("element-vir").DefineEvent<string>;
|
|
13
|
+
}, "vir-color-format-sliders-", "vir-color-format-sliders-", readonly [], readonly []>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* node:coverage disable */
|
|
2
|
+
import { getObjectTypedKeys } from '@augment-vir/common';
|
|
3
|
+
import { css, defineElement, defineElementEvent, html, listen } from 'element-vir';
|
|
4
|
+
import { noNativeSpacing } from 'vira';
|
|
5
|
+
import { colorFormats, } from '../color-class/color-formats.js';
|
|
6
|
+
import { VirColorSlider } from './vir-color-slider.element.js';
|
|
7
|
+
/**
|
|
8
|
+
* Color sliders for all coordinates within a specific color format.
|
|
9
|
+
*
|
|
10
|
+
* @category Elements
|
|
11
|
+
*/
|
|
12
|
+
export const VirColorFormatSliders = defineElement()({
|
|
13
|
+
tagName: 'vir-color-format-sliders',
|
|
14
|
+
styles: css `
|
|
15
|
+
:host {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
h3 {
|
|
21
|
+
${noNativeSpacing};
|
|
22
|
+
}
|
|
23
|
+
`,
|
|
24
|
+
events: {
|
|
25
|
+
colorChange: defineElementEvent(),
|
|
26
|
+
},
|
|
27
|
+
render({ inputs, dispatch, events }) {
|
|
28
|
+
const colorFormat = colorFormats[inputs.colorFormatName];
|
|
29
|
+
const coordinateTemplates = getObjectTypedKeys(colorFormat.coords).map((colorCoordinate) => {
|
|
30
|
+
return html `
|
|
31
|
+
<${VirColorSlider.assign({
|
|
32
|
+
color: inputs.color,
|
|
33
|
+
colorCoordinateName: colorCoordinate,
|
|
34
|
+
colorFormatName: inputs.colorFormatName,
|
|
35
|
+
})}
|
|
36
|
+
${listen(VirColorSlider.events.valueChange, (event) => {
|
|
37
|
+
const newColor = inputs.color.clone();
|
|
38
|
+
newColor.set({
|
|
39
|
+
[inputs.colorFormatName]: {
|
|
40
|
+
[colorCoordinate]: event.detail,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
const newValue = newColor.toCss()[inputs.colorFormatName];
|
|
44
|
+
dispatch(new events.colorChange(newValue));
|
|
45
|
+
})}
|
|
46
|
+
></${VirColorSlider}>
|
|
47
|
+
`;
|
|
48
|
+
});
|
|
49
|
+
return html `
|
|
50
|
+
<h3>${inputs.colorFormatName}</h3>
|
|
51
|
+
${coordinateTemplates}
|
|
52
|
+
`;
|
|
53
|
+
},
|
|
54
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ColorCoordinateName, type ColorFormatName } from '../color-class/color-formats.js';
|
|
2
|
+
import { Color } from '../color-class/color.js';
|
|
3
|
+
/**
|
|
4
|
+
* A slider for a specific color coordinate in a specific color space in a specific color.
|
|
5
|
+
*
|
|
6
|
+
* @category Elements
|
|
7
|
+
*/
|
|
8
|
+
export declare const VirColorSlider: import("element-vir").DeclarativeElementDefinition<"vir-color-slider", {
|
|
9
|
+
color: Readonly<Color>;
|
|
10
|
+
colorFormatName: ColorFormatName;
|
|
11
|
+
colorCoordinateName: ColorCoordinateName;
|
|
12
|
+
}, {}, {
|
|
13
|
+
valueChange: import("element-vir").DefineEvent<number>;
|
|
14
|
+
}, "vir-color-slider-", "vir-color-slider-gradient", readonly [], readonly []>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/* node:coverage disable */
|
|
2
|
+
import { assertWrap } from '@augment-vir/assert';
|
|
3
|
+
import { createArray } from '@augment-vir/common';
|
|
4
|
+
import { extractEventTarget } from '@augment-vir/web';
|
|
5
|
+
import { css, defineElement, defineElementEvent, html, listen, unsafeCSS } from 'element-vir';
|
|
6
|
+
import { viraFontCssVars, ViraInput } from 'vira';
|
|
7
|
+
import { colorFormats, } from '../color-class/color-formats.js';
|
|
8
|
+
import { Color } from '../color-class/color.js';
|
|
9
|
+
/**
|
|
10
|
+
* A slider for a specific color coordinate in a specific color space in a specific color.
|
|
11
|
+
*
|
|
12
|
+
* @category Elements
|
|
13
|
+
*/
|
|
14
|
+
export const VirColorSlider = defineElement()({
|
|
15
|
+
tagName: 'vir-color-slider',
|
|
16
|
+
cssVars: {
|
|
17
|
+
'vir-color-slider-gradient': 'black',
|
|
18
|
+
},
|
|
19
|
+
styles: ({ cssVars }) => css `
|
|
20
|
+
:host {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
font-family: ${viraFontCssVars['vira-monospace'].value};
|
|
24
|
+
gap: 2px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
input[type='range'] {
|
|
28
|
+
flex-grow: 1;
|
|
29
|
+
appearance: none;
|
|
30
|
+
background: ${cssVars['vir-color-slider-gradient'].value};
|
|
31
|
+
height: 9px;
|
|
32
|
+
border-radius: 4px;
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
${ViraInput} {
|
|
37
|
+
width: 76px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.coordinate {
|
|
41
|
+
font-size: 18px;
|
|
42
|
+
margin-top: -4px;
|
|
43
|
+
}
|
|
44
|
+
`,
|
|
45
|
+
events: {
|
|
46
|
+
valueChange: defineElementEvent(),
|
|
47
|
+
},
|
|
48
|
+
render({ inputs, events, dispatch, cssVars }) {
|
|
49
|
+
const formatDefinition = colorFormats[inputs.colorFormatName];
|
|
50
|
+
const coordinateDefinition = formatDefinition.coords[inputs.colorCoordinateName];
|
|
51
|
+
if (!coordinateDefinition) {
|
|
52
|
+
throw new Error(`Invalid color coordinate '${inputs.colorCoordinateName}' for color format '${inputs.colorFormatName}'`);
|
|
53
|
+
}
|
|
54
|
+
const totalStops = 10;
|
|
55
|
+
const colorStops = createArray(totalStops, (index) => {
|
|
56
|
+
const value = coordinateDefinition.min +
|
|
57
|
+
(coordinateDefinition.max - coordinateDefinition.min) * (index / totalStops);
|
|
58
|
+
const stopColor = new Color({
|
|
59
|
+
[inputs.colorFormatName]: {
|
|
60
|
+
...inputs.color[inputs.colorFormatName],
|
|
61
|
+
[inputs.colorCoordinateName]: value,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
return stopColor.toCss()[inputs.colorFormatName];
|
|
65
|
+
});
|
|
66
|
+
const gradient = css `linear-gradient(to right, ${unsafeCSS(colorStops.join(','))})`;
|
|
67
|
+
const coordinateValue = assertWrap.isNumber(inputs.color[inputs.colorFormatName][inputs.colorCoordinateName]);
|
|
68
|
+
return html `
|
|
69
|
+
<span class="coordinate">${inputs.colorCoordinateName.toUpperCase()}</span>
|
|
70
|
+
<input
|
|
71
|
+
type="range"
|
|
72
|
+
style=${css `
|
|
73
|
+
${cssVars['vir-color-slider-gradient'].name}: ${gradient};
|
|
74
|
+
`}
|
|
75
|
+
min=${coordinateDefinition.min}
|
|
76
|
+
max=${coordinateDefinition.max}
|
|
77
|
+
.value=${String(coordinateValue)}
|
|
78
|
+
step=${Math.pow(10, coordinateDefinition.digits ? -coordinateDefinition.digits : 0)}
|
|
79
|
+
${listen('input', (event) => {
|
|
80
|
+
const element = extractEventTarget(event, HTMLInputElement);
|
|
81
|
+
const newValue = Number(element.value);
|
|
82
|
+
if (isNaN(newValue)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
dispatch(new events.valueChange(newValue));
|
|
86
|
+
})}
|
|
87
|
+
/>
|
|
88
|
+
<${ViraInput.assign({
|
|
89
|
+
value: String(coordinateValue),
|
|
90
|
+
})}
|
|
91
|
+
${listen(ViraInput.events.valueChange, (event) => {
|
|
92
|
+
const newValue = Number(event.detail);
|
|
93
|
+
if (isNaN(newValue)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
dispatch(new events.valueChange(newValue));
|
|
97
|
+
})}
|
|
98
|
+
></${ViraInput}>
|
|
99
|
+
`;
|
|
100
|
+
},
|
|
101
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -2,5 +2,8 @@ export * from './color-class/color-formats.js';
|
|
|
2
2
|
export * from './color-class/color-name-length.js';
|
|
3
3
|
export * from './color-class/color.js';
|
|
4
4
|
export * from './contrast/contrast.js';
|
|
5
|
+
export * from './elements/vir-all-color-space-sliders.element.js';
|
|
6
|
+
export * from './elements/vir-color-format-sliders.element.js';
|
|
5
7
|
export * from './elements/vir-color-pair.element.js';
|
|
8
|
+
export * from './elements/vir-color-slider.element.js';
|
|
6
9
|
export * from './elements/vir-contrast-indicator.element.js';
|
package/dist/index.js
CHANGED
|
@@ -2,5 +2,8 @@ export * from './color-class/color-formats.js';
|
|
|
2
2
|
export * from './color-class/color-name-length.js';
|
|
3
3
|
export * from './color-class/color.js';
|
|
4
4
|
export * from './contrast/contrast.js';
|
|
5
|
+
export * from './elements/vir-all-color-space-sliders.element.js';
|
|
6
|
+
export * from './elements/vir-color-format-sliders.element.js';
|
|
5
7
|
export * from './elements/vir-color-pair.element.js';
|
|
8
|
+
export * from './elements/vir-color-slider.element.js';
|
|
6
9
|
export * from './elements/vir-contrast-indicator.element.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electrovir/color",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A wrapper for culori with an extremely simple API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"color",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@augment-vir/assert": "^31.57.3",
|
|
54
54
|
"@augment-vir/common": "^31.57.3",
|
|
55
|
+
"@augment-vir/web": "^31.57.3",
|
|
55
56
|
"apca-w3": "^0.1.9",
|
|
56
57
|
"color-name": "^2.1.0",
|
|
57
58
|
"culori": "^4.0.2",
|
|
@@ -101,7 +102,7 @@
|
|
|
101
102
|
"typedoc": "^0.28.15",
|
|
102
103
|
"typescript": "^5.9.3",
|
|
103
104
|
"typescript-eslint": "^8.51.0",
|
|
104
|
-
"vira": "^28.
|
|
105
|
+
"vira": "^28.16.0",
|
|
105
106
|
"virmator": "^14.4.0",
|
|
106
107
|
"vite": "^7.3.0"
|
|
107
108
|
},
|