@363045841yyt/klinechart-core 0.7.6 → 0.7.7

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 +15 -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 +18 -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
@@ -52,15 +52,24 @@ export const DEFAULT_SETTINGS = [
52
52
  { key: 'showVolumePriceMarkers', label: '显示量价关系标记', type: 'boolean', default: false, group: 'main' },
53
53
  { key: 'logarithmicScale', label: '对数价格轴', type: 'boolean', default: false, group: 'main' },
54
54
  { key: 'disableMainPaneVerticalScroll', label: '主图纵轴刻度自适应调整', type: 'boolean', default: true, group: 'main' },
55
+ { key: 'isAsiaMarket', label: '亚洲市场颜色(红涨绿跌)', type: 'boolean', default: false, group: 'main' },
55
56
  { key: 'enableWebGLRendering', label: '启用 WebGL 硬件加速渲染', type: 'boolean', default: ENABLE_WEBGL_DEFAULT, group: 'main' },
57
+ { key: 'theme', label: '主题', type: 'select', default: 'light', group: 'main', options: [
58
+ { value: 'light', label: '浅色' },
59
+ { value: 'dark', label: '深色' },
60
+ { value: 'auto', label: '跟随系统' },
61
+ ] },
56
62
  { key: 'performanceTest10kKlines', label: '万条K线性能测试', type: 'boolean', default: false, group: 'experimental' },
57
63
  { key: 'enableCanvasProfiler', label: 'Canvas 性能分析插桩', type: 'boolean', default: false, group: 'experimental' },
58
64
  ] as const
59
65
 
60
66
  /** 图表设置类型(从 DEFAULT_SETTINGS 自动推导,同时兼容扩展) */
61
67
  export type ChartSettings = {
62
- [K in (typeof DEFAULT_SETTINGS)[number]['key']]?: boolean
63
- } & Record<string, boolean | string>
68
+ [K in (typeof DEFAULT_SETTINGS)[number]['key']]?: boolean | string
69
+ } & Record<string, boolean | string | ColorPresetSettings | undefined> & {
70
+ colorPresetSettings?: ColorPresetSettings
71
+ }
64
72
 
65
73
  /** localStorage 存储键名 */
66
74
  export const SETTINGS_STORAGE_KEY = 'kline-chart-settings'
75
+ import type { ColorPresetSettings } from '../tokens/colorPresetSettings'
@@ -1116,6 +1116,8 @@ export class Chart {
1116
1116
  yAxisRanges: sharedYAxisRanges,
1117
1117
  xAxisRanges: sharedXAxisRanges,
1118
1118
  theme: this._themeSignal.peek(),
1119
+ isAsiaMarket: this.settings.isAsiaMarket as boolean,
1120
+ colorPresetSettings: this.settings.colorPresetSettings,
1119
1121
  }
1120
1122
 
1121
1123
  if (shouldUpdateMain || shouldUpdateOverlay) {
@@ -1193,6 +1195,8 @@ export class Chart {
1193
1195
  xAxisLabels: sharedXAxisLabels,
1194
1196
  xAxisRanges: sharedXAxisRanges,
1195
1197
  theme: this._themeSignal.peek(),
1198
+ isAsiaMarket: this.settings.isAsiaMarket as boolean,
1199
+ colorPresetSettings: this.settings.colorPresetSettings,
1196
1200
  }
1197
1201
  const errors = this.rendererPluginManager.renderPlugin('timeAxis', timeAxisContext)
1198
1202
  if (errors.length > 0) {
@@ -2,8 +2,6 @@
2
2
  * 像素对齐工具函数 - 逻辑像素空间(配合 ctx.scale(dpr) 使用)
3
3
  */
4
4
 
5
- import { getColors } from '../theme/colors'
6
-
7
5
  /**
8
6
  * 将逻辑坐标对齐到物理像素边界(用于矩形填充)
9
7
  * @param value - 逻辑坐标值
@@ -190,7 +190,7 @@ export function createDrawingRendererPlugin(options: {
190
190
  description: '绘图渲染器(仅负责绘制形状)',
191
191
  debugName: '绘图层',
192
192
  paneId: options.paneId ?? 'main',
193
- priority: -25,
193
+ priority: 55,
194
194
  draw(context: RenderContext) {
195
195
  const { ctx, pane, data, range, dpr, paneWidth, kLinePositions, kLineCenters, kBarRects, kWidth, kGap } = context
196
196
  const viewport = context.viewport ?? {
@@ -1,5 +1,6 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
+ import { resolveThemeColors } from '../../../tokens'
3
4
  import type { ATRRenderState } from '../../indicators/atrState'
4
5
  import { createATRStateKey } from '../../indicators/atrState'
5
6
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
@@ -88,6 +89,8 @@ export function createATRRendererPlugin(options: ATRRendererOptions = {}): Rende
88
89
 
89
90
  draw(context: RenderContext) {
90
91
  const { ctx, pane, range, scrollLeft, kLineCenters, lineWebGLSurface } = context
92
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
93
+ const atrColor = colors.palette?.indicatorAtr ?? ATR_COLOR
91
94
 
92
95
  const stateKey = resolveKey()
93
96
  if (!stateKey) return
@@ -147,7 +150,7 @@ export function createATRRendererPlugin(options: ATRRendererOptions = {}): Rende
147
150
  if (enableWebGL && lineWebGLSurface?.isAvailable()) {
148
151
  if (cachedPoints.length >= 2) {
149
152
  const ok = lineWebGLSurface.drawLineStrips(
150
- [{ points: cachedPoints, width: 1, color: ATR_COLOR }],
153
+ [{ points: cachedPoints, width: 1, color: atrColor }],
151
154
  scrollLeft,
152
155
  )
153
156
  if (ok) {
@@ -158,7 +161,7 @@ export function createATRRendererPlugin(options: ATRRendererOptions = {}): Rende
158
161
  }
159
162
 
160
163
  if (!usedWebGL) {
161
- drawWithCanvas2D(ctx, scrollLeft, cachedPoints)
164
+ drawWithCanvas2D(ctx, scrollLeft, cachedPoints, atrColor)
162
165
  }
163
166
  },
164
167
 
@@ -179,11 +182,12 @@ function drawWithCanvas2D(
179
182
  ctx: CanvasRenderingContext2D,
180
183
  scrollLeft: number,
181
184
  points: LinePoint[],
185
+ atrColor: string,
182
186
  ): void {
183
187
  if (points.length < 2) return
184
188
  ctx.save()
185
189
  ctx.translate(-scrollLeft, 0)
186
- ctx.strokeStyle = ATR_COLOR
190
+ ctx.strokeStyle = atrColor
187
191
  ctx.lineWidth = 1
188
192
  ctx.lineJoin = 'round'
189
193
  ctx.lineCap = 'round'
@@ -2,7 +2,7 @@ import type { RendererPluginWithHost, PluginHost, RenderContext } from '../../..
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { KLineData } from '../../../types/price'
4
4
  import { alignToPhysicalPixelCenter } from '../../draw/pixelAlign'
5
- import { getColors } from '../../theme/colors'
5
+ import { resolveThemeColors } from '../../../tokens'
6
6
  import { BOLL_STATE_KEY, type BOLLRenderState } from '../../indicators/bollState'
7
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
8
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
@@ -54,7 +54,7 @@ function drawBOLLWithWebGL(
54
54
  bandLowerPoints: LinePoint[]
55
55
  }
56
56
  ): boolean {
57
- const colors = getColors(context.theme)
57
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
58
58
  if (context.settings?.enableWebGLRendering === false) return false
59
59
  const surface = context.lineWebGLSurface
60
60
  if (!surface || !surface.isAvailable()) return false
@@ -66,24 +66,24 @@ function drawBOLLWithWebGL(
66
66
  surface.clear()
67
67
  allOk = surface.drawFilledBand(
68
68
  { upperPoints: data.bandUpperPoints, lowerPoints: data.bandLowerPoints },
69
- toOpaqueRgba(colors.BOLL.BAND_FILL),
69
+ toOpaqueRgba(colors.boll.bandFill),
70
70
  context.scrollLeft
71
71
  )
72
72
  if (allOk) {
73
- compositeLineSurface(context, surface, getRgbaAlpha(colors.BOLL.BAND_FILL))
73
+ compositeLineSurface(context, surface, getRgbaAlpha(colors.boll.bandFill))
74
74
  }
75
75
  }
76
76
  surface.clear()
77
77
 
78
78
  const lineStrips: Array<{ points: LinePoint[]; width: number; color: string }> = []
79
79
  if (data.showUpper && data.upperPoints.length >= 2) {
80
- lineStrips.push({ points: data.upperPoints, width: BOLL_LINE_WIDTH, color: colors.BOLL.UPPER })
80
+ lineStrips.push({ points: data.upperPoints, width: BOLL_LINE_WIDTH, color: colors.boll.upper })
81
81
  }
82
82
  if (data.showMiddle && data.middlePoints.length >= 2) {
83
- lineStrips.push({ points: data.middlePoints, width: BOLL_LINE_WIDTH, color: colors.BOLL.MIDDLE })
83
+ lineStrips.push({ points: data.middlePoints, width: BOLL_LINE_WIDTH, color: colors.boll.middle })
84
84
  }
85
85
  if (data.showLower && data.lowerPoints.length >= 2) {
86
- lineStrips.push({ points: data.lowerPoints, width: BOLL_LINE_WIDTH, color: colors.BOLL.LOWER })
86
+ lineStrips.push({ points: data.lowerPoints, width: BOLL_LINE_WIDTH, color: colors.boll.lower })
87
87
  }
88
88
 
89
89
  if (lineStrips.length > 0) {
@@ -183,7 +183,7 @@ export function createBOLLRendererPlugin(): RendererPluginWithHost {
183
183
  draw(context: RenderContext) {
184
184
  const { ctx, pane, data, range, scrollLeft, dpr, kLineCenters } = context
185
185
  const klineData = data as KLineData[]
186
- const colors = getColors(context.theme)
186
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
187
187
 
188
188
  const stateKey = resolveKey()
189
189
  if (!stateKey) return
@@ -281,7 +281,7 @@ export function createBOLLRendererPlugin(): RendererPluginWithHost {
281
281
  bandPath.lineTo(bandLowerPoints[i].x, bandLowerPoints[i].y)
282
282
  }
283
283
  bandPath.closePath()
284
- ctx.fillStyle = colors.BOLL.BAND_FILL
284
+ ctx.fillStyle = colors.boll.bandFill
285
285
  ctx.fill(bandPath)
286
286
  }
287
287
 
@@ -296,9 +296,9 @@ export function createBOLLRendererPlugin(): RendererPluginWithHost {
296
296
  ctx.stroke()
297
297
  }
298
298
 
299
- if (showUpper) drawLine(upperPoints, colors.BOLL.UPPER)
300
- if (showMiddle) drawLine(middlePoints, colors.BOLL.MIDDLE)
301
- if (showLower) drawLine(lowerPoints, colors.BOLL.LOWER)
299
+ if (showUpper) drawLine(upperPoints, colors.boll.upper)
300
+ if (showMiddle) drawLine(middlePoints, colors.boll.middle)
301
+ if (showLower) drawLine(lowerPoints, colors.boll.lower)
302
302
 
303
303
  ctx.restore()
304
304
  },
@@ -1,6 +1,6 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
- import { getColors, type ChartTheme } from '../../theme/colors'
3
+ import { resolveThemeColors } from '../../../tokens'
4
4
  import type { CCIRenderState } from '../../indicators/cciState'
5
5
  import { createCCIStateKey } from '../../indicators/cciState'
6
6
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
@@ -92,7 +92,7 @@ export function createCCIRendererPlugin(options: CCIRendererOptions = {}): Rende
92
92
 
93
93
  draw(context: RenderContext) {
94
94
  const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = context
95
- const colors = getColors(context.theme)
95
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
96
96
 
97
97
  const stateKey = resolveKey()
98
98
  if (!stateKey) return
@@ -123,7 +123,7 @@ const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = co
123
123
  const lineStartX = scrollLeft
124
124
  const lineEndX = scrollLeft + context.paneWidth
125
125
 
126
- ctx.strokeStyle = colors.CCI.OVERBOUGHT
126
+ ctx.strokeStyle = colors.cci.overbought
127
127
  ctx.lineWidth = 1
128
128
  ctx.setLineDash([4, 4])
129
129
  ctx.beginPath()
@@ -131,7 +131,7 @@ const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = co
131
131
  ctx.lineTo(lineEndX, y100)
132
132
  ctx.stroke()
133
133
 
134
- ctx.strokeStyle = colors.CCI.OVERSOLD
134
+ ctx.strokeStyle = colors.cci.oversold
135
135
  ctx.beginPath()
136
136
  ctx.moveTo(lineStartX, yNeg100)
137
137
  ctx.lineTo(lineEndX, yNeg100)
@@ -177,7 +177,7 @@ const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = co
177
177
  if (enableWebGL && lineWebGLSurface?.isAvailable()) {
178
178
  if (params.showCCI && cachedCCIPoints.length >= 2) {
179
179
  const ok = lineWebGLSurface.drawLineStrips(
180
- [{ points: cachedCCIPoints, width: 1, color: colors.CCI.CCI }],
180
+ [{ points: cachedCCIPoints, width: 1, color: colors.cci.cci }],
181
181
  scrollLeft
182
182
  )
183
183
  if (ok) {
@@ -213,13 +213,13 @@ function drawCCILineWithCanvas2D(
213
213
  scrollLeft: number,
214
214
  cciPoints: LinePoint[],
215
215
  params: { showCCI: boolean },
216
- colors: { CCI: { CCI: string; OVERBOUGHT: string; OVERSOLD: string } }
216
+ colors: { cci: { cci: string; overbought: string; oversold: string } }
217
217
  ): void {
218
218
  if (!params.showCCI || cciPoints.length < 2) return
219
219
 
220
220
  ctx.save()
221
221
  ctx.translate(-scrollLeft, 0)
222
- ctx.strokeStyle = colors.CCI.CCI
222
+ ctx.strokeStyle = colors.cci.cci
223
223
  ctx.lineWidth = 1
224
224
  ctx.lineJoin = 'round'
225
225
  ctx.lineCap = 'round'
@@ -241,9 +241,10 @@ export function getCCITitleInfo(
241
241
  period: number,
242
242
  pluginHost: PluginHost,
243
243
  paneId: string = 'sub_CCI',
244
- theme: ChartTheme = 'light'
244
+ theme: 'light' | 'dark' = 'light',
245
+ isAsiaMarket?: boolean
245
246
  ): { name: string; params: number[]; values: Array<{ label: string; value: number; color: string }> } | null {
246
- const colors = getColors(theme)
247
+ const colors = resolveThemeColors(theme, isAsiaMarket)
247
248
  const state = pluginHost.getSharedState<CCIRenderState>(createCCIStateKey(paneId))
248
249
  if (!state) return null
249
250
 
@@ -254,7 +255,7 @@ export function getCCITitleInfo(
254
255
  name: 'CCI',
255
256
  params: [period],
256
257
  values: [
257
- { label: 'CCI', value: cci, color: colors.CCI.CCI },
258
+ { label: 'CCI', value: cci, color: colors.cci.cci },
258
259
  ],
259
260
  }
260
261
  }
@@ -2,7 +2,7 @@ import type { RendererPluginWithHost, PluginHost, RenderContext } from '../../..
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { KLineData } from '../../../types/price'
4
4
  import { alignToPhysicalPixelCenter } from '../../draw/pixelAlign'
5
- import { getColors } from '../../theme/colors'
5
+ import { resolveThemeColors } from '../../../tokens'
6
6
  import { ENE_STATE_KEY, type ENERenderState } from '../../indicators/eneState'
7
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
8
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
@@ -40,7 +40,7 @@ function drawENEWithWebGL(
40
40
  lowerPoints: LinePoint[]
41
41
  }
42
42
  ): boolean {
43
- const colors = getColors(context.theme)
43
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
44
44
  if (context.settings?.enableWebGLRendering === false) return false
45
45
  const surface = context.lineWebGLSurface
46
46
  if (!surface || !surface.isAvailable()) return false
@@ -52,24 +52,24 @@ function drawENEWithWebGL(
52
52
  surface.clear()
53
53
  allOk = surface.drawFilledBand(
54
54
  { upperPoints: data.upperPoints, lowerPoints: data.lowerPoints },
55
- toOpaqueRgba(colors.ENE.BAND_FILL),
55
+ toOpaqueRgba(colors.ene.bandFill),
56
56
  context.scrollLeft
57
57
  )
58
58
  if (allOk) {
59
- compositeLineSurface(context, surface, getRgbaAlpha(colors.ENE.BAND_FILL))
59
+ compositeLineSurface(context, surface, getRgbaAlpha(colors.ene.bandFill))
60
60
  }
61
61
  }
62
62
  surface.clear()
63
63
 
64
64
  const lineStrips: Array<{ points: LinePoint[]; width: number; color: string }> = []
65
65
  if (data.upperPoints.length >= 2) {
66
- lineStrips.push({ points: data.upperPoints, width: 1, color: colors.ENE.UPPER })
66
+ lineStrips.push({ points: data.upperPoints, width: 1, color: colors.ene.upper })
67
67
  }
68
68
  if (data.middlePoints.length >= 2) {
69
- lineStrips.push({ points: data.middlePoints, width: 1, color: colors.ENE.MIDDLE })
69
+ lineStrips.push({ points: data.middlePoints, width: 1, color: colors.ene.middle })
70
70
  }
71
71
  if (data.lowerPoints.length >= 2) {
72
- lineStrips.push({ points: data.lowerPoints, width: 1, color: colors.ENE.LOWER })
72
+ lineStrips.push({ points: data.lowerPoints, width: 1, color: colors.ene.lower })
73
73
  }
74
74
  if (lineStrips.length > 0) {
75
75
  allOk = surface.drawLineStrips(lineStrips, context.scrollLeft)
@@ -143,7 +143,7 @@ export function createENERendererPlugin(): RendererPluginWithHost {
143
143
  draw(context: RenderContext) {
144
144
  const { ctx, pane, data, range, scrollLeft, dpr, kLineCenters } = context
145
145
  const klineData = data as KLineData[]
146
- const colors = getColors(context.theme)
146
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
147
147
 
148
148
  const stateKey = resolveKey()
149
149
  if (!stateKey) return
@@ -193,7 +193,7 @@ export function createENERendererPlugin(): RendererPluginWithHost {
193
193
  ctx.save()
194
194
  ctx.translate(-scrollLeft, 0)
195
195
 
196
- ctx.fillStyle = colors.ENE.BAND_FILL
196
+ ctx.fillStyle = colors.ene.bandFill
197
197
  ctx.beginPath()
198
198
  if (upperPoints.length > 0) {
199
199
  ctx.moveTo(upperPoints[0]!.x, upperPoints[0]!.y)
@@ -225,9 +225,9 @@ export function createENERendererPlugin(): RendererPluginWithHost {
225
225
  ctx.stroke()
226
226
  }
227
227
 
228
- drawLine(upperPoints, colors.ENE.UPPER)
229
- drawLine(middlePoints, colors.ENE.MIDDLE)
230
- drawLine(lowerPoints, colors.ENE.LOWER)
228
+ drawLine(upperPoints, colors.ene.upper)
229
+ drawLine(middlePoints, colors.ene.middle)
230
+ drawLine(lowerPoints, colors.ene.lower)
231
231
 
232
232
  ctx.restore()
233
233
  },
@@ -2,7 +2,7 @@ import type { RendererPluginWithHost, PluginHost, RenderContext } from '../../..
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
3
  import type { KLineData } from '../../../types/price'
4
4
  import { alignToPhysicalPixelCenter } from '../../draw/pixelAlign'
5
- import { getColors } from '../../theme/colors'
5
+ import { resolveThemeColors } from '../../../tokens'
6
6
  import { EXPMA_STATE_KEY, type EXPMARenderState } from '../../indicators/expmaState'
7
7
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
8
8
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
@@ -82,7 +82,7 @@ export function createEXPMARendererPlugin(): RendererPluginWithHost {
82
82
  draw(context: RenderContext) {
83
83
  const { ctx, pane, data, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = context
84
84
  const klineData = data as KLineData[]
85
- const colors = getColors(context.theme)
85
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
86
86
  const stateKey = resolveKey()
87
87
  if (!stateKey) return
88
88
  const state = pluginHost?.getSharedState<EXPMARenderState>(stateKey)
@@ -123,10 +123,10 @@ export function createEXPMARendererPlugin(): RendererPluginWithHost {
123
123
  if (enableWebGL && lineWebGLSurface?.isAvailable()) {
124
124
  const lines: Array<{ points: LinePoint[]; width: number; color: string }> = []
125
125
  if (cachedFastPoints.length >= 2) {
126
- lines.push({ points: cachedFastPoints, width: 1, color: colors.EXPMA.FAST })
126
+ lines.push({ points: cachedFastPoints, width: 1, color: colors.expma.fast })
127
127
  }
128
128
  if (cachedSlowPoints.length >= 2) {
129
- lines.push({ points: cachedSlowPoints, width: 1, color: colors.EXPMA.SLOW })
129
+ lines.push({ points: cachedSlowPoints, width: 1, color: colors.expma.slow })
130
130
  }
131
131
 
132
132
  const allOk = lines.length > 0 && lineWebGLSurface.drawLineStrips(lines, scrollLeft)
@@ -146,7 +146,7 @@ export function createEXPMARendererPlugin(): RendererPluginWithHost {
146
146
  ctx.lineCap = 'round'
147
147
 
148
148
  if (cachedFastPoints.length >= 2) {
149
- ctx.strokeStyle = colors.EXPMA.FAST
149
+ ctx.strokeStyle = colors.expma.fast
150
150
  ctx.beginPath()
151
151
  ctx.moveTo(cachedFastPoints[0]!.x, cachedFastPoints[0]!.y)
152
152
  for (let i = 1; i < cachedFastPoints.length; i++) {
@@ -157,7 +157,7 @@ export function createEXPMARendererPlugin(): RendererPluginWithHost {
157
157
  }
158
158
 
159
159
  if (cachedSlowPoints.length >= 2) {
160
- ctx.strokeStyle = colors.EXPMA.SLOW
160
+ ctx.strokeStyle = colors.expma.slow
161
161
  ctx.beginPath()
162
162
  ctx.moveTo(cachedSlowPoints[0]!.x, cachedSlowPoints[0]!.y)
163
163
  for (let i = 1; i < cachedSlowPoints.length; i++) {
@@ -1,6 +1,6 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
- import { getColors, type ChartTheme } from '../../theme/colors'
3
+ import { resolveThemeColors } from '../../../tokens'
4
4
  import { alignToPhysicalPixelCenter } from '../../draw/pixelAlign'
5
5
  import type { FASTKRenderState } from '../../indicators/fastkState'
6
6
  import { createFASTKStateKey } from '../../indicators/fastkState'
@@ -148,7 +148,7 @@ export function createFASTKRendererPlugin(options: FASTKRendererOptions = {}): R
148
148
 
149
149
  draw(context: RenderContext) {
150
150
  const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = context
151
- const colors = getColors(context.theme)
151
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
152
152
 
153
153
  const stateKey = resolveKey()
154
154
  if (!stateKey) return
@@ -218,7 +218,7 @@ const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = co
218
218
  if (enableWebGL && lineWebGLSurface?.isAvailable()) {
219
219
  if (params.showFASTK && cachedFASTKPoints.length >= 2) {
220
220
  const ok = lineWebGLSurface.drawLineStrips(
221
- [{ points: cachedFASTKPoints, width: 1, color: colors.KDJ.K }],
221
+ [{ points: cachedFASTKPoints, width: 1, color: colors.kdj.k }],
222
222
  scrollLeft
223
223
  )
224
224
  if (ok) {
@@ -254,13 +254,13 @@ function drawFASTKLineWithCanvas2D(
254
254
  scrollLeft: number,
255
255
  fastkPoints: LinePoint[],
256
256
  params: { showFASTK: boolean },
257
- colors: { KDJ: { K: string } }
257
+ colors: { kdj: { k: string } }
258
258
  ): void {
259
259
  if (!params.showFASTK || fastkPoints.length < 2) return
260
260
 
261
261
  ctx.save()
262
262
  ctx.translate(-scrollLeft, 0)
263
- ctx.strokeStyle = colors.KDJ.K
263
+ ctx.strokeStyle = colors.kdj.k
264
264
  ctx.lineWidth = 1
265
265
  ctx.lineJoin = 'round'
266
266
  ctx.lineCap = 'round'
@@ -282,9 +282,10 @@ export function getFASTKTitleInfo(
282
282
  period: number,
283
283
  pluginHost: PluginHost,
284
284
  paneId: string = 'sub_FASTK',
285
- theme: ChartTheme = 'light'
285
+ theme: 'light' | 'dark' = 'light',
286
+ isAsiaMarket?: boolean
286
287
  ): { name: string; params: number[]; values: Array<{ label: string; value: number; color: string }> } | null {
287
- const colors = getColors(theme)
288
+ const colors = resolveThemeColors(theme, isAsiaMarket)
288
289
  const state = pluginHost.getSharedState<FASTKRenderState>(createFASTKStateKey(paneId))
289
290
  if (!state) return null
290
291
 
@@ -295,7 +296,7 @@ export function getFASTKTitleInfo(
295
296
  name: 'FASTK',
296
297
  params: [period],
297
298
  values: [
298
- { label: 'FASTK', value: fastk, color: colors.KDJ.K },
299
+ { label: 'FASTK', value: fastk, color: colors.kdj.k },
299
300
  ],
300
301
  }
301
302
  }
@@ -1,6 +1,6 @@
1
1
  import type { RendererPluginWithHost, RenderContext, PluginHost } from '../../../plugin'
2
2
  import { RENDERER_PRIORITY } from '../../../plugin'
3
- import { getColors, type ChartTheme } from '../../theme/colors'
3
+ import { resolveThemeColors } from '../../../tokens'
4
4
  import type { KSTRenderState } from '../../indicators/kstState'
5
5
  import { createKSTStateKey } from '../../indicators/kstState'
6
6
  import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
@@ -99,7 +99,7 @@ export function createKSTRendererPlugin(options: KSTRendererOptions = {}): Rende
99
99
 
100
100
  draw(context: RenderContext) {
101
101
  const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = context
102
- const colors = getColors(context.theme)
102
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
103
103
 
104
104
  const stateKey = resolveKey()
105
105
  if (!stateKey) return
@@ -178,10 +178,10 @@ const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = co
178
178
  if (enableWebGL && lineWebGLSurface?.isAvailable()) {
179
179
  const lines: Array<{ points: LinePoint[]; width: number; color: string }> = []
180
180
  if (params.showKST && cachedKSTPoints.length >= 2) {
181
- lines.push({ points: cachedKSTPoints, width: 1, color: colors.KST.KST })
181
+ lines.push({ points: cachedKSTPoints, width: 1, color: colors.kst.kst })
182
182
  }
183
183
  if (params.showSignal && cachedSignalPoints.length >= 2) {
184
- lines.push({ points: cachedSignalPoints, width: 1, color: colors.KST.SIGNAL })
184
+ lines.push({ points: cachedSignalPoints, width: 1, color: colors.kst.signal })
185
185
  }
186
186
 
187
187
  const allOk = lines.length > 0 && lineWebGLSurface.drawLineStrips(lines, scrollLeft)
@@ -219,7 +219,7 @@ function drawKSTLinesWithCanvas2D(
219
219
  kstPoints: LinePoint[],
220
220
  signalPoints: LinePoint[],
221
221
  params: { showKST: boolean; showSignal: boolean },
222
- colors: { KST: { KST: string; SIGNAL: string } }
222
+ colors: { kst: { kst: string; signal: string } }
223
223
  ): void {
224
224
  ctx.save()
225
225
  ctx.translate(-scrollLeft, 0)
@@ -228,7 +228,7 @@ function drawKSTLinesWithCanvas2D(
228
228
  ctx.lineCap = 'round'
229
229
 
230
230
  if (params.showKST && kstPoints.length >= 2) {
231
- ctx.strokeStyle = colors.KST.KST
231
+ ctx.strokeStyle = colors.kst.kst
232
232
  ctx.beginPath()
233
233
  ctx.moveTo(kstPoints[0]!.x, kstPoints[0]!.y)
234
234
  for (let i = 1; i < kstPoints.length; i++) {
@@ -239,7 +239,7 @@ function drawKSTLinesWithCanvas2D(
239
239
  }
240
240
 
241
241
  if (params.showSignal && signalPoints.length >= 2) {
242
- ctx.strokeStyle = colors.KST.SIGNAL
242
+ ctx.strokeStyle = colors.kst.signal
243
243
  ctx.beginPath()
244
244
  ctx.moveTo(signalPoints[0]!.x, signalPoints[0]!.y)
245
245
  for (let i = 1; i < signalPoints.length; i++) {
@@ -264,9 +264,10 @@ export function getKSTTitleInfo(
264
264
  signalPeriod: number,
265
265
  pluginHost: PluginHost,
266
266
  paneId: string = 'sub_KST',
267
- theme: ChartTheme = 'light'
267
+ theme: 'light' | 'dark' = 'light',
268
+ isAsiaMarket?: boolean
268
269
  ): { name: string; params: number[]; values: Array<{ label: string; value: number; color: string }> } | null {
269
- const colors = getColors(theme)
270
+ const colors = resolveThemeColors(theme, isAsiaMarket)
270
271
  const state = pluginHost.getSharedState<KSTRenderState>(createKSTStateKey(paneId))
271
272
  if (!state) return null
272
273
 
@@ -274,8 +275,8 @@ export function getKSTTitleInfo(
274
275
  if (!point) return null
275
276
 
276
277
  const values = []
277
- if (state.params.showKST) values.push({ label: 'KST', value: point.kst, color: colors.KST.KST })
278
- if (state.params.showSignal) values.push({ label: 'Signal', value: point.signal, color: colors.KST.SIGNAL })
278
+ if (state.params.showKST) values.push({ label: 'KST', value: point.kst, color: colors.kst.kst })
279
+ if (state.params.showSignal) values.push({ label: 'Signal', value: point.signal, color: colors.kst.signal })
279
280
 
280
281
  if (values.length === 0) return null
281
282
 
@@ -5,7 +5,7 @@ import { Indicator } from '../../indicators/indicatorDefinitionRegistry'
5
5
  import { resolveStateKey } from '../../indicators/indicatorMetadata'
6
6
  import type { IndicatorScheduler } from '../../indicators/scheduler'
7
7
  import { alignToPhysicalPixelCenter } from '../../draw/pixelAlign'
8
- import { getColors } from '../../theme/colors'
8
+ import { resolveThemeColors } from '../../../tokens'
9
9
 
10
10
  // Re-export MAFlags from calculators for backward compatibility
11
11
  export type { MAFlags } from '../../indicators/calculators'
@@ -97,8 +97,8 @@ export function createMARendererPlugin(): RendererPluginWithHost {
97
97
 
98
98
  draw(context: RenderContext) {
99
99
  const { ctx, pane, range, scrollLeft, dpr, kLineCenters, lineWebGLSurface } = context
100
- const colors = getColors(context.theme)
101
- const maColors: Record<number, string> = { 5: colors.MA.MA5, 10: colors.MA.MA10, 20: colors.MA.MA20, 30: colors.MA.MA30, 60: colors.MA.MA60 }
100
+ const colors = resolveThemeColors(context.theme, context.isAsiaMarket, context.colorPresetSettings)
101
+ const maColors: Record<number, string> = { 5: colors.ma.ma5, 10: colors.ma.ma10, 20: colors.ma.ma20, 30: colors.ma.ma30, 60: colors.ma.ma60 }
102
102
  const stateKey = resolveKey()
103
103
  if (!stateKey) return
104
104
  const state = pluginHost?.getSharedState<MARenderState>(stateKey)
@@ -147,7 +147,7 @@ export function createMARendererPlugin(): RendererPluginWithHost {
147
147
  for (const period of state.enabledPeriods) {
148
148
  const points = cachedLines.get(period)
149
149
  if (!points) continue
150
- lines.push({ points, width: 1, color: maColors[period] ?? colors.MA.MA5 })
150
+ lines.push({ points, width: 1, color: maColors[period] ?? colors.ma.ma5 })
151
151
  }
152
152
  const allOk = lines.length > 0 && lineWebGLSurface.drawLineStrips(lines, scrollLeft)
153
153
 
@@ -170,7 +170,7 @@ export function createMARendererPlugin(): RendererPluginWithHost {
170
170
  for (const period of state.enabledPeriods) {
171
171
  const points = cachedLines.get(period)
172
172
  if (!points || points.length < 2) continue
173
- ctx.strokeStyle = maColors[period] ?? colors.MA.MA5
173
+ ctx.strokeStyle = maColors[period] ?? colors.ma.ma5
174
174
  ctx.beginPath()
175
175
  ctx.moveTo(points[0]!.x, points[0]!.y)
176
176
  for (let i = 1; i < points.length; i++) {