@electrovir/color 1.2.0 → 1.3.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.
@@ -0,0 +1,14 @@
1
+ /**
2
+ * A color swatch alongside the color in all of its different supported formats.
3
+ *
4
+ * @category Internal
5
+ */
6
+ export declare const VirColorDetails: import("element-vir").DeclarativeElementDefinition<"vir-color-details", {
7
+ color: string;
8
+ /** Show a text input that triggers an event when it is edited, for changing the color. */
9
+ showInput: boolean;
10
+ }, {
11
+ inputColorString: undefined | string;
12
+ }, {
13
+ colorChange: import("element-vir").DefineEvent<string>;
14
+ }, "vir-color-details-", "vir-color-details-", readonly [], readonly []>;
@@ -0,0 +1,122 @@
1
+ /* node:coverage disable */
2
+ import { getObjectTypedEntries, omitObjectKeys } from '@augment-vir/common';
3
+ import { css, defineElement, defineElementEvent, html, listen } from 'element-vir';
4
+ import { defineTable, noNativeSpacing, viraFontCssVars, ViraInput } from 'vira';
5
+ import { Color } from '../color-class/color.js';
6
+ import { VirColorSwatch } from './vir-color-swatch.element.js';
7
+ /**
8
+ * A color swatch alongside the color in all of its different supported formats.
9
+ *
10
+ * @category Internal
11
+ */
12
+ export const VirColorDetails = defineElement()({
13
+ tagName: 'vir-color-details',
14
+ styles: css `
15
+ :host {
16
+ display: flex;
17
+ gap: 16px;
18
+ }
19
+
20
+ ${VirColorSwatch} {
21
+ height: 200px;
22
+ width: 200px;
23
+ }
24
+
25
+ .swatch {
26
+ display: flex;
27
+ flex-direction: column;
28
+ gap: 8px;
29
+ align-items: center;
30
+ }
31
+
32
+ ${ViraInput} {
33
+ font-size: 14px;
34
+ font-family: ${viraFontCssVars['vira-monospace'].value};
35
+ max-width: 200px;
36
+ }
37
+
38
+ td {
39
+ font-weight: bold;
40
+ }
41
+
42
+ th {
43
+ padding: 4px 8px;
44
+ font-weight: normal;
45
+ text-align: right;
46
+ }
47
+ pre {
48
+ ${noNativeSpacing};
49
+ font-family: ${viraFontCssVars['vira-monospace'].value};
50
+ }
51
+ `,
52
+ events: {
53
+ colorChange: defineElementEvent(),
54
+ },
55
+ state() {
56
+ return {
57
+ inputColorString: undefined,
58
+ };
59
+ },
60
+ render({ inputs, dispatch, events, state, updateState }) {
61
+ const color = new Color(inputs.color);
62
+ const colorStrings = omitObjectKeys(color.toFormattedStrings(), ['name']);
63
+ if (state.inputColorString == undefined) {
64
+ updateState({
65
+ inputColorString: inputs.color,
66
+ });
67
+ }
68
+ const { rows } = defineTable([
69
+ {
70
+ key: 'colorFormat',
71
+ },
72
+ {
73
+ key: 'formattedString',
74
+ },
75
+ ], getObjectTypedEntries(colorStrings), ([colorFormat, value,]) => {
76
+ return {
77
+ colorFormat: `${colorFormat}:`,
78
+ formattedString: html `
79
+ <pre>${value}</pre>
80
+ `,
81
+ };
82
+ });
83
+ const inputTemplate = inputs.showInput
84
+ ? html `
85
+ <${ViraInput.assign({
86
+ value: state.inputColorString || '',
87
+ fitText: true,
88
+ })}
89
+ ${listen(ViraInput.events.valueChange, (event) => {
90
+ updateState({
91
+ inputColorString: event.detail,
92
+ });
93
+ dispatch(new events.colorChange(event.detail));
94
+ })}
95
+ ></${ViraInput}>
96
+ `
97
+ : '';
98
+ return html `
99
+ <div class="swatch">
100
+ <${VirColorSwatch.assign({
101
+ backgroundColor: inputs.color,
102
+ })}></${VirColorSwatch}>
103
+ ${inputTemplate}
104
+ </div>
105
+ <table>
106
+ <tbody>
107
+ ${rows.map((row) => {
108
+ const cells = row.cells.map((cell, index) => {
109
+ const element = index ? 'td' : 'th';
110
+ return html `
111
+ <${element}>${cell.content}</${element}>
112
+ `;
113
+ });
114
+ return html `
115
+ <tr>${cells}</tr>
116
+ `;
117
+ })}
118
+ </tbody>
119
+ </table>
120
+ `;
121
+ },
122
+ });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * A huge summary of a color pair's contrast levels, font sizes, font weights, etc.
3
+ *
4
+ * @category Elements
5
+ */
6
+ export declare const VirColorPairContrastSummary: import("element-vir").DeclarativeElementDefinition<"vir-color-pair-contrast-summary", {
7
+ foregroundColor: string;
8
+ backgroundColor: string;
9
+ }, {}, {}, "vir-color-pair-contrast-summary-", "vir-color-pair-contrast-summary-", readonly [], readonly []>;
@@ -0,0 +1,290 @@
1
+ /* node:coverage disable */
2
+ import { assertWrap } from '@augment-vir/assert';
3
+ import { getObjectTypedEntries, round } from '@augment-vir/common';
4
+ import { classMap, css, defineElement, html, unsafeCSS } from 'element-vir';
5
+ import { defineTable, noNativeSpacing, ViraBoldText, viraFontCssVars } from 'vira';
6
+ import { Color } from '../color-class/color.js';
7
+ import { calculateContrast, calculateFontSizes, contrastLevelLabel, contrastLevels, fontWeightByName, } from '../contrast/contrast.js';
8
+ import { VirColorSwatch } from './vir-color-swatch.element.js';
9
+ import { VirContrastIndicator } from './vir-contrast-indicator.element.js';
10
+ /**
11
+ * A huge summary of a color pair's contrast levels, font sizes, font weights, etc.
12
+ *
13
+ * @category Elements
14
+ */
15
+ export const VirColorPairContrastSummary = defineElement()({
16
+ tagName: 'vir-color-pair-contrast-summary',
17
+ styles: css `
18
+ :host {
19
+ display: flex;
20
+ justify-content: center;
21
+ align-items: center;
22
+ gap: 32px;
23
+ }
24
+
25
+ /* Color overlay styles */
26
+ .color-overlay {
27
+ display: flex;
28
+ align-items: center;
29
+ max-width: 100%;
30
+ gap: 8px;
31
+ }
32
+
33
+ .constant-size-wrapper {
34
+ display: flex;
35
+ align-items: baseline;
36
+ gap: 5cqmin;
37
+ font-size: 20cqmin;
38
+ }
39
+
40
+ .square {
41
+ margin: 12px 0;
42
+ width: 20cqmin;
43
+ height: 20cqmin;
44
+ background-color: currentColor;
45
+ }
46
+
47
+ .foreground-content {
48
+ display: flex;
49
+ flex-direction: column;
50
+ position: relative;
51
+ }
52
+
53
+ .needed-size {
54
+ display: flex;
55
+ justify-content: center;
56
+ top: 100%;
57
+ left: 0;
58
+ text-align: center;
59
+ position: absolute;
60
+ width: 100%;
61
+ }
62
+
63
+ ${VirContrastIndicator} {
64
+ width: 100%;
65
+ }
66
+
67
+ .color-overlay td {
68
+ padding: 4px 8px;
69
+ font-weight: bold;
70
+ }
71
+
72
+ .color-overlay th {
73
+ padding: 4px 8px;
74
+ text-align: end;
75
+ font-weight: normal;
76
+ }
77
+
78
+ /* Text weights styles */
79
+ .text-weights td {
80
+ padding: 4px;
81
+ }
82
+
83
+ .size-display {
84
+ height: 50px;
85
+ width: 100px;
86
+ overflow: hidden;
87
+ display: flex;
88
+ align-items: center;
89
+ }
90
+
91
+ .cell-size {
92
+ width: 5em;
93
+ }
94
+
95
+ /* Contrast levels styles */
96
+ .contrast-levels td {
97
+ padding: 4px;
98
+ }
99
+
100
+ .contrast-levels tr {
101
+ opacity: 0.4;
102
+ }
103
+
104
+ .contrast-levels .selected-row {
105
+ opacity: 1;
106
+ font-weight: bold;
107
+ }
108
+
109
+ pre {
110
+ ${noNativeSpacing};
111
+ font-family: ${viraFontCssVars['vira-monospace'].value};
112
+ }
113
+
114
+ .monospace-font {
115
+ font-family: ${viraFontCssVars['vira-monospace'].value};
116
+ }
117
+ `,
118
+ render({ inputs }) {
119
+ const contrast = calculateContrast({
120
+ background: new Color(inputs.backgroundColor).toCss().rgb,
121
+ foreground: new Color(inputs.foregroundColor).toCss().rgb,
122
+ });
123
+ const { rows: colorPairRows } = defineTable([
124
+ {
125
+ key: 'colorLayer',
126
+ },
127
+ {
128
+ key: 'colorValue',
129
+ },
130
+ ], getObjectTypedEntries({
131
+ 'Foreground:': new Color(inputs.foregroundColor).toCss().hex,
132
+ 'Background:': new Color(inputs.backgroundColor).toCss().hex,
133
+ 'Contrast:': `${contrast.contrast} Lc`.padEnd(9, ' '),
134
+ }), ([colorLayer, value,]) => {
135
+ return {
136
+ colorLayer,
137
+ colorValue: html `
138
+ <pre>${value}</pre>
139
+ `,
140
+ };
141
+ });
142
+ const { rows: weightRows } = defineTable([
143
+ {
144
+ key: 'weight',
145
+ },
146
+ {
147
+ key: 'size',
148
+ },
149
+ ], Object.entries(contrast.fontSizes).map(([weight, size,]) => {
150
+ return {
151
+ weight: Number(weight),
152
+ size,
153
+ };
154
+ }), ({ size, weight }) => {
155
+ return {
156
+ size: `${round(size, { digits: 1 })}px`,
157
+ weight: html `
158
+ <span
159
+ style=${css `
160
+ font-weight: ${weight};
161
+ `}
162
+ >
163
+ ${weight}
164
+ </span>
165
+ `,
166
+ };
167
+ });
168
+ const { rows: levelRows } = defineTable([
169
+ {
170
+ key: 'boundaryLc',
171
+ },
172
+ {
173
+ key: 'levelName',
174
+ },
175
+ ], contrastLevels, (contrastLevel) => {
176
+ return {
177
+ boundaryLc: `${contrastLevel.min} Lc`,
178
+ levelName: contrastLevelLabel[contrastLevel.name],
179
+ };
180
+ });
181
+ return html `
182
+ <div class="color-overlay">
183
+ <${VirColorSwatch.assign({
184
+ backgroundColor: inputs.backgroundColor,
185
+ foregroundColor: inputs.foregroundColor,
186
+ })}>
187
+ <div class="foreground-content">
188
+ <div class="constant-size-wrapper">
189
+ <div class="square"></div>
190
+ <b>Aa</b>
191
+ </div>
192
+ <div class="needed-size">
193
+ <span
194
+ style=${css `
195
+ font-size: ${contrast.fontSizes[fontWeightByName.Normal]}px;
196
+ line-height: ${contrast.fontSizes[fontWeightByName.Normal] *
197
+ 0.77}px;
198
+ visibility: ${unsafeCSS(contrast.fontSizes[fontWeightByName.Normal] > 900
199
+ ? 'hidden'
200
+ : 'visible')};
201
+ `}
202
+ >
203
+ Min Size
204
+ </span>
205
+ </div>
206
+ </div>
207
+ </${VirColorSwatch}>
208
+ <div class="details">
209
+ <table>
210
+ <tbody>
211
+ ${colorPairRows.map((row) => {
212
+ const cells = row.cells.map((cell, index) => {
213
+ const element = index ? 'td' : 'th';
214
+ return html `
215
+ <${element}>${cell.content}</${element}>
216
+ `;
217
+ });
218
+ return html `
219
+ <tr>${cells}</tr>
220
+ `;
221
+ })}
222
+ </tbody>
223
+ </table>
224
+
225
+ <${VirContrastIndicator.assign({
226
+ contrast,
227
+ fontWeight: fontWeightByName.Normal,
228
+ })}></${VirContrastIndicator}>
229
+ </div>
230
+ </div>
231
+
232
+ <table class="text-weights">
233
+ ${weightRows.map((row) => {
234
+ const cells = row.cells.map((cell) => {
235
+ return html `
236
+ <td class="cell-${cell.key} monospace-font">${cell.content}</td>
237
+ `;
238
+ });
239
+ return html `
240
+ <tr>
241
+ ${cells}
242
+ <td>
243
+ <div
244
+ class="size-display"
245
+ style=${css `
246
+ background-color: ${unsafeCSS(inputs.backgroundColor)};
247
+ color: ${unsafeCSS(inputs.foregroundColor)};
248
+ font-weight: ${row.data.weight};
249
+ font-size: ${row.data.size}px;
250
+ `}
251
+ >
252
+ <span>Text</span>
253
+ </div>
254
+ </td>
255
+ </tr>
256
+ `;
257
+ })}
258
+ </table>
259
+
260
+ <table class="contrast-levels">
261
+ ${levelRows.map((row) => {
262
+ const isSelectedRow = contrast.contrastLevel.name === row.data.name;
263
+ const cells = row.cells.map((cell) => {
264
+ return html `
265
+ <td><${ViraBoldText.assign({
266
+ bold: isSelectedRow,
267
+ text: assertWrap.isString(cell.content),
268
+ })}><${ViraBoldText}></td>
269
+ `;
270
+ });
271
+ const title = [
272
+ row.data.description,
273
+ '\nFont weights to font sizes:',
274
+ JSON.stringify(calculateFontSizes(row.data.min), null, 4),
275
+ ].join('\n');
276
+ return html `
277
+ <tr
278
+ title=${title}
279
+ class=${classMap({
280
+ 'selected-row': isSelectedRow,
281
+ })}
282
+ >
283
+ ${cells}
284
+ </tr>
285
+ `;
286
+ })}
287
+ </table>
288
+ `;
289
+ },
290
+ });
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Show a background and/or foreground color. Note that if a foreground color is provided that it is
3
+ * not actually applied to anything, you must provide a child element for it to be applied to.
4
+ *
5
+ * @category Elements
6
+ */
7
+ export declare const VirColorSwatch: import("element-vir").DeclarativeElementDefinition<"vir-color-swatch", ((Required<Pick<{
8
+ foregroundColor: string;
9
+ backgroundColor: string;
10
+ }, "foregroundColor">> & Partial<Pick<{
11
+ foregroundColor: string;
12
+ backgroundColor: string;
13
+ }, "backgroundColor">>) | (Required<Pick<{
14
+ foregroundColor: string;
15
+ backgroundColor: string;
16
+ }, "backgroundColor">> & Partial<Pick<{
17
+ foregroundColor: string;
18
+ backgroundColor: string;
19
+ }, "foregroundColor">>)) & {}, {}, {}, "vir-color-swatch-", "vir-color-swatch-", readonly [], readonly []>;
@@ -0,0 +1,48 @@
1
+ /* node:coverage disable */
2
+ import { css, defineElement, html, unsafeCSS } from 'element-vir';
3
+ /**
4
+ * Show a background and/or foreground color. Note that if a foreground color is provided that it is
5
+ * not actually applied to anything, you must provide a child element for it to be applied to.
6
+ *
7
+ * @category Elements
8
+ */
9
+ export const VirColorSwatch = defineElement()({
10
+ tagName: 'vir-color-swatch',
11
+ styles: css `
12
+ :host {
13
+ display: flex;
14
+ height: 400px;
15
+ width: 400px;
16
+ border: 1px solid black;
17
+ max-height: 100%;
18
+ max-width: 100%;
19
+ container-type: size;
20
+ overflow: hidden;
21
+ }
22
+
23
+ div {
24
+ flex-grow: 1;
25
+ height: 100%;
26
+ max-height: 100%;
27
+ width: 100%;
28
+ max-width: 100%;
29
+ display: flex;
30
+ justify-content: center;
31
+ align-items: center;
32
+ }
33
+ `,
34
+ render({ inputs }) {
35
+ const backgroundColor = inputs.backgroundColor || inputs.foregroundColor;
36
+ const foregroundColor = inputs.foregroundColor || 'transparent';
37
+ return html `
38
+ <div
39
+ style=${css `
40
+ background-color: ${unsafeCSS(backgroundColor)};
41
+ color: ${unsafeCSS(foregroundColor)};
42
+ `}
43
+ >
44
+ <slot></slot>
45
+ </div>
46
+ `;
47
+ },
48
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electrovir/color",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "A wrapper for culori with an extremely simple API.",
5
5
  "keywords": [
6
6
  "color",