@363045841yyt/klinechart-core 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -201
- package/README.zh-CN.md +201 -201
- package/dist/controllers/index.d.ts +1 -0
- package/dist/controllers/index.d.ts.map +1 -1
- package/dist/controllers/index.js +1 -0
- package/dist/controllers/index.js.map +1 -1
- package/dist/engine/chart.d.ts +11 -19
- package/dist/engine/chart.d.ts.map +1 -1
- package/dist/engine/chart.js +92 -109
- package/dist/engine/chart.js.map +1 -1
- package/dist/engine/renderers/Indicator/indicatorData.d.ts +1 -0
- package/dist/engine/renderers/Indicator/indicatorData.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/indicatorData.js +1 -1
- package/dist/engine/renderers/Indicator/indicatorData.js.map +1 -1
- package/dist/engine/renderers/webgl/candleSurface.js +47 -47
- package/dist/engine/subPaneManager.d.ts +4 -0
- package/dist/engine/subPaneManager.d.ts.map +1 -1
- package/dist/engine/subPaneManager.js +13 -0
- package/dist/engine/subPaneManager.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -2
- package/dist/version.js.map +1 -1
- package/package.json +129 -122
- package/src/__tests__/signal.test.ts +124 -124
- package/src/config/chartSettings.ts +66 -66
- package/src/controllers/__tests__/drawing.test.ts +214 -214
- package/src/controllers/__tests__/indicatorSelector.test.ts +481 -481
- package/src/controllers/__tests__/toolbar.test.ts +225 -225
- package/src/controllers/createChartController.ts +665 -665
- package/src/controllers/createDrawingController.ts +96 -96
- package/src/controllers/createIndicatorSelectorController.ts +307 -307
- package/src/controllers/createToolbarController.ts +146 -146
- package/src/controllers/index.ts +20 -19
- package/src/controllers/types.ts +284 -284
- package/src/engine/__tests__/chart.dpr.test.ts +401 -401
- package/src/engine/__tests__/paneRenderer.resize.test.ts +92 -92
- package/src/engine/chart-store.ts +121 -121
- package/src/engine/chart.d.ts +617 -617
- package/src/engine/chart.ts +2803 -2815
- package/src/engine/controller/__tests__/interaction.dpr.test.ts +259 -259
- package/src/engine/controller/interaction.ts +722 -722
- package/src/engine/controller/markerInteraction.ts +130 -130
- package/src/engine/controller/pinchTracker.ts +82 -82
- package/src/engine/controller/tooltipPosition.ts +48 -48
- package/src/engine/draw/__tests__/pixelAlign.spec.ts +176 -176
- package/src/engine/draw/pixelAlign.ts +259 -259
- package/src/engine/drawing/index.ts +655 -655
- package/src/engine/drawing/interaction.ts +842 -842
- package/src/engine/drawing/plugin.ts +343 -343
- package/src/engine/indicators/__tests__/__fixtures__/golden/atr.json +38 -38
- package/src/engine/indicators/__tests__/__fixtures__/golden/dema.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/hma.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/index.ts +55 -55
- package/src/engine/indicators/__tests__/__fixtures__/golden/kama.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/tema.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/wma.json +40 -40
- package/src/engine/indicators/__tests__/__fixtures__/synthetic.ts +65 -65
- package/src/engine/indicators/__tests__/_propertyAssertions.ts +76 -76
- package/src/engine/indicators/__tests__/atr.test.ts +153 -153
- package/src/engine/indicators/__tests__/calculators.test.ts +614 -614
- package/src/engine/indicators/__tests__/cmf-mfi.test.ts +100 -100
- package/src/engine/indicators/__tests__/dema.test.ts +73 -73
- package/src/engine/indicators/__tests__/donchian.test.ts +70 -70
- package/src/engine/indicators/__tests__/hma.test.ts +73 -73
- package/src/engine/indicators/__tests__/ichimoku.test.ts +105 -105
- package/src/engine/indicators/__tests__/kama.test.ts +80 -80
- package/src/engine/indicators/__tests__/keltner.test.ts +65 -65
- package/src/engine/indicators/__tests__/pivot-fib.test.ts +110 -110
- package/src/engine/indicators/__tests__/roc.test.ts +68 -68
- package/src/engine/indicators/__tests__/sar.test.ts +86 -86
- package/src/engine/indicators/__tests__/scheduler.test.ts +831 -831
- package/src/engine/indicators/__tests__/soa.test.ts +533 -533
- package/src/engine/indicators/__tests__/structure.test.ts +110 -110
- package/src/engine/indicators/__tests__/supertrend.test.ts +65 -65
- package/src/engine/indicators/__tests__/tema.test.ts +68 -68
- package/src/engine/indicators/__tests__/trix.test.ts +70 -70
- package/src/engine/indicators/__tests__/volatility.test.ts +117 -117
- package/src/engine/indicators/__tests__/volume.test.ts +115 -115
- package/src/engine/indicators/__tests__/volumeProfile.test.ts +74 -74
- package/src/engine/indicators/__tests__/vwap.test.ts +69 -69
- package/src/engine/indicators/__tests__/wma.test.ts +112 -112
- package/src/engine/indicators/__tests__/zones.test.ts +95 -95
- package/src/engine/indicators/atrState.ts +27 -27
- package/src/engine/indicators/bollState.ts +51 -51
- package/src/engine/indicators/calculators.ts +2593 -2593
- package/src/engine/indicators/cciState.ts +25 -25
- package/src/engine/indicators/chaikinVolState.ts +32 -32
- package/src/engine/indicators/cmfState.ts +27 -27
- package/src/engine/indicators/demaState.ts +27 -27
- package/src/engine/indicators/donchianState.ts +43 -43
- package/src/engine/indicators/eneState.ts +43 -43
- package/src/engine/indicators/expmaState.ts +43 -43
- package/src/engine/indicators/fastkState.ts +25 -25
- package/src/engine/indicators/fibState.ts +41 -41
- package/src/engine/indicators/hmaState.ts +27 -27
- package/src/engine/indicators/hvState.ts +28 -28
- package/src/engine/indicators/ichimokuState.ts +70 -70
- package/src/engine/indicators/indicator.worker.ts +169 -169
- package/src/engine/indicators/indicatorDefinitionRegistry.ts +62 -62
- package/src/engine/indicators/indicatorMetadata.ts +110 -110
- package/src/engine/indicators/indicatorRegistry.ts +106 -106
- package/src/engine/indicators/indicatorRuntime.ts +1548 -1548
- package/src/engine/indicators/kamaState.ts +34 -34
- package/src/engine/indicators/keltnerState.ts +49 -49
- package/src/engine/indicators/kstState.ts +42 -42
- package/src/engine/indicators/maState.ts +36 -36
- package/src/engine/indicators/macdState.ts +76 -76
- package/src/engine/indicators/mfiState.ts +27 -27
- package/src/engine/indicators/momState.ts +25 -25
- package/src/engine/indicators/obvState.ts +25 -25
- package/src/engine/indicators/parkinsonState.ts +28 -28
- package/src/engine/indicators/pivotState.ts +51 -51
- package/src/engine/indicators/pvtState.ts +25 -25
- package/src/engine/indicators/rocState.ts +27 -27
- package/src/engine/indicators/rsiState.ts +65 -65
- package/src/engine/indicators/sarState.ts +41 -41
- package/src/engine/indicators/scheduler.ts +1205 -1205
- package/src/engine/indicators/soa.ts +352 -352
- package/src/engine/indicators/stateComposer.ts +1262 -1262
- package/src/engine/indicators/stochState.ts +26 -26
- package/src/engine/indicators/structureState.ts +69 -69
- package/src/engine/indicators/supertrendState.ts +37 -37
- package/src/engine/indicators/temaState.ts +27 -27
- package/src/engine/indicators/trixState.ts +35 -35
- package/src/engine/indicators/vmaState.ts +27 -27
- package/src/engine/indicators/volumeProfileState.ts +63 -63
- package/src/engine/indicators/vwapState.ts +29 -29
- package/src/engine/indicators/wmaState.ts +27 -27
- package/src/engine/indicators/wmsrState.ts +25 -25
- package/src/engine/indicators/workerProtocol.ts +613 -613
- package/src/engine/indicators/zonesState.ts +47 -47
- package/src/engine/layout/pane.ts +161 -161
- package/src/engine/marker/registry.ts +265 -265
- package/src/engine/paneRenderer.ts +169 -169
- package/src/engine/renderers/Indicator/atr.ts +237 -237
- package/src/engine/renderers/Indicator/boll.ts +317 -317
- package/src/engine/renderers/Indicator/cci.ts +275 -275
- package/src/engine/renderers/Indicator/chaikinVol.ts +138 -138
- package/src/engine/renderers/Indicator/cmf.ts +137 -137
- package/src/engine/renderers/Indicator/dema.ts +136 -136
- package/src/engine/renderers/Indicator/donchian.ts +137 -137
- package/src/engine/renderers/Indicator/ene.ts +271 -271
- package/src/engine/renderers/Indicator/expma.ts +197 -197
- package/src/engine/renderers/Indicator/fastk.ts +316 -316
- package/src/engine/renderers/Indicator/fib.ts +141 -141
- package/src/engine/renderers/Indicator/hma.ts +136 -136
- package/src/engine/renderers/Indicator/hv.ts +124 -124
- package/src/engine/renderers/Indicator/ichimoku.ts +181 -181
- package/src/engine/renderers/Indicator/index.ts +241 -241
- package/src/engine/renderers/Indicator/indicatorData.ts +650 -650
- package/src/engine/renderers/Indicator/kama.ts +136 -136
- package/src/engine/renderers/Indicator/keltner.ts +137 -137
- package/src/engine/renderers/Indicator/kst.ts +302 -302
- package/src/engine/renderers/Indicator/ma.ts +200 -200
- package/src/engine/renderers/Indicator/macd.ts +477 -477
- package/src/engine/renderers/Indicator/macdLegend.ts +141 -141
- package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +272 -272
- package/src/engine/renderers/Indicator/mfi.ts +142 -142
- package/src/engine/renderers/Indicator/mom.ts +311 -311
- package/src/engine/renderers/Indicator/obv.ts +123 -123
- package/src/engine/renderers/Indicator/parkinson.ts +124 -124
- package/src/engine/renderers/Indicator/pivot.ts +131 -131
- package/src/engine/renderers/Indicator/pvt.ts +123 -123
- package/src/engine/renderers/Indicator/roc.ts +143 -143
- package/src/engine/renderers/Indicator/rsi.ts +390 -390
- package/src/engine/renderers/Indicator/sar.ts +113 -113
- package/src/engine/renderers/Indicator/scale/atr_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/cci_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/fastk_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/indicator_scale.ts +204 -204
- package/src/engine/renderers/Indicator/scale/kst_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/macd_scale.ts +22 -22
- package/src/engine/renderers/Indicator/scale/mom_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/rsi_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/stoch_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/volume_scale.ts +26 -26
- package/src/engine/renderers/Indicator/scale/wmsr_scale.ts +19 -19
- package/src/engine/renderers/Indicator/stoch.ts +359 -359
- package/src/engine/renderers/Indicator/structure.ts +126 -126
- package/src/engine/renderers/Indicator/subPaneConfig.ts +265 -265
- package/src/engine/renderers/Indicator/supertrend.ts +115 -115
- package/src/engine/renderers/Indicator/tema.ts +136 -136
- package/src/engine/renderers/Indicator/trix.ts +158 -158
- package/src/engine/renderers/Indicator/vma.ts +124 -124
- package/src/engine/renderers/Indicator/volumeProfile.ts +125 -125
- package/src/engine/renderers/Indicator/vwap.ts +123 -123
- package/src/engine/renderers/Indicator/wma.ts +136 -136
- package/src/engine/renderers/Indicator/wmsr.ts +328 -328
- package/src/engine/renderers/Indicator/zones.ts +104 -104
- package/src/engine/renderers/__tests__/boll.renderer.test.ts +314 -314
- package/src/engine/renderers/__tests__/ene.renderer.test.ts +305 -305
- package/src/engine/renderers/__tests__/expma.renderer.test.ts +279 -279
- package/src/engine/renderers/__tests__/ma.renderer.test.ts +426 -426
- package/src/engine/renderers/__tests__/mainIndicatorLegend.renderer.test.ts +502 -502
- package/src/engine/renderers/__tests__/yAxis.renderer.test.ts +173 -173
- package/src/engine/renderers/candle.ts +459 -459
- package/src/engine/renderers/crosshair.ts +69 -69
- package/src/engine/renderers/customMarkers.ts +162 -162
- package/src/engine/renderers/extremaMarkers.ts +246 -246
- package/src/engine/renderers/gridLines.ts +90 -90
- package/src/engine/renderers/lastPrice.ts +97 -97
- package/src/engine/renderers/paneTitle.ts +136 -136
- package/src/engine/renderers/subVolume.ts +236 -236
- package/src/engine/renderers/timeAxis.ts +121 -121
- package/src/engine/renderers/webgl/candleSurface.ts +955 -955
- package/src/engine/renderers/webgl/sharedWebGLSurface.ts +146 -146
- package/src/engine/renderers/yAxis.ts +105 -105
- package/src/engine/scale/__tests__/logFormula.spec.ts +148 -148
- package/src/engine/scale/logFormula.ts +130 -130
- package/src/engine/scale/price.ts +39 -39
- package/src/engine/scale/priceScale.ts +264 -264
- package/src/engine/subPaneManager.ts +442 -427
- package/src/engine/theme/colors.ts +642 -642
- package/src/engine/theme/fonts.ts +20 -20
- package/src/engine/utils/klineConfig.ts +49 -49
- package/src/engine/utils/tickCount.ts +11 -11
- package/src/engine/utils/tickPosition.ts +214 -214
- package/src/engine/utils/zoom.ts +83 -83
- package/src/engine/viewport/viewport.ts +67 -67
- package/src/index.ts +3 -3
- package/src/plugin/ConfigManager.ts +93 -93
- package/src/plugin/EventBus.ts +77 -77
- package/src/plugin/HookSystem.ts +106 -106
- package/src/plugin/PluginHost.ts +243 -243
- package/src/plugin/PluginRegistry.ts +92 -92
- package/src/plugin/StateStore.ts +73 -73
- package/src/plugin/index.ts +19 -19
- package/src/plugin/rendererPluginManager.ts +368 -368
- package/src/plugin/stateKeys.ts +8 -8
- package/src/plugin/types.ts +526 -526
- package/src/reactivity/index.ts +2 -2
- package/src/reactivity/signal.ts +119 -119
- package/src/semantic/controller.ts +251 -251
- package/src/semantic/drawShape.ts +260 -260
- package/src/semantic/index.ts +28 -28
- package/src/semantic/schema.json +256 -256
- package/src/semantic/types.ts +251 -251
- package/src/semantic/validator.ts +349 -349
- package/src/types/kLine.ts +13 -13
- package/src/types/price.ts +56 -56
- package/src/types/volumePrice.ts +33 -33
- package/src/utils/dateFormat.ts +208 -208
- package/src/utils/kLineDraw/axis.ts +562 -562
- package/src/utils/priceToY.ts +34 -34
- package/src/utils/volumePrice.ts +202 -202
- package/src/version.ts +1 -1
|
@@ -1,146 +1,146 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ToolbarController — framework-agnostic implementation.
|
|
3
|
-
*
|
|
4
|
-
* Extracted from src/components/LeftToolbar.vue. This module owns the pure
|
|
5
|
-
* state machine of the toolbar:
|
|
6
|
-
* - the registered tool list (catalog)
|
|
7
|
-
* - which tool is currently active (selection)
|
|
8
|
-
* - which tools are disabled (per-id mask)
|
|
9
|
-
*
|
|
10
|
-
* Behaviours owned here:
|
|
11
|
-
* - Group-based mutual exclusion (radio): selecting a tool deselects any
|
|
12
|
-
* other active tool in the same `group` (used in LeftToolbar.vue for the
|
|
13
|
-
* "lines" / "channels" tool groups via parent + children).
|
|
14
|
-
* - Disabled-state gating: a disabled tool cannot be selected. Disabling a
|
|
15
|
-
* currently-active tool clears the selection.
|
|
16
|
-
* - Idempotent disposal: post-dispose mutators are silent no-ops.
|
|
17
|
-
*
|
|
18
|
-
* Everything DOM / icons / click handlers / pointer event stoppers / Teleport
|
|
19
|
-
* for the settings modal stays in the Vue adapter — the controller deals
|
|
20
|
-
* only with the data layer.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { createSignal, type Signal } from '../reactivity'
|
|
24
|
-
import type { ToolbarController, ToolDefinition, ToolId } from './types'
|
|
25
|
-
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
// Factory
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
export interface ToolbarInit {
|
|
31
|
-
tools: ReadonlyArray<ToolDefinition>
|
|
32
|
-
initialActiveTool?: ToolId | null
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function createToolbarController(init: ToolbarInit): ToolbarController {
|
|
36
|
-
// -------------------------------------------------------------------
|
|
37
|
-
// Signals (state)
|
|
38
|
-
// -------------------------------------------------------------------
|
|
39
|
-
const tools: Signal<ReadonlyArray<ToolDefinition>> = createSignal<
|
|
40
|
-
ReadonlyArray<ToolDefinition>
|
|
41
|
-
>(init.tools)
|
|
42
|
-
const activeTool: Signal<ToolId | null> = createSignal<ToolId | null>(
|
|
43
|
-
init.initialActiveTool ?? null,
|
|
44
|
-
)
|
|
45
|
-
const disabledTools: Signal<ReadonlySet<ToolId>> = createSignal<
|
|
46
|
-
ReadonlySet<ToolId>
|
|
47
|
-
>(new Set<ToolId>())
|
|
48
|
-
|
|
49
|
-
// -------------------------------------------------------------------
|
|
50
|
-
// Lookups (use peek — mutations must not track in `effect`)
|
|
51
|
-
// -------------------------------------------------------------------
|
|
52
|
-
function findTool(id: ToolId): ToolDefinition | null {
|
|
53
|
-
const list = tools.peek()
|
|
54
|
-
for (const t of list) {
|
|
55
|
-
if (t.id === id) return t
|
|
56
|
-
}
|
|
57
|
-
return null
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function isDisabled(id: ToolId): boolean {
|
|
61
|
-
return disabledTools.peek().has(id)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// -------------------------------------------------------------------
|
|
65
|
-
// Mutations
|
|
66
|
-
// -------------------------------------------------------------------
|
|
67
|
-
function selectTool(id: ToolId): void {
|
|
68
|
-
const tool = findTool(id)
|
|
69
|
-
if (tool === null) return // unknown id — no-op
|
|
70
|
-
if (isDisabled(id)) return // disabled — no-op
|
|
71
|
-
|
|
72
|
-
// Group-based mutual exclusion: when the requested tool belongs to a
|
|
73
|
-
// `group`, deselect any currently-active tool that shares the group.
|
|
74
|
-
// (Group membership is metadata on the definition; the controller
|
|
75
|
-
// does not infer groups from parent/child relations — adapters that
|
|
76
|
-
// model nested groups should flatten them with a shared group key.)
|
|
77
|
-
const currentActive = activeTool.peek()
|
|
78
|
-
if (currentActive !== null && tool.group !== undefined) {
|
|
79
|
-
const currentTool = findTool(currentActive)
|
|
80
|
-
if (
|
|
81
|
-
currentTool !== null &&
|
|
82
|
-
currentTool.group === tool.group &&
|
|
83
|
-
currentTool.id !== tool.id
|
|
84
|
-
) {
|
|
85
|
-
// Replace: writing the new id covers both "deselect old" and
|
|
86
|
-
// "select new" in a single notification.
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
activeTool.set(id)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function clearSelection(): void {
|
|
94
|
-
activeTool.set(null)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function setDisabled(id: ToolId, disabled: boolean): void {
|
|
98
|
-
const current = disabledTools.peek()
|
|
99
|
-
const has = current.has(id)
|
|
100
|
-
if (disabled === has) return // no change
|
|
101
|
-
|
|
102
|
-
// Immutable update — never mutate the existing Set in place.
|
|
103
|
-
const next = new Set(current)
|
|
104
|
-
if (disabled) {
|
|
105
|
-
next.add(id)
|
|
106
|
-
} else {
|
|
107
|
-
next.delete(id)
|
|
108
|
-
}
|
|
109
|
-
disabledTools.set(next)
|
|
110
|
-
|
|
111
|
-
// If the disabled tool was the active one, clear the active signal
|
|
112
|
-
// so adapters re-render without an "active + disabled" state.
|
|
113
|
-
if (disabled && activeTool.peek() === id) {
|
|
114
|
-
activeTool.set(null)
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// -------------------------------------------------------------------
|
|
119
|
-
// Disposal
|
|
120
|
-
// -------------------------------------------------------------------
|
|
121
|
-
// After dispose() the controller becomes inert: mutators silently no-op
|
|
122
|
-
// so previously-attached subscribers see no further notifications.
|
|
123
|
-
let disposed = false
|
|
124
|
-
|
|
125
|
-
function dispose(): void {
|
|
126
|
-
if (disposed) return
|
|
127
|
-
disposed = true
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function guard<T extends (...args: never[]) => unknown>(fn: T): T {
|
|
131
|
-
return ((...args: Parameters<T>): ReturnType<T> => {
|
|
132
|
-
if (disposed) return undefined as ReturnType<T>
|
|
133
|
-
return fn(...args) as ReturnType<T>
|
|
134
|
-
}) as T
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
tools,
|
|
139
|
-
activeTool,
|
|
140
|
-
disabledTools,
|
|
141
|
-
selectTool: guard(selectTool),
|
|
142
|
-
clearSelection: guard(clearSelection),
|
|
143
|
-
setDisabled: guard(setDisabled),
|
|
144
|
-
dispose,
|
|
145
|
-
}
|
|
146
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* ToolbarController — framework-agnostic implementation.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from src/components/LeftToolbar.vue. This module owns the pure
|
|
5
|
+
* state machine of the toolbar:
|
|
6
|
+
* - the registered tool list (catalog)
|
|
7
|
+
* - which tool is currently active (selection)
|
|
8
|
+
* - which tools are disabled (per-id mask)
|
|
9
|
+
*
|
|
10
|
+
* Behaviours owned here:
|
|
11
|
+
* - Group-based mutual exclusion (radio): selecting a tool deselects any
|
|
12
|
+
* other active tool in the same `group` (used in LeftToolbar.vue for the
|
|
13
|
+
* "lines" / "channels" tool groups via parent + children).
|
|
14
|
+
* - Disabled-state gating: a disabled tool cannot be selected. Disabling a
|
|
15
|
+
* currently-active tool clears the selection.
|
|
16
|
+
* - Idempotent disposal: post-dispose mutators are silent no-ops.
|
|
17
|
+
*
|
|
18
|
+
* Everything DOM / icons / click handlers / pointer event stoppers / Teleport
|
|
19
|
+
* for the settings modal stays in the Vue adapter — the controller deals
|
|
20
|
+
* only with the data layer.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { createSignal, type Signal } from '../reactivity'
|
|
24
|
+
import type { ToolbarController, ToolDefinition, ToolId } from './types'
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Factory
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
export interface ToolbarInit {
|
|
31
|
+
tools: ReadonlyArray<ToolDefinition>
|
|
32
|
+
initialActiveTool?: ToolId | null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function createToolbarController(init: ToolbarInit): ToolbarController {
|
|
36
|
+
// -------------------------------------------------------------------
|
|
37
|
+
// Signals (state)
|
|
38
|
+
// -------------------------------------------------------------------
|
|
39
|
+
const tools: Signal<ReadonlyArray<ToolDefinition>> = createSignal<
|
|
40
|
+
ReadonlyArray<ToolDefinition>
|
|
41
|
+
>(init.tools)
|
|
42
|
+
const activeTool: Signal<ToolId | null> = createSignal<ToolId | null>(
|
|
43
|
+
init.initialActiveTool ?? null,
|
|
44
|
+
)
|
|
45
|
+
const disabledTools: Signal<ReadonlySet<ToolId>> = createSignal<
|
|
46
|
+
ReadonlySet<ToolId>
|
|
47
|
+
>(new Set<ToolId>())
|
|
48
|
+
|
|
49
|
+
// -------------------------------------------------------------------
|
|
50
|
+
// Lookups (use peek — mutations must not track in `effect`)
|
|
51
|
+
// -------------------------------------------------------------------
|
|
52
|
+
function findTool(id: ToolId): ToolDefinition | null {
|
|
53
|
+
const list = tools.peek()
|
|
54
|
+
for (const t of list) {
|
|
55
|
+
if (t.id === id) return t
|
|
56
|
+
}
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function isDisabled(id: ToolId): boolean {
|
|
61
|
+
return disabledTools.peek().has(id)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// -------------------------------------------------------------------
|
|
65
|
+
// Mutations
|
|
66
|
+
// -------------------------------------------------------------------
|
|
67
|
+
function selectTool(id: ToolId): void {
|
|
68
|
+
const tool = findTool(id)
|
|
69
|
+
if (tool === null) return // unknown id — no-op
|
|
70
|
+
if (isDisabled(id)) return // disabled — no-op
|
|
71
|
+
|
|
72
|
+
// Group-based mutual exclusion: when the requested tool belongs to a
|
|
73
|
+
// `group`, deselect any currently-active tool that shares the group.
|
|
74
|
+
// (Group membership is metadata on the definition; the controller
|
|
75
|
+
// does not infer groups from parent/child relations — adapters that
|
|
76
|
+
// model nested groups should flatten them with a shared group key.)
|
|
77
|
+
const currentActive = activeTool.peek()
|
|
78
|
+
if (currentActive !== null && tool.group !== undefined) {
|
|
79
|
+
const currentTool = findTool(currentActive)
|
|
80
|
+
if (
|
|
81
|
+
currentTool !== null &&
|
|
82
|
+
currentTool.group === tool.group &&
|
|
83
|
+
currentTool.id !== tool.id
|
|
84
|
+
) {
|
|
85
|
+
// Replace: writing the new id covers both "deselect old" and
|
|
86
|
+
// "select new" in a single notification.
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
activeTool.set(id)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function clearSelection(): void {
|
|
94
|
+
activeTool.set(null)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function setDisabled(id: ToolId, disabled: boolean): void {
|
|
98
|
+
const current = disabledTools.peek()
|
|
99
|
+
const has = current.has(id)
|
|
100
|
+
if (disabled === has) return // no change
|
|
101
|
+
|
|
102
|
+
// Immutable update — never mutate the existing Set in place.
|
|
103
|
+
const next = new Set(current)
|
|
104
|
+
if (disabled) {
|
|
105
|
+
next.add(id)
|
|
106
|
+
} else {
|
|
107
|
+
next.delete(id)
|
|
108
|
+
}
|
|
109
|
+
disabledTools.set(next)
|
|
110
|
+
|
|
111
|
+
// If the disabled tool was the active one, clear the active signal
|
|
112
|
+
// so adapters re-render without an "active + disabled" state.
|
|
113
|
+
if (disabled && activeTool.peek() === id) {
|
|
114
|
+
activeTool.set(null)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// -------------------------------------------------------------------
|
|
119
|
+
// Disposal
|
|
120
|
+
// -------------------------------------------------------------------
|
|
121
|
+
// After dispose() the controller becomes inert: mutators silently no-op
|
|
122
|
+
// so previously-attached subscribers see no further notifications.
|
|
123
|
+
let disposed = false
|
|
124
|
+
|
|
125
|
+
function dispose(): void {
|
|
126
|
+
if (disposed) return
|
|
127
|
+
disposed = true
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function guard<T extends (...args: never[]) => unknown>(fn: T): T {
|
|
131
|
+
return ((...args: Parameters<T>): ReturnType<T> => {
|
|
132
|
+
if (disposed) return undefined as ReturnType<T>
|
|
133
|
+
return fn(...args) as ReturnType<T>
|
|
134
|
+
}) as T
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
tools,
|
|
139
|
+
activeTool,
|
|
140
|
+
disabledTools,
|
|
141
|
+
selectTool: guard(selectTool),
|
|
142
|
+
clearSelection: guard(clearSelection),
|
|
143
|
+
setDisabled: guard(setDisabled),
|
|
144
|
+
dispose,
|
|
145
|
+
}
|
|
146
|
+
}
|
package/src/controllers/index.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
KLineData,
|
|
3
|
-
IndicatorPaneRole,
|
|
4
|
-
IndicatorRole,
|
|
5
|
-
IndicatorParamDef,
|
|
6
|
-
IndicatorDefinition,
|
|
7
|
-
IndicatorInstance,
|
|
8
|
-
SubPaneInfo,
|
|
9
|
-
DrawingToolType,
|
|
10
|
-
DrawingObject,
|
|
11
|
-
InteractionSnapshot,
|
|
12
|
-
DrawingControllerCallbacks,
|
|
13
|
-
ChartMountOptions,
|
|
14
|
-
ChartViewport,
|
|
15
|
-
ChartController,
|
|
16
|
-
ChartControllerFactory,
|
|
17
|
-
} from './types'
|
|
18
|
-
|
|
19
|
-
export { createChartController } from './createChartController'
|
|
1
|
+
export type {
|
|
2
|
+
KLineData,
|
|
3
|
+
IndicatorPaneRole,
|
|
4
|
+
IndicatorRole,
|
|
5
|
+
IndicatorParamDef,
|
|
6
|
+
IndicatorDefinition,
|
|
7
|
+
IndicatorInstance,
|
|
8
|
+
SubPaneInfo,
|
|
9
|
+
DrawingToolType,
|
|
10
|
+
DrawingObject,
|
|
11
|
+
InteractionSnapshot,
|
|
12
|
+
DrawingControllerCallbacks,
|
|
13
|
+
ChartMountOptions,
|
|
14
|
+
ChartViewport,
|
|
15
|
+
ChartController,
|
|
16
|
+
ChartControllerFactory,
|
|
17
|
+
} from './types'
|
|
18
|
+
|
|
19
|
+
export { createChartController } from './createChartController'
|
|
20
|
+
export { createIndicatorSelectorController } from './createIndicatorSelectorController'
|