@363045841yyt/klinechart-core 0.7.6 → 0.7.8
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/config/chartSettings.d.ts +27 -2
- package/dist/config/chartSettings.d.ts.map +1 -1
- package/dist/config/chartSettings.js +6 -0
- package/dist/config/chartSettings.js.map +1 -1
- package/dist/engine/chart.d.ts.map +1 -1
- package/dist/engine/chart.js +4 -0
- package/dist/engine/chart.js.map +1 -1
- package/dist/engine/draw/pixelAlign.d.ts.map +1 -1
- package/dist/engine/draw/pixelAlign.js.map +1 -1
- package/dist/engine/drawing/plugin.js +1 -1
- package/dist/engine/drawing/plugin.js.map +1 -1
- package/dist/engine/renderers/Indicator/atr.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/atr.js +7 -4
- package/dist/engine/renderers/Indicator/atr.js.map +1 -1
- package/dist/engine/renderers/Indicator/boll.js +12 -12
- package/dist/engine/renderers/Indicator/boll.js.map +1 -1
- package/dist/engine/renderers/Indicator/cci.d.ts +1 -2
- package/dist/engine/renderers/Indicator/cci.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/cci.js +9 -9
- package/dist/engine/renderers/Indicator/cci.js.map +1 -1
- package/dist/engine/renderers/Indicator/ene.js +12 -12
- package/dist/engine/renderers/Indicator/ene.js.map +1 -1
- package/dist/engine/renderers/Indicator/expma.js +6 -6
- package/dist/engine/renderers/Indicator/expma.js.map +1 -1
- package/dist/engine/renderers/Indicator/fastk.d.ts +1 -2
- package/dist/engine/renderers/Indicator/fastk.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/fastk.js +7 -7
- package/dist/engine/renderers/Indicator/fastk.js.map +1 -1
- package/dist/engine/renderers/Indicator/kst.d.ts +1 -2
- package/dist/engine/renderers/Indicator/kst.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/kst.js +10 -10
- package/dist/engine/renderers/Indicator/kst.js.map +1 -1
- package/dist/engine/renderers/Indicator/ma.js +5 -5
- package/dist/engine/renderers/Indicator/ma.js.map +1 -1
- package/dist/engine/renderers/Indicator/macd.d.ts +1 -2
- package/dist/engine/renderers/Indicator/macd.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/macd.js +24 -24
- package/dist/engine/renderers/Indicator/macd.js.map +1 -1
- package/dist/engine/renderers/Indicator/macdLegend.js +6 -6
- package/dist/engine/renderers/Indicator/macdLegend.js.map +1 -1
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.js +16 -16
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.js.map +1 -1
- package/dist/engine/renderers/Indicator/mom.d.ts +1 -2
- package/dist/engine/renderers/Indicator/mom.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/mom.js +8 -8
- package/dist/engine/renderers/Indicator/mom.js.map +1 -1
- package/dist/engine/renderers/Indicator/rsi.d.ts +2 -3
- package/dist/engine/renderers/Indicator/rsi.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/rsi.js +19 -15
- package/dist/engine/renderers/Indicator/rsi.js.map +1 -1
- package/dist/engine/renderers/Indicator/scale/indicator_scale.d.ts +1 -2
- package/dist/engine/renderers/Indicator/scale/indicator_scale.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/scale/indicator_scale.js +5 -5
- package/dist/engine/renderers/Indicator/scale/indicator_scale.js.map +1 -1
- package/dist/engine/renderers/Indicator/stoch.d.ts +1 -2
- package/dist/engine/renderers/Indicator/stoch.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/stoch.js +10 -10
- package/dist/engine/renderers/Indicator/stoch.js.map +1 -1
- package/dist/engine/renderers/Indicator/structure.js +5 -5
- package/dist/engine/renderers/Indicator/structure.js.map +1 -1
- package/dist/engine/renderers/Indicator/wmsr.d.ts +1 -2
- package/dist/engine/renderers/Indicator/wmsr.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/wmsr.js +10 -10
- package/dist/engine/renderers/Indicator/wmsr.js.map +1 -1
- package/dist/engine/renderers/Indicator/zones.js +6 -6
- package/dist/engine/renderers/Indicator/zones.js.map +1 -1
- package/dist/engine/renderers/candle.d.ts +1 -1
- package/dist/engine/renderers/candle.d.ts.map +1 -1
- package/dist/engine/renderers/candle.js +21 -21
- package/dist/engine/renderers/candle.js.map +1 -1
- package/dist/engine/renderers/crosshair.js +3 -3
- package/dist/engine/renderers/crosshair.js.map +1 -1
- package/dist/engine/renderers/extremaMarkers.d.ts.map +1 -1
- package/dist/engine/renderers/extremaMarkers.js +12 -12
- package/dist/engine/renderers/extremaMarkers.js.map +1 -1
- package/dist/engine/renderers/gridLines.js +3 -3
- package/dist/engine/renderers/gridLines.js.map +1 -1
- package/dist/engine/renderers/lastPrice.js +7 -7
- package/dist/engine/renderers/lastPrice.js.map +1 -1
- package/dist/engine/renderers/paneTitle.js +6 -6
- package/dist/engine/renderers/paneTitle.js.map +1 -1
- package/dist/engine/renderers/subVolume.d.ts.map +1 -1
- package/dist/engine/renderers/subVolume.js +23 -20
- package/dist/engine/renderers/subVolume.js.map +1 -1
- package/dist/engine/renderers/timeAxis.js +9 -9
- package/dist/engine/renderers/timeAxis.js.map +1 -1
- package/dist/engine/renderers/webgl/candleSurface.d.ts.map +1 -1
- package/dist/engine/renderers/webgl/candleSurface.js +39 -7
- package/dist/engine/renderers/webgl/candleSurface.js.map +1 -1
- package/dist/engine/renderers/yAxis.d.ts.map +1 -1
- package/dist/engine/renderers/yAxis.js +5 -5
- package/dist/engine/renderers/yAxis.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/plugin/types.d.ts +5 -1
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/types.js.map +1 -1
- package/dist/tokens/colorPresetSettings.d.ts +15 -0
- package/dist/tokens/colorPresetSettings.d.ts.map +1 -0
- package/dist/tokens/colorPresetSettings.js +65 -0
- package/dist/tokens/colorPresetSettings.js.map +1 -0
- package/dist/tokens/index.d.ts +17 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +16 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/tokens/mergeTheme.d.ts +17 -0
- package/dist/tokens/mergeTheme.d.ts.map +1 -0
- package/dist/tokens/mergeTheme.js +43 -0
- package/dist/tokens/mergeTheme.js.map +1 -0
- package/dist/tokens/theme-china.d.ts +45 -0
- package/dist/tokens/theme-china.d.ts.map +1 -0
- package/dist/tokens/theme-china.js +116 -0
- package/dist/tokens/theme-china.js.map +1 -0
- package/dist/tokens/theme-dark.d.ts +21 -0
- package/dist/tokens/theme-dark.d.ts.map +1 -0
- package/dist/tokens/theme-dark.js +228 -0
- package/dist/tokens/theme-dark.js.map +1 -0
- package/dist/tokens/theme-light.d.ts +23 -0
- package/dist/tokens/theme-light.d.ts.map +1 -0
- package/dist/tokens/theme-light.js +234 -0
- package/dist/tokens/theme-light.js.map +1 -0
- package/dist/tokens/themeToCssVars.d.ts +74 -0
- package/dist/tokens/themeToCssVars.d.ts.map +1 -0
- package/dist/tokens/themeToCssVars.js +108 -0
- package/dist/tokens/themeToCssVars.js.map +1 -0
- package/dist/tokens/types.d.ts +335 -0
- package/dist/tokens/types.d.ts.map +1 -0
- package/dist/tokens/types.js +20 -0
- package/dist/tokens/types.js.map +1 -0
- package/dist/utils/kLineDraw/axis.d.ts +8 -7
- package/dist/utils/kLineDraw/axis.d.ts.map +1 -1
- package/dist/utils/kLineDraw/axis.js +24 -24
- package/dist/utils/kLineDraw/axis.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/config/chartSettings.ts +11 -2
- package/src/engine/chart.ts +4 -0
- package/src/engine/draw/pixelAlign.ts +0 -2
- package/src/engine/drawing/plugin.ts +1 -1
- package/src/engine/renderers/Indicator/atr.ts +7 -3
- package/src/engine/renderers/Indicator/boll.ts +12 -12
- package/src/engine/renderers/Indicator/cci.ts +11 -10
- package/src/engine/renderers/Indicator/ene.ts +12 -12
- package/src/engine/renderers/Indicator/expma.ts +6 -6
- package/src/engine/renderers/Indicator/fastk.ts +9 -8
- package/src/engine/renderers/Indicator/kst.ts +12 -11
- package/src/engine/renderers/Indicator/ma.ts +5 -5
- package/src/engine/renderers/Indicator/macd.ts +27 -25
- package/src/engine/renderers/Indicator/macdLegend.ts +6 -6
- package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +16 -16
- package/src/engine/renderers/Indicator/mom.ts +11 -10
- package/src/engine/renderers/Indicator/rsi.ts +22 -15
- package/src/engine/renderers/Indicator/scale/indicator_scale.ts +6 -6
- package/src/engine/renderers/Indicator/stoch.ts +12 -11
- package/src/engine/renderers/Indicator/structure.ts +5 -5
- package/src/engine/renderers/Indicator/wmsr.ts +13 -12
- package/src/engine/renderers/Indicator/zones.ts +7 -7
- package/src/engine/renderers/candle.ts +21 -21
- package/src/engine/renderers/crosshair.ts +3 -3
- package/src/engine/renderers/extremaMarkers.ts +13 -12
- package/src/engine/renderers/gridLines.ts +3 -3
- package/src/engine/renderers/lastPrice.ts +7 -7
- package/src/engine/renderers/paneTitle.ts +6 -6
- package/src/engine/renderers/subVolume.ts +23 -20
- package/src/engine/renderers/timeAxis.ts +9 -9
- package/src/engine/renderers/webgl/candleSurface.ts +43 -7
- package/src/engine/renderers/yAxis.ts +6 -5
- package/src/index.ts +1 -0
- package/src/plugin/types.ts +5 -1
- package/src/tokens/__tests__/__snapshots__/baseline.test.ts.snap +393 -0
- package/src/tokens/__tests__/baseline.test.ts +183 -0
- package/src/tokens/__tests__/themeToCssVars.test.ts +175 -0
- package/src/tokens/__tests__/tokens.test.ts +215 -0
- package/src/tokens/colorPresetSettings.ts +128 -0
- package/src/tokens/index.ts +65 -0
- package/src/tokens/mergeTheme.ts +48 -0
- package/src/tokens/theme-china.ts +132 -0
- package/src/tokens/theme-dark.ts +244 -0
- package/src/tokens/theme-light.ts +250 -0
- package/src/tokens/themeToCssVars.ts +138 -0
- package/src/tokens/types.ts +394 -0
- package/src/utils/kLineDraw/axis.ts +31 -30
- package/src/version.ts +1 -1
- package/dist/engine/theme/colors.d.ts +0 -223
- package/dist/engine/theme/colors.d.ts.map +0 -1
- package/dist/engine/theme/colors.js +0 -375
- package/dist/engine/theme/colors.js.map +0 -1
- package/src/engine/theme/colors.ts +0 -642
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`theme baseline — dark > CSS declaration block (snapshot) 1`] = `
|
|
4
|
+
":root {
|
|
5
|
+
--klc-color-background: #111827;
|
|
6
|
+
--klc-color-foreground: #E8EAED;
|
|
7
|
+
--klc-color-candle-up-body: #22D69B;
|
|
8
|
+
--klc-color-candle-up-border: #22D69B;
|
|
9
|
+
--klc-color-candle-up-wick: #22D69B;
|
|
10
|
+
--klc-color-candle-down-body: #FF6464;
|
|
11
|
+
--klc-color-candle-down-border: #FF6464;
|
|
12
|
+
--klc-color-candle-down-wick: #FF6464;
|
|
13
|
+
--klc-color-candle-doji-border: #8A8F98;
|
|
14
|
+
--klc-color-volume-up: #22D69B66;
|
|
15
|
+
--klc-color-volume-down: #FF646466;
|
|
16
|
+
--klc-color-axis-text: #9AA0A6;
|
|
17
|
+
--klc-color-axis-line: #2A2F36;
|
|
18
|
+
--klc-color-axis-tick: #2A2F36;
|
|
19
|
+
--klc-color-grid-major: #1B1F26;
|
|
20
|
+
--klc-color-grid-minor: #161A20;
|
|
21
|
+
--klc-color-crosshair-line: #5F6368;
|
|
22
|
+
--klc-color-crosshair-label-bg: #E8EAED;
|
|
23
|
+
--klc-color-crosshair-label-text: #0E1116;
|
|
24
|
+
--klc-color-selection-fill: #4A9EFF33;
|
|
25
|
+
--klc-color-selection-stroke: #4A9EFF;
|
|
26
|
+
--klc-color-tooltip-bg: #1B1F26EE;
|
|
27
|
+
--klc-color-tooltip-text: #E8EAED;
|
|
28
|
+
--klc-color-tooltip-border: #2A2F36;
|
|
29
|
+
--klc-color-heatmap-coldest: #0E1116;
|
|
30
|
+
--klc-color-heatmap-hottest: #80B7FF;
|
|
31
|
+
--klc-color-volume-profile-fill: #6B727A66;
|
|
32
|
+
--klc-color-volume-profile-poc: #FFA94D;
|
|
33
|
+
--klc-color-volume-profile-value-area: #4A9EFF33;
|
|
34
|
+
--klc-color-footprint-ask: #22D69B80;
|
|
35
|
+
--klc-color-footprint-bid: #FF646480;
|
|
36
|
+
--klc-color-footprint-imbalance: #FFA94D;
|
|
37
|
+
--klc-color-alert-active: #4A9EFF;
|
|
38
|
+
--klc-color-alert-triggered: #FFA94D;
|
|
39
|
+
--klc-color-alert-muted: #6B727A;
|
|
40
|
+
--klc-color-avwap-line: #A78BFA;
|
|
41
|
+
--klc-color-avwap-band: #A78BFA33;
|
|
42
|
+
--klc-color-mtf-overlay: #38BDF8;
|
|
43
|
+
--klc-color-palette-i1: #4A9EFF;
|
|
44
|
+
--klc-color-palette-i2: #FFB95A;
|
|
45
|
+
--klc-color-palette-i3: #22D69B;
|
|
46
|
+
--klc-color-palette-i4: #E879BA;
|
|
47
|
+
--klc-color-palette-i5: #FF8848;
|
|
48
|
+
--klc-color-palette-i6: #7DD3FC;
|
|
49
|
+
--klc-color-palette-i7: #FCE96A;
|
|
50
|
+
--klc-color-palette-i8: #A78BFA;
|
|
51
|
+
--klc-color-palette-i9: #60A5FA;
|
|
52
|
+
--klc-color-palette-i10: #9AA0A6;
|
|
53
|
+
--klc-color-palette-indicator-atr: #F59E0B;
|
|
54
|
+
--klc-color-text-primary: hsl(210, 10%, 85%);
|
|
55
|
+
--klc-color-text-secondary: hsl(210, 8%, 75%);
|
|
56
|
+
--klc-color-text-tertiary: hsl(210, 6%, 60%);
|
|
57
|
+
--klc-color-text-weak: hsl(210, 5%, 45%);
|
|
58
|
+
--klc-color-text-white: rgba(255, 255, 255, 0.95);
|
|
59
|
+
--klc-color-price-up-light: rgba(255, 80, 100, 0.85);
|
|
60
|
+
--klc-color-price-up-tick: hsl(0, 70%, 60%);
|
|
61
|
+
--klc-color-price-down-light: rgba(60, 200, 160, 0.85);
|
|
62
|
+
--klc-color-price-down-tick: hsl(150, 50%, 65%);
|
|
63
|
+
--klc-color-price-last-price: rgba(230, 100, 115, 0.95);
|
|
64
|
+
--klc-color-tag-bg-white: rgb(40, 40, 55);
|
|
65
|
+
--klc-color-tag-bg-light-gray: rgba(50, 50, 65, 0.92);
|
|
66
|
+
--klc-color-tag-bg-pure-white: #282837;
|
|
67
|
+
--klc-color-tag-bg-transparent: transparent;
|
|
68
|
+
--klc-color-tag-bg-active: #1890ff;
|
|
69
|
+
--klc-color-tag-bg-active-hover: #40a9ff;
|
|
70
|
+
--klc-color-tag-bg-hover: #3a3a4a;
|
|
71
|
+
--klc-color-border-dark: rgba(255, 255, 255, 0.15);
|
|
72
|
+
--klc-color-border-medium: rgba(255, 255, 255, 0.12);
|
|
73
|
+
--klc-color-border-light: rgba(255, 255, 255, 0.08);
|
|
74
|
+
--klc-color-border-separator: rgba(255, 255, 255, 0.10);
|
|
75
|
+
--klc-color-border-button: #505060;
|
|
76
|
+
--klc-color-border-chart: #3A4048;
|
|
77
|
+
--klc-color-ma-ma5: rgba(255, 200, 50, 1);
|
|
78
|
+
--klc-color-ma-ma10: rgba(200, 150, 30, 1);
|
|
79
|
+
--klc-color-ma-ma20: rgba(90, 140, 255, 1);
|
|
80
|
+
--klc-color-ma-ma30: rgba(90, 190, 95, 1);
|
|
81
|
+
--klc-color-ma-ma60: rgba(170, 60, 195, 1);
|
|
82
|
+
--klc-color-boll-upper: rgba(200, 60, 60, 1);
|
|
83
|
+
--klc-color-boll-middle: rgba(90, 140, 255, 1);
|
|
84
|
+
--klc-color-boll-lower: rgba(50, 170, 60, 1);
|
|
85
|
+
--klc-color-boll-band-fill: rgba(120, 170, 255, 0.15);
|
|
86
|
+
--klc-color-macd-dif: rgba(90, 140, 255, 1);
|
|
87
|
+
--klc-color-macd-dea: rgba(255, 170, 50, 1);
|
|
88
|
+
--klc-color-macd-bar-up: #ff6b6b;
|
|
89
|
+
--klc-color-macd-bar-up-light: #ffb3b3;
|
|
90
|
+
--klc-color-macd-bar-down: #4ecdc4;
|
|
91
|
+
--klc-color-macd-bar-down-light: #a8e6e1;
|
|
92
|
+
--klc-color-rsi-rsi1: rgba(90, 140, 255, 1);
|
|
93
|
+
--klc-color-rsi-rsi2: rgba(255, 170, 50, 1);
|
|
94
|
+
--klc-color-rsi-rsi3: rgba(180, 70, 205, 1);
|
|
95
|
+
--klc-color-cci-cci: rgba(90, 140, 255, 1);
|
|
96
|
+
--klc-color-cci-overbought: rgba(255, 80, 100, 0.6);
|
|
97
|
+
--klc-color-cci-oversold: rgba(60, 200, 160, 0.6);
|
|
98
|
+
--klc-color-kdj-k: rgba(90, 140, 255, 1);
|
|
99
|
+
--klc-color-kdj-d: rgba(255, 170, 50, 1);
|
|
100
|
+
--klc-color-kdj-j: rgba(180, 70, 205, 1);
|
|
101
|
+
--klc-color-mom-mom: rgba(90, 140, 255, 1);
|
|
102
|
+
--klc-color-mom-zero: rgba(255, 255, 255, 0.2);
|
|
103
|
+
--klc-color-wmsr-wmsr: rgba(90, 140, 255, 1);
|
|
104
|
+
--klc-color-wmsr-overbought: rgba(255, 80, 100, 0.6);
|
|
105
|
+
--klc-color-wmsr-oversold: rgba(60, 200, 160, 0.6);
|
|
106
|
+
--klc-color-kst-kst: rgba(90, 140, 255, 1);
|
|
107
|
+
--klc-color-kst-signal: rgba(255, 170, 50, 1);
|
|
108
|
+
--klc-color-expma-fast: rgba(255, 170, 50, 1);
|
|
109
|
+
--klc-color-expma-slow: rgba(90, 140, 255, 1);
|
|
110
|
+
--klc-color-ene-upper: rgba(255, 80, 100, 1);
|
|
111
|
+
--klc-color-ene-middle: rgba(90, 140, 255, 1);
|
|
112
|
+
--klc-color-ene-lower: rgba(60, 200, 160, 1);
|
|
113
|
+
--klc-color-ene-band-fill: rgba(90, 140, 255, 0.12);
|
|
114
|
+
--klc-color-label-bg: rgba(30, 30, 40, 0.9);
|
|
115
|
+
--klc-color-label-text: #ffffff;
|
|
116
|
+
--klc-color-last-price-label-bg: rgba(60, 50, 55, 0.98);
|
|
117
|
+
--klc-color-volume-price-rise-with: #FF6666;
|
|
118
|
+
--klc-color-volume-price-rise-without: #66FF99;
|
|
119
|
+
--klc-color-volume-price-fall-with: #FF6666;
|
|
120
|
+
--klc-color-volume-price-fall-without: #66FF99;
|
|
121
|
+
--klc-color-structure-hh: #4ade80;
|
|
122
|
+
--klc-color-structure-hl: #22c55e;
|
|
123
|
+
--klc-color-structure-lh: #f87171;
|
|
124
|
+
--klc-color-structure-ll: #ef4444;
|
|
125
|
+
--klc-color-structure-choch: #a78bfa;
|
|
126
|
+
--klc-color-structure-bos: #fbbf24;
|
|
127
|
+
--klc-color-zones-fvg-bull-fill: rgba(74, 222, 128, 0.20);
|
|
128
|
+
--klc-color-zones-fvg-bear-fill: rgba(248, 113, 113, 0.20);
|
|
129
|
+
--klc-color-zones-fvg-bull-border: rgba(74, 222, 128, 0.8);
|
|
130
|
+
--klc-color-zones-fvg-bear-border: rgba(248, 113, 113, 0.8);
|
|
131
|
+
--klc-color-zones-ob-bull-fill: rgba(74, 222, 128, 0.35);
|
|
132
|
+
--klc-color-zones-ob-bear-fill: rgba(248, 113, 113, 0.35);
|
|
133
|
+
--klc-color-wmsr-grid: rgba(255, 255, 255, 0.1);
|
|
134
|
+
--klc-spacing-none: 0;
|
|
135
|
+
--klc-spacing-xxs: 2px;
|
|
136
|
+
--klc-spacing-xs: 4px;
|
|
137
|
+
--klc-spacing-sm: 8px;
|
|
138
|
+
--klc-spacing-md: 12px;
|
|
139
|
+
--klc-spacing-lg: 16px;
|
|
140
|
+
--klc-spacing-xl: 24px;
|
|
141
|
+
--klc-spacing-xxl: 32px;
|
|
142
|
+
--klc-spacing-xxxl: 64px;
|
|
143
|
+
--klc-typography-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
144
|
+
--klc-typography-font-family-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
|
|
145
|
+
--klc-typography-font-size-sm: 10px;
|
|
146
|
+
--klc-typography-font-size-md: 12px;
|
|
147
|
+
--klc-typography-font-size-lg: 14px;
|
|
148
|
+
--klc-typography-font-weight-regular: 400;
|
|
149
|
+
--klc-typography-font-weight-medium: 500;
|
|
150
|
+
--klc-typography-font-weight-bold: 700;
|
|
151
|
+
--klc-typography-line-height-tight: 1.2;
|
|
152
|
+
--klc-typography-line-height-standard: 1.4;
|
|
153
|
+
--klc-motion-duration-instant: 0ms;
|
|
154
|
+
--klc-motion-duration-fast: 120ms;
|
|
155
|
+
--klc-motion-duration-moderate: 200ms;
|
|
156
|
+
--klc-motion-easing-standard: cubic-bezier(0.4, 0, 0.2, 1);
|
|
157
|
+
--klc-motion-easing-decelerate: cubic-bezier(0, 0, 0.2, 1);
|
|
158
|
+
}"
|
|
159
|
+
`;
|
|
160
|
+
|
|
161
|
+
exports[`theme baseline — dark > contrast report (snapshot) 1`] = `
|
|
162
|
+
"# Theme contrast — dark
|
|
163
|
+
|
|
164
|
+
Each role is measured against its own surface (default: \`colors.background\`).
|
|
165
|
+
|
|
166
|
+
| Role | Value | Surface | Ratio | Floor | Pass |
|
|
167
|
+
|---|---|---|---|---|---|
|
|
168
|
+
| foreground | #E8EAED | background | 14.72 | 4.5:1 | ✅ |
|
|
169
|
+
| axisText | #9AA0A6 | background | 6.72 | 4.5:1 | ✅ |
|
|
170
|
+
| crosshairLabelText | #0E1116 | crosshairLabelBg | 15.69 | 4.5:1 | ✅ |
|
|
171
|
+
| tooltipText | #E8EAED | tooltipBg | 13.71 | 4.5:1 | ✅ |
|
|
172
|
+
| candleUpBody | #22D69B | background | 9.43 | 3.0:1 | ✅ |
|
|
173
|
+
| candleDownBody | #FF6464 | background | 6.13 | 3.0:1 | ✅ |
|
|
174
|
+
| candleDojiBorder | #8A8F98 | background | 5.46 | 3.0:1 | ✅ |
|
|
175
|
+
| crosshairLine | #5F6368 | background | 2.93 | 3.0:1 | ❌ |
|
|
176
|
+
| selectionStroke | #4A9EFF | background | 6.44 | 3.0:1 | ✅ |
|
|
177
|
+
| alertActive | #4A9EFF | background | 6.44 | 3.0:1 | ✅ |
|
|
178
|
+
| alertTriggered | #FFA94D | background | 9.32 | 3.0:1 | ✅ |
|
|
179
|
+
| avwapLine | #A78BFA | background | 6.52 | 3.0:1 | ✅ |
|
|
180
|
+
| mtfOverlay | #38BDF8 | background | 8.28 | 3.0:1 | ✅ |
|
|
181
|
+
|
|
182
|
+
## Indicator palette
|
|
183
|
+
|
|
184
|
+
| Slot | Value | Ratio vs BG |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| i1 | #4A9EFF | 6.44 |
|
|
187
|
+
| i2 | #FFB95A | 10.42 |
|
|
188
|
+
| i3 | #22D69B | 9.43 |
|
|
189
|
+
| i4 | #E879BA | 6.65 |
|
|
190
|
+
| i5 | #FF8848 | 7.49 |
|
|
191
|
+
| i6 | #7DD3FC | 10.64 |
|
|
192
|
+
| i7 | #FCE96A | 14.36 |
|
|
193
|
+
| i8 | #A78BFA | 6.52 |
|
|
194
|
+
| i9 | #60A5FA | 6.98 |
|
|
195
|
+
| i10 | #9AA0A6 | 6.72 |
|
|
196
|
+
| indicatorAtr | #F59E0B | 8.26 |"
|
|
197
|
+
`;
|
|
198
|
+
|
|
199
|
+
exports[`theme baseline — light > CSS declaration block (snapshot) 1`] = `
|
|
200
|
+
":root {
|
|
201
|
+
--klc-color-background: #FAFAFA;
|
|
202
|
+
--klc-color-foreground: #1F1F1F;
|
|
203
|
+
--klc-color-candle-up-body: #0F8B5C;
|
|
204
|
+
--klc-color-candle-up-border: #0F8B5C;
|
|
205
|
+
--klc-color-candle-up-wick: #0F8B5C;
|
|
206
|
+
--klc-color-candle-down-body: #C2363B;
|
|
207
|
+
--klc-color-candle-down-border: #C2363B;
|
|
208
|
+
--klc-color-candle-down-wick: #C2363B;
|
|
209
|
+
--klc-color-candle-doji-border: #6E6E6E;
|
|
210
|
+
--klc-color-volume-up: #0F8B5C66;
|
|
211
|
+
--klc-color-volume-down: #C2363B66;
|
|
212
|
+
--klc-color-axis-text: #5A5A5A;
|
|
213
|
+
--klc-color-axis-line: #D0D0D0;
|
|
214
|
+
--klc-color-axis-tick: #D0D0D0;
|
|
215
|
+
--klc-color-grid-major: #E5E5E5;
|
|
216
|
+
--klc-color-grid-minor: #F0F0F0;
|
|
217
|
+
--klc-color-crosshair-line: #8C8C8C;
|
|
218
|
+
--klc-color-crosshair-label-bg: #1F1F1F;
|
|
219
|
+
--klc-color-crosshair-label-text: #FAFAFA;
|
|
220
|
+
--klc-color-selection-fill: #2D7FF933;
|
|
221
|
+
--klc-color-selection-stroke: #2D7FF9;
|
|
222
|
+
--klc-color-tooltip-bg: #FFFFFFEE;
|
|
223
|
+
--klc-color-tooltip-text: #1F1F1F;
|
|
224
|
+
--klc-color-tooltip-border: #D0D0D0;
|
|
225
|
+
--klc-color-heatmap-coldest: #F0F4F8;
|
|
226
|
+
--klc-color-heatmap-hottest: #1F3A5F;
|
|
227
|
+
--klc-color-volume-profile-fill: #9CA3AF66;
|
|
228
|
+
--klc-color-volume-profile-poc: #F97316;
|
|
229
|
+
--klc-color-volume-profile-value-area: #2D7FF933;
|
|
230
|
+
--klc-color-footprint-ask: #0F8B5C80;
|
|
231
|
+
--klc-color-footprint-bid: #C2363B80;
|
|
232
|
+
--klc-color-footprint-imbalance: #F97316;
|
|
233
|
+
--klc-color-alert-active: #2D7FF9;
|
|
234
|
+
--klc-color-alert-triggered: #C2410C;
|
|
235
|
+
--klc-color-alert-muted: #9CA3AF;
|
|
236
|
+
--klc-color-avwap-line: #7C3AED;
|
|
237
|
+
--klc-color-avwap-band: #7C3AED33;
|
|
238
|
+
--klc-color-mtf-overlay: #0369A1;
|
|
239
|
+
--klc-color-palette-i1: #0072B2;
|
|
240
|
+
--klc-color-palette-i2: #E69F00;
|
|
241
|
+
--klc-color-palette-i3: #009E73;
|
|
242
|
+
--klc-color-palette-i4: #CC79A7;
|
|
243
|
+
--klc-color-palette-i5: #D55E00;
|
|
244
|
+
--klc-color-palette-i6: #56B4E9;
|
|
245
|
+
--klc-color-palette-i7: #F0E442;
|
|
246
|
+
--klc-color-palette-i8: #7C3AED;
|
|
247
|
+
--klc-color-palette-i9: #2D7FF9;
|
|
248
|
+
--klc-color-palette-i10: #6E6E6E;
|
|
249
|
+
--klc-color-palette-indicator-atr: #d97706;
|
|
250
|
+
--klc-color-text-primary: hsl(210, 9%, 31%);
|
|
251
|
+
--klc-color-text-secondary: hsl(210, 9%, 35%);
|
|
252
|
+
--klc-color-text-tertiary: hsl(210, 8%, 50%);
|
|
253
|
+
--klc-color-text-weak: hsl(210, 7%, 65%);
|
|
254
|
+
--klc-color-text-white: rgba(255, 255, 255, 0.92);
|
|
255
|
+
--klc-color-price-up-light: rgba(214, 10, 34, 0.92);
|
|
256
|
+
--klc-color-price-up-tick: hsl(0, 60%, 50%);
|
|
257
|
+
--klc-color-price-down-light: rgba(3, 123, 102, 0.92);
|
|
258
|
+
--klc-color-price-down-tick: hsl(150, 30%, 60%);
|
|
259
|
+
--klc-color-price-last-price: rgba(196, 74, 86, 0.95);
|
|
260
|
+
--klc-color-tag-bg-white: rgb(255, 255, 255);
|
|
261
|
+
--klc-color-tag-bg-light-gray: rgba(255, 255, 255, 0.92);
|
|
262
|
+
--klc-color-tag-bg-pure-white: #ffffff;
|
|
263
|
+
--klc-color-tag-bg-transparent: transparent;
|
|
264
|
+
--klc-color-tag-bg-active: #1890ff;
|
|
265
|
+
--klc-color-tag-bg-active-hover: #40a9ff;
|
|
266
|
+
--klc-color-tag-bg-hover: #f0f0f0;
|
|
267
|
+
--klc-color-border-dark: rgba(0, 0, 0, 0.12);
|
|
268
|
+
--klc-color-border-medium: rgba(0, 0, 0, 0.10);
|
|
269
|
+
--klc-color-border-light: rgba(0, 0, 0, 0.08);
|
|
270
|
+
--klc-color-border-separator: rgba(0, 0, 0, 0.10);
|
|
271
|
+
--klc-color-border-button: #d0d0d0;
|
|
272
|
+
--klc-color-border-chart: #e5e5e5;
|
|
273
|
+
--klc-color-ma-ma5: rgba(255, 193, 37, 1);
|
|
274
|
+
--klc-color-ma-ma10: rgba(190, 131, 12, 1);
|
|
275
|
+
--klc-color-ma-ma20: rgba(69, 112, 249, 1);
|
|
276
|
+
--klc-color-ma-ma30: rgba(76, 175, 80, 1);
|
|
277
|
+
--klc-color-ma-ma60: rgba(156, 39, 176, 1);
|
|
278
|
+
--klc-color-boll-upper: rgba(178, 34, 34, 1);
|
|
279
|
+
--klc-color-boll-middle: rgba(69, 112, 249, 1);
|
|
280
|
+
--klc-color-boll-lower: rgba(34, 139, 34, 1);
|
|
281
|
+
--klc-color-boll-band-fill: rgba(100, 149, 237, 0.1);
|
|
282
|
+
--klc-color-macd-dif: rgba(69, 112, 249, 1);
|
|
283
|
+
--klc-color-macd-dea: rgba(255, 152, 0, 1);
|
|
284
|
+
--klc-color-macd-bar-up: #ff5252;
|
|
285
|
+
--klc-color-macd-bar-up-light: #fccbcd;
|
|
286
|
+
--klc-color-macd-bar-down: #22ab94;
|
|
287
|
+
--klc-color-macd-bar-down-light: #ace5dc;
|
|
288
|
+
--klc-color-rsi-rsi1: rgba(69, 112, 249, 1);
|
|
289
|
+
--klc-color-rsi-rsi2: rgba(255, 152, 0, 1);
|
|
290
|
+
--klc-color-rsi-rsi3: rgba(156, 39, 176, 1);
|
|
291
|
+
--klc-color-cci-cci: rgba(69, 112, 249, 1);
|
|
292
|
+
--klc-color-cci-overbought: rgba(214, 10, 34, 0.5);
|
|
293
|
+
--klc-color-cci-oversold: rgba(3, 123, 102, 0.5);
|
|
294
|
+
--klc-color-kdj-k: rgba(69, 112, 249, 1);
|
|
295
|
+
--klc-color-kdj-d: rgba(255, 152, 0, 1);
|
|
296
|
+
--klc-color-kdj-j: rgba(156, 39, 176, 1);
|
|
297
|
+
--klc-color-mom-mom: rgba(69, 112, 249, 1);
|
|
298
|
+
--klc-color-mom-zero: rgba(0, 0, 0, 0.2);
|
|
299
|
+
--klc-color-wmsr-wmsr: rgba(69, 112, 249, 1);
|
|
300
|
+
--klc-color-wmsr-overbought: rgba(214, 10, 34, 0.5);
|
|
301
|
+
--klc-color-wmsr-oversold: rgba(3, 123, 102, 0.5);
|
|
302
|
+
--klc-color-kst-kst: rgba(69, 112, 249, 1);
|
|
303
|
+
--klc-color-kst-signal: rgba(255, 152, 0, 1);
|
|
304
|
+
--klc-color-expma-fast: rgba(255, 152, 0, 1);
|
|
305
|
+
--klc-color-expma-slow: rgba(69, 112, 249, 1);
|
|
306
|
+
--klc-color-ene-upper: rgba(214, 10, 34, 1);
|
|
307
|
+
--klc-color-ene-middle: rgba(69, 112, 249, 1);
|
|
308
|
+
--klc-color-ene-lower: rgba(3, 123, 102, 1);
|
|
309
|
+
--klc-color-ene-band-fill: rgba(69, 112, 249, 0.08);
|
|
310
|
+
--klc-color-label-bg: rgba(0, 0, 0, 0.8);
|
|
311
|
+
--klc-color-label-text: #ffffff;
|
|
312
|
+
--klc-color-last-price-label-bg: rgba(255, 247, 248, 0.98);
|
|
313
|
+
--klc-color-volume-price-rise-with: #FF4444;
|
|
314
|
+
--klc-color-volume-price-rise-without: #00C853;
|
|
315
|
+
--klc-color-volume-price-fall-with: #FF4444;
|
|
316
|
+
--klc-color-volume-price-fall-without: #00C853;
|
|
317
|
+
--klc-color-structure-hh: #16a34a;
|
|
318
|
+
--klc-color-structure-hl: #22c55e;
|
|
319
|
+
--klc-color-structure-lh: #dc2626;
|
|
320
|
+
--klc-color-structure-ll: #ef4444;
|
|
321
|
+
--klc-color-structure-choch: #8b5cf6;
|
|
322
|
+
--klc-color-structure-bos: #f59e0b;
|
|
323
|
+
--klc-color-zones-fvg-bull-fill: rgba(34, 197, 94, 0.15);
|
|
324
|
+
--klc-color-zones-fvg-bear-fill: rgba(239, 68, 68, 0.15);
|
|
325
|
+
--klc-color-zones-fvg-bull-border: rgba(34, 197, 94, 0.6);
|
|
326
|
+
--klc-color-zones-fvg-bear-border: rgba(239, 68, 68, 0.6);
|
|
327
|
+
--klc-color-zones-ob-bull-fill: rgba(34, 197, 94, 0.25);
|
|
328
|
+
--klc-color-zones-ob-bear-fill: rgba(239, 68, 68, 0.25);
|
|
329
|
+
--klc-color-wmsr-grid: rgba(0, 0, 0, 0.1);
|
|
330
|
+
--klc-spacing-none: 0;
|
|
331
|
+
--klc-spacing-xxs: 2px;
|
|
332
|
+
--klc-spacing-xs: 4px;
|
|
333
|
+
--klc-spacing-sm: 8px;
|
|
334
|
+
--klc-spacing-md: 12px;
|
|
335
|
+
--klc-spacing-lg: 16px;
|
|
336
|
+
--klc-spacing-xl: 24px;
|
|
337
|
+
--klc-spacing-xxl: 32px;
|
|
338
|
+
--klc-spacing-xxxl: 64px;
|
|
339
|
+
--klc-typography-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
340
|
+
--klc-typography-font-family-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
|
|
341
|
+
--klc-typography-font-size-sm: 10px;
|
|
342
|
+
--klc-typography-font-size-md: 12px;
|
|
343
|
+
--klc-typography-font-size-lg: 14px;
|
|
344
|
+
--klc-typography-font-weight-regular: 400;
|
|
345
|
+
--klc-typography-font-weight-medium: 500;
|
|
346
|
+
--klc-typography-font-weight-bold: 700;
|
|
347
|
+
--klc-typography-line-height-tight: 1.2;
|
|
348
|
+
--klc-typography-line-height-standard: 1.4;
|
|
349
|
+
--klc-motion-duration-instant: 0ms;
|
|
350
|
+
--klc-motion-duration-fast: 120ms;
|
|
351
|
+
--klc-motion-duration-moderate: 200ms;
|
|
352
|
+
--klc-motion-easing-standard: cubic-bezier(0.4, 0, 0.2, 1);
|
|
353
|
+
--klc-motion-easing-decelerate: cubic-bezier(0, 0, 0.2, 1);
|
|
354
|
+
}"
|
|
355
|
+
`;
|
|
356
|
+
|
|
357
|
+
exports[`theme baseline — light > contrast report (snapshot) 1`] = `
|
|
358
|
+
"# Theme contrast — light
|
|
359
|
+
|
|
360
|
+
Each role is measured against its own surface (default: \`colors.background\`).
|
|
361
|
+
|
|
362
|
+
| Role | Value | Surface | Ratio | Floor | Pass |
|
|
363
|
+
|---|---|---|---|---|---|
|
|
364
|
+
| foreground | #1F1F1F | background | 15.79 | 4.5:1 | ✅ |
|
|
365
|
+
| axisText | #5A5A5A | background | 6.61 | 4.5:1 | ✅ |
|
|
366
|
+
| crosshairLabelText | #FAFAFA | crosshairLabelBg | 15.79 | 4.5:1 | ✅ |
|
|
367
|
+
| tooltipText | #1F1F1F | tooltipBg | 16.48 | 4.5:1 | ✅ |
|
|
368
|
+
| candleUpBody | #0F8B5C | background | 4.13 | 3.0:1 | ✅ |
|
|
369
|
+
| candleDownBody | #C2363B | background | 5.18 | 3.0:1 | ✅ |
|
|
370
|
+
| candleDojiBorder | #6E6E6E | background | 4.89 | 3.0:1 | ✅ |
|
|
371
|
+
| crosshairLine | #8C8C8C | background | 3.22 | 3.0:1 | ✅ |
|
|
372
|
+
| selectionStroke | #2D7FF9 | background | 3.65 | 3.0:1 | ✅ |
|
|
373
|
+
| alertActive | #2D7FF9 | background | 3.65 | 3.0:1 | ✅ |
|
|
374
|
+
| alertTriggered | #C2410C | background | 4.96 | 3.0:1 | ✅ |
|
|
375
|
+
| avwapLine | #7C3AED | background | 5.46 | 3.0:1 | ✅ |
|
|
376
|
+
| mtfOverlay | #0369A1 | background | 5.68 | 3.0:1 | ✅ |
|
|
377
|
+
|
|
378
|
+
## Indicator palette
|
|
379
|
+
|
|
380
|
+
| Slot | Value | Ratio vs BG |
|
|
381
|
+
|---|---|---|
|
|
382
|
+
| i1 | #0072B2 | 4.97 |
|
|
383
|
+
| i2 | #E69F00 | 2.16 |
|
|
384
|
+
| i3 | #009E73 | 3.28 |
|
|
385
|
+
| i4 | #CC79A7 | 2.93 |
|
|
386
|
+
| i5 | #D55E00 | 3.71 |
|
|
387
|
+
| i6 | #56B4E9 | 2.21 |
|
|
388
|
+
| i7 | #F0E442 | 1.27 |
|
|
389
|
+
| i8 | #7C3AED | 5.46 |
|
|
390
|
+
| i9 | #2D7FF9 | 3.65 |
|
|
391
|
+
| i10 | #6E6E6E | 4.89 |
|
|
392
|
+
| indicatorAtr | #d97706 | 3.05 |"
|
|
393
|
+
`;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme baseline snapshots.
|
|
3
|
+
*
|
|
4
|
+
* Purpose: lock the SHIPPED look. Any change to the light or dark
|
|
5
|
+
* theme — adding a token, changing a value, renaming a key — shows
|
|
6
|
+
* up as a snapshot diff and forces an explicit review. The intent is
|
|
7
|
+
* the same as a visual-regression baseline (pixel diff against a
|
|
8
|
+
* rendered chart), one layer earlier: the tokens are the source of
|
|
9
|
+
* truth that the renderer turns into pixels.
|
|
10
|
+
*
|
|
11
|
+
* What we snapshot, and why:
|
|
12
|
+
*
|
|
13
|
+
* 1. The full CSS declaration block emitted via
|
|
14
|
+
* `toCssDeclarationBlock(themeToCssVars(theme))`. This is the
|
|
15
|
+
* exact text that lands in a stylesheet when a consumer
|
|
16
|
+
* installs the theme, so the snapshot is what *users* see.
|
|
17
|
+
*
|
|
18
|
+
* 2. A contrast report. Each color-vs-background ratio is rounded
|
|
19
|
+
* to two decimals and dumped as a Markdown table. A bull/bear
|
|
20
|
+
* tweak that crosses the WCAG threshold shows up in the diff
|
|
21
|
+
* AND in the explicit assertion below.
|
|
22
|
+
*
|
|
23
|
+
* To update an intentional change: run `vitest -u` and review the
|
|
24
|
+
* diff carefully. The reviewer's checklist: is the new value
|
|
25
|
+
* accessible? Does the new key follow the naming convention?
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { describe, it, expect } from 'vitest'
|
|
29
|
+
|
|
30
|
+
import {
|
|
31
|
+
lightTheme,
|
|
32
|
+
darkTheme,
|
|
33
|
+
themeToCssVars,
|
|
34
|
+
toCssDeclarationBlock,
|
|
35
|
+
} from '..'
|
|
36
|
+
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Local contrast helpers (kept inline so the snapshot files don't reach
|
|
39
|
+
// into renderer internals).
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
const HEX_WITH_ALPHA = /^#[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/
|
|
43
|
+
|
|
44
|
+
function parseHex(color: string): { r: number; g: number; b: number } | null {
|
|
45
|
+
if (!HEX_WITH_ALPHA.test(color)) return null
|
|
46
|
+
return {
|
|
47
|
+
r: parseInt(color.slice(1, 3), 16),
|
|
48
|
+
g: parseInt(color.slice(3, 5), 16),
|
|
49
|
+
b: parseInt(color.slice(5, 7), 16),
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function relLum(c: string): number | null {
|
|
54
|
+
const p = parseHex(c)
|
|
55
|
+
if (p === null) return null
|
|
56
|
+
const linear = (v: number): number => {
|
|
57
|
+
const s = v / 255
|
|
58
|
+
return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4)
|
|
59
|
+
}
|
|
60
|
+
return 0.2126 * linear(p.r) + 0.7152 * linear(p.g) + 0.0722 * linear(p.b)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function contrast(a: string, b: string): number | null {
|
|
64
|
+
const la = relLum(a)
|
|
65
|
+
const lb = relLum(b)
|
|
66
|
+
if (la === null || lb === null) return null
|
|
67
|
+
const [hi, lo] = la > lb ? [la, lb] : [lb, la]
|
|
68
|
+
return (hi + 0.05) / (lo + 0.05)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function hexBase(c: string): string {
|
|
72
|
+
return c.length === 9 ? c.slice(0, 7) : c
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Roles we want explicitly contrast-tracked. Adding to this list expands
|
|
77
|
+
* the baseline. The audit categories are: must-be-visible (candle, axis,
|
|
78
|
+
* crosshair) and prefer-strong (palette, accent).
|
|
79
|
+
*/
|
|
80
|
+
interface TrackedRole {
|
|
81
|
+
role: string
|
|
82
|
+
threshold: number
|
|
83
|
+
/** Role this is measured against. Default `'background'`. */
|
|
84
|
+
against?: string
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const TRACKED_ROLES: ReadonlyArray<TrackedRole> = [
|
|
88
|
+
// Floor 4.5:1 (WCAG AA for normal text). Text-on-tinted-surface roles
|
|
89
|
+
// (crosshair label, tooltip) are measured against their own surface,
|
|
90
|
+
// NOT the chart background, since that's where they actually render.
|
|
91
|
+
{ role: 'foreground', threshold: 4.5 },
|
|
92
|
+
{ role: 'axisText', threshold: 4.5 },
|
|
93
|
+
{ role: 'crosshairLabelText', threshold: 4.5, against: 'crosshairLabelBg' },
|
|
94
|
+
{ role: 'tooltipText', threshold: 4.5, against: 'tooltipBg' },
|
|
95
|
+
// Floor 3:1 (WCAG AA for non-text graphic objects)
|
|
96
|
+
{ role: 'candleUpBody', threshold: 3 },
|
|
97
|
+
{ role: 'candleDownBody', threshold: 3 },
|
|
98
|
+
{ role: 'candleDojiBorder', threshold: 3 },
|
|
99
|
+
{ role: 'crosshairLine', threshold: 3 },
|
|
100
|
+
{ role: 'selectionStroke', threshold: 3 },
|
|
101
|
+
{ role: 'alertActive', threshold: 3 },
|
|
102
|
+
{ role: 'alertTriggered', threshold: 3 },
|
|
103
|
+
{ role: 'avwapLine', threshold: 3 },
|
|
104
|
+
{ role: 'mtfOverlay', threshold: 3 },
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
function buildContrastReport(theme: typeof lightTheme): string {
|
|
108
|
+
const lines: string[] = []
|
|
109
|
+
lines.push(`# Theme contrast — ${theme.name}`)
|
|
110
|
+
lines.push('')
|
|
111
|
+
lines.push('Each role is measured against its own surface (default: `colors.background`).')
|
|
112
|
+
lines.push('')
|
|
113
|
+
lines.push('| Role | Value | Surface | Ratio | Floor | Pass |')
|
|
114
|
+
lines.push('|---|---|---|---|---|---|')
|
|
115
|
+
for (const { role, threshold, against } of TRACKED_ROLES) {
|
|
116
|
+
const value = (theme.colors as unknown as Record<string, string>)[role]
|
|
117
|
+
const surfaceKey = against ?? 'background'
|
|
118
|
+
const surfaceVal = (theme.colors as unknown as Record<string, string>)[surfaceKey]
|
|
119
|
+
const r = contrast(hexBase(value), hexBase(surfaceVal))
|
|
120
|
+
const ratio = r === null ? 'n/a' : r.toFixed(2)
|
|
121
|
+
const pass = r === null ? '?' : r >= threshold ? '✅' : '❌'
|
|
122
|
+
lines.push(`| ${role} | ${hexBase(value)} | ${surfaceKey} | ${ratio} | ${threshold.toFixed(1)}:1 | ${pass} |`)
|
|
123
|
+
}
|
|
124
|
+
const bg = hexBase(theme.colors.background)
|
|
125
|
+
// Palette is a separate section — informational only, no fixed floor.
|
|
126
|
+
lines.push('')
|
|
127
|
+
lines.push('## Indicator palette')
|
|
128
|
+
lines.push('')
|
|
129
|
+
lines.push('| Slot | Value | Ratio vs BG |')
|
|
130
|
+
lines.push('|---|---|---|')
|
|
131
|
+
for (const [k, v] of Object.entries(theme.colors.palette)) {
|
|
132
|
+
const r = contrast(hexBase(v), bg)
|
|
133
|
+
const ratio = r === null ? 'n/a' : r.toFixed(2)
|
|
134
|
+
lines.push(`| ${k} | ${v} | ${ratio} |`)
|
|
135
|
+
}
|
|
136
|
+
return lines.join('\n')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
// Snapshots
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
describe('theme baseline — light', () => {
|
|
144
|
+
it('CSS declaration block (snapshot)', () => {
|
|
145
|
+
const css = toCssDeclarationBlock(themeToCssVars(lightTheme))
|
|
146
|
+
expect(css).toMatchSnapshot()
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('contrast report (snapshot)', () => {
|
|
150
|
+
expect(buildContrastReport(lightTheme)).toMatchSnapshot()
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
describe('theme baseline — dark', () => {
|
|
155
|
+
it('CSS declaration block (snapshot)', () => {
|
|
156
|
+
const css = toCssDeclarationBlock(themeToCssVars(darkTheme))
|
|
157
|
+
expect(css).toMatchSnapshot()
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('contrast report (snapshot)', () => {
|
|
161
|
+
expect(buildContrastReport(darkTheme)).toMatchSnapshot()
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
// Explicit threshold assertions — supplement the snapshot diff with
|
|
167
|
+
// hard fails when an essential role drops below its WCAG floor.
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
|
|
170
|
+
describe('theme baseline — contrast floors hold', () => {
|
|
171
|
+
for (const theme of [lightTheme, darkTheme]) {
|
|
172
|
+
for (const { role, threshold, against } of TRACKED_ROLES) {
|
|
173
|
+
it(`${theme.name}: ${role} ≥ ${threshold}:1`, () => {
|
|
174
|
+
const value = (theme.colors as unknown as Record<string, string>)[role]
|
|
175
|
+
const surfaceKey = against ?? 'background'
|
|
176
|
+
const surface = (theme.colors as unknown as Record<string, string>)[surfaceKey]
|
|
177
|
+
const r = contrast(hexBase(value), hexBase(surface))
|
|
178
|
+
expect(r).not.toBeNull()
|
|
179
|
+
expect(r as number).toBeGreaterThanOrEqual(threshold)
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
})
|