@electrovir/color 1.4.0 → 1.5.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.d.ts +17 -0
- package/dist/color-class/color.js +25 -3
- package/dist/demo/all-book-pages.d.ts +2 -0
- package/dist/demo/all-book-pages.js +9 -0
- package/dist/demo/top-level-pages.d.ts +2 -0
- package/dist/demo/top-level-pages.js +9 -0
- package/dist/demo/vir-color-demo.element.d.ts +1 -0
- package/dist/demo/vir-color-demo.element.js +29 -0
- package/dist/elements/vir-color-picker.element.d.ts +14 -0
- package/dist/elements/vir-color-picker.element.js +115 -0
- package/dist/elements/vir-color-swatch.element.d.ts +9 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +2 -1
|
@@ -23,6 +23,14 @@ export type AllColorsValues = ColorValue & {
|
|
|
23
23
|
[ColorSyntaxName.name]: string;
|
|
24
24
|
names: string[];
|
|
25
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* The output of `Color.serialize()`.
|
|
28
|
+
*
|
|
29
|
+
* @category Internal
|
|
30
|
+
*/
|
|
31
|
+
export type SerializedColor = AllColorsValues & {
|
|
32
|
+
originalColorSyntax: ColorSyntaxName;
|
|
33
|
+
};
|
|
26
34
|
/**
|
|
27
35
|
* A `Color` class with state and the following features:
|
|
28
36
|
*
|
|
@@ -39,11 +47,20 @@ export declare class Color {
|
|
|
39
47
|
constructor(
|
|
40
48
|
/** Any valid CSS color string or an object of color coordinate values. */
|
|
41
49
|
initValue: string | Readonly<ColorUpdate>);
|
|
50
|
+
/** Checks, with a type guard, that a given input is a Color class instance. */
|
|
51
|
+
static isColor<T>(value: T): value is Extract<T, Readonly<Color>>;
|
|
42
52
|
/**
|
|
43
53
|
* Create a new {@link Color} instance by parsing the output of another instance's
|
|
44
54
|
* {@link Color.serialize} method.
|
|
45
55
|
*/
|
|
46
56
|
static deserialize(input: string): Color;
|
|
57
|
+
/**
|
|
58
|
+
* Converts the color class to a CSS string format in the color space and format that it was
|
|
59
|
+
* originally set with.
|
|
60
|
+
*/
|
|
61
|
+
toString(): string;
|
|
62
|
+
/** The color syntax the this color was set with. */
|
|
63
|
+
protected originalColorSyntax: ColorSyntaxName;
|
|
47
64
|
/** All current color values. These are updated whenever {@link Color.set} is called. */
|
|
48
65
|
protected readonly _allColors: {
|
|
49
66
|
names: string[];
|
|
@@ -2,7 +2,7 @@ import { assert, assertWrap, check } from '@augment-vir/assert';
|
|
|
2
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 { ColorFormatName, colorFormats, ColorSyntaxName, } from './color-formats.js';
|
|
5
|
+
import { ColorFormatName, colorFormats, ColorSyntaxName, getColorSyntaxFromCssString, } 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:
|
|
@@ -21,6 +21,10 @@ export class Color {
|
|
|
21
21
|
initValue) {
|
|
22
22
|
this.set(initValue);
|
|
23
23
|
}
|
|
24
|
+
/** Checks, with a type guard, that a given input is a Color class instance. */
|
|
25
|
+
static isColor(value) {
|
|
26
|
+
return value instanceof Color;
|
|
27
|
+
}
|
|
24
28
|
/**
|
|
25
29
|
* Create a new {@link Color} instance by parsing the output of another instance's
|
|
26
30
|
* {@link Color.serialize} method.
|
|
@@ -29,10 +33,24 @@ export class Color {
|
|
|
29
33
|
const parsed = JSON.parse(input);
|
|
30
34
|
const newColor = new Color('black');
|
|
31
35
|
getObjectTypedEntries(parsed).forEach(([key, value,]) => {
|
|
32
|
-
|
|
36
|
+
if (key === 'originalColorSyntax') {
|
|
37
|
+
newColor.originalColorSyntax = assertWrap.isEnumValue(value, ColorSyntaxName, 'Cannot deserialize: invalid color syntax.');
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
newColor._allColors[key] = value;
|
|
41
|
+
}
|
|
33
42
|
});
|
|
34
43
|
return newColor;
|
|
35
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Converts the color class to a CSS string format in the color space and format that it was
|
|
47
|
+
* originally set with.
|
|
48
|
+
*/
|
|
49
|
+
toString() {
|
|
50
|
+
return this.toCss()[this.originalColorSyntax];
|
|
51
|
+
}
|
|
52
|
+
/** The color syntax the this color was set with. */
|
|
53
|
+
originalColorSyntax = ColorSyntaxName.hex;
|
|
36
54
|
#internalColor = assertWrap.isDefined(parse('black'));
|
|
37
55
|
/** All current color values. These are updated whenever {@link Color.set} is called. */
|
|
38
56
|
_allColors = {
|
|
@@ -89,6 +107,7 @@ export class Color {
|
|
|
89
107
|
if (!newColor) {
|
|
90
108
|
throw new Error(`Unable to parse invalid color string: '${cssColorString}'`);
|
|
91
109
|
}
|
|
110
|
+
this.originalColorSyntax = getColorSyntaxFromCssString(cssColorString);
|
|
92
111
|
this.#internalColor = newColor;
|
|
93
112
|
this.pullFromInternalColor();
|
|
94
113
|
}
|
|
@@ -157,7 +176,10 @@ export class Color {
|
|
|
157
176
|
* match the current {@link Color} instance.
|
|
158
177
|
*/
|
|
159
178
|
serialize() {
|
|
160
|
-
return JSON.stringify(
|
|
179
|
+
return JSON.stringify({
|
|
180
|
+
...this.allColors,
|
|
181
|
+
originalColorSyntax: this.originalColorSyntax,
|
|
182
|
+
});
|
|
161
183
|
}
|
|
162
184
|
/** This individual color expressed in all the supported color formats. */
|
|
163
185
|
get allColors() {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { colorExamplesPage } from './book-pages/color-examples.book.js';
|
|
2
|
+
import { virColorPickerBookPage } from './book-pages/vir-color-picker.element.book.js';
|
|
3
|
+
import { elementsBookPage, examplesBookPage } from './top-level-pages.js';
|
|
4
|
+
export const allBookPages = [
|
|
5
|
+
elementsBookPage,
|
|
6
|
+
examplesBookPage,
|
|
7
|
+
colorExamplesPage,
|
|
8
|
+
virColorPickerBookPage,
|
|
9
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VirColorDemo: import("element-vir").DeclarativeElementDefinition<"vir-color-demo", {}, {}, {}, "vir-color-demo-", "vir-color-demo-", readonly [], readonly []>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/* node:coverage disable */
|
|
2
|
+
import { ElementBookApp } from 'element-book';
|
|
3
|
+
import { css, defineElement, html } from 'element-vir';
|
|
4
|
+
import { allBookPages } from './all-book-pages.js';
|
|
5
|
+
export const VirColorDemo = defineElement()({
|
|
6
|
+
tagName: 'vir-color-demo',
|
|
7
|
+
styles: css `
|
|
8
|
+
:host {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
height: 100%;
|
|
12
|
+
width: 100%;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
${ElementBookApp} {
|
|
17
|
+
flex-grow: 1;
|
|
18
|
+
max-width: 100%;
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
}
|
|
21
|
+
`,
|
|
22
|
+
render() {
|
|
23
|
+
return html `
|
|
24
|
+
<${ElementBookApp.assign({
|
|
25
|
+
pages: allBookPages,
|
|
26
|
+
})}></${ElementBookApp}>
|
|
27
|
+
`;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ColorFormatName as ColorFormatNameType } from '../color-class/color-formats.js';
|
|
2
|
+
import { Color } from '../color-class/color.js';
|
|
3
|
+
/**
|
|
4
|
+
* A color picker element with a swatch that opens a popup with color format sliders.
|
|
5
|
+
*
|
|
6
|
+
* @category Elements
|
|
7
|
+
*/
|
|
8
|
+
export declare const VirColorPicker: import("element-vir").DeclarativeElementDefinition<"vir-color-picker", {
|
|
9
|
+
color: string | Readonly<Color> | undefined;
|
|
10
|
+
}, {
|
|
11
|
+
selectedFormatName: ColorFormatNameType;
|
|
12
|
+
}, {
|
|
13
|
+
colorChange: import("element-vir").DefineEvent<string>;
|
|
14
|
+
}, "vir-color-picker-", "vir-color-picker-width" | "vir-color-picker-height", readonly [], readonly []>;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* node:coverage disable */
|
|
2
|
+
import { checkWrap } from '@augment-vir/assert';
|
|
3
|
+
import { getObjectTypedValues } from '@augment-vir/common';
|
|
4
|
+
import { css, defineElement, defineElementEvent, html, listen, onResize } from 'element-vir';
|
|
5
|
+
import { setCssVarValue } from 'lit-css-vars';
|
|
6
|
+
import { ViraPopUpTrigger, ViraSelect, viraShadows } from 'vira';
|
|
7
|
+
import { ColorFormatName, } from '../color-class/color-formats.js';
|
|
8
|
+
import { Color } from '../color-class/color.js';
|
|
9
|
+
import { VirColorFormatSliders } from './vir-color-format-sliders.element.js';
|
|
10
|
+
import { VirColorSwatch } from './vir-color-swatch.element.js';
|
|
11
|
+
const colorFormatOptions = getObjectTypedValues(ColorFormatName).map((formatName) => ({
|
|
12
|
+
value: formatName,
|
|
13
|
+
label: formatName.toUpperCase(),
|
|
14
|
+
}));
|
|
15
|
+
/**
|
|
16
|
+
* A color picker element with a swatch that opens a popup with color format sliders.
|
|
17
|
+
*
|
|
18
|
+
* @category Elements
|
|
19
|
+
*/
|
|
20
|
+
export const VirColorPicker = defineElement()({
|
|
21
|
+
tagName: 'vir-color-picker',
|
|
22
|
+
cssVars: {
|
|
23
|
+
'vir-color-picker-width': '100px',
|
|
24
|
+
'vir-color-picker-height': '100px',
|
|
25
|
+
},
|
|
26
|
+
styles: ({ cssVars }) => css `
|
|
27
|
+
:host {
|
|
28
|
+
display: inline-block;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
${ViraPopUpTrigger} {
|
|
32
|
+
width: 100%;
|
|
33
|
+
height: 100%;
|
|
34
|
+
box-sizing: border-box;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
${VirColorSwatch} {
|
|
38
|
+
width: ${cssVars['vir-color-picker-width'].value};
|
|
39
|
+
height: ${cssVars['vir-color-picker-height'].value};
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
box-sizing: border-box;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.popup-content {
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
gap: 16px;
|
|
48
|
+
padding: 16px;
|
|
49
|
+
background: white;
|
|
50
|
+
border: 1px solid #ccc;
|
|
51
|
+
border-radius: 8px;
|
|
52
|
+
${viraShadows.menuShadow}
|
|
53
|
+
}
|
|
54
|
+
`,
|
|
55
|
+
events: {
|
|
56
|
+
colorChange: defineElementEvent(),
|
|
57
|
+
},
|
|
58
|
+
state() {
|
|
59
|
+
return {
|
|
60
|
+
selectedFormatName: ColorFormatName.rgb,
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
render({ inputs, dispatch, events, state, updateState, host, cssVars }) {
|
|
64
|
+
const color = Color.isColor(inputs.color)
|
|
65
|
+
? inputs.color
|
|
66
|
+
: new Color(inputs.color || 'black');
|
|
67
|
+
return html `
|
|
68
|
+
<${ViraPopUpTrigger.assign({
|
|
69
|
+
keepOpenAfterInteraction: true,
|
|
70
|
+
})}
|
|
71
|
+
${onResize((size) => {
|
|
72
|
+
setCssVarValue({
|
|
73
|
+
onElement: host,
|
|
74
|
+
forCssVar: cssVars['vir-color-picker-width'],
|
|
75
|
+
toValue: `${size.contentRect.width}px`,
|
|
76
|
+
});
|
|
77
|
+
setCssVarValue({
|
|
78
|
+
onElement: host,
|
|
79
|
+
forCssVar: cssVars['vir-color-picker-height'],
|
|
80
|
+
toValue: `${size.contentRect.height}px`,
|
|
81
|
+
});
|
|
82
|
+
})}
|
|
83
|
+
>
|
|
84
|
+
<${VirColorSwatch.assign({
|
|
85
|
+
backgroundColor: color,
|
|
86
|
+
})}
|
|
87
|
+
slot=${ViraPopUpTrigger.slotNames.trigger}
|
|
88
|
+
></${VirColorSwatch}>
|
|
89
|
+
<div class="popup-content" slot=${ViraPopUpTrigger.slotNames.popUp}>
|
|
90
|
+
<${ViraSelect.assign({
|
|
91
|
+
options: colorFormatOptions,
|
|
92
|
+
value: state.selectedFormatName,
|
|
93
|
+
})}
|
|
94
|
+
${listen(ViraSelect.events.valueChange, (event) => {
|
|
95
|
+
const selectedFormat = checkWrap.isEnumValue(event.detail, ColorFormatName);
|
|
96
|
+
if (selectedFormat) {
|
|
97
|
+
updateState({
|
|
98
|
+
selectedFormatName: selectedFormat,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
})}
|
|
102
|
+
></${ViraSelect}>
|
|
103
|
+
<${VirColorFormatSliders.assign({
|
|
104
|
+
color,
|
|
105
|
+
colorFormatName: state.selectedFormatName,
|
|
106
|
+
})}
|
|
107
|
+
${listen(VirColorFormatSliders.events.colorChange, (event) => {
|
|
108
|
+
dispatch(new events.colorChange(event.detail));
|
|
109
|
+
})}
|
|
110
|
+
></${VirColorFormatSliders}>
|
|
111
|
+
</div>
|
|
112
|
+
</${ViraPopUpTrigger}>
|
|
113
|
+
`;
|
|
114
|
+
},
|
|
115
|
+
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Color } from '../color-class/color.js';
|
|
1
2
|
/**
|
|
2
3
|
* Show a background and/or foreground color. Note that if a foreground color is provided that it is
|
|
3
4
|
* not actually applied to anything, you must provide a child element for it to be applied to.
|
|
@@ -5,15 +6,15 @@
|
|
|
5
6
|
* @category Elements
|
|
6
7
|
*/
|
|
7
8
|
export declare const VirColorSwatch: import("element-vir").DeclarativeElementDefinition<"vir-color-swatch", ((Required<Pick<{
|
|
8
|
-
foregroundColor: string
|
|
9
|
-
backgroundColor: string
|
|
9
|
+
foregroundColor: string | Readonly<Color>;
|
|
10
|
+
backgroundColor: string | Readonly<Color>;
|
|
10
11
|
}, "foregroundColor">> & Partial<Pick<{
|
|
11
|
-
foregroundColor: string
|
|
12
|
-
backgroundColor: string
|
|
12
|
+
foregroundColor: string | Readonly<Color>;
|
|
13
|
+
backgroundColor: string | Readonly<Color>;
|
|
13
14
|
}, "backgroundColor">>) | (Required<Pick<{
|
|
14
|
-
foregroundColor: string
|
|
15
|
-
backgroundColor: string
|
|
15
|
+
foregroundColor: string | Readonly<Color>;
|
|
16
|
+
backgroundColor: string | Readonly<Color>;
|
|
16
17
|
}, "backgroundColor">> & Partial<Pick<{
|
|
17
|
-
foregroundColor: string
|
|
18
|
-
backgroundColor: string
|
|
18
|
+
foregroundColor: string | Readonly<Color>;
|
|
19
|
+
backgroundColor: string | Readonly<Color>;
|
|
19
20
|
}, "foregroundColor">>)) & {}, {}, {}, "vir-color-swatch-", "vir-color-swatch-", readonly [], readonly []>;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './elements/vir-color-details.element.js';
|
|
|
8
8
|
export * from './elements/vir-color-format-sliders.element.js';
|
|
9
9
|
export * from './elements/vir-color-pair-contrast-summary.element.js';
|
|
10
10
|
export * from './elements/vir-color-pair.element.js';
|
|
11
|
+
export * from './elements/vir-color-picker.element.js';
|
|
11
12
|
export * from './elements/vir-color-slider.element.js';
|
|
12
13
|
export * from './elements/vir-color-swatch.element.js';
|
|
13
14
|
export * from './elements/vir-contrast-indicator.element.js';
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export * from './elements/vir-color-details.element.js';
|
|
|
8
8
|
export * from './elements/vir-color-format-sliders.element.js';
|
|
9
9
|
export * from './elements/vir-color-pair-contrast-summary.element.js';
|
|
10
10
|
export * from './elements/vir-color-pair.element.js';
|
|
11
|
+
export * from './elements/vir-color-picker.element.js';
|
|
11
12
|
export * from './elements/vir-color-slider.element.js';
|
|
12
13
|
export * from './elements/vir-color-swatch.element.js';
|
|
13
14
|
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.5.0",
|
|
4
4
|
"description": "A wrapper for culori with an extremely simple API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"color",
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
"@web/test-runner-visual-regression": "^0.10.0",
|
|
75
75
|
"cspell": "^9.4.0",
|
|
76
76
|
"dependency-cruiser": "^17.3.5",
|
|
77
|
+
"element-book": "^26.14.1",
|
|
77
78
|
"element-vir": "^26.14.0",
|
|
78
79
|
"esbuild": "^0.27.2",
|
|
79
80
|
"eslint": "^9.39.2",
|