theme-vir 28.25.0 → 28.25.2
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-theme/build-color-theme.js +33 -17
- package/dist/color-theme/color-palette-book-pages.js +9 -7
- package/dist/color-theme/color-theme-book-pages.js +7 -5
- package/dist/color-theme/color-theme-code.js +21 -5
- package/dist/color-theme/color-theme.js +1 -0
- package/dist/create-theme/define-theme-elements.js +7 -1
- package/package.json +21 -21
|
@@ -139,9 +139,7 @@ function resolveExtremeContrastColor({ comparison, isHighestContrast, lightestCo
|
|
|
139
139
|
? lightestColorString
|
|
140
140
|
: darkestColorString;
|
|
141
141
|
}
|
|
142
|
-
function findColorWithPreference(colors, desiredContrastLevel, preference,
|
|
143
|
-
/** Pre-computed contrast-against-white values per color string. Higher = darker. */
|
|
144
|
-
lightnessProxies) {
|
|
142
|
+
function findColorWithPreference({ colors, desiredContrastLevel, preference, lightnessProxies, }) {
|
|
145
143
|
const minContrast = contrastLevelNameMap[desiredContrastLevel].min;
|
|
146
144
|
const candidateColors = check.isArray(colors.foreground)
|
|
147
145
|
? colors.foreground
|
|
@@ -214,10 +212,12 @@ export function buildColorTheme(colorPalette, { omittedColorValues = defaultOmit
|
|
|
214
212
|
const colorStrings = colors.map((color) => color.definition.default);
|
|
215
213
|
const firstColor = colors[0];
|
|
216
214
|
// Create an object for O(1) color lookup instead of O(n) find()
|
|
217
|
-
const colorByDefault = arrayToObject(colors, (color) =>
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
215
|
+
const colorByDefault = arrayToObject(colors, (color) => {
|
|
216
|
+
return {
|
|
217
|
+
key: color.definition.default,
|
|
218
|
+
value: color,
|
|
219
|
+
};
|
|
220
|
+
});
|
|
221
221
|
/** Pre-computed contrast-against-white per color. Higher value = darker shade. */
|
|
222
222
|
const lightnessProxies = arrayToObject(colorStrings, (colorString) => {
|
|
223
223
|
return {
|
|
@@ -229,27 +229,43 @@ export function buildColorTheme(colorPalette, { omittedColorValues = defaultOmit
|
|
|
229
229
|
};
|
|
230
230
|
});
|
|
231
231
|
/** Lightest palette color (least contrast against white). */
|
|
232
|
-
const lightestColorString = colorStrings.reduce((lightest, color) =>
|
|
233
|
-
|
|
234
|
-
|
|
232
|
+
const lightestColorString = colorStrings.reduce((lightest, color) => {
|
|
233
|
+
return (lightnessProxies[color] ?? 0) < (lightnessProxies[lightest] ?? 0)
|
|
234
|
+
? color
|
|
235
|
+
: lightest;
|
|
236
|
+
});
|
|
235
237
|
/** Darkest palette color (most contrast against white). */
|
|
236
|
-
const darkestColorString = colorStrings.reduce((darkest, color) =>
|
|
238
|
+
const darkestColorString = colorStrings.reduce((darkest, color) => {
|
|
239
|
+
return (lightnessProxies[color] ?? 0) > (lightnessProxies[darkest] ?? 0)
|
|
240
|
+
? color
|
|
241
|
+
: darkest;
|
|
242
|
+
});
|
|
237
243
|
/**
|
|
238
244
|
* On-self light mode: lightest fg achieving small-body contrast on the lightest palette
|
|
239
245
|
* bg. Fixed across all on-self contrast levels.
|
|
240
246
|
*/
|
|
241
247
|
const lightSelfFgString = assertWrap.isTruthy(findColorWithPreference({
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
248
|
+
colors: {
|
|
249
|
+
foreground: colorStrings,
|
|
250
|
+
background: lightestColorString,
|
|
251
|
+
},
|
|
252
|
+
desiredContrastLevel: ContrastLevelName.SmallBodyText,
|
|
253
|
+
preference: 'lightest',
|
|
254
|
+
lightnessProxies,
|
|
255
|
+
}), `Failed to find light mode on-self foreground color for ${firstColor.colorName}`);
|
|
245
256
|
/**
|
|
246
257
|
* On-self dark mode: darkest fg achieving small-body contrast on the darkest palette
|
|
247
258
|
* bg. Fixed across all on-self contrast levels.
|
|
248
259
|
*/
|
|
249
260
|
const darkSelfFgString = assertWrap.isTruthy(findColorWithPreference({
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
261
|
+
colors: {
|
|
262
|
+
foreground: colorStrings,
|
|
263
|
+
background: darkestColorString,
|
|
264
|
+
},
|
|
265
|
+
desiredContrastLevel: ContrastLevelName.SmallBodyText,
|
|
266
|
+
preference: 'darkest',
|
|
267
|
+
lightnessProxies,
|
|
268
|
+
}), `Failed to find dark mode on-self foreground color for ${firstColor.colorName}`);
|
|
253
269
|
/**
|
|
254
270
|
* Reversed palette order for dark mode on-self backgrounds. `findColorAtContrastLevel`
|
|
255
271
|
* picks the last qualifying color in array order. With the natural lightest-to-darkest
|
|
@@ -241,13 +241,15 @@ export function createColorPaletteBookPages({ colors, parent, title, includeCont
|
|
|
241
241
|
}
|
|
242
242
|
const blackWhiteContrastPage = createContrastPage('Contrast Black White', blackWhiteCells);
|
|
243
243
|
function createSelfContrastPage(fontWeight) {
|
|
244
|
-
return createContrastPage(`Contrast Self ${fontWeight}`, (colors) =>
|
|
245
|
-
return {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
244
|
+
return createContrastPage(`Contrast Self ${fontWeight}`, (colors) => {
|
|
245
|
+
return colors.map((color) => {
|
|
246
|
+
return {
|
|
247
|
+
fontWeight,
|
|
248
|
+
title: color.suffix || '',
|
|
249
|
+
foreground: color.definition,
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
});
|
|
251
253
|
}
|
|
252
254
|
function createThemePages() {
|
|
253
255
|
const generatedTheme = buildColorTheme(colors, options);
|
|
@@ -116,11 +116,13 @@ export function createColorThemeBookPages({ parent, title, theme, hideInverseCol
|
|
|
116
116
|
const currentTheme = selectedOverride?.asTheme || defaultTheme;
|
|
117
117
|
return html `
|
|
118
118
|
<div class="theme-wrapper">
|
|
119
|
-
${group.map((entry) =>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
${group.map((entry) => {
|
|
120
|
+
return buildThemeColorTemplate({
|
|
121
|
+
controls,
|
|
122
|
+
theme: currentTheme,
|
|
123
|
+
themeColorName: entry,
|
|
124
|
+
});
|
|
125
|
+
})}
|
|
124
126
|
</div>
|
|
125
127
|
`;
|
|
126
128
|
},
|
|
@@ -8,8 +8,18 @@ import { CSSResult } from 'element-vir';
|
|
|
8
8
|
*/
|
|
9
9
|
export function generateThemeCode(theme, options) {
|
|
10
10
|
const paletteVarName = options?.paletteVarName;
|
|
11
|
-
const defaultInitCode = colorInitToCode(
|
|
12
|
-
|
|
11
|
+
const defaultInitCode = colorInitToCode({
|
|
12
|
+
colorInit: theme.init.default,
|
|
13
|
+
indentLevel: 1,
|
|
14
|
+
defaultInit: undefined,
|
|
15
|
+
paletteVarName,
|
|
16
|
+
});
|
|
17
|
+
const colorsInitCode = colorThemeInitToCode({
|
|
18
|
+
colorsInit: theme.init.colors,
|
|
19
|
+
indentLevel: 1,
|
|
20
|
+
defaultInit: theme.init.default,
|
|
21
|
+
paletteVarName,
|
|
22
|
+
});
|
|
13
23
|
const themeCode = `export const theme = defineColorTheme(\n${defaultInitCode},\n${colorsInitCode},\n);`;
|
|
14
24
|
const overridesCodes = (options?.overrides || []).map((override) => {
|
|
15
25
|
return generateOverrideCode(override, paletteVarName);
|
|
@@ -63,6 +73,7 @@ function generateOverrideCode(override, paletteVarName) {
|
|
|
63
73
|
function tab(level) {
|
|
64
74
|
return ' '.repeat(level);
|
|
65
75
|
}
|
|
76
|
+
// eslint-disable-next-line @virmator/prefer-params-object
|
|
66
77
|
function colorInitValuesEqual(a, b) {
|
|
67
78
|
if (typeof a !== typeof b) {
|
|
68
79
|
return false;
|
|
@@ -116,7 +127,7 @@ function colorInitValueToCode(value, indentLevel, paletteVarName) {
|
|
|
116
127
|
return `'${value.default}'`;
|
|
117
128
|
}
|
|
118
129
|
}
|
|
119
|
-
function colorInitToCode(colorInit, indentLevel, defaultInit, paletteVarName) {
|
|
130
|
+
function colorInitToCode({ colorInit, indentLevel, defaultInit, paletteVarName, }) {
|
|
120
131
|
const entries = [];
|
|
121
132
|
if ('foreground' in colorInit &&
|
|
122
133
|
(!defaultInit || !colorInitValuesEqual(colorInit.foreground, defaultInit.foreground)) &&
|
|
@@ -142,9 +153,14 @@ function colorInitToCode(colorInit, indentLevel, defaultInit, paletteVarName) {
|
|
|
142
153
|
}
|
|
143
154
|
return `${tab(indentLevel)}{\n${entries.join('\n')}\n${tab(indentLevel)}}`;
|
|
144
155
|
}
|
|
145
|
-
function colorThemeInitToCode(colorsInit, indentLevel, defaultInit, paletteVarName) {
|
|
156
|
+
function colorThemeInitToCode({ colorsInit, indentLevel, defaultInit, paletteVarName, }) {
|
|
146
157
|
const entries = getObjectTypedEntries(colorsInit).map(([colorName, colorInit,]) => {
|
|
147
|
-
return `${tab(indentLevel + 1)}'${colorName}': ${colorInitToCode(
|
|
158
|
+
return `${tab(indentLevel + 1)}'${colorName}': ${colorInitToCode({
|
|
159
|
+
colorInit,
|
|
160
|
+
indentLevel: indentLevel + 1,
|
|
161
|
+
defaultInit,
|
|
162
|
+
paletteVarName,
|
|
163
|
+
}).trimStart()},`;
|
|
148
164
|
});
|
|
149
165
|
return `${tab(indentLevel)}{\n${entries.join('\n')}\n${tab(indentLevel)}}`;
|
|
150
166
|
}
|
|
@@ -16,6 +16,7 @@ export function noRefColorInitToString(init) {
|
|
|
16
16
|
*
|
|
17
17
|
* @category Internal
|
|
18
18
|
*/
|
|
19
|
+
// eslint-disable-next-line @virmator/prefer-params-object
|
|
19
20
|
export function createColorCssVarDefault(fromName, init, defaultInit, colorsInit) {
|
|
20
21
|
const defaultForegroundKey = `${defaultInit.prefix}-default-fg`;
|
|
21
22
|
const defaultBackgroundKey = `${defaultInit.prefix}-default-bg`;
|
|
@@ -77,7 +77,13 @@ function defineHeadingElement(options) {
|
|
|
77
77
|
const headingSelectors = unsafeCSS(getEnumValues(HeadingLevel).join(', '));
|
|
78
78
|
return defineElement()({
|
|
79
79
|
tagName: headingTag,
|
|
80
|
-
hostClasses: typedObjectFromEntries(
|
|
80
|
+
hostClasses: typedObjectFromEntries(
|
|
81
|
+
/**
|
|
82
|
+
* `mapEnumToObject` cannot be used here: host class keys must be prefixed with the
|
|
83
|
+
* element's tag name, not the bare enum values.
|
|
84
|
+
*/
|
|
85
|
+
// eslint-disable-next-line @virmator/prefer-map-enum-to-object
|
|
86
|
+
getEnumValues(HeadingLevel).map((headingLevel) => {
|
|
81
87
|
return [
|
|
82
88
|
`${headingTag}-${headingLevel}`,
|
|
83
89
|
({ inputs }) => inputs.headingLevel === headingLevel,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theme-vir",
|
|
3
|
-
"version": "28.25.
|
|
3
|
+
"version": "28.25.2",
|
|
4
4
|
"description": "Create an entire web theme.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"design",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"type": "git",
|
|
23
23
|
"url": "git+https://github.com/electrovir/theme-vir.git"
|
|
24
24
|
},
|
|
25
|
-
"license": "(MIT
|
|
25
|
+
"license": "(MIT OR CC0-1.0)",
|
|
26
26
|
"author": {
|
|
27
27
|
"name": "electrovir",
|
|
28
28
|
"url": "https://github.com/electrovir"
|
|
@@ -43,35 +43,35 @@
|
|
|
43
43
|
"test:update": "virmator test web update"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@augment-vir/assert": "^
|
|
47
|
-
"@augment-vir/common": "^
|
|
48
|
-
"@electrovir/color": "^1.7.
|
|
46
|
+
"@augment-vir/assert": "^32.2.3",
|
|
47
|
+
"@augment-vir/common": "^32.2.3",
|
|
48
|
+
"@electrovir/color": "^1.7.11",
|
|
49
49
|
"apca-w3": "^0.1.9",
|
|
50
|
-
"lit-css-vars": "^3.
|
|
51
|
-
"type-fest": "^5.
|
|
50
|
+
"lit-css-vars": "^3.6.3",
|
|
51
|
+
"type-fest": "^5.8.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@augment-vir/test": "^
|
|
54
|
+
"@augment-vir/test": "^32.2.3",
|
|
55
55
|
"@types/apca-w3": "^0.1.3",
|
|
56
|
-
"@web/dev-server-esbuild": "^
|
|
57
|
-
"@web/test-runner": "^0.
|
|
58
|
-
"@web/test-runner-commands": "^0.
|
|
59
|
-
"@web/test-runner-playwright": "^0.
|
|
60
|
-
"@web/test-runner-visual-regression": "^0.
|
|
61
|
-
"element-book": "^26.17.
|
|
62
|
-
"element-vir": "^26.
|
|
63
|
-
"esbuild": "^0.
|
|
56
|
+
"@web/dev-server-esbuild": "^2.0.0",
|
|
57
|
+
"@web/test-runner": "^1.0.0",
|
|
58
|
+
"@web/test-runner-commands": "^1.0.1",
|
|
59
|
+
"@web/test-runner-playwright": "^1.0.0",
|
|
60
|
+
"@web/test-runner-visual-regression": "^1.0.1",
|
|
61
|
+
"element-book": "^26.17.4",
|
|
62
|
+
"element-vir": "^26.17.3",
|
|
63
|
+
"esbuild": "^0.28.2",
|
|
64
64
|
"istanbul-smart-text-reporter": "^1.1.5",
|
|
65
|
-
"markdown-code-example-inserter": "^3.0.
|
|
66
|
-
"typedoc": "^0.28.
|
|
65
|
+
"markdown-code-example-inserter": "^3.0.6",
|
|
66
|
+
"typedoc": "^0.28.20",
|
|
67
67
|
"typescript": "5.9.3",
|
|
68
|
-
"vira": "^
|
|
69
|
-
"vite": "^
|
|
68
|
+
"vira": "^31.31.6",
|
|
69
|
+
"vite": "^8.2.2",
|
|
70
70
|
"vite-tsconfig-paths": "^6.1.1"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
73
|
"element-book": ">=17",
|
|
74
|
-
"element-vir": "
|
|
74
|
+
"element-vir": "^26",
|
|
75
75
|
"vira": ">=28"
|
|
76
76
|
},
|
|
77
77
|
"engines": {
|