@363045841yyt/klinechart 0.8.2 → 0.8.4
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/dist/components/IndicatorSelector.vue.d.ts.map +1 -1
- package/dist/components/KLineChart.vue.d.ts +19 -1
- package/dist/components/KLineChart.vue.d.ts.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.css +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +641 -620
- package/dist/web-component.d.ts +16 -0
- package/dist/web-component.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/components/IndicatorSelector.vue +13 -5
- package/src/components/KLineChart.vue +18 -3
- package/src/index.ts +41 -14
package/dist/web-component.d.ts
CHANGED
|
@@ -12,6 +12,22 @@ declare const KLineChartElement: import('vue').VueElementConstructor<{
|
|
|
12
12
|
initialZoomLevel?: number;
|
|
13
13
|
isFullscreen?: boolean;
|
|
14
14
|
timezone?: string;
|
|
15
|
+
mcp?: {
|
|
16
|
+
wsUrl?: string;
|
|
17
|
+
onToolCall?: (call: {
|
|
18
|
+
name: string;
|
|
19
|
+
input: Record<string, unknown>;
|
|
20
|
+
}) => {
|
|
21
|
+
success: boolean;
|
|
22
|
+
error?: string;
|
|
23
|
+
data?: unknown;
|
|
24
|
+
} | Promise<{
|
|
25
|
+
success: boolean;
|
|
26
|
+
error?: string;
|
|
27
|
+
data?: unknown;
|
|
28
|
+
}>;
|
|
29
|
+
autoReconnect?: boolean;
|
|
30
|
+
};
|
|
15
31
|
}>;
|
|
16
32
|
export { KLineChartElement };
|
|
17
33
|
export default KLineChartElement;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-component.d.ts","sourceRoot":"","sources":["../src/web-component.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAE9F,QAAA,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"web-component.d.ts","sourceRoot":"","sources":["../src/web-component.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAE9F,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;aAUo0zC,CAAC;kBAAyB,CAAC;;;;;iBAAsH,CAAC;gBAAc,CAAC;;;iBAAuD,CAAC;gBAAc,CAAC;;qBAAgC,CAAC;;EARlm0C,CAAA;AAIF,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAC5B,eAAe,iBAAiB,CAAA;AAEhC,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@363045841yyt/klinechart",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
4
|
"description": "Vue 3 bindings for @363045841yyt/klinechart-core. Idiomatic composables, SFC components.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"vue": "^3.4.0"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
|
+
"@363045841yyt/klinechart-ai-runtime": "workspace:*",
|
|
74
75
|
"@arethetypeswrong/cli": "^0.18.3",
|
|
75
76
|
"@size-limit/preset-small-lib": "^12.1.0",
|
|
76
77
|
"@vitejs/plugin-vue": "^6.0.7",
|
|
@@ -219,6 +219,8 @@ import {
|
|
|
219
219
|
allIndicators,
|
|
220
220
|
findIndicator,
|
|
221
221
|
type Indicator,
|
|
222
|
+
loadBuiltinIndicators,
|
|
223
|
+
isBuiltinIndicatorsLoaded,
|
|
222
224
|
} from '@363045841yyt/klinechart-core/controllers'
|
|
223
225
|
|
|
224
226
|
const props = defineProps<{
|
|
@@ -233,7 +235,7 @@ const emit = defineEmits<{
|
|
|
233
235
|
}>()
|
|
234
236
|
|
|
235
237
|
// ── 将 Indicator[] 转换为 IndicatorDefinition[] ──
|
|
236
|
-
function toIndicatorDefinitions(source:
|
|
238
|
+
function toIndicatorDefinitions(source: Indicator[]): IndicatorDefinition[] {
|
|
237
239
|
return source.map((i) => ({
|
|
238
240
|
id: i.id,
|
|
239
241
|
label: i.label,
|
|
@@ -253,9 +255,7 @@ function toIndicatorDefinitions(source: typeof allIndicators): IndicatorDefiniti
|
|
|
253
255
|
}
|
|
254
256
|
|
|
255
257
|
// ── Controller ──
|
|
256
|
-
const controller = createIndicatorSelectorController(
|
|
257
|
-
catalog: toIndicatorDefinitions(allIndicators),
|
|
258
|
-
})
|
|
258
|
+
const controller = createIndicatorSelectorController()
|
|
259
259
|
|
|
260
260
|
// ── 从 Controller Signal 桥接的 Vue 响应式状态 ──
|
|
261
261
|
const menuOpen = coreSignalToVueRef(controller.menuOpen)
|
|
@@ -267,7 +267,15 @@ const hasSearchResults = computed(
|
|
|
267
267
|
() => filteredMain.value.length > 0 || filteredSub.value.length > 0,
|
|
268
268
|
)
|
|
269
269
|
|
|
270
|
-
const
|
|
270
|
+
const catalog = coreSignalToVueRef(controller.catalog)
|
|
271
|
+
const catalogLen = computed(() => catalog.value.length)
|
|
272
|
+
|
|
273
|
+
onMounted(async () => {
|
|
274
|
+
if (!isBuiltinIndicatorsLoaded()) {
|
|
275
|
+
await loadBuiltinIndicators()
|
|
276
|
+
}
|
|
277
|
+
controller.catalog.set(toIndicatorDefinitions(allIndicators()))
|
|
278
|
+
})
|
|
271
279
|
|
|
272
280
|
// ── 本地 UI 状态(非 Controller 管理的纯 UI 状态) ──
|
|
273
281
|
const paramsVisible = ref(false)
|
|
@@ -196,6 +196,18 @@ const props = withDefaults(
|
|
|
196
196
|
isFullscreen?: boolean
|
|
197
197
|
/** 时区,默认 Asia/Shanghai */
|
|
198
198
|
timezone?: string
|
|
199
|
+
|
|
200
|
+
/** MCP / AI runtime bridge 配置。传入后自动连接 MCP WebSocket server */
|
|
201
|
+
mcp?: {
|
|
202
|
+
wsUrl?: string
|
|
203
|
+
onToolCall?: (call: {
|
|
204
|
+
name: string
|
|
205
|
+
input: Record<string, unknown>
|
|
206
|
+
}) =>
|
|
207
|
+
| { success: boolean; error?: string; data?: unknown }
|
|
208
|
+
| Promise<{ success: boolean; error?: string; data?: unknown }>
|
|
209
|
+
autoReconnect?: boolean
|
|
210
|
+
}
|
|
199
211
|
}>(),
|
|
200
212
|
{
|
|
201
213
|
yPaddingPx: 20,
|
|
@@ -864,6 +876,7 @@ defineExpose({
|
|
|
864
876
|
zoomOut: (anchorX?: number) => applyZoomToLevel(zoomLevel.value - 1, anchorX),
|
|
865
877
|
getZoomLevel: () => zoomLevel.value,
|
|
866
878
|
getZoomLevelCount: () => controller.value?.getZoomLevelCount() ?? 10,
|
|
879
|
+
getController: () => controller.value,
|
|
867
880
|
})
|
|
868
881
|
|
|
869
882
|
// ==================== onMounted 拆分函数 ====================
|
|
@@ -881,7 +894,7 @@ function initChart(
|
|
|
881
894
|
canvasLayer: HTMLDivElement,
|
|
882
895
|
rightAxisLayer: HTMLDivElement,
|
|
883
896
|
xAxisCanvas: HTMLCanvasElement,
|
|
884
|
-
): ChartController {
|
|
897
|
+
): Promise<ChartController> {
|
|
885
898
|
const ctrl = createChartController({
|
|
886
899
|
container,
|
|
887
900
|
data: [],
|
|
@@ -896,6 +909,7 @@ function initChart(
|
|
|
896
909
|
priceLabelWidth: props.priceLabelWidth,
|
|
897
910
|
minKWidth: props.minKWidth,
|
|
898
911
|
maxKWidth: props.maxKWidth,
|
|
912
|
+
mcp: props.mcp,
|
|
899
913
|
})
|
|
900
914
|
return ctrl
|
|
901
915
|
}
|
|
@@ -1082,7 +1096,7 @@ function setupSemanticController(ctrl: ChartController): void {
|
|
|
1082
1096
|
// })
|
|
1083
1097
|
}
|
|
1084
1098
|
|
|
1085
|
-
onMounted(() => {
|
|
1099
|
+
onMounted(async () => {
|
|
1086
1100
|
useAnchorPositioning.value = false
|
|
1087
1101
|
|
|
1088
1102
|
const container = containerRef.value
|
|
@@ -1097,7 +1111,8 @@ onMounted(() => {
|
|
|
1097
1111
|
const canvasLayer = container.querySelector<HTMLDivElement>('.canvas-layer')
|
|
1098
1112
|
const xAxisCanvas = container.querySelector<HTMLCanvasElement>('.x-axis-canvas')
|
|
1099
1113
|
const rightAxisLayer = chartMain.querySelector<HTMLDivElement>('.right-axis-host')
|
|
1100
|
-
const ctrl = initChart(container, canvasLayer!, rightAxisLayer!, xAxisCanvas!)
|
|
1114
|
+
const ctrl = await initChart(container, canvasLayer!, rightAxisLayer!, xAxisCanvas!)
|
|
1115
|
+
if (!containerRef.value || !chartMainRef.value) return // 组件已卸载
|
|
1101
1116
|
controller.value = ctrl
|
|
1102
1117
|
|
|
1103
1118
|
// 3) 信号回调
|
package/src/index.ts
CHANGED
|
@@ -88,7 +88,7 @@ export function __setControllerFactory(
|
|
|
88
88
|
*
|
|
89
89
|
* Throws if container is null/undefined (SSR-safe guard).
|
|
90
90
|
*/
|
|
91
|
-
export function createChart(opts: ChartMountOptions): ChartController {
|
|
91
|
+
export function createChart(opts: ChartMountOptions): ChartController | Promise<ChartController> {
|
|
92
92
|
if (opts.container == null) {
|
|
93
93
|
throw new Error(
|
|
94
94
|
'[@363045841yyt/klinechart] createChart: `container` is required and must be a non-null HTMLElement',
|
|
@@ -147,10 +147,24 @@ export function useChart(
|
|
|
147
147
|
opts: Omit<ChartMountOptions, 'container'>,
|
|
148
148
|
): { chart: Ref<ChartController | null> } {
|
|
149
149
|
const chart = shallowRef<ChartController | null>(null)
|
|
150
|
+
let disposed = false
|
|
150
151
|
|
|
151
152
|
const mountIfReady = (el: HTMLElement | null): void => {
|
|
152
153
|
if (el == null || chart.value != null) return
|
|
153
|
-
|
|
154
|
+
const created = createChart({ ...opts, container: el })
|
|
155
|
+
const applyController = (ctrl: ChartController): void => {
|
|
156
|
+
if (disposed) {
|
|
157
|
+
ctrl.dispose()
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
chart.value = ctrl
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (typeof (created as Promise<ChartController>).then === 'function') {
|
|
164
|
+
;(created as Promise<ChartController>).then(applyController)
|
|
165
|
+
} else {
|
|
166
|
+
applyController(created as ChartController)
|
|
167
|
+
}
|
|
154
168
|
}
|
|
155
169
|
|
|
156
170
|
// Mount synchronously if the ref is already populated (e.g. SFC where the
|
|
@@ -167,6 +181,7 @@ export function useChart(
|
|
|
167
181
|
)
|
|
168
182
|
|
|
169
183
|
const dispose = (): void => {
|
|
184
|
+
disposed = true
|
|
170
185
|
stopWatch()
|
|
171
186
|
const ctrl = chart.value
|
|
172
187
|
if (ctrl != null) {
|
|
@@ -359,29 +374,40 @@ export const KLineChart = defineComponent({
|
|
|
359
374
|
const scope = effectScope()
|
|
360
375
|
|
|
361
376
|
const chart = shallowRef<ChartController | null>(null)
|
|
377
|
+
let mounted = true
|
|
378
|
+
|
|
379
|
+
const applyController = (ctrl: ChartController): void => {
|
|
380
|
+
if (!mounted) {
|
|
381
|
+
ctrl.dispose()
|
|
382
|
+
return
|
|
383
|
+
}
|
|
384
|
+
chart.value = ctrl
|
|
385
|
+
emit('ready', ctrl)
|
|
386
|
+
// Bridge viewport changes back out as zoomLevelChange.
|
|
387
|
+
const emitViewport = (): void => {
|
|
388
|
+
const vp = ctrl.viewport.peek()
|
|
389
|
+
emit('zoomLevelChange', vp.zoomLevel, vp.kWidth)
|
|
390
|
+
}
|
|
391
|
+
emitViewport()
|
|
392
|
+
const unsub = ctrl.viewport.subscribe(emitViewport)
|
|
393
|
+
onScopeDispose(unsub)
|
|
394
|
+
}
|
|
362
395
|
|
|
363
396
|
onMounted(() => {
|
|
364
397
|
const el = containerRef.value
|
|
365
398
|
if (el == null) return
|
|
366
399
|
scope.run(() => {
|
|
367
|
-
|
|
400
|
+
const created = createChart({
|
|
368
401
|
container: el,
|
|
369
402
|
data: props.data,
|
|
370
403
|
initialZoomLevel: props.initialZoomLevel,
|
|
371
404
|
zoomLevels: props.zoomLevels,
|
|
372
405
|
theme: props.theme,
|
|
373
406
|
})
|
|
374
|
-
if (
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
const emitViewport = (): void => {
|
|
379
|
-
const vp = ctrl.viewport.peek()
|
|
380
|
-
emit('zoomLevelChange', vp.zoomLevel, vp.kWidth)
|
|
381
|
-
}
|
|
382
|
-
emitViewport()
|
|
383
|
-
const unsub = ctrl.viewport.subscribe(emitViewport)
|
|
384
|
-
onScopeDispose(unsub)
|
|
407
|
+
if (typeof (created as Promise<ChartController>).then === 'function') {
|
|
408
|
+
;(created as Promise<ChartController>).then(applyController)
|
|
409
|
+
} else {
|
|
410
|
+
applyController(created as ChartController)
|
|
385
411
|
}
|
|
386
412
|
})
|
|
387
413
|
|
|
@@ -401,6 +427,7 @@ export const KLineChart = defineComponent({
|
|
|
401
427
|
})
|
|
402
428
|
|
|
403
429
|
onUnmounted(() => {
|
|
430
|
+
mounted = false
|
|
404
431
|
chart.value?.dispose()
|
|
405
432
|
chart.value = null
|
|
406
433
|
scope.stop()
|