@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.
Files changed (191) hide show
  1. package/dist/config/chartSettings.d.ts +27 -2
  2. package/dist/config/chartSettings.d.ts.map +1 -1
  3. package/dist/config/chartSettings.js +6 -0
  4. package/dist/config/chartSettings.js.map +1 -1
  5. package/dist/engine/chart.d.ts.map +1 -1
  6. package/dist/engine/chart.js +4 -0
  7. package/dist/engine/chart.js.map +1 -1
  8. package/dist/engine/draw/pixelAlign.d.ts.map +1 -1
  9. package/dist/engine/draw/pixelAlign.js.map +1 -1
  10. package/dist/engine/drawing/plugin.js +1 -1
  11. package/dist/engine/drawing/plugin.js.map +1 -1
  12. package/dist/engine/renderers/Indicator/atr.d.ts.map +1 -1
  13. package/dist/engine/renderers/Indicator/atr.js +7 -4
  14. package/dist/engine/renderers/Indicator/atr.js.map +1 -1
  15. package/dist/engine/renderers/Indicator/boll.js +12 -12
  16. package/dist/engine/renderers/Indicator/boll.js.map +1 -1
  17. package/dist/engine/renderers/Indicator/cci.d.ts +1 -2
  18. package/dist/engine/renderers/Indicator/cci.d.ts.map +1 -1
  19. package/dist/engine/renderers/Indicator/cci.js +9 -9
  20. package/dist/engine/renderers/Indicator/cci.js.map +1 -1
  21. package/dist/engine/renderers/Indicator/ene.js +12 -12
  22. package/dist/engine/renderers/Indicator/ene.js.map +1 -1
  23. package/dist/engine/renderers/Indicator/expma.js +6 -6
  24. package/dist/engine/renderers/Indicator/expma.js.map +1 -1
  25. package/dist/engine/renderers/Indicator/fastk.d.ts +1 -2
  26. package/dist/engine/renderers/Indicator/fastk.d.ts.map +1 -1
  27. package/dist/engine/renderers/Indicator/fastk.js +7 -7
  28. package/dist/engine/renderers/Indicator/fastk.js.map +1 -1
  29. package/dist/engine/renderers/Indicator/kst.d.ts +1 -2
  30. package/dist/engine/renderers/Indicator/kst.d.ts.map +1 -1
  31. package/dist/engine/renderers/Indicator/kst.js +10 -10
  32. package/dist/engine/renderers/Indicator/kst.js.map +1 -1
  33. package/dist/engine/renderers/Indicator/ma.js +5 -5
  34. package/dist/engine/renderers/Indicator/ma.js.map +1 -1
  35. package/dist/engine/renderers/Indicator/macd.d.ts +1 -2
  36. package/dist/engine/renderers/Indicator/macd.d.ts.map +1 -1
  37. package/dist/engine/renderers/Indicator/macd.js +24 -24
  38. package/dist/engine/renderers/Indicator/macd.js.map +1 -1
  39. package/dist/engine/renderers/Indicator/macdLegend.js +6 -6
  40. package/dist/engine/renderers/Indicator/macdLegend.js.map +1 -1
  41. package/dist/engine/renderers/Indicator/mainIndicatorLegend.js +16 -16
  42. package/dist/engine/renderers/Indicator/mainIndicatorLegend.js.map +1 -1
  43. package/dist/engine/renderers/Indicator/mom.d.ts +1 -2
  44. package/dist/engine/renderers/Indicator/mom.d.ts.map +1 -1
  45. package/dist/engine/renderers/Indicator/mom.js +8 -8
  46. package/dist/engine/renderers/Indicator/mom.js.map +1 -1
  47. package/dist/engine/renderers/Indicator/rsi.d.ts +2 -3
  48. package/dist/engine/renderers/Indicator/rsi.d.ts.map +1 -1
  49. package/dist/engine/renderers/Indicator/rsi.js +19 -15
  50. package/dist/engine/renderers/Indicator/rsi.js.map +1 -1
  51. package/dist/engine/renderers/Indicator/scale/indicator_scale.d.ts +1 -2
  52. package/dist/engine/renderers/Indicator/scale/indicator_scale.d.ts.map +1 -1
  53. package/dist/engine/renderers/Indicator/scale/indicator_scale.js +5 -5
  54. package/dist/engine/renderers/Indicator/scale/indicator_scale.js.map +1 -1
  55. package/dist/engine/renderers/Indicator/stoch.d.ts +1 -2
  56. package/dist/engine/renderers/Indicator/stoch.d.ts.map +1 -1
  57. package/dist/engine/renderers/Indicator/stoch.js +10 -10
  58. package/dist/engine/renderers/Indicator/stoch.js.map +1 -1
  59. package/dist/engine/renderers/Indicator/structure.js +5 -5
  60. package/dist/engine/renderers/Indicator/structure.js.map +1 -1
  61. package/dist/engine/renderers/Indicator/wmsr.d.ts +1 -2
  62. package/dist/engine/renderers/Indicator/wmsr.d.ts.map +1 -1
  63. package/dist/engine/renderers/Indicator/wmsr.js +10 -10
  64. package/dist/engine/renderers/Indicator/wmsr.js.map +1 -1
  65. package/dist/engine/renderers/Indicator/zones.js +6 -6
  66. package/dist/engine/renderers/Indicator/zones.js.map +1 -1
  67. package/dist/engine/renderers/candle.d.ts +1 -1
  68. package/dist/engine/renderers/candle.d.ts.map +1 -1
  69. package/dist/engine/renderers/candle.js +21 -21
  70. package/dist/engine/renderers/candle.js.map +1 -1
  71. package/dist/engine/renderers/crosshair.js +3 -3
  72. package/dist/engine/renderers/crosshair.js.map +1 -1
  73. package/dist/engine/renderers/extremaMarkers.d.ts.map +1 -1
  74. package/dist/engine/renderers/extremaMarkers.js +12 -12
  75. package/dist/engine/renderers/extremaMarkers.js.map +1 -1
  76. package/dist/engine/renderers/gridLines.js +3 -3
  77. package/dist/engine/renderers/gridLines.js.map +1 -1
  78. package/dist/engine/renderers/lastPrice.js +7 -7
  79. package/dist/engine/renderers/lastPrice.js.map +1 -1
  80. package/dist/engine/renderers/paneTitle.js +6 -6
  81. package/dist/engine/renderers/paneTitle.js.map +1 -1
  82. package/dist/engine/renderers/subVolume.d.ts.map +1 -1
  83. package/dist/engine/renderers/subVolume.js +23 -20
  84. package/dist/engine/renderers/subVolume.js.map +1 -1
  85. package/dist/engine/renderers/timeAxis.js +9 -9
  86. package/dist/engine/renderers/timeAxis.js.map +1 -1
  87. package/dist/engine/renderers/webgl/candleSurface.d.ts.map +1 -1
  88. package/dist/engine/renderers/webgl/candleSurface.js +39 -7
  89. package/dist/engine/renderers/webgl/candleSurface.js.map +1 -1
  90. package/dist/engine/renderers/yAxis.d.ts.map +1 -1
  91. package/dist/engine/renderers/yAxis.js +5 -5
  92. package/dist/engine/renderers/yAxis.js.map +1 -1
  93. package/dist/index.d.ts +1 -0
  94. package/dist/index.d.ts.map +1 -1
  95. package/dist/index.js +1 -0
  96. package/dist/index.js.map +1 -1
  97. package/dist/plugin/types.d.ts +5 -1
  98. package/dist/plugin/types.d.ts.map +1 -1
  99. package/dist/plugin/types.js.map +1 -1
  100. package/dist/tokens/colorPresetSettings.d.ts +15 -0
  101. package/dist/tokens/colorPresetSettings.d.ts.map +1 -0
  102. package/dist/tokens/colorPresetSettings.js +65 -0
  103. package/dist/tokens/colorPresetSettings.js.map +1 -0
  104. package/dist/tokens/index.d.ts +17 -0
  105. package/dist/tokens/index.d.ts.map +1 -0
  106. package/dist/tokens/index.js +16 -0
  107. package/dist/tokens/index.js.map +1 -0
  108. package/dist/tokens/mergeTheme.d.ts +17 -0
  109. package/dist/tokens/mergeTheme.d.ts.map +1 -0
  110. package/dist/tokens/mergeTheme.js +43 -0
  111. package/dist/tokens/mergeTheme.js.map +1 -0
  112. package/dist/tokens/theme-china.d.ts +45 -0
  113. package/dist/tokens/theme-china.d.ts.map +1 -0
  114. package/dist/tokens/theme-china.js +116 -0
  115. package/dist/tokens/theme-china.js.map +1 -0
  116. package/dist/tokens/theme-dark.d.ts +21 -0
  117. package/dist/tokens/theme-dark.d.ts.map +1 -0
  118. package/dist/tokens/theme-dark.js +228 -0
  119. package/dist/tokens/theme-dark.js.map +1 -0
  120. package/dist/tokens/theme-light.d.ts +23 -0
  121. package/dist/tokens/theme-light.d.ts.map +1 -0
  122. package/dist/tokens/theme-light.js +234 -0
  123. package/dist/tokens/theme-light.js.map +1 -0
  124. package/dist/tokens/themeToCssVars.d.ts +74 -0
  125. package/dist/tokens/themeToCssVars.d.ts.map +1 -0
  126. package/dist/tokens/themeToCssVars.js +108 -0
  127. package/dist/tokens/themeToCssVars.js.map +1 -0
  128. package/dist/tokens/types.d.ts +335 -0
  129. package/dist/tokens/types.d.ts.map +1 -0
  130. package/dist/tokens/types.js +20 -0
  131. package/dist/tokens/types.js.map +1 -0
  132. package/dist/utils/kLineDraw/axis.d.ts +8 -7
  133. package/dist/utils/kLineDraw/axis.d.ts.map +1 -1
  134. package/dist/utils/kLineDraw/axis.js +24 -24
  135. package/dist/utils/kLineDraw/axis.js.map +1 -1
  136. package/dist/version.d.ts +1 -1
  137. package/dist/version.js +1 -1
  138. package/package.json +1 -1
  139. package/src/config/chartSettings.ts +11 -2
  140. package/src/engine/chart.ts +4 -0
  141. package/src/engine/draw/pixelAlign.ts +0 -2
  142. package/src/engine/drawing/plugin.ts +1 -1
  143. package/src/engine/renderers/Indicator/atr.ts +7 -3
  144. package/src/engine/renderers/Indicator/boll.ts +12 -12
  145. package/src/engine/renderers/Indicator/cci.ts +11 -10
  146. package/src/engine/renderers/Indicator/ene.ts +12 -12
  147. package/src/engine/renderers/Indicator/expma.ts +6 -6
  148. package/src/engine/renderers/Indicator/fastk.ts +9 -8
  149. package/src/engine/renderers/Indicator/kst.ts +12 -11
  150. package/src/engine/renderers/Indicator/ma.ts +5 -5
  151. package/src/engine/renderers/Indicator/macd.ts +27 -25
  152. package/src/engine/renderers/Indicator/macdLegend.ts +6 -6
  153. package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +16 -16
  154. package/src/engine/renderers/Indicator/mom.ts +11 -10
  155. package/src/engine/renderers/Indicator/rsi.ts +22 -15
  156. package/src/engine/renderers/Indicator/scale/indicator_scale.ts +6 -6
  157. package/src/engine/renderers/Indicator/stoch.ts +12 -11
  158. package/src/engine/renderers/Indicator/structure.ts +5 -5
  159. package/src/engine/renderers/Indicator/wmsr.ts +13 -12
  160. package/src/engine/renderers/Indicator/zones.ts +7 -7
  161. package/src/engine/renderers/candle.ts +21 -21
  162. package/src/engine/renderers/crosshair.ts +3 -3
  163. package/src/engine/renderers/extremaMarkers.ts +13 -12
  164. package/src/engine/renderers/gridLines.ts +3 -3
  165. package/src/engine/renderers/lastPrice.ts +7 -7
  166. package/src/engine/renderers/paneTitle.ts +6 -6
  167. package/src/engine/renderers/subVolume.ts +23 -20
  168. package/src/engine/renderers/timeAxis.ts +9 -9
  169. package/src/engine/renderers/webgl/candleSurface.ts +43 -7
  170. package/src/engine/renderers/yAxis.ts +6 -5
  171. package/src/index.ts +1 -0
  172. package/src/plugin/types.ts +5 -1
  173. package/src/tokens/__tests__/__snapshots__/baseline.test.ts.snap +393 -0
  174. package/src/tokens/__tests__/baseline.test.ts +183 -0
  175. package/src/tokens/__tests__/themeToCssVars.test.ts +175 -0
  176. package/src/tokens/__tests__/tokens.test.ts +215 -0
  177. package/src/tokens/colorPresetSettings.ts +128 -0
  178. package/src/tokens/index.ts +65 -0
  179. package/src/tokens/mergeTheme.ts +48 -0
  180. package/src/tokens/theme-china.ts +132 -0
  181. package/src/tokens/theme-dark.ts +244 -0
  182. package/src/tokens/theme-light.ts +250 -0
  183. package/src/tokens/themeToCssVars.ts +138 -0
  184. package/src/tokens/types.ts +394 -0
  185. package/src/utils/kLineDraw/axis.ts +31 -30
  186. package/src/version.ts +1 -1
  187. package/dist/engine/theme/colors.d.ts +0 -223
  188. package/dist/engine/theme/colors.d.ts.map +0 -1
  189. package/dist/engine/theme/colors.js +0 -375
  190. package/dist/engine/theme/colors.js.map +0 -1
  191. 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
+ })