@lifecorner/angular-ui-kit 3.22.2 → 3.22.4
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/fesm2022/lifecorner-angular-ui-kit-card.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-card.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs +4 -4
- package/fesm2022/lifecorner-angular-ui-kit-dependency-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-description-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-diff-viewer.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-diff-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-log-viewer.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-notification-center.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-progress-ring.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-progress-ring.mjs.map +1 -1
- package/package.json +1 -1
- package/src/styles/theme-contrast.spec.ts +377 -6
|
@@ -778,9 +778,10 @@ describe('Component pairings of 3.21.1 (request 029)', () => {
|
|
|
778
778
|
* element and its real backgrounds. Text 4.85 L (card success chip) and 4.60
|
|
779
779
|
* D (NC high on the panel top, card warning on surface-2); graphics 3.52 L
|
|
780
780
|
* (diff +, dependency success border) and 4.83 D (NC warning icon on an
|
|
781
|
-
* unread row). F-1: the NC high chip on an unread row in dark
|
|
781
|
+
* unread row). F-1: the NC high chip on an unread row in dark was 3.67; since
|
|
782
|
+
* 3.22.4 (request 034 D-1) the chip paints its tint over an opaque surface: 5.55.
|
|
782
783
|
*/
|
|
783
|
-
const expected = { text: [4.85, 4.6], graphic: [3.52, 4.83], ncUnread: [5.52,
|
|
784
|
+
const expected = { text: [4.85, 4.6], graphic: [3.52, 4.83], ncUnread: [5.52, 5.55], completeGlyph: [4.36, 9.12] };
|
|
784
785
|
const floor = (n: number) => Math.floor(n * 100) / 100;
|
|
785
786
|
|
|
786
787
|
/**
|
|
@@ -887,12 +888,382 @@ describe('Component pairings of 3.21.1 (request 029)', () => {
|
|
|
887
888
|
expect(glyph).toBeGreaterThanOrEqual(3);
|
|
888
889
|
});
|
|
889
890
|
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
891
|
+
// F-1 was a known residual (3.67 dark) until 3.22.4: request 034 D-1 gives
|
|
892
|
+
// the chips on an unread row an opaque --color-surface under their tint, so
|
|
893
|
+
// the translucent teal row no longer shows through.
|
|
894
|
+
it('F-1 (fixed in 3.22.4): the NC priority chips on an unread row', () => {
|
|
895
|
+
const unreadBase = rulesOf(sheets.nc).filter((r) =>
|
|
896
|
+
r.selector.split(/,(?![^(]*\))/).map((s) => s.trim()).includes('.lc-nc__item--unread .lc-nc__item-priority'),
|
|
894
897
|
);
|
|
898
|
+
expect(unreadBase).toHaveLength(1);
|
|
899
|
+
const tintOf = (modifier: string) => {
|
|
900
|
+
const image = fills('nc', `.lc-nc__item--unread .lc-nc__item-priority--${modifier}`)['background-image'];
|
|
901
|
+
const token = image.match(/^linear-gradient\((var\(--[\w-]+\)), \1\)$/);
|
|
902
|
+
expect(token).not.toBeNull();
|
|
903
|
+
return (token as RegExpMatchArray)[1];
|
|
904
|
+
};
|
|
905
|
+
const chipOnUnread = (v: string, modifier: string) =>
|
|
906
|
+
lowest(inkOf(v), unread.map((row) => layer(tintOf(modifier), layer(decls(unreadBase[0].body)['background-color'], row))));
|
|
907
|
+
const min = Math.min(chipOnUnread('warning', 'high'), chipOnUnread('error', 'urgent'));
|
|
895
908
|
expect(floor(min)).toBe(expected.ncUnread[i]);
|
|
909
|
+
expect(min).toBeGreaterThanOrEqual(4.5);
|
|
896
910
|
});
|
|
897
911
|
});
|
|
898
912
|
});
|
|
913
|
+
|
|
914
|
+
// Request 034 (3.22.4): follow-ups F-1 to F-7 of 029. Text reaches 4.5:1 and
|
|
915
|
+
// graphics and boundaries 3:1 on their real backgrounds in both themes, with
|
|
916
|
+
// pairings the kit already asserts (status inks, the lc-badge primary pair, the
|
|
917
|
+
// text steps). No token is added and no shared status value changes (design
|
|
918
|
+
// 034 §2, §5).
|
|
919
|
+
describe('Component pairings of 3.22.4 (request 034)', () => {
|
|
920
|
+
const lib = (path: string) => resolve(__dirname, '../lib', path);
|
|
921
|
+
const sheets = {
|
|
922
|
+
nc: compile(lib('notification-center/notification-center.component.scss')).css,
|
|
923
|
+
ring: compile(lib('progress-ring/progress-ring.component.scss')).css,
|
|
924
|
+
diff: compile(lib('diff-viewer/diff-viewer.component.scss')).css,
|
|
925
|
+
card: compile(lib('card/card.component.scss')).css,
|
|
926
|
+
log: compile(lib('log-viewer/log-viewer.component.scss')).css,
|
|
927
|
+
dep: compile(lib('dependency-viewer/dependency-viewer.component.scss')).css,
|
|
928
|
+
};
|
|
929
|
+
type Sheet = keyof typeof sheets;
|
|
930
|
+
const depTs = readFileSync(lib('dependency-viewer/dependency-viewer.component.ts'), 'utf8');
|
|
931
|
+
const depHtml = readFileSync(lib('dependency-viewer/dependency-viewer.component.html'), 'utf8');
|
|
932
|
+
|
|
933
|
+
/** Every rule as its selector list and body (`a, b { … }` names both). */
|
|
934
|
+
const rulesOf = (css: string) =>
|
|
935
|
+
[...css.matchAll(/([^{}]+)\{([^{}]*)\}/g)].map((m) => ({
|
|
936
|
+
selectors: m[1].split(/,(?![^(]*\))/).map((s) => s.trim()),
|
|
937
|
+
body: m[2],
|
|
938
|
+
}));
|
|
939
|
+
const decls = (body: string): Record<string, string> =>
|
|
940
|
+
Object.fromEntries([...body.matchAll(/([\w-]+):\s*([^;]+);/g)].map((m) => [m[1], m[2].trim()]));
|
|
941
|
+
/** The declarations of every rule that names `selector`, merged in source order. */
|
|
942
|
+
const fills = (sheet: Sheet, selector: string): Record<string, string> => {
|
|
943
|
+
const found = rulesOf(sheets[sheet]).filter((r) => r.selectors.includes(selector));
|
|
944
|
+
expect(found.length).toBeGreaterThan(0);
|
|
945
|
+
return Object.assign({}, ...found.map((r) => decls(r.body)));
|
|
946
|
+
};
|
|
947
|
+
/** The colour a relation reads in RELATION_STYLES. */
|
|
948
|
+
const relationColor = (relation: string) => {
|
|
949
|
+
const found = depTs.match(new RegExp(`\\n ${relation}:\\s*\\{ color: '([^']+)'`));
|
|
950
|
+
expect(found).not.toBeNull();
|
|
951
|
+
return (found as RegExpMatchArray)[1];
|
|
952
|
+
};
|
|
953
|
+
|
|
954
|
+
const ink = (v: string) => `var(--color-on-${v}-subtle)`;
|
|
955
|
+
const flat = (token: string) => `linear-gradient(var(${token}), var(${token}))`;
|
|
956
|
+
const secondary = 'var(--color-text-secondary)';
|
|
957
|
+
const tertiary = 'var(--color-text-tertiary)';
|
|
958
|
+
const meta = ['line-num', 'timestamp', 'source'];
|
|
959
|
+
type Row = [Sheet, string, Record<string, string>];
|
|
960
|
+
|
|
961
|
+
const declared: Row[] = [
|
|
962
|
+
// F-1: the chips on an unread row paint their tint over an opaque surface.
|
|
963
|
+
['nc', '.lc-nc__item--unread .lc-nc__item-priority', { 'background-color': 'var(--color-surface)' }],
|
|
964
|
+
['nc', '.lc-nc__item--unread .lc-nc__item-category', { 'background-color': 'var(--color-surface)', 'background-image': flat('--color-surface-hover') }],
|
|
965
|
+
['nc', '.lc-nc__item--unread .lc-nc__item-priority--high', { 'background-image': flat('--color-warning-subtle') }],
|
|
966
|
+
['nc', '.lc-nc__item--unread .lc-nc__item-priority--urgent', { 'background-image': flat('--color-error-subtle') }],
|
|
967
|
+
['nc', '.lc-nc__item--unread .lc-nc__item-priority--low', { 'background-image': flat('--color-surface-hover') }],
|
|
968
|
+
// F-2: the ring arcs take the progress-bar inks.
|
|
969
|
+
['ring', '.lc-progress-ring__value--primary', { stroke: 'var(--color-primary-500)' }],
|
|
970
|
+
['ring', '.lc-progress-ring__value--secondary', { stroke: 'var(--color-secondary-600)' }],
|
|
971
|
+
...['success', 'warning', 'error', 'info'].map((v): Row => ['ring', `.lc-progress-ring__value--${v}`, { stroke: ink(v) }]),
|
|
972
|
+
// F-3: subtle line tints, secondary line numbers.
|
|
973
|
+
['diff', '.lc-diff__line--added', { background: 'var(--color-success-subtle)' }],
|
|
974
|
+
['diff', '.lc-diff__line--removed', { background: 'var(--color-error-subtle)' }],
|
|
975
|
+
['diff', '.lc-diff__num', { color: secondary }],
|
|
976
|
+
// F-4: the lc-badge primary pair with a primary border.
|
|
977
|
+
['card', '.card__badge--primary', { 'background-color': 'var(--color-primary-subtle)', color: 'var(--color-on-primary-subtle)', border: '1px solid var(--color-primary-500)' }],
|
|
978
|
+
// F-5: a 40 px hit area into half of each gap; the visible pill is unchanged.
|
|
979
|
+
['log', '.lc-log-viewer__level-pill', { position: 'relative', padding: '0.125rem 0.5rem', 'font-size': '0.6875rem' }],
|
|
980
|
+
['log', '.lc-log-viewer__level-pill::before', { content: '""', position: 'absolute', 'inset-inline': '-0.125rem', top: 'calc(50% - 20px)', bottom: 'calc(50% - 20px)' }],
|
|
981
|
+
// F-7: three text steps instead of opacity, in the log and the terminal.
|
|
982
|
+
['log', '.lc-log-viewer__line--debug', { color: secondary }],
|
|
983
|
+
...meta.map((m): Row => ['log', `.lc-log-viewer__${m}`, { color: secondary }]),
|
|
984
|
+
...meta.map((m): Row => ['log', `.lc-log-viewer__line--debug .lc-log-viewer__${m}`, { color: tertiary }]),
|
|
985
|
+
['log', '.lc-log-viewer__line-count', { color: tertiary }],
|
|
986
|
+
['log', '.lc-log-viewer__search-input::placeholder', { color: tertiary, opacity: '1' }],
|
|
987
|
+
...meta.map((m): Row => ['log', `.lc-log-viewer--terminal .lc-log-viewer__${m}`, { color: '#a6adc8' }]),
|
|
988
|
+
['log', '.lc-log-viewer--terminal .lc-log-viewer__line--debug', { color: '#a6adc8' }],
|
|
989
|
+
...meta.map((m): Row => ['log', `.lc-log-viewer--terminal .lc-log-viewer__line--debug .lc-log-viewer__${m}`, { color: '#9399b2' }]),
|
|
990
|
+
['log', '.lc-log-viewer--terminal .lc-log-viewer__line-count', { color: '#9399b2' }],
|
|
991
|
+
['log', '.lc-log-viewer--terminal .lc-log-viewer__search-input::placeholder', { color: '#9399b2' }],
|
|
992
|
+
];
|
|
993
|
+
|
|
994
|
+
it.each(declared)('AC-1…9: %s %s declares the design 034 values', (sheet, selector, expectedDecls) => {
|
|
995
|
+
const found = fills(sheet, selector);
|
|
996
|
+
for (const [property, value] of Object.entries(expectedDecls)) expect(found[property]).toBe(value);
|
|
997
|
+
});
|
|
998
|
+
|
|
999
|
+
it('AC-7: no opacity dims log text (debug line, number, time, source, line count, placeholder)', () => {
|
|
1000
|
+
const textRules = rulesOf(sheets.log).filter((r) =>
|
|
1001
|
+
r.selectors.some((s) => /__line--debug|__line-num|__timestamp|__source|__line-count|::placeholder/.test(s)),
|
|
1002
|
+
);
|
|
1003
|
+
expect(textRules.length).toBeGreaterThanOrEqual(8);
|
|
1004
|
+
for (const r of textRules) {
|
|
1005
|
+
const opacity = decls(r.body).opacity;
|
|
1006
|
+
if (opacity !== undefined) expect(Number(opacity)).toBeGreaterThanOrEqual(1);
|
|
1007
|
+
}
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
it('AC-7: the terminal rules are flat selectors (no inverted nesting)', () => {
|
|
1011
|
+
expect(sheets.log).not.toMatch(/\.lc-log-viewer__[\w-]+ \.lc-log-viewer--terminal/);
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
it('AC-9: uses and extends read the tertiary text and the primary ink (edge, arrow, label, legend)', () => {
|
|
1015
|
+
const relations: [string, string][] = [['uses', tertiary], ['extends', 'var(--color-on-primary-subtle)']];
|
|
1016
|
+
for (const [relation, value] of relations) {
|
|
1017
|
+
expect(relationColor(relation)).toBe(value);
|
|
1018
|
+
const escaped = value.replace(/[()]/g, '\\$&');
|
|
1019
|
+
expect(depHtml).toMatch(new RegExp(`<marker id="arrow-${relation}"[^>]*><path [^>]*fill="${escaped}"/>`));
|
|
1020
|
+
}
|
|
1021
|
+
// The dash style still tells the relations apart (not colour alone).
|
|
1022
|
+
expect(depTs).toMatch(/\n {2}uses:\s*\{ color: '[^']+', dashed: true,/);
|
|
1023
|
+
expect(depTs).toMatch(/\n {2}extends:\s*\{ color: '[^']+', dashed: true,/);
|
|
1024
|
+
// Out of scope (follow-up F-9): `depends` and the tree edges keep their neutral lines.
|
|
1025
|
+
expect(relationColor('depends')).toBe('var(--color-neutral-400)');
|
|
1026
|
+
expect(depTs.match(/color: 'var\(--color-neutral-300\)', dashed: false, isCrossRef: false/g)).toHaveLength(2);
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
// The shared status values of 3.22.3, per palette [light, dark] (AC-2).
|
|
1030
|
+
const shared: Record<string, [string, string]> = {
|
|
1031
|
+
'--color-success': ['#8ea475', '#8ea475'],
|
|
1032
|
+
'--color-error': ['#9d0e0e', '#9d0e0e'],
|
|
1033
|
+
'--color-warning': ['#e1a040', '#e1a040'],
|
|
1034
|
+
'--color-info': ['#3b6588', '#3b6588'],
|
|
1035
|
+
'--color-success-default': ['#8ea475', '#cdd6c2'],
|
|
1036
|
+
'--color-error-default': ['#9d0e0e', '#f7a1a1'],
|
|
1037
|
+
'--color-warning-default': ['#e1a040', '#f1d3a7'],
|
|
1038
|
+
'--color-info-default': ['#3b6588', '#b8cee0'],
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Design 034 §5, floored, per palette [light, dark]. Text minimum: the diff
|
|
1043
|
+
* `+` (4.85 L, 5.17 D). Graphic minimum: the card border on hover and
|
|
1044
|
+
* selected and the `uses` cross-reference line (3.75 L), the `uses` line
|
|
1045
|
+
* (4.76 D). The terminal is always dark: 5.28 (debug level and meta).
|
|
1046
|
+
*/
|
|
1047
|
+
const expected = {
|
|
1048
|
+
text: [4.85, 5.17],
|
|
1049
|
+
graphic: [3.75, 4.76],
|
|
1050
|
+
ncUnread: { high: [5.52, 5.55], urgent: [10.97, 8.37], low: [5.3, 5.99], category: [5.3, 5.99] },
|
|
1051
|
+
ringTrack: { primary: [3.96, 6.69], secondary: [4.19, 8.35], success: [4.81, 6.15], warning: [5.47, 5.6], error: [11.43, 6.37], info: [9.22, 7.8] },
|
|
1052
|
+
diff: {
|
|
1053
|
+
numAdded: [6.91, 6.86], numRemoved: [6.58, 9.26], numContext: [7.23, 9.25],
|
|
1054
|
+
plus: [4.85, 5.17], minus: [10.97, 7.21], contentAdded: [16.24, 9.75], contentRemoved: [15.46, 13.16],
|
|
1055
|
+
},
|
|
1056
|
+
// The border on the chip fill computes to 4.05 L from the tokens (the design's browser value: 4.06).
|
|
1057
|
+
card: { text: [8.48, 5.79], borderOnCard: [3.75, 6.87], borderOnChip: [4.05, 5.79] },
|
|
1058
|
+
dep: { usesLabel: [5.83, 6.7], usesLine: [3.75, 4.76], usesLegend: [5.58, 5.56], extendsLabel: [9.13, 9.12], extendsLine: [5.32, 6.29], extendsLegend: [8.74, 7.57] },
|
|
1059
|
+
log: { meta: [5.6, 8.29], debugMessage: [6.92, 10.18], debugDim: [5.34, 6.12], count: [5.83, 6.7] },
|
|
1060
|
+
};
|
|
1061
|
+
const floor = (n: number) => Math.floor(n * 100) / 100;
|
|
1062
|
+
|
|
1063
|
+
describe.each(palettes.map(([name, tokens], i) => [name, tokens, i] as const))('%s palette', (_palette, tokens, i) => {
|
|
1064
|
+
const c = (name: string) => color(tokens, name);
|
|
1065
|
+
/** A `var(--x)`, a one-colour gradient of it, or a literal colour. */
|
|
1066
|
+
const value = (text: string): Rgba => {
|
|
1067
|
+
const gradient = text.match(/^linear-gradient\((var\(--[\w-]+\)), \1\)$/);
|
|
1068
|
+
const ref = (gradient ? gradient[1] : text).match(/^var\((--[\w-]+)\)$/);
|
|
1069
|
+
return ref ? c(ref[1]) : parse(text);
|
|
1070
|
+
};
|
|
1071
|
+
const lowest = (fg: Rgba, bases: Rgba[]) => Math.min(...bases.map((bg) => ratio(over(fg, bg), bg)));
|
|
1072
|
+
const S = c('--color-surface');
|
|
1073
|
+
const S2 = c('--color-surface-2');
|
|
1074
|
+
const BG = c('--color-background');
|
|
1075
|
+
const pages = [BG, S, S2];
|
|
1076
|
+
const ringVariants = ['primary', 'secondary', 'success', 'warning', 'error', 'info'] as const;
|
|
1077
|
+
let cache: ReturnType<typeof measure> | undefined;
|
|
1078
|
+
/** Every §5 cell, measured once on first use (inside a test, not at collection). */
|
|
1079
|
+
const measured = () => (cache ??= measure());
|
|
1080
|
+
|
|
1081
|
+
function measure() {
|
|
1082
|
+
// F-1: the chip fill is its tint over the opaque base, on any unread row.
|
|
1083
|
+
const unreadRows = [S, S2].map((row) => over(c('--color-surface-selected'), row));
|
|
1084
|
+
const unreadChip = (selector: string) => {
|
|
1085
|
+
const base = fills('nc', '.lc-nc__item--unread .lc-nc__item-priority')['background-color'];
|
|
1086
|
+
return unreadRows.map((row) => over(value(fills('nc', selector)['background-image']), over(value(base), row)));
|
|
1087
|
+
};
|
|
1088
|
+
const chipInk = (selector: string) => value(fills('nc', selector).color);
|
|
1089
|
+
const nc = {
|
|
1090
|
+
high: lowest(chipInk('.lc-nc__item-priority--high'), unreadChip('.lc-nc__item--unread .lc-nc__item-priority--high')),
|
|
1091
|
+
urgent: lowest(chipInk('.lc-nc__item-priority--urgent'), unreadChip('.lc-nc__item--unread .lc-nc__item-priority--urgent')),
|
|
1092
|
+
low: lowest(chipInk('.lc-nc__item-priority--low'), unreadChip('.lc-nc__item--unread .lc-nc__item-priority--low')),
|
|
1093
|
+
category: lowest(chipInk('.lc-nc__item-category'), unreadChip('.lc-nc__item--unread .lc-nc__item-category')),
|
|
1094
|
+
};
|
|
1095
|
+
|
|
1096
|
+
// F-2: the arc against the track (over every page) and against the page.
|
|
1097
|
+
const track = value(fills('ring', '.lc-progress-ring__track').stroke);
|
|
1098
|
+
const arc = (v: string) => value(fills('ring', `.lc-progress-ring__value--${v}`).stroke);
|
|
1099
|
+
const ringTrack = Object.fromEntries(ringVariants.map((v) => [v, lowest(arc(v), pages.map((p) => over(track, p)))]));
|
|
1100
|
+
const ringPage = ringVariants.map((v) => lowest(arc(v), pages));
|
|
1101
|
+
const ringText = lowest(value(fills('ring', '.lc-progress-ring__text').fill), pages);
|
|
1102
|
+
|
|
1103
|
+
// F-3: the line tints over every page the viewer sits on.
|
|
1104
|
+
const lineOf = (selector: string) => pages.map((p) => over(value(fills('diff', selector).background), p));
|
|
1105
|
+
const added = lineOf('.lc-diff__line--added');
|
|
1106
|
+
const removed = lineOf('.lc-diff__line--removed');
|
|
1107
|
+
const num = value(fills('diff', '.lc-diff__num').color);
|
|
1108
|
+
const content = value(fills('diff', '.lc-diff__content').color);
|
|
1109
|
+
const diff = {
|
|
1110
|
+
numAdded: lowest(num, added),
|
|
1111
|
+
numRemoved: lowest(num, removed),
|
|
1112
|
+
numContext: lowest(num, pages),
|
|
1113
|
+
plus: lowest(value(fills('diff', '.lc-diff__line--added .lc-diff__prefix').color), added),
|
|
1114
|
+
minus: lowest(value(fills('diff', '.lc-diff__line--removed .lc-diff__prefix').color), removed),
|
|
1115
|
+
contentAdded: lowest(content, added),
|
|
1116
|
+
contentRemoved: lowest(content, removed),
|
|
1117
|
+
};
|
|
1118
|
+
|
|
1119
|
+
// F-4: a card is surface, surface-2, hover, selected (over the page and
|
|
1120
|
+
// over the surface), the muted tile or the page itself.
|
|
1121
|
+
const sel = (base: Rgba) => over(c('--color-surface-selected'), base);
|
|
1122
|
+
const cards = [S, S2, over(c('--color-surface-hover'), S), sel(BG), sel(S), c('--color-muted-tile'), BG];
|
|
1123
|
+
const badge = fills('card', '.card__badge--primary');
|
|
1124
|
+
const chipFills = cards.map((base) => over(value(badge['background-color']), base));
|
|
1125
|
+
const border = value(badge.border.replace(/^1px solid /, ''));
|
|
1126
|
+
const card = {
|
|
1127
|
+
text: lowest(value(badge.color), chipFills),
|
|
1128
|
+
borderOnCard: lowest(border, cards),
|
|
1129
|
+
borderOnChip: lowest(border, chipFills),
|
|
1130
|
+
};
|
|
1131
|
+
|
|
1132
|
+
// F-6: labels on their surface halo, lines at the cross-reference opacity
|
|
1133
|
+
// on the viewer, legend lines on the legend's surface-2.
|
|
1134
|
+
const halo = value(fills('dep', '.dep-viewer__edge-label').stroke);
|
|
1135
|
+
const lineOpacity = Number(fills('dep', '.dep-viewer__edge--cross-ref').opacity);
|
|
1136
|
+
const legend = value(fills('dep', '.dep-viewer__legend').background);
|
|
1137
|
+
const faded = (rgba: Rgba): Rgba => [rgba[0], rgba[1], rgba[2], rgba[3] * lineOpacity];
|
|
1138
|
+
const relation = (name: string) => value(relationColor(name));
|
|
1139
|
+
const dep = {
|
|
1140
|
+
usesLabel: lowest(relation('uses'), [halo]),
|
|
1141
|
+
usesLine: lowest(faded(relation('uses')), [S]),
|
|
1142
|
+
usesLegend: lowest(relation('uses'), [legend]),
|
|
1143
|
+
extendsLabel: lowest(relation('extends'), [halo]),
|
|
1144
|
+
extendsLine: lowest(faded(relation('extends')), [S]),
|
|
1145
|
+
extendsLegend: lowest(relation('extends'), [legend]),
|
|
1146
|
+
};
|
|
1147
|
+
|
|
1148
|
+
// F-7: surface, the warn and error tints, each with and without hover;
|
|
1149
|
+
// debug lines have no tint. The toolbar and the search row are the surface.
|
|
1150
|
+
const logBg = value(fills('log', '.lc-log-viewer--log')['background-color']);
|
|
1151
|
+
const hover = parse(fills('log', '.lc-log-viewer__line:hover')['background-color']);
|
|
1152
|
+
const withHover = (bases: Rgba[]) => bases.flatMap((b) => [b, over(hover, b)]);
|
|
1153
|
+
const tintOf = (lv: string) => over(parse(fills('log', `.lc-log-viewer--log .lc-log-viewer__line--${lv}`)['background-color']), logBg);
|
|
1154
|
+
const logLines = withHover([logBg, tintOf('warn'), tintOf('error')]);
|
|
1155
|
+
const debugLines = withHover([logBg]);
|
|
1156
|
+
const ink7 = (selector: string) => value(fills('log', selector).color);
|
|
1157
|
+
const log = {
|
|
1158
|
+
meta: Math.min(...meta.map((m) => lowest(ink7(`.lc-log-viewer__${m}`), logLines))),
|
|
1159
|
+
debugMessage: lowest(ink7('.lc-log-viewer__line--debug'), debugLines),
|
|
1160
|
+
debugDim: Math.min(
|
|
1161
|
+
lowest(ink7('.lc-log-viewer__line--debug .lc-log-viewer__level'), debugLines),
|
|
1162
|
+
...meta.map((m) => lowest(ink7(`.lc-log-viewer__line--debug .lc-log-viewer__${m}`), debugLines)),
|
|
1163
|
+
),
|
|
1164
|
+
count: Math.min(
|
|
1165
|
+
lowest(ink7('.lc-log-viewer__line-count'), [logBg]),
|
|
1166
|
+
lowest(ink7('.lc-log-viewer__search-input::placeholder'), [logBg]),
|
|
1167
|
+
),
|
|
1168
|
+
};
|
|
1169
|
+
return { nc, ringTrack, ringPage, ringText, diff, card, dep, log };
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
it('AC-1: the NC chips on an unread row (high, urgent, low, category)', () => {
|
|
1173
|
+
const { nc } = measured();
|
|
1174
|
+
for (const [key, ncRatio] of Object.entries(nc)) {
|
|
1175
|
+
expect([key, floor(ncRatio)]).toEqual([key, expected.ncUnread[key as keyof typeof nc][i]]);
|
|
1176
|
+
expect(ncRatio).toBeGreaterThanOrEqual(4.5);
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
|
|
1180
|
+
it('AC-3: every ring arc reaches 3:1 against its track and the page; the centre text 4.5:1', () => {
|
|
1181
|
+
const { ringTrack, ringPage, ringText } = measured();
|
|
1182
|
+
for (const v of ringVariants) {
|
|
1183
|
+
expect([v, floor(ringTrack[v])]).toEqual([v, expected.ringTrack[v][i]]);
|
|
1184
|
+
expect(ringTrack[v]).toBeGreaterThanOrEqual(3);
|
|
1185
|
+
}
|
|
1186
|
+
expect(Math.min(...ringPage)).toBeGreaterThanOrEqual(3);
|
|
1187
|
+
expect(ringText).toBeGreaterThanOrEqual(4.5);
|
|
1188
|
+
});
|
|
1189
|
+
|
|
1190
|
+
it('AC-4: diff numbers and prefixes reach 4.5:1 on added, removed and context lines', () => {
|
|
1191
|
+
const { diff } = measured();
|
|
1192
|
+
for (const key of Object.keys(expected.diff) as (keyof typeof expected.diff)[]) {
|
|
1193
|
+
expect([key, floor(diff[key])]).toEqual([key, expected.diff[key][i]]);
|
|
1194
|
+
}
|
|
1195
|
+
expect(Math.min(...Object.values(diff))).toBeGreaterThanOrEqual(4.5);
|
|
1196
|
+
});
|
|
1197
|
+
|
|
1198
|
+
it('AC-5: the card primary chip text reaches 4.5:1 and its border 3:1, also on a selected card', () => {
|
|
1199
|
+
const { card } = measured();
|
|
1200
|
+
for (const key of Object.keys(card) as (keyof typeof card)[]) {
|
|
1201
|
+
expect([key, floor(card[key])]).toEqual([key, expected.card[key][i]]);
|
|
1202
|
+
}
|
|
1203
|
+
expect(card.text).toBeGreaterThanOrEqual(4.5);
|
|
1204
|
+
expect(Math.min(card.borderOnCard, card.borderOnChip)).toBeGreaterThanOrEqual(3);
|
|
1205
|
+
});
|
|
1206
|
+
|
|
1207
|
+
it('AC-9: uses and extends labels reach 4.5:1, their lines and legend lines 3:1', () => {
|
|
1208
|
+
const { dep } = measured();
|
|
1209
|
+
for (const key of Object.keys(dep) as (keyof typeof dep)[]) {
|
|
1210
|
+
expect([key, floor(dep[key])]).toEqual([key, expected.dep[key][i]]);
|
|
1211
|
+
}
|
|
1212
|
+
expect(Math.min(dep.usesLabel, dep.extendsLabel)).toBeGreaterThanOrEqual(4.5);
|
|
1213
|
+
expect(Math.min(dep.usesLine, dep.usesLegend, dep.extendsLine, dep.extendsLegend)).toBeGreaterThanOrEqual(3);
|
|
1214
|
+
});
|
|
1215
|
+
|
|
1216
|
+
it('AC-8: log meta, debug text, line count and placeholder reach 4.5:1 on every line background', () => {
|
|
1217
|
+
const { log } = measured();
|
|
1218
|
+
for (const key of Object.keys(log) as (keyof typeof log)[]) {
|
|
1219
|
+
expect([key, floor(log[key])]).toEqual([key, expected.log[key][i]]);
|
|
1220
|
+
expect(log[key]).toBeGreaterThanOrEqual(4.5);
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
it('§5: the text minimum is the diff +, the graphic minimum the card border and the uses line', () => {
|
|
1225
|
+
const { nc, ringTrack, ringPage, ringText, diff, card, dep, log } = measured();
|
|
1226
|
+
const text = Math.min(...Object.values(nc), ...Object.values(diff), card.text, dep.usesLabel, dep.extendsLabel, ...Object.values(log), ringText);
|
|
1227
|
+
const graphic = Math.min(...Object.values(ringTrack), ...ringPage, card.borderOnCard, card.borderOnChip,
|
|
1228
|
+
dep.usesLine, dep.usesLegend, dep.extendsLine, dep.extendsLegend);
|
|
1229
|
+
expect(floor(text)).toBe(expected.text[i]);
|
|
1230
|
+
expect(floor(graphic)).toBe(expected.graphic[i]);
|
|
1231
|
+
});
|
|
1232
|
+
|
|
1233
|
+
it('AC-2: the shared status values keep their 3.22.3 hex', () => {
|
|
1234
|
+
for (const [name, hexes] of Object.entries(shared)) expect([name, hex(tokens, name)]).toEqual([name, hexes[i]]);
|
|
1235
|
+
});
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
it('AC-8: the terminal meta, debug text, line count and placeholder reach 4.5:1; the levels keep their 029 ratios', () => {
|
|
1239
|
+
const T = parse(fills('log', '.lc-log-viewer--terminal')['background-color']);
|
|
1240
|
+
const bar = parse(fills('log', '.lc-log-viewer--terminal .lc-log-viewer__toolbar')['background-color']);
|
|
1241
|
+
const searchRow = parse(fills('log', '.lc-log-viewer--terminal .lc-log-viewer__search')['background-color']);
|
|
1242
|
+
const hover = parse(fills('log', '.lc-log-viewer__line:hover')['background-color']);
|
|
1243
|
+
const tint = (lv: string) => over(parse(fills('log', `.lc-log-viewer--terminal .lc-log-viewer__line--${lv}`)['background-color']), T);
|
|
1244
|
+
const withHover = (bases: Rgba[]) => bases.flatMap((b) => [b, over(hover, b)]);
|
|
1245
|
+
const lines = withHover([T, tint('warn'), tint('error')]);
|
|
1246
|
+
const debugLines = withHover([T]);
|
|
1247
|
+
const ink7 = (selector: string) => parse(fills('log', selector).color);
|
|
1248
|
+
const lowest = (fg: Rgba, bases: Rgba[]) => Math.min(...bases.map((bg) => ratio(fg, bg)));
|
|
1249
|
+
const terminal = {
|
|
1250
|
+
meta: Math.min(...meta.map((m) => lowest(ink7(`.lc-log-viewer--terminal .lc-log-viewer__${m}`), lines))),
|
|
1251
|
+
debugMessage: lowest(ink7('.lc-log-viewer--terminal .lc-log-viewer__line--debug'), debugLines),
|
|
1252
|
+
debugDim: Math.min(
|
|
1253
|
+
lowest(ink7('.lc-log-viewer--terminal .lc-log-viewer__line--debug .lc-log-viewer__level'), debugLines),
|
|
1254
|
+
...meta.map((m) => lowest(ink7(`.lc-log-viewer--terminal .lc-log-viewer__line--debug .lc-log-viewer__${m}`), debugLines)),
|
|
1255
|
+
),
|
|
1256
|
+
count: Math.min(
|
|
1257
|
+
lowest(ink7('.lc-log-viewer--terminal .lc-log-viewer__line-count'), [bar]),
|
|
1258
|
+
lowest(ink7('.lc-log-viewer--terminal .lc-log-viewer__search-input::placeholder'), [searchRow]),
|
|
1259
|
+
),
|
|
1260
|
+
};
|
|
1261
|
+
expect(Object.fromEntries(Object.entries(terminal).map(([k, v]) => [k, floor(v)]))).toEqual({ meta: 5.85, debugMessage: 6.7, debugDim: 5.28, count: 6.21 });
|
|
1262
|
+
expect(Math.min(...Object.values(terminal))).toBeGreaterThanOrEqual(4.5);
|
|
1263
|
+
const levelBases: Record<string, Rgba> = { debug: T, info: T, warn: tint('warn'), error: tint('error') };
|
|
1264
|
+
const levels = ['debug', 'info', 'warn', 'error'].map((lv) =>
|
|
1265
|
+
floor(ratio(ink7(`.lc-log-viewer--terminal .lc-log-viewer__line--${lv} .lc-log-viewer__level`), levelBases[lv])),
|
|
1266
|
+
);
|
|
1267
|
+
expect(levels).toEqual([5.81, 7.78, 11.43, 6.19]);
|
|
1268
|
+
});
|
|
1269
|
+
});
|