@363045841yyt/klinechart-core 0.7.5 → 0.7.6

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 (59) hide show
  1. package/README.md +8 -8
  2. package/README.zh-CN.md +8 -8
  3. package/dist/controllers/createChartController.d.ts.map +1 -1
  4. package/dist/controllers/createChartController.js +145 -21
  5. package/dist/controllers/createChartController.js.map +1 -1
  6. package/dist/controllers/index.d.ts +9 -1
  7. package/dist/controllers/index.d.ts.map +1 -1
  8. package/dist/controllers/index.js +9 -0
  9. package/dist/controllers/index.js.map +1 -1
  10. package/dist/controllers/types.d.ts +65 -8
  11. package/dist/controllers/types.d.ts.map +1 -1
  12. package/dist/engine/chart.d.ts +2 -12
  13. package/dist/engine/chart.d.ts.map +1 -1
  14. package/dist/engine/chart.js +28 -31
  15. package/dist/engine/chart.js.map +1 -1
  16. package/dist/engine/controller/interaction.d.ts +1 -1
  17. package/dist/engine/controller/interaction.d.ts.map +1 -1
  18. package/dist/engine/controller/interaction.js +10 -2
  19. package/dist/engine/controller/interaction.js.map +1 -1
  20. package/dist/engine/drawing/interaction.d.ts +3 -3
  21. package/dist/engine/drawing/interaction.d.ts.map +1 -1
  22. package/dist/engine/drawing/interaction.js +38 -46
  23. package/dist/engine/drawing/interaction.js.map +1 -1
  24. package/dist/engine/renderers/paneTitle.d.ts +5 -24
  25. package/dist/engine/renderers/paneTitle.d.ts.map +1 -1
  26. package/dist/engine/renderers/paneTitle.js +10 -5
  27. package/dist/engine/renderers/paneTitle.js.map +1 -1
  28. package/dist/engine/renderers/webgl/candleSurface.d.ts +4 -4
  29. package/dist/engine/renderers/webgl/candleSurface.d.ts.map +1 -1
  30. package/dist/engine/renderers/webgl/candleSurface.js +36 -56
  31. package/dist/engine/renderers/webgl/candleSurface.js.map +1 -1
  32. package/dist/engine/subPaneManager.d.ts +2 -0
  33. package/dist/engine/subPaneManager.d.ts.map +1 -1
  34. package/dist/engine/subPaneManager.js +25 -1
  35. package/dist/engine/subPaneManager.js.map +1 -1
  36. package/dist/semantic/controller.d.ts +1 -2
  37. package/dist/semantic/controller.d.ts.map +1 -1
  38. package/dist/semantic/index.d.ts +1 -1
  39. package/dist/semantic/index.d.ts.map +1 -1
  40. package/dist/version.d.ts +1 -1
  41. package/dist/version.js +1 -1
  42. package/package.json +6 -6
  43. package/src/controllers/createChartController.ts +158 -29
  44. package/src/controllers/index.ts +33 -0
  45. package/src/controllers/types.ts +79 -8
  46. package/src/engine/chart.ts +28 -37
  47. package/src/engine/controller/interaction.ts +9 -2
  48. package/src/engine/drawing/interaction.ts +38 -47
  49. package/src/engine/renderers/paneTitle.ts +16 -25
  50. package/src/engine/renderers/webgl/candleSurface.ts +40 -56
  51. package/src/engine/subPaneManager.ts +28 -1
  52. package/src/semantic/controller.ts +1 -1
  53. package/src/semantic/index.ts +1 -1
  54. package/src/version.ts +1 -1
  55. package/dist/engine/chart-store.d.ts +0 -75
  56. package/dist/engine/chart-store.d.ts.map +0 -1
  57. package/dist/engine/chart-store.js +0 -88
  58. package/dist/engine/chart-store.js.map +0 -1
  59. package/src/engine/chart-store.ts +0 -121
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/semantic/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,aAAa,EACb,YAAY,EACZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,uBAAuB,EAAE,KAAK,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAChG,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEnH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/semantic/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,mBAAmB,EACnB,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,aAAa,EACb,YAAY,EACZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,cAAc,GACf,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,uBAAuB,EAAE,KAAK,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAChG,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAErE,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEnH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.7.5";
1
+ export declare const VERSION = "0.7.6";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = "0.7.5";
1
+ export const VERSION = "0.7.6";
2
2
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@363045841yyt/klinechart-core",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "Headless K-line chart engine + reactive controllers. Zero framework dependencies.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -47,10 +47,6 @@
47
47
  "types": "./dist/engine/chart.d.ts",
48
48
  "import": "./dist/engine/chart.js"
49
49
  },
50
- "./engine/chart-store": {
51
- "types": "./dist/engine/chart-store.d.ts",
52
- "import": "./dist/engine/chart-store.js"
53
- },
54
50
  "./engine/utils/zoom": {
55
51
  "types": "./dist/engine/utils/zoom.d.ts",
56
52
  "import": "./dist/engine/utils/zoom.js"
@@ -79,6 +75,10 @@
79
75
  "types": "./dist/engine/controller/interaction.d.ts",
80
76
  "import": "./dist/engine/controller/interaction.js"
81
77
  },
78
+ "./engine/marker/registry": {
79
+ "types": "./dist/engine/marker/registry.d.ts",
80
+ "import": "./dist/engine/marker/registry.js"
81
+ },
82
82
  "./engine/drawing": {
83
83
  "types": "./dist/engine/drawing/index.d.ts",
84
84
  "import": "./dist/engine/drawing/index.js"
@@ -126,4 +126,4 @@
126
126
  "vite-plugin-babel": "^1.3.2",
127
127
  "vitest": "^4.1.5"
128
128
  }
129
- }
129
+ }
@@ -25,12 +25,13 @@ import type {
25
25
  DrawingControllerCallbacks,
26
26
  IndicatorDefinition,
27
27
  KLineData,
28
+ PaneInfo,
29
+ PaneSpec,
28
30
  } from './types'
29
31
  import type { CustomMarkerEntity } from '../engine/marker/registry'
30
32
  import {
31
33
  Chart,
32
34
  type ChartOptions,
33
- type Viewport as LegacyViewport,
34
35
  type ViewportState as LegacyViewportState,
35
36
  type IndicatorInstance as LegacyIndicatorInstance,
36
37
  type SubPaneInfo as LegacySubPaneInfo,
@@ -185,14 +186,13 @@ function mapPaneRatios(ratios: Readonly<Record<string, number>>): Readonly<Recor
185
186
  return { ...ratios }
186
187
  }
187
188
 
188
- function mapInteractionRecord(
189
- value: Record<string, any> | null | undefined,
190
- ): Record<string, unknown> | null {
189
+ function mapInteractionRecord<T>(
190
+ value: T | null | undefined,
191
+ ): T | null {
191
192
  if (!value) {
192
193
  return null
193
194
  }
194
-
195
- return { ...value }
195
+ return { ...value } as T
196
196
  }
197
197
 
198
198
  function mapInteractionSnapshot(snapshot: LegacyInteractionSnapshot): InteractionSnapshot {
@@ -287,17 +287,27 @@ export function createChartController(opts: ChartMountOptions): ChartController
287
287
  throw new Error('[createChartController] opts.container must be a non-null HTMLElement')
288
288
  }
289
289
 
290
- const mounted = buildDom(opts.container)
290
+ const hasExistingDom = !!(opts.canvasLayer && opts.rightAxisLayer && opts.xAxisCanvas)
291
+ const mounted = hasExistingDom
292
+ ? {
293
+ container: opts.container as HTMLDivElement,
294
+ canvasLayer: opts.canvasLayer as HTMLDivElement,
295
+ rightAxisLayer: opts.rightAxisLayer as HTMLDivElement,
296
+ xAxisCanvas: opts.xAxisCanvas!,
297
+ cleanup: () => { /* DOM owned by caller */ },
298
+ }
299
+ : buildDom(opts.container)
300
+
291
301
  const initialZoomLevel = opts.initialZoomLevel ?? DEFAULT_OPTS.initialZoomLevel
292
302
  const zoomLevelCount = opts.zoomLevels ?? DEFAULT_OPTS.zoomLevels
293
303
 
294
304
  const chartOptions: ChartOptions = {
295
- yPaddingPx: DEFAULT_OPTS.yPaddingPx,
296
- rightAxisWidth: DEFAULT_OPTS.rightAxisWidth,
297
- bottomAxisHeight: DEFAULT_OPTS.bottomAxisHeight,
298
- minKWidth: DEFAULT_OPTS.minKWidth,
299
- maxKWidth: DEFAULT_OPTS.maxKWidth,
300
- priceLabelWidth: DEFAULT_OPTS.priceLabelWidth,
305
+ yPaddingPx: opts.yPaddingPx ?? DEFAULT_OPTS.yPaddingPx,
306
+ rightAxisWidth: opts.rightAxisWidth ?? DEFAULT_OPTS.rightAxisWidth,
307
+ bottomAxisHeight: opts.bottomAxisHeight ?? DEFAULT_OPTS.bottomAxisHeight,
308
+ minKWidth: opts.minKWidth ?? DEFAULT_OPTS.minKWidth,
309
+ maxKWidth: opts.maxKWidth ?? DEFAULT_OPTS.maxKWidth,
310
+ priceLabelWidth: opts.priceLabelWidth ?? DEFAULT_OPTS.priceLabelWidth,
301
311
  panes: [{ id: 'main', ratio: 1 }],
302
312
  paneGap: 0,
303
313
  zoomLevels: zoomLevelCount,
@@ -433,6 +443,12 @@ export function createChartController(opts: ChartMountOptions): ChartController
433
443
  chart.paneRatios.subscribe(() => paneRatios.set(mapPaneRatios(chart.paneRatios.peek()))),
434
444
  )
435
445
 
446
+ // paneLayout
447
+ const paneLayout: Signal<ReadonlyArray<PaneSpec>> = createSignal<ReadonlyArray<PaneSpec>>([])
448
+ unsubs.push(
449
+ chart.paneLayout.subscribe(() => paneLayout.set([...chart.paneLayout.peek()])),
450
+ )
451
+
436
452
  // interactionState
437
453
  unsubs.push(
438
454
  chart.interactionState.subscribe(() =>
@@ -440,21 +456,6 @@ export function createChartController(opts: ChartMountOptions): ChartController
440
456
  ),
441
457
  )
442
458
 
443
- // -------------------------------------------------------------------
444
- // Legacy callback for resize (chart's viewport signal doesn't fire
445
- // on resize — only on zoom/scroll through facade methods)
446
- // -------------------------------------------------------------------
447
-
448
- chart.setOnViewportChange((vp: LegacyViewport) => {
449
- const current = viewport.peek()
450
- viewport.set({
451
- ...current,
452
- plotWidth: vp.plotWidth,
453
- plotHeight: vp.plotHeight,
454
- dpr: vp.dpr > 0 ? vp.dpr : current.dpr,
455
- })
456
- })
457
-
458
459
  // -------------------------------------------------------------------
459
460
  // Lifecycle guard
460
461
  // -------------------------------------------------------------------
@@ -481,6 +482,16 @@ export function createChartController(opts: ChartMountOptions): ChartController
481
482
  setData(merged)
482
483
  }
483
484
 
485
+ function getData(): ReadonlyArray<KLineData> {
486
+ if (disposed) return []
487
+ return chart.getData()
488
+ }
489
+
490
+ function getZoomLevelCount(): number {
491
+ if (disposed) return 0
492
+ return chart.getZoomLevelCount()
493
+ }
494
+
484
495
  function setTheme(nextTheme: 'light' | 'dark'): void {
485
496
  if (disposed) return
486
497
  chart.setTheme(nextTheme)
@@ -551,6 +562,28 @@ export function createChartController(opts: ChartMountOptions): ChartController
551
562
  chart.updateRendererConfig(name, config)
552
563
  }
553
564
 
565
+ function setTooltipSize(size: { width: number; height: number }): void {
566
+ if (disposed) return
567
+ chart.interaction.setTooltipSize(size)
568
+ }
569
+
570
+ function setTooltipAnchorPositioning(enabled: boolean): void {
571
+ if (disposed) return
572
+ chart.interaction.setTooltipAnchorPositioning(enabled)
573
+ }
574
+
575
+ function getContentWidth(): number {
576
+ if (disposed) return 0
577
+ return chart.getContentWidth()
578
+ }
579
+
580
+ function getIndicatorTitle(instanceId: string): string | undefined {
581
+ if (disposed) return undefined
582
+ const instances = chart.indicators.peek()
583
+ const match = instances.find(inst => inst.id === instanceId)
584
+ return match?.label
585
+ }
586
+
554
587
  function setDrawingTool(tool: DrawingToolType | null): void {
555
588
  if (disposed) return
556
589
  chart.setDrawingTool(tool)
@@ -566,6 +599,65 @@ export function createChartController(opts: ChartMountOptions): ChartController
566
599
  chart.removeDrawing(drawingId)
567
600
  }
568
601
 
602
+ // ---- DrawingChartAdapter methods ----
603
+
604
+ function setDrawings(drawings: any[]): void {
605
+ if (disposed) return
606
+ chart.setDrawings(drawings)
607
+ }
608
+
609
+ function setSelectedDrawingId(id: string | null): void {
610
+ if (disposed) return
611
+ chart.setSelectedDrawingId(id)
612
+ }
613
+
614
+ function getViewport(): { scrollLeft: number; plotWidth: number; plotHeight: number } | null {
615
+ if (disposed) return null
616
+ const vp = chart.getViewport()
617
+ return vp
618
+ }
619
+
620
+ function getKWidthKGap(): { kWidth: number; kGap: number } {
621
+ if (disposed) return { kWidth: 0, kGap: 0 }
622
+ const opt = chart.getOption()
623
+ return { kWidth: opt.kWidth, kGap: opt.kGap }
624
+ }
625
+
626
+ function getCurrentDpr(): number {
627
+ if (disposed) return 1
628
+ return chart.getCurrentDpr()
629
+ }
630
+
631
+ function getLogicalIndexAtX(mouseX: number): number | null {
632
+ if (disposed) return null
633
+ return chart.getLogicalIndexAtX(mouseX)
634
+ }
635
+
636
+ function getTimestampAtLogicalIndex(index: number): number | null {
637
+ if (disposed) return null
638
+ return chart.getTimestampAtLogicalIndex(index)
639
+ }
640
+
641
+ function priceToY(paneId: string, price: number): number {
642
+ if (disposed) return 0
643
+ const renderer = chart.getPaneRenderers().find(item => item.getPane().id === paneId)
644
+ return renderer?.getPane().yAxis.priceToY(price) ?? 0
645
+ }
646
+
647
+ function yToPrice(paneId: string, y: number): number {
648
+ if (disposed) return 0
649
+ const renderer = chart.getPaneRenderers().find(item => item.getPane().id === paneId)
650
+ return renderer?.getPane().yAxis.yToPrice(y) ?? 0
651
+ }
652
+
653
+ function getPaneInfo(paneId: string): PaneInfo | undefined {
654
+ if (disposed) return undefined
655
+ const renderer = chart.getPaneRenderers().find(item => item.getPane().id === paneId)
656
+ const pane = renderer?.getPane()
657
+ if (!pane) return undefined
658
+ return { paneId: pane.id, top: pane.top, height: pane.height }
659
+ }
660
+
569
661
  function createSubPane(paneId: string, indicatorId: string, params?: Record<string, unknown>): boolean {
570
662
  if (disposed) return false
571
663
  return chart.createSubPane(paneId, indicatorId as never, params as Record<string, string | number | boolean> | undefined)
@@ -576,6 +668,25 @@ export function createChartController(opts: ChartMountOptions): ChartController
576
668
  chart.clearSubPanes()
577
669
  }
578
670
 
671
+ function replaceSubPaneIndicator(
672
+ paneId: string,
673
+ indicatorId: string,
674
+ params?: Record<string, unknown>,
675
+ ): boolean {
676
+ if (disposed) return false
677
+ try {
678
+ chart.replaceSubPaneIndicator(paneId, indicatorId as never, params as Record<string, string | number | boolean>)
679
+ return true
680
+ } catch {
681
+ return false
682
+ }
683
+ }
684
+
685
+ function updatePaneLayout(panes: PaneSpec[]): void {
686
+ if (disposed) return
687
+ chart.updatePaneLayout(panes)
688
+ }
689
+
579
690
  function resizeSubPane(paneId: string, deltaY: number): boolean {
580
691
  if (disposed) return false
581
692
  return chart.resizeSubPane(paneId, deltaY)
@@ -604,7 +715,6 @@ export function createChartController(opts: ChartMountOptions): ChartController
604
715
  function dispose(): void {
605
716
  if (disposed) return
606
717
  disposed = true
607
- // Unsubscribe all signal bridges first
608
718
  for (const unsub of unsubs) {
609
719
  try {
610
720
  unsub()
@@ -633,11 +743,14 @@ export function createChartController(opts: ChartMountOptions): ChartController
633
743
  drawingTool,
634
744
  drawings,
635
745
  paneRatios,
746
+ paneLayout,
636
747
  interactionState,
637
748
  catalog: DEFAULT_INDICATOR_CATALOG,
638
749
  setData,
639
750
  appendData,
640
751
  updateData: setData,
752
+ getData,
753
+ getZoomLevelCount,
641
754
  setTheme,
642
755
  zoomToLevel,
643
756
  zoomIn,
@@ -650,11 +763,27 @@ export function createChartController(opts: ChartMountOptions): ChartController
650
763
  removeIndicator,
651
764
  updateIndicatorParams,
652
765
  updateRendererConfig,
766
+ setTooltipSize,
767
+ setTooltipAnchorPositioning,
768
+ getIndicatorTitle,
769
+ getContentWidth,
653
770
  setDrawingTool,
654
771
  clearDrawings,
655
772
  removeDrawing,
773
+ setDrawings,
774
+ setSelectedDrawingId,
775
+ getViewport,
776
+ getKWidthKGap,
777
+ getCurrentDpr,
778
+ getLogicalIndexAtX,
779
+ getTimestampAtLogicalIndex,
780
+ priceToY,
781
+ yToPrice,
782
+ getPaneInfo,
656
783
  createSubPane,
657
784
  clearSubPanes,
785
+ replaceSubPaneIndicator,
786
+ updatePaneLayout,
658
787
  resizeSubPane,
659
788
  updateCustomMarkers,
660
789
  clearCustomMarkers,
@@ -1,3 +1,4 @@
1
+ // -- Controller types (framework-agnostic) --
1
2
  export type {
2
3
  KLineData,
3
4
  IndicatorPaneRole,
@@ -14,7 +15,39 @@ export type {
14
15
  ChartViewport,
15
16
  ChartController,
16
17
  ChartControllerFactory,
18
+ PaneSpec,
19
+ DrawingChartAdapter,
20
+ DrawingChartViewport,
21
+ PaneInfo,
17
22
  } from './types'
18
23
 
19
24
  export { createChartController } from './createChartController'
20
25
  export { createIndicatorSelectorController } from './createIndicatorSelectorController'
26
+
27
+ // -- Engine sub-path re-exports (Phase 9: facade for Vue adapter) --
28
+
29
+ // Utility functions
30
+ export {
31
+ zoomLevelToKWidth,
32
+ kGapFromKWidth,
33
+ } from '../engine/utils/zoom'
34
+ export { getPhysicalKLineConfig } from '../engine/utils/klineConfig'
35
+
36
+ // Indicator types & config
37
+ export type { SubIndicatorType } from '../engine/renderers/Indicator'
38
+ export {
39
+ SUB_PANE_INDICATOR_CONFIGS,
40
+ SUB_PANE_INDICATORS,
41
+ } from '../engine/renderers/Indicator/subPaneConfig'
42
+
43
+ // Indicator data helpers
44
+ export {
45
+ allIndicators,
46
+ findIndicator,
47
+ isSubIndicatorId,
48
+ } from '../engine/renderers/Indicator/indicatorData'
49
+ export type { Indicator } from '../engine/renderers/Indicator/indicatorData'
50
+
51
+ // Drawing
52
+ export { DrawingInteractionController } from '../engine/drawing'
53
+ export type { DrawingToolId } from '../engine/drawing'
@@ -9,7 +9,8 @@
9
9
  */
10
10
 
11
11
  import type { Signal } from '../reactivity'
12
- import type { CustomMarkerEntity } from '../engine/marker/registry'
12
+ import type { CustomMarkerEntity, MarkerEntity } from '../engine/marker/registry'
13
+ import type { PaneSpec } from '../engine/chart'
13
14
 
14
15
  // Controller-owned public surface. Legacy engine types may mirror these
15
16
  // shapes internally, but adapters depend only on core-defined contracts.
@@ -73,6 +74,8 @@ export interface KLineData {
73
74
  turnoverRate?: number
74
75
  }
75
76
 
77
+ export type { PaneSpec }
78
+
76
79
  // ---------------------------------------------------------------------------
77
80
  // Indicator metadata
78
81
  // ---------------------------------------------------------------------------
@@ -109,8 +112,8 @@ export interface InteractionSnapshot {
109
112
  activePaneId: string | null
110
113
  tooltipPos: { x: number; y: number }
111
114
  tooltipAnchorPlacement: 'right-bottom' | 'left-bottom'
112
- hoveredMarkerData: Record<string, unknown> | null
113
- hoveredCustomMarker: Record<string, unknown> | null
115
+ hoveredMarkerData: MarkerEntity | null
116
+ hoveredCustomMarker: CustomMarkerEntity | null
114
117
  isDragging: boolean
115
118
  isResizingPaneBoundary: boolean
116
119
  isHoveringPaneBoundary: boolean
@@ -118,6 +121,51 @@ export interface InteractionSnapshot {
118
121
  isHoveringRightAxis: boolean
119
122
  }
120
123
 
124
+ // ---------------------------------------------------------------------------
125
+ // Pane info (read-only pane metadata for DrawingChartAdapter)
126
+ // ---------------------------------------------------------------------------
127
+
128
+ export interface PaneInfo {
129
+ paneId: string
130
+ top: number
131
+ height: number
132
+ }
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // Drawing adapter — narrow interface for DrawingInteractionController
136
+ // ---------------------------------------------------------------------------
137
+
138
+ export interface DrawingChartViewport {
139
+ scrollLeft: number
140
+ plotWidth: number
141
+ plotHeight: number
142
+ }
143
+
144
+ export interface DrawingChartAdapter {
145
+ /** persist full drawing list to the chart engine */
146
+ setDrawings(drawings: any[]): void
147
+ /** highlight a drawing by ID */
148
+ setSelectedDrawingId(id: string | null): void
149
+ /** current viewport (nullable if chart not ready) */
150
+ getViewport(): DrawingChartViewport | null
151
+ /** resolved chart options (kWidth, kGap) */
152
+ getKWidthKGap(): { kWidth: number; kGap: number }
153
+ /** device pixel ratio */
154
+ getCurrentDpr(): number
155
+ /** raw K-line data */
156
+ getData(): ReadonlyArray<KLineData>
157
+ /** screen-x → logical bar index */
158
+ getLogicalIndexAtX(mouseX: number): number | null
159
+ /** logical index → unix timestamp (ms) */
160
+ getTimestampAtLogicalIndex(index: number): number | null
161
+ /** price → Y within the given pane */
162
+ priceToY(paneId: string, price: number): number
163
+ /** Y within the given pane → price */
164
+ yToPrice(paneId: string, y: number): number
165
+ /** read-only pane metadata by pane ID */
166
+ getPaneInfo(paneId: string): PaneInfo | undefined
167
+ }
168
+
121
169
  // ---------------------------------------------------------------------------
122
170
  // Drawing controller callback type (passed to handlePointerEvent)
123
171
  // ---------------------------------------------------------------------------
@@ -138,9 +186,22 @@ export interface ChartMountOptions {
138
186
  initialZoomLevel?: number
139
187
  zoomLevels?: number
140
188
  theme?: 'light' | 'dark'
189
+
190
+ // Pre-existing DOM elements (skip buildDom when provided)
191
+ canvasLayer?: HTMLElement
192
+ rightAxisLayer?: HTMLElement
193
+ xAxisCanvas?: HTMLCanvasElement
194
+
195
+ // Chart options overrides
196
+ yPaddingPx?: number
197
+ rightAxisWidth?: number
198
+ bottomAxisHeight?: number
199
+ priceLabelWidth?: number
200
+ minKWidth?: number
201
+ maxKWidth?: number
141
202
  }
142
203
 
143
- export interface ChartController {
204
+ export interface ChartController extends DrawingChartAdapter {
144
205
  // ---- Signals ----
145
206
  readonly viewport: Signal<ChartViewport>
146
207
  readonly data: Signal<ReadonlyArray<KLineData>>
@@ -150,6 +211,7 @@ export interface ChartController {
150
211
  readonly drawingTool: Signal<DrawingToolType | null>
151
212
  readonly drawings: Signal<ReadonlyArray<DrawingObject>>
152
213
  readonly paneRatios: Signal<Readonly<Record<string, number>>>
214
+ readonly paneLayout: Signal<ReadonlyArray<PaneSpec>>
153
215
  readonly interactionState: Signal<InteractionSnapshot>
154
216
 
155
217
  // indicator catalog (static — adapters use for picker UI)
@@ -159,6 +221,8 @@ export interface ChartController {
159
221
  setData(next: ReadonlyArray<KLineData>): void
160
222
  appendData(next: ReadonlyArray<KLineData>): void
161
223
  updateData(next: ReadonlyArray<KLineData>): void
224
+ getData(): ReadonlyArray<KLineData>
225
+ getZoomLevelCount(): number
162
226
 
163
227
  // ---- Theme ----
164
228
  setTheme(theme: 'light' | 'dark'): void
@@ -193,11 +257,22 @@ export interface ChartController {
193
257
  resizeSubPane(paneId: string, deltaY: number): boolean
194
258
  createSubPane(paneId: string, indicatorId: string, params?: Record<string, unknown>): boolean
195
259
  clearSubPanes(): void
260
+ replaceSubPaneIndicator(paneId: string, indicatorId: string, params?: Record<string, unknown>): boolean
261
+ updatePaneLayout(panes: PaneSpec[]): void
196
262
 
197
263
  // ---- Drawing / Markers ----
198
264
  updateCustomMarkers(markers: ReadonlyArray<CustomMarkerEntity>): void
199
265
  clearCustomMarkers(): void
200
266
 
267
+ // ---- Interaction sub-methods ----
268
+ setTooltipSize(size: { width: number; height: number }): void
269
+ setTooltipAnchorPositioning(enabled: boolean): void
270
+
271
+ // ---- Narrow queries ----
272
+ getIndicatorTitle(instanceId: string): string | undefined
273
+ /** total scrollable content width (replaces direct computeContentWidth imports) */
274
+ getContentWidth(): number
275
+
201
276
  // ---- Settings ----
202
277
  updateSettingsFacade(settings: Record<string, unknown>): void
203
278
  updateOptionsFacade(options: Record<string, unknown>): void
@@ -218,7 +293,6 @@ export type ChartControllerFactory = (opts: ChartMountOptions) => ChartControlle
218
293
  // Legacy type aliases (deprecated — kept for internal sub-controller tests)
219
294
  // ---------------------------------------------------------------------------
220
295
 
221
- /** @deprecated Use `IndicatorInstance` instead. Kept for createIndicatorSelectorController tests. */
222
296
  export interface ActiveIndicator {
223
297
  id: string
224
298
  definitionId: string
@@ -228,7 +302,6 @@ export interface ActiveIndicator {
228
302
  params: Readonly<Record<string, number | string | boolean>>
229
303
  }
230
304
 
231
- /** @deprecated Flattened into ChartController. Kept for createIndicatorSelectorController tests. */
232
305
  export interface IndicatorSelectorController {
233
306
  readonly catalog: Signal<ReadonlyArray<IndicatorDefinition>>
234
307
  readonly active: Signal<ReadonlyArray<ActiveIndicator>>
@@ -258,7 +331,6 @@ export interface ToolDefinition {
258
331
  disabled?: boolean
259
332
  }
260
333
 
261
- /** @deprecated Flattened into ChartController. Kept for createToolbarController tests. */
262
334
  export interface ToolbarController {
263
335
  readonly tools: Signal<ReadonlyArray<ToolDefinition>>
264
336
  readonly activeTool: Signal<ToolId | null>
@@ -274,7 +346,6 @@ export interface DrawingState {
274
346
  readonly drawingCount: number
275
347
  }
276
348
 
277
- /** @deprecated Flattened into ChartController. Kept for createDrawingController tests. */
278
349
  export interface DrawingController {
279
350
  readonly state: Signal<DrawingState>
280
351
  setActiveTool(tool: DrawingToolType | null): void