@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,132 @@
1
+ /**
2
+ * Asia-market (Chinese) colour convention helper.
3
+ *
4
+ * Asian markets traditionally use **red for "up"** (bull) and **green
5
+ * for "down"** (bear) — the reverse of the Western convention.
6
+ *
7
+ * {@link withAsiaMarketColors} takes any {@link Theme} and returns a new
8
+ * Theme with all bull/bear colour pairs swapped, so the caller only needs
9
+ * a single boolean (`isAsiaMarket`) to switch conventions at runtime.
10
+ *
11
+ * {@link resolveThemeColors} is a convenience for renderers that currently
12
+ * hard-code `theme === 'dark' ? darkTheme.colors : lightTheme.colors`.
13
+ *
14
+ * Usage:
15
+ * ```ts
16
+ * import { resolveThemeColors } from '../../tokens'
17
+ *
18
+ * const colors = resolveThemeColors(context.theme, context.isAsiaMarket)
19
+ * ```
20
+ */
21
+
22
+ import type { ColorTokens, Theme } from './types'
23
+ import { lightTheme } from './theme-light'
24
+ import { darkTheme } from './theme-dark'
25
+ import { applyColorPresetOverrides, type ColorPresetSettings } from './colorPresetSettings'
26
+
27
+ /**
28
+ * Swap all bull/bear colour pairs in a Theme so that "up" (bull) uses
29
+ * the formerly "down" (bear) colour and vice versa.
30
+ *
31
+ * @param theme — the base Theme (Western convention)
32
+ * @returns a **new** Theme object; the original is not mutated.
33
+ */
34
+ export function withAsiaMarketColors(theme: Theme): Theme {
35
+ return {
36
+ ...theme,
37
+ colors: {
38
+ ...theme.colors,
39
+
40
+ // ── Candle / OHLC ──
41
+ candleUpBody: theme.colors.candleDownBody,
42
+ candleDownBody: theme.colors.candleUpBody,
43
+ candleUpBorder: theme.colors.candleDownBorder,
44
+ candleDownBorder: theme.colors.candleUpBorder,
45
+ candleUpWick: theme.colors.candleDownWick,
46
+ candleDownWick: theme.colors.candleUpWick,
47
+
48
+ // ── Volume bars ──
49
+ volumeUp: theme.colors.volumeDown,
50
+ volumeDown: theme.colors.volumeUp,
51
+
52
+ // ── Footprint (ask = buy = bull, bid = sell = bear) ──
53
+ footprintAsk: theme.colors.footprintBid,
54
+ footprintBid: theme.colors.footprintAsk,
55
+
56
+ // ── Nested: price accents ──
57
+ price: {
58
+ ...theme.colors.price,
59
+ upLight: theme.colors.price.downLight,
60
+ downLight: theme.colors.price.upLight,
61
+ upTick: theme.colors.price.downTick,
62
+ downTick: theme.colors.price.upTick,
63
+ },
64
+
65
+ // ── Nested: MACD histogram bars ──
66
+ macd: {
67
+ ...theme.colors.macd,
68
+ barUp: theme.colors.macd.barDown,
69
+ barDown: theme.colors.macd.barUp,
70
+ barUpLight: theme.colors.macd.barDownLight,
71
+ barDownLight: theme.colors.macd.barUpLight,
72
+ },
73
+
74
+ // ── Nested: SMC structure (HH/HL = bull, LH/LL = bear) ──
75
+ structure: {
76
+ ...theme.colors.structure,
77
+ hh: theme.colors.structure.ll,
78
+ ll: theme.colors.structure.hh,
79
+ hl: theme.colors.structure.lh,
80
+ lh: theme.colors.structure.hl,
81
+ },
82
+
83
+ // ── Nested: Zones / FVG / Order Block ──
84
+ zones: {
85
+ ...theme.colors.zones,
86
+ fvgBullFill: theme.colors.zones.fvgBearFill,
87
+ fvgBearFill: theme.colors.zones.fvgBullFill,
88
+ fvgBullBorder: theme.colors.zones.fvgBearBorder,
89
+ fvgBearBorder: theme.colors.zones.fvgBullBorder,
90
+ obBullFill: theme.colors.zones.obBearFill,
91
+ obBearFill: theme.colors.zones.obBullFill,
92
+ },
93
+
94
+ // ── Nested: CCI overbought (bull) / oversold (bear) ──
95
+ cci: {
96
+ ...theme.colors.cci,
97
+ overbought: theme.colors.cci.oversold,
98
+ oversold: theme.colors.cci.overbought,
99
+ },
100
+
101
+ // ── Nested: WMSR overbought / oversold ──
102
+ wmsr: {
103
+ ...theme.colors.wmsr,
104
+ overbought: theme.colors.wmsr.oversold,
105
+ oversold: theme.colors.wmsr.overbought,
106
+ },
107
+ },
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Resolve a theme name + optional Asia-market flag into concrete
113
+ * {@link ColorTokens}.
114
+ *
115
+ * Renderers replace this pattern:
116
+ * ```ts
117
+ * const colors = theme === 'dark' ? darkTheme.colors : lightTheme.colors
118
+ * ```
119
+ * with:
120
+ * ```ts
121
+ * const colors = resolveThemeColors(theme, isAsiaMarket)
122
+ * ```
123
+ */
124
+ export function resolveThemeColors(
125
+ themeName: 'light' | 'dark',
126
+ isAsiaMarket?: boolean,
127
+ colorPresetSettings?: ColorPresetSettings,
128
+ ): ColorTokens {
129
+ const base = themeName === 'dark' ? darkTheme : lightTheme
130
+ const active = isAsiaMarket ? withAsiaMarketColors(base) : base
131
+ return applyColorPresetOverrides(active.colors, themeName, colorPresetSettings)
132
+ }
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Dark theme — paired with {@link lightTheme}.
3
+ *
4
+ * Color choices:
5
+ *
6
+ * - Background = #0E1116 (deep but not pure black — pure black creates
7
+ * halation around bright lines on OLED).
8
+ * - Bull = brighter green (#22D69B) — needed on dark background for
9
+ * 7.5:1 contrast (passes WCAG AAA for non-text).
10
+ * - Bear = brighter red (#FF6464) — 6.2:1 contrast.
11
+ * - Grid is barely visible (1.2:1 over background) so it never competes
12
+ * with the data.
13
+ * - Indicator palette is the same Okabe-Ito set but with the few hues
14
+ * that need a brightness bump on dark background pre-tuned.
15
+ *
16
+ * Same shape as light — only values change. The parity test in
17
+ * `__tests__/themes.test.ts` enforces this.
18
+ */
19
+
20
+ import type { Theme } from './types'
21
+
22
+ export const darkTheme: Theme = {
23
+ name: 'dark',
24
+ colors: {
25
+ background: '#111827',
26
+ foreground: '#E8EAED',
27
+ chartBackground: '#111827',
28
+
29
+ candleUpBody: '#22D69B',
30
+ candleUpBorder: '#22D69B',
31
+ candleUpWick: '#22D69B',
32
+ candleDownBody: '#FF6464',
33
+ candleDownBorder: '#FF6464',
34
+ candleDownWick: '#FF6464',
35
+ candleDojiBorder: '#8A8F98',
36
+
37
+ volumeUp: '#22D69B66',
38
+ volumeDown: '#FF646466',
39
+
40
+ axisText: '#9AA0A6',
41
+ axisLine: '#2A2F36',
42
+ axisTick: '#2A2F36',
43
+
44
+ gridMajor: '#1B1F26',
45
+ gridMinor: '#161A20',
46
+
47
+ crosshairLine: '#5F6368',
48
+ crosshairLabelBg: '#E8EAED',
49
+ crosshairLabelText: '#0E1116',
50
+
51
+ selectionFill: '#4A9EFF33',
52
+ selectionStroke: '#4A9EFF',
53
+
54
+ tooltipBg: '#1B1F26EE',
55
+ tooltipText: '#E8EAED',
56
+ tooltipBorder: '#2A2F36',
57
+
58
+ heatmapColdest: '#0E1116',
59
+ heatmapHottest: '#80B7FF',
60
+ volumeProfileFill: '#6B727A66',
61
+ volumeProfilePoc: '#FFA94D',
62
+ volumeProfileValueArea: '#4A9EFF33',
63
+ footprintAsk: '#22D69B80',
64
+ footprintBid: '#FF646480',
65
+ footprintImbalance: '#FFA94D',
66
+
67
+ alertActive: '#4A9EFF',
68
+ alertTriggered: '#FFA94D',
69
+ alertMuted: '#6B727A',
70
+
71
+ avwapLine: '#A78BFA',
72
+ avwapBand: '#A78BFA33',
73
+ mtfOverlay: '#38BDF8',
74
+
75
+ palette: {
76
+ // Same hue ordering as light theme; values tuned for dark BG.
77
+ i1: '#4A9EFF', // blue (brightened)
78
+ i2: '#FFB95A', // amber
79
+ i3: '#22D69B', // teal-green
80
+ i4: '#E879BA', // pink
81
+ i5: '#FF8848', // burnt orange
82
+ i6: '#7DD3FC', // sky
83
+ i7: '#FCE96A', // yellow
84
+ i8: '#A78BFA', // purple
85
+ i9: '#60A5FA', // blue
86
+ i10: '#9AA0A6', // neutral gray
87
+ indicatorAtr: '#F59E0B',
88
+ },
89
+
90
+ // ── Legacy indicator colours (from engine/theme/colors) ──
91
+ text: {
92
+ primary: 'hsl(210, 10%, 85%)',
93
+ secondary: 'hsl(210, 8%, 75%)',
94
+ tertiary: 'hsl(210, 6%, 60%)',
95
+ weak: 'hsl(210, 5%, 45%)',
96
+ white: 'rgba(255, 255, 255, 0.95)',
97
+ },
98
+ price: {
99
+ upLight: 'rgba(255, 80, 100, 0.85)',
100
+ upTick: 'hsl(0, 70%, 60%)',
101
+ downLight: 'rgba(60, 200, 160, 0.85)',
102
+ downTick: 'hsl(150, 50%, 65%)',
103
+ lastPrice: 'rgba(230, 100, 115, 0.95)',
104
+ },
105
+ tagBg: {
106
+ white: 'rgb(40, 40, 55)',
107
+ lightGray: 'rgba(50, 50, 65, 0.92)',
108
+ pureWhite: '#282837',
109
+ transparent: 'transparent',
110
+ active: '#1890ff',
111
+ activeHover: '#40a9ff',
112
+ hover: '#3a3a4a',
113
+ },
114
+ border: {
115
+ dark: 'rgba(255, 255, 255, 0.15)',
116
+ medium: 'rgba(255, 255, 255, 0.12)',
117
+ light: 'rgba(255, 255, 255, 0.08)',
118
+ separator: 'rgba(255, 255, 255, 0.10)',
119
+ button: '#505060',
120
+ chart: '#3A4048',
121
+ },
122
+ ma: {
123
+ ma5: 'rgba(255, 200, 50, 1)',
124
+ ma10: 'rgba(200, 150, 30, 1)',
125
+ ma20: 'rgba(90, 140, 255, 1)',
126
+ ma30: 'rgba(90, 190, 95, 1)',
127
+ ma60: 'rgba(170, 60, 195, 1)',
128
+ },
129
+ boll: {
130
+ upper: 'rgba(200, 60, 60, 1)',
131
+ middle: 'rgba(90, 140, 255, 1)',
132
+ lower: 'rgba(50, 170, 60, 1)',
133
+ bandFill: 'rgba(120, 170, 255, 0.15)',
134
+ },
135
+ macd: {
136
+ dif: 'rgba(90, 140, 255, 1)',
137
+ dea: 'rgba(255, 170, 50, 1)',
138
+ barUp: '#ff6b6b',
139
+ barUpLight: '#ffb3b3',
140
+ barDown: '#4ecdc4',
141
+ barDownLight: '#a8e6e1',
142
+ },
143
+ rsi: {
144
+ rsi1: 'rgba(90, 140, 255, 1)',
145
+ rsi2: 'rgba(255, 170, 50, 1)',
146
+ rsi3: 'rgba(180, 70, 205, 1)',
147
+ },
148
+ cci: {
149
+ cci: 'rgba(90, 140, 255, 1)',
150
+ overbought: 'rgba(255, 80, 100, 0.6)',
151
+ oversold: 'rgba(60, 200, 160, 0.6)',
152
+ },
153
+ kdj: {
154
+ k: 'rgba(90, 140, 255, 1)',
155
+ d: 'rgba(255, 170, 50, 1)',
156
+ j: 'rgba(180, 70, 205, 1)',
157
+ },
158
+ mom: {
159
+ mom: 'rgba(90, 140, 255, 1)',
160
+ zero: 'rgba(255, 255, 255, 0.2)',
161
+ },
162
+ wmsr: {
163
+ wmsr: 'rgba(90, 140, 255, 1)',
164
+ overbought: 'rgba(255, 80, 100, 0.6)',
165
+ oversold: 'rgba(60, 200, 160, 0.6)',
166
+ },
167
+ kst: {
168
+ kst: 'rgba(90, 140, 255, 1)',
169
+ signal: 'rgba(255, 170, 50, 1)',
170
+ },
171
+ expma: {
172
+ fast: 'rgba(255, 170, 50, 1)',
173
+ slow: 'rgba(90, 140, 255, 1)',
174
+ },
175
+ ene: {
176
+ upper: 'rgba(255, 80, 100, 1)',
177
+ middle: 'rgba(90, 140, 255, 1)',
178
+ lower: 'rgba(60, 200, 160, 1)',
179
+ bandFill: 'rgba(90, 140, 255, 0.12)',
180
+ },
181
+ label: {
182
+ bg: 'rgba(30, 30, 40, 0.9)',
183
+ text: '#ffffff',
184
+ },
185
+ lastPriceLabel: {
186
+ bg: 'rgba(60, 50, 55, 0.98)',
187
+ },
188
+ volumePrice: {
189
+ riseWith: '#FF6666',
190
+ riseWithout: '#66FF99',
191
+ fallWith: '#FF6666',
192
+ fallWithout: '#66FF99',
193
+ },
194
+ structure: {
195
+ hh: '#4ade80',
196
+ hl: '#22c55e',
197
+ lh: '#f87171',
198
+ ll: '#ef4444',
199
+ choch: '#a78bfa',
200
+ bos: '#fbbf24',
201
+ },
202
+ zones: {
203
+ fvgBullFill: 'rgba(74, 222, 128, 0.20)',
204
+ fvgBearFill: 'rgba(248, 113, 113, 0.20)',
205
+ fvgBullBorder: 'rgba(74, 222, 128, 0.8)',
206
+ fvgBearBorder: 'rgba(248, 113, 113, 0.8)',
207
+ obBullFill: 'rgba(74, 222, 128, 0.35)',
208
+ obBearFill: 'rgba(248, 113, 113, 0.35)',
209
+ },
210
+ wmsrGrid: 'rgba(255, 255, 255, 0.1)',
211
+ },
212
+ spacing: {
213
+ none: '0',
214
+ xxs: '2px',
215
+ xs: '4px',
216
+ sm: '8px',
217
+ md: '12px',
218
+ lg: '16px',
219
+ xl: '24px',
220
+ xxl: '32px',
221
+ xxxl: '64px',
222
+ },
223
+ typography: {
224
+ fontFamily:
225
+ "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
226
+ fontFamilyMono:
227
+ "ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace",
228
+ fontSizeSm: '10px',
229
+ fontSizeMd: '12px',
230
+ fontSizeLg: '14px',
231
+ fontWeightRegular: 400,
232
+ fontWeightMedium: 500,
233
+ fontWeightBold: 700,
234
+ lineHeightTight: 1.2,
235
+ lineHeightStandard: 1.4,
236
+ },
237
+ motion: {
238
+ durationInstant: '0ms',
239
+ durationFast: '120ms',
240
+ durationModerate: '200ms',
241
+ easingStandard: 'cubic-bezier(0.4, 0, 0.2, 1)',
242
+ easingDecelerate: 'cubic-bezier(0, 0, 0.2, 1)',
243
+ },
244
+ }
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Light theme — concrete token values.
3
+ *
4
+ * Color choices:
5
+ *
6
+ * - Bull (up) = a dark saturated green (#0F8B5C). Picked to clear the
7
+ * WCAG AA non-text threshold (≥ 3:1) against #FAFAFA. The lighter
8
+ * industry-standard greens like #26A69A fail that bar by ~25 %.
9
+ * - Bear (down) = a dark saturated red (#C2363B). Same rationale —
10
+ * the common #EE4D4D fails AA at ~2.6:1.
11
+ * - Background = #FAFAFA (slightly off-white, kinder to eyes than pure
12
+ * #FFFFFF for long sessions).
13
+ * - Grid major / minor split: major lines for round-number price tiers,
14
+ * minor for between-tier rhythm. Both very low contrast (1.3:1, 1.1:1)
15
+ * so they don't dominate.
16
+ *
17
+ * Indicator palette: ten qualitatively distinct hues using the Okabe-Ito
18
+ * colorblind-safe set (extended to ten by adding three desaturated mids).
19
+ * Each WCAG AA against the background (>= 3:1 for non-text).
20
+ */
21
+
22
+ import type { Theme } from './types'
23
+
24
+ export const lightTheme: Theme = {
25
+ name: 'light',
26
+ colors: {
27
+ background: '#FAFAFA',
28
+ foreground: '#1F1F1F',
29
+ chartBackground: '#FFFFFF',
30
+
31
+ candleUpBody: '#0F8B5C',
32
+ candleUpBorder: '#0F8B5C',
33
+ candleUpWick: '#0F8B5C',
34
+ candleDownBody: '#C2363B',
35
+ candleDownBorder: '#C2363B',
36
+ candleDownWick: '#C2363B',
37
+ candleDojiBorder: '#6E6E6E',
38
+
39
+ volumeUp: '#0F8B5C66', // 40% alpha — paired with candleUp
40
+ volumeDown: '#C2363B66',
41
+
42
+ axisText: '#5A5A5A',
43
+ axisLine: '#D0D0D0',
44
+ axisTick: '#D0D0D0',
45
+
46
+ gridMajor: '#E5E5E5',
47
+ gridMinor: '#F0F0F0',
48
+
49
+ crosshairLine: '#8C8C8C',
50
+ crosshairLabelBg: '#1F1F1F',
51
+ crosshairLabelText: '#FAFAFA',
52
+
53
+ selectionFill: '#2D7FF933',
54
+ selectionStroke: '#2D7FF9',
55
+
56
+ tooltipBg: '#FFFFFFEE',
57
+ tooltipText: '#1F1F1F',
58
+ tooltipBorder: '#D0D0D0',
59
+
60
+ heatmapColdest: '#F0F4F8',
61
+ heatmapHottest: '#1F3A5F',
62
+ volumeProfileFill: '#9CA3AF66',
63
+ volumeProfilePoc: '#F97316',
64
+ volumeProfileValueArea: '#2D7FF933',
65
+ footprintAsk: '#0F8B5C80',
66
+ footprintBid: '#C2363B80',
67
+ footprintImbalance: '#F97316',
68
+
69
+ alertActive: '#2D7FF9',
70
+ // alertTriggered: orange #F97316 was 2.69:1 on white (fails AA
71
+ // non-text). Darkened to #C2410C → 4.13:1.
72
+ alertTriggered: '#C2410C',
73
+ alertMuted: '#9CA3AF',
74
+
75
+ avwapLine: '#7C3AED',
76
+ avwapBand: '#7C3AED33',
77
+ // mtfOverlay: sky #0EA5E9 was 2.66:1 on white. Darkened to
78
+ // #0369A1 → 4.59:1.
79
+ mtfOverlay: '#0369A1',
80
+
81
+ palette: {
82
+ // Okabe-Ito-derived qualitative scale, AA on #FAFAFA
83
+ i1: '#0072B2', // strong blue
84
+ i2: '#E69F00', // amber
85
+ i3: '#009E73', // teal-green
86
+ i4: '#CC79A7', // pink
87
+ i5: '#D55E00', // burnt orange
88
+ i6: '#56B4E9', // sky
89
+ i7: '#F0E442', // yellow (use sparingly — low contrast)
90
+ i8: '#7C3AED', // purple
91
+ i9: '#2D7FF9', // blue
92
+ i10: '#6E6E6E', // neutral gray
93
+ indicatorAtr: '#d97706',
94
+ },
95
+
96
+ // ── Legacy indicator colours (from engine/theme/colors) ──
97
+ text: {
98
+ primary: 'hsl(210, 9%, 31%)',
99
+ secondary: 'hsl(210, 9%, 35%)',
100
+ tertiary: 'hsl(210, 8%, 50%)',
101
+ weak: 'hsl(210, 7%, 65%)',
102
+ white: 'rgba(255, 255, 255, 0.92)',
103
+ },
104
+ price: {
105
+ upLight: 'rgba(214, 10, 34, 0.92)',
106
+ upTick: 'hsl(0, 60%, 50%)',
107
+ downLight: 'rgba(3, 123, 102, 0.92)',
108
+ downTick: 'hsl(150, 30%, 60%)',
109
+ lastPrice: 'rgba(196, 74, 86, 0.95)',
110
+ },
111
+ tagBg: {
112
+ white: 'rgb(255, 255, 255)',
113
+ lightGray: 'rgba(255, 255, 255, 0.92)',
114
+ pureWhite: '#ffffff',
115
+ transparent: 'transparent',
116
+ active: '#1890ff',
117
+ activeHover: '#40a9ff',
118
+ hover: '#f0f0f0',
119
+ },
120
+ border: {
121
+ dark: 'rgba(0, 0, 0, 0.12)',
122
+ medium: 'rgba(0, 0, 0, 0.10)',
123
+ light: 'rgba(0, 0, 0, 0.08)',
124
+ separator: 'rgba(0, 0, 0, 0.10)',
125
+ button: '#d0d0d0',
126
+ chart: '#e5e5e5',
127
+ },
128
+ ma: {
129
+ ma5: 'rgba(255, 193, 37, 1)',
130
+ ma10: 'rgba(190, 131, 12, 1)',
131
+ ma20: 'rgba(69, 112, 249, 1)',
132
+ ma30: 'rgba(76, 175, 80, 1)',
133
+ ma60: 'rgba(156, 39, 176, 1)',
134
+ },
135
+ boll: {
136
+ upper: 'rgba(178, 34, 34, 1)',
137
+ middle: 'rgba(69, 112, 249, 1)',
138
+ lower: 'rgba(34, 139, 34, 1)',
139
+ bandFill: 'rgba(100, 149, 237, 0.1)',
140
+ },
141
+ macd: {
142
+ dif: 'rgba(69, 112, 249, 1)',
143
+ dea: 'rgba(255, 152, 0, 1)',
144
+ barUp: '#ff5252',
145
+ barUpLight: '#fccbcd',
146
+ barDown: '#22ab94',
147
+ barDownLight: '#ace5dc',
148
+ },
149
+ rsi: {
150
+ rsi1: 'rgba(69, 112, 249, 1)',
151
+ rsi2: 'rgba(255, 152, 0, 1)',
152
+ rsi3: 'rgba(156, 39, 176, 1)',
153
+ },
154
+ cci: {
155
+ cci: 'rgba(69, 112, 249, 1)',
156
+ overbought: 'rgba(214, 10, 34, 0.5)',
157
+ oversold: 'rgba(3, 123, 102, 0.5)',
158
+ },
159
+ kdj: {
160
+ k: 'rgba(69, 112, 249, 1)',
161
+ d: 'rgba(255, 152, 0, 1)',
162
+ j: 'rgba(156, 39, 176, 1)',
163
+ },
164
+ mom: {
165
+ mom: 'rgba(69, 112, 249, 1)',
166
+ zero: 'rgba(0, 0, 0, 0.2)',
167
+ },
168
+ wmsr: {
169
+ wmsr: 'rgba(69, 112, 249, 1)',
170
+ overbought: 'rgba(214, 10, 34, 0.5)',
171
+ oversold: 'rgba(3, 123, 102, 0.5)',
172
+ },
173
+ kst: {
174
+ kst: 'rgba(69, 112, 249, 1)',
175
+ signal: 'rgba(255, 152, 0, 1)',
176
+ },
177
+ expma: {
178
+ fast: 'rgba(255, 152, 0, 1)',
179
+ slow: 'rgba(69, 112, 249, 1)',
180
+ },
181
+ ene: {
182
+ upper: 'rgba(214, 10, 34, 1)',
183
+ middle: 'rgba(69, 112, 249, 1)',
184
+ lower: 'rgba(3, 123, 102, 1)',
185
+ bandFill: 'rgba(69, 112, 249, 0.08)',
186
+ },
187
+ label: {
188
+ bg: 'rgba(0, 0, 0, 0.8)',
189
+ text: '#ffffff',
190
+ },
191
+ lastPriceLabel: {
192
+ bg: 'rgba(255, 247, 248, 0.98)',
193
+ },
194
+ volumePrice: {
195
+ riseWith: '#FF4444',
196
+ riseWithout: '#00C853',
197
+ fallWith: '#FF4444',
198
+ fallWithout: '#00C853',
199
+ },
200
+ structure: {
201
+ hh: '#16a34a',
202
+ hl: '#22c55e',
203
+ lh: '#dc2626',
204
+ ll: '#ef4444',
205
+ choch: '#8b5cf6',
206
+ bos: '#f59e0b',
207
+ },
208
+ zones: {
209
+ fvgBullFill: 'rgba(34, 197, 94, 0.15)',
210
+ fvgBearFill: 'rgba(239, 68, 68, 0.15)',
211
+ fvgBullBorder: 'rgba(34, 197, 94, 0.6)',
212
+ fvgBearBorder: 'rgba(239, 68, 68, 0.6)',
213
+ obBullFill: 'rgba(34, 197, 94, 0.25)',
214
+ obBearFill: 'rgba(239, 68, 68, 0.25)',
215
+ },
216
+ wmsrGrid: 'rgba(0, 0, 0, 0.1)',
217
+ },
218
+ spacing: {
219
+ none: '0',
220
+ xxs: '2px',
221
+ xs: '4px',
222
+ sm: '8px',
223
+ md: '12px',
224
+ lg: '16px',
225
+ xl: '24px',
226
+ xxl: '32px',
227
+ xxxl: '64px',
228
+ },
229
+ typography: {
230
+ fontFamily:
231
+ "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
232
+ fontFamilyMono:
233
+ "ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace",
234
+ fontSizeSm: '10px',
235
+ fontSizeMd: '12px',
236
+ fontSizeLg: '14px',
237
+ fontWeightRegular: 400,
238
+ fontWeightMedium: 500,
239
+ fontWeightBold: 700,
240
+ lineHeightTight: 1.2,
241
+ lineHeightStandard: 1.4,
242
+ },
243
+ motion: {
244
+ durationInstant: '0ms',
245
+ durationFast: '120ms',
246
+ durationModerate: '200ms',
247
+ easingStandard: 'cubic-bezier(0.4, 0, 0.2, 1)',
248
+ easingDecelerate: 'cubic-bezier(0, 0, 0.2, 1)',
249
+ },
250
+ }