@siyahi/tools 0.1.9-next.24 → 0.1.9-next.26
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/contrast.mjs +38 -16
- package/package.json +1 -1
- package/types/contrast.d.mts +1 -0
package/contrast.mjs
CHANGED
|
@@ -23,10 +23,14 @@ import { readTheme } from "./theme.mjs";
|
|
|
23
23
|
* What a component paints, written as Tailwind writes it:
|
|
24
24
|
* `muted` is the token, `muted/50` the token at 50% over what lies under it,
|
|
25
25
|
* and `positive@60` is `color-mix(in oklab, var(--positive) 60%, var(--card))`,
|
|
26
|
-
* a treemap tile.
|
|
26
|
+
* a treemap tile; `positive@heat-5` takes the share from the theme's --heat-5.
|
|
27
27
|
* @typedef {string} Paint
|
|
28
28
|
*/
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* `surface` limits a pair to the canvas or the card, for a paint only one of them ever holds, such as a chart card's
|
|
31
|
+
* hover band.
|
|
32
|
+
* @typedef {{ fg: Paint, bg: Paint, min: number, scheme?: Scheme, surface?: "background" | "card" }} Pair
|
|
33
|
+
*/
|
|
30
34
|
|
|
31
35
|
const TEXT = 4.5;
|
|
32
36
|
const MARK = 3;
|
|
@@ -34,14 +38,12 @@ const SURFACES = ["background", "card"];
|
|
|
34
38
|
const CHARTS = ["chart-1", "chart-2", "chart-3", "chart-4", "chart-5"];
|
|
35
39
|
|
|
36
40
|
/**
|
|
37
|
-
* The
|
|
38
|
-
* @
|
|
39
|
-
* @returns {Pair[]}
|
|
41
|
+
* The label on each heat step, both sides, at the shares the theme's --heat-1 to --heat-5 set.
|
|
42
|
+
* @type {Pair[]}
|
|
40
43
|
*/
|
|
41
|
-
const
|
|
42
|
-
[
|
|
43
|
-
|
|
44
|
-
);
|
|
44
|
+
const HEAT_LABELS = ["positive", "negative"].flatMap((side) =>
|
|
45
|
+
[1, 2, 3, 4, 5].map((step) => ({ fg: "foreground", bg: `${side}@heat-${step}`, min: TEXT })),
|
|
46
|
+
);
|
|
45
47
|
|
|
46
48
|
/** @type {Pair[]} */
|
|
47
49
|
const PAIRS = [
|
|
@@ -95,16 +97,27 @@ const PAIRS = [
|
|
|
95
97
|
["positive", "positive/8"],
|
|
96
98
|
["negative", "negative/8"],
|
|
97
99
|
].map(([fg = "", bg = ""]) => ({ fg, bg, min: MARK })),
|
|
100
|
+
// A StatusHeatmap's degraded and critical days against a healthy one, its
|
|
101
|
+
// default 30% grey, so a bad day stands out of a run of good ones.
|
|
102
|
+
...["warning", "destructive"].map((fg) => ({ fg, bg: "muted-foreground/30", min: MARK })),
|
|
98
103
|
// The selected tab's fill against its list.
|
|
99
104
|
{ fg: "foreground", bg: "muted", min: MARK },
|
|
100
105
|
// Chart marks on the canvas and the card. A dimmed bar keeps its full colour
|
|
101
106
|
// as its outline, so these are the outlines too.
|
|
102
107
|
...[...CHARTS, "positive", "negative"].map((fg) => ({ fg, bg: "", min: MARK })),
|
|
103
108
|
...CHARTS.slice(0, -1).map((fg, i) => ({ fg, bg: CHARTS[i + 1] ?? "", min: MARK })),
|
|
104
|
-
//
|
|
105
|
-
// the
|
|
106
|
-
|
|
107
|
-
...
|
|
109
|
+
// A waterfall's rise and fall: the full-colour edge against the tint it
|
|
110
|
+
// encloses, on the bar and its legend chip; and every bar colour against the
|
|
111
|
+
// 40% muted band a chart card lays behind a hovered category (lib/chart-frame).
|
|
112
|
+
...["positive", "negative"].map((side) => ({ fg: side, bg: `${side}@35`, min: MARK })),
|
|
113
|
+
...[...CHARTS, "positive", "negative"].map((fg) => ({ fg, bg: "muted/40", min: MARK, surface: "card" })),
|
|
114
|
+
// A chart card's footer text, on the footer's muted wash.
|
|
115
|
+
{ fg: "foreground", bg: "muted/50", min: TEXT },
|
|
116
|
+
// Treemap, ChangeGrid and signed-calendar labels on every heat step
|
|
117
|
+
// (lib/heat.ts heatFill), at the theme's own --heat-N shares. A ChangeGrid
|
|
118
|
+
// cell with no change is muted, with its figure in the text colour.
|
|
119
|
+
{ fg: "foreground", bg: "muted", min: TEXT },
|
|
120
|
+
...HEAT_LABELS,
|
|
108
121
|
];
|
|
109
122
|
|
|
110
123
|
/**
|
|
@@ -115,6 +128,12 @@ export function checkContrast(theme) {
|
|
|
115
128
|
/** @type {Map<string, Check>} */
|
|
116
129
|
const checks = new Map();
|
|
117
130
|
for (const scheme of /** @type {const} */ (["light", "dark"])) {
|
|
131
|
+
const percentage = (/** @type {string} */ name) => {
|
|
132
|
+
const value = theme[scheme][name];
|
|
133
|
+
const match = value === undefined ? null : /^([\d.]+)%$/.exec(value);
|
|
134
|
+
if (!match) throw new Error(`${scheme}: --${name} is "${value}", not a percentage`);
|
|
135
|
+
return Number(match[1]);
|
|
136
|
+
};
|
|
118
137
|
const token = (/** @type {string} */ name) => {
|
|
119
138
|
const value = theme[scheme][name];
|
|
120
139
|
if (value === undefined) throw new Error(`${scheme}: --${name} is not set in the ${scheme} block`);
|
|
@@ -127,11 +146,13 @@ export function checkContrast(theme) {
|
|
|
127
146
|
* @param {Paint} paint @param {{ rgb: [number, number, number], name: string }} under
|
|
128
147
|
*/
|
|
129
148
|
const paintOver = (paint, under) => {
|
|
130
|
-
const [, name = "", sep, amount] = /^([\w-]+)(?:([/@])([\
|
|
149
|
+
const [, name = "", sep, amount = ""] = /^([\w-]+)(?:([/@])([\w.-]+))?$/.exec(paint) ?? [];
|
|
131
150
|
const base = token(name);
|
|
132
151
|
if (sep === "@") {
|
|
133
|
-
|
|
134
|
-
|
|
152
|
+
// A share is a number, or the name of a theme token holding a percentage, such as heat-5.
|
|
153
|
+
const share = /^[\d.]+$/.test(amount) ? Number(amount) : percentage(amount);
|
|
154
|
+
const rgb = oklchToSrgb(mixOklab(base, token("card"), share / 100));
|
|
155
|
+
return { rgb, name: `--${name} ${share}% in --card` };
|
|
135
156
|
}
|
|
136
157
|
const alpha = base.alpha * (sep === "/" ? Number(amount) / 100 : 1);
|
|
137
158
|
if (alpha === 1) return { rgb: oklchToSrgb(base), name: `--${paint}` };
|
|
@@ -140,6 +161,7 @@ export function checkContrast(theme) {
|
|
|
140
161
|
for (const pair of PAIRS) {
|
|
141
162
|
if (pair.scheme && pair.scheme !== scheme) continue;
|
|
142
163
|
for (const surface of SURFACES) {
|
|
164
|
+
if (pair.surface && pair.surface !== surface) continue;
|
|
143
165
|
const page = { rgb: oklchToSrgb(token(surface)), name: `--${surface}` };
|
|
144
166
|
const bg = pair.bg ? paintOver(pair.bg, page) : page;
|
|
145
167
|
const fg = paintOver(pair.fg, bg);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@siyahi/tools",
|
|
3
|
-
"version": "0.1.9-next.
|
|
3
|
+
"version": "0.1.9-next.26",
|
|
4
4
|
"description": "Checks and build helpers for Siyahi pages: a lint plugin, a font preload plugin, a theme contrast check, and screenshot and layout shift scripts.",
|
|
5
5
|
"homepage": "https://siyahi.jatinbansal.com",
|
|
6
6
|
"license": "MIT",
|