@eagami/ui 5.50.0 → 5.52.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagami/ui",
3
- "version": "5.50.0",
3
+ "version": "5.52.0",
4
4
  "description": "Lightweight, accessible, themeable Angular UI component library and icon set built on CSS custom properties",
5
5
  "author": "Michal Wiraszka <michal@eagami.com>",
6
6
  "license": "MIT",
@@ -173,6 +173,18 @@
173
173
  --color-picker-sv-white: #ffffff;
174
174
  --color-picker-sv-black: #000000;
175
175
  --color-picker-thumb-halo: rgba(0, 0, 0, 0.25);
176
+
177
+ // Categorical chart palette. The order is what keeps adjacent series
178
+ // distinguishable under colour-vision deficiency, so reorder only after
179
+ // re-checking every neighbouring pair.
180
+ --color-chart-1: #2a78d6;
181
+ --color-chart-2: #eb6834;
182
+ --color-chart-3: #1baf7a;
183
+ --color-chart-4: #eda100;
184
+ --color-chart-5: #e87ba4;
185
+ --color-chart-6: #008300;
186
+ --color-chart-7: #4a3aa7;
187
+ --color-chart-8: #e34948;
176
188
  }
177
189
 
178
190
  // Dark mode: applied when the OS prefers dark, unless forced light via
@@ -262,6 +274,15 @@
262
274
  --color-warning-text: var(--color-warning-200);
263
275
  --color-error-text: var(--color-error-200);
264
276
  --color-info-text: var(--color-info-200);
277
+
278
+ --color-chart-1: #3987e5;
279
+ --color-chart-2: #d95926;
280
+ --color-chart-3: #199e70;
281
+ --color-chart-4: #c98500;
282
+ --color-chart-5: #d55181;
283
+ --color-chart-6: #008300;
284
+ --color-chart-7: #9085e9;
285
+ --color-chart-8: #e66767;
265
286
  }
266
287
 
267
288
  @media (prefers-color-scheme: dark) {
@@ -0,0 +1,72 @@
1
+ /// <reference types="node" />
2
+ import { readFileSync, readdirSync } from 'node:fs';
3
+ import { join, relative } from 'node:path';
4
+
5
+ /**
6
+ * Source-level guards for the type scale, so text at a given size tier renders
7
+ * at the same pixel size in every component. A component's `size` input picks
8
+ * the base font-size; text below the body line inside the component is a fixed
9
+ * fraction of it, taken from the one scale below. A near-miss ratio (0.85em
10
+ * beside 0.875em) is invisible in review and only shows as mismatched text
11
+ * when two components sit side by side.
12
+ */
13
+
14
+ const SRC = process.cwd();
15
+
16
+ /** Relative sizes for text below the body line, by role. */
17
+ const SUB_BODY_SCALE: Record<string, number> = {
18
+ secondary: 0.875,
19
+ helper: 0.8125,
20
+ caption: 0.75,
21
+ micro: 0.625,
22
+ };
23
+
24
+ function libStylesheets(): { name: string; css: string }[] {
25
+ const lib = join(SRC, 'src/lib');
26
+ return readdirSync(lib, { recursive: true, encoding: 'utf8' })
27
+ .filter(file => file.endsWith('.scss'))
28
+ .map(file => ({
29
+ name: relative(lib, join(lib, file)),
30
+ css: readFileSync(join(lib, file), 'utf8'),
31
+ }));
32
+ }
33
+
34
+ describe('Type scale', () => {
35
+ it('sets each size tier to its own font-size token', () => {
36
+ const mismatches: string[] = [];
37
+ for (const { name, css } of libStylesheets()) {
38
+ for (const [, tier, body] of css.matchAll(
39
+ /&--(2xs|xs|sm|md|lg|xl)\s*\{([^{}]*)\}/g,
40
+ )) {
41
+ const size = body.match(/(?:^|[\s;])font-size:\s*([^;]+);/)?.[1];
42
+ // A consumer override may sit in front, as long as it falls back to the tier's token
43
+ const token = `var(--font-size-${tier})`;
44
+ const overridable = new RegExp(
45
+ `^var\\(--ea-[\\w-]+-font-size, ${token.replace(/[()]/g, '\\$&')}\\)$`,
46
+ );
47
+ if (size && size.trim() !== token && !overridable.test(size.trim())) {
48
+ mismatches.push(`${name} --${tier}: ${size.trim()}`);
49
+ }
50
+ }
51
+ }
52
+
53
+ expect(mismatches).toEqual([]);
54
+ });
55
+
56
+ it('draws text below the body line from the shared scale', () => {
57
+ const allowed = new Set(Object.values(SUB_BODY_SCALE));
58
+ const offScale: string[] = [];
59
+ for (const { name, css } of libStylesheets()) {
60
+ for (const [declaration, value] of css.matchAll(
61
+ /(?:font-size|--ea-field-(?:label|messages)-size):\s*([\d.]+)em\b/g,
62
+ )) {
63
+ const ratio = Number(value);
64
+ if (ratio < 1 && !allowed.has(ratio)) {
65
+ offScale.push(`${name}: ${declaration}`);
66
+ }
67
+ }
68
+ }
69
+
70
+ expect(offScale).toEqual([]);
71
+ });
72
+ });