@baron1996/klinecharts-adapter 0.9.5 → 0.9.9
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/adapter.d.ts +2 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +77 -22
- package/dist/conversion/id-map.d.ts.map +1 -1
- package/dist/conversion/id-map.js +6 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +2 -1
- package/dist/gap-aware-series.d.ts +44 -0
- package/dist/gap-aware-series.d.ts.map +1 -0
- package/dist/gap-aware-series.js +221 -0
- package/dist/static-data-loader.d.ts +2 -3
- package/dist/static-data-loader.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/adapter.d.ts
CHANGED
|
@@ -29,6 +29,8 @@ export interface AdapterSnapshot {
|
|
|
29
29
|
readonly engineVersion: string;
|
|
30
30
|
readonly runtimeVersion: ChartScene['runtime']['runtimeVersion'];
|
|
31
31
|
readonly dataCount: number;
|
|
32
|
+
readonly timelineSlotCount: number;
|
|
33
|
+
readonly gapCount: number;
|
|
32
34
|
readonly paneIds: readonly string[];
|
|
33
35
|
readonly indicators: readonly AdapterIndicatorSnapshot[];
|
|
34
36
|
readonly overlays: readonly SceneOverlay[];
|
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EAEV,OAAO,EACP,UAAU,EACV,cAAc,EACd,YAAY,EACZ,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGN,UAAU,EACV,MAAM,+BAA+B,CAAC;AAWvC,OAAO,EAKN,KAAK,oBAAoB,EAGzB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter.js
CHANGED
|
@@ -8,6 +8,7 @@ import { createSceneOverlays, fromEngineOverlay, normalizeSceneOverlayPrices, to
|
|
|
8
8
|
import { normalizePriceValue } from './conversion/price.js';
|
|
9
9
|
import { applyViewport } from './conversion/viewport.js';
|
|
10
10
|
import { createStaticDataLoader } from './static-data-loader.js';
|
|
11
|
+
import { assertGapAwareSceneSupported, engineDataForScene, GAP_AWARE_CANDLE_INDICATOR_ID, gapCount, installGapAwareMainSeries, isGapAwareScene, timelineItemOf, timelineSlotCount, } from './gap-aware-series.js';
|
|
11
12
|
import { toOverlayStyles } from './conversion/overlays.js';
|
|
12
13
|
import { drawingToSceneOverlay, sceneOverlayToDrawing, } from './drawing/overlay-conversion.js';
|
|
13
14
|
import { MainSeriesPresentationError, presentationToSceneCandle, STANDARD_CLOSE_LINE_PRESENTATION, } from './main-series-presentation.js';
|
|
@@ -83,14 +84,16 @@ export class KLineChartsSceneAdapter {
|
|
|
83
84
|
}
|
|
84
85
|
const match = barIndex === null ? undefined : data[barIndex];
|
|
85
86
|
const timestamp = match?.timestamp ?? null;
|
|
86
|
-
const
|
|
87
|
+
const timelineItem = timelineItemOf(match);
|
|
88
|
+
const source = timelineItem?.kind === 'bar' ? timelineItem.bar : match;
|
|
89
|
+
const bar = source === undefined || timelineItem?.kind === 'gap'
|
|
87
90
|
? null
|
|
88
91
|
: {
|
|
89
|
-
open:
|
|
90
|
-
high:
|
|
91
|
-
low:
|
|
92
|
-
close:
|
|
93
|
-
volume:
|
|
92
|
+
open: source.open,
|
|
93
|
+
high: source.high,
|
|
94
|
+
low: source.low,
|
|
95
|
+
close: source.close,
|
|
96
|
+
volume: source.volume ?? null,
|
|
94
97
|
};
|
|
95
98
|
const snapshot = { timestamp, bar };
|
|
96
99
|
for (const listener of this.#crosshairListeners) {
|
|
@@ -147,6 +150,8 @@ export class KLineChartsSceneAdapter {
|
|
|
147
150
|
#historicalDataLoading;
|
|
148
151
|
/** 当前唯一待完成的历史行情请求,防止重复并发前插。 */
|
|
149
152
|
#pendingHistoricalData;
|
|
153
|
+
/** 历史行情请求期间冻结平移前的宿主滚动状态。 */
|
|
154
|
+
#historicalScrollEnabled;
|
|
150
155
|
/** 历史行情请求的单调序号。 */
|
|
151
156
|
#historicalDataSequence = 0;
|
|
152
157
|
/** 交互启用开关。 */
|
|
@@ -184,6 +189,7 @@ export class KLineChartsSceneAdapter {
|
|
|
184
189
|
let adapter;
|
|
185
190
|
try {
|
|
186
191
|
handle = await createEngine(container, scene);
|
|
192
|
+
installGapAwareMainSeries(scene, handle.chart, handle.module.registerIndicator);
|
|
187
193
|
registerProjectOverlays(handle.module.registerOverlay);
|
|
188
194
|
const idMap = createEngineIdMap(scene, handle.chart);
|
|
189
195
|
applyPanes(scene, handle.chart, idMap);
|
|
@@ -221,6 +227,7 @@ export class KLineChartsSceneAdapter {
|
|
|
221
227
|
? {}
|
|
222
228
|
: { displayTimezone: options.displayTimezone }),
|
|
223
229
|
});
|
|
230
|
+
installGapAwareMainSeries(scene, handle.chart, handle.module.registerIndicator);
|
|
224
231
|
registerProjectOverlays(handle.module.registerOverlay);
|
|
225
232
|
const idMap = createEngineIdMap(scene, handle.chart);
|
|
226
233
|
applyPanes(scene, handle.chart, idMap);
|
|
@@ -307,7 +314,7 @@ export class KLineChartsSceneAdapter {
|
|
|
307
314
|
}
|
|
308
315
|
}
|
|
309
316
|
#historicalDataLoader(scene) {
|
|
310
|
-
const snapshot = structuredClone(scene
|
|
317
|
+
const snapshot = structuredClone(engineDataForScene(scene));
|
|
311
318
|
return {
|
|
312
319
|
getBars: ({ type, timestamp, callback }) => {
|
|
313
320
|
if (type === 'init') {
|
|
@@ -333,6 +340,7 @@ export class KLineChartsSceneAdapter {
|
|
|
333
340
|
period: structuredClone(this.#scene.period),
|
|
334
341
|
dataCount: this.#scene.data.length,
|
|
335
342
|
};
|
|
343
|
+
this.#lockHistoricalScroll();
|
|
336
344
|
this.#pendingHistoricalData = { request, callback };
|
|
337
345
|
for (const listener of this.#historicalDataListeners) {
|
|
338
346
|
listener(structuredClone(request));
|
|
@@ -340,13 +348,37 @@ export class KLineChartsSceneAdapter {
|
|
|
340
348
|
},
|
|
341
349
|
};
|
|
342
350
|
}
|
|
351
|
+
#lockHistoricalScroll() {
|
|
352
|
+
if (this.#historicalScrollEnabled === undefined) {
|
|
353
|
+
this.#historicalScrollEnabled =
|
|
354
|
+
this.#chartInteractionSnapshot?.scrollEnabled ??
|
|
355
|
+
this.#chart.isScrollEnabled();
|
|
356
|
+
}
|
|
357
|
+
this.#chart.setScrollEnabled(false);
|
|
358
|
+
}
|
|
359
|
+
#restoreHistoricalScrollIfIdle() {
|
|
360
|
+
if (this.#pendingHistoricalData !== undefined ||
|
|
361
|
+
this.#historicalScrollEnabled === undefined) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
const scrollEnabled = this.#historicalScrollEnabled;
|
|
365
|
+
this.#historicalScrollEnabled = undefined;
|
|
366
|
+
this.#chart.setScrollEnabled(this.#chartInteractionSnapshot === undefined
|
|
367
|
+
? scrollEnabled
|
|
368
|
+
: false);
|
|
369
|
+
}
|
|
343
370
|
#settlePendingHistoricalData(hasMore) {
|
|
344
371
|
const pending = this.#pendingHistoricalData;
|
|
345
372
|
if (pending === undefined) {
|
|
346
373
|
return;
|
|
347
374
|
}
|
|
348
375
|
this.#pendingHistoricalData = undefined;
|
|
349
|
-
|
|
376
|
+
try {
|
|
377
|
+
pending.callback([], { forward: hasMore, backward: false });
|
|
378
|
+
}
|
|
379
|
+
finally {
|
|
380
|
+
this.#restoreHistoricalScrollIfIdle();
|
|
381
|
+
}
|
|
350
382
|
}
|
|
351
383
|
#restoreWorkspaceDrawings(drawings) {
|
|
352
384
|
for (const overlay of this.#workspaceOverlays) {
|
|
@@ -412,7 +444,7 @@ export class KLineChartsSceneAdapter {
|
|
|
412
444
|
return;
|
|
413
445
|
}
|
|
414
446
|
this.#chartInteractionSnapshot = {
|
|
415
|
-
scrollEnabled: this.#chart.isScrollEnabled(),
|
|
447
|
+
scrollEnabled: this.#historicalScrollEnabled ?? this.#chart.isScrollEnabled(),
|
|
416
448
|
zoomEnabled: this.#chart.isZoomEnabled(),
|
|
417
449
|
crosshairVisible: this.#chart.getStyles().crosshair.show,
|
|
418
450
|
};
|
|
@@ -426,7 +458,9 @@ export class KLineChartsSceneAdapter {
|
|
|
426
458
|
return;
|
|
427
459
|
}
|
|
428
460
|
this.#chartInteractionSnapshot = undefined;
|
|
429
|
-
this.#chart.setScrollEnabled(
|
|
461
|
+
this.#chart.setScrollEnabled(this.#historicalScrollEnabled === undefined
|
|
462
|
+
? snapshot.scrollEnabled
|
|
463
|
+
: false);
|
|
430
464
|
this.#chart.setZoomEnabled(snapshot.zoomEnabled);
|
|
431
465
|
this.#chart.setStyles({ crosshair: { show: snapshot.crosshairVisible } });
|
|
432
466
|
}
|
|
@@ -1319,6 +1353,10 @@ export class KLineChartsSceneAdapter {
|
|
|
1319
1353
|
replaceScene(value) {
|
|
1320
1354
|
this.#assertActive();
|
|
1321
1355
|
const candidate = parseChartScene(value);
|
|
1356
|
+
if (candidate.version !== this.#scene.version) {
|
|
1357
|
+
throw new SceneError('INVALID_REFERENCE', '/version', 'Scene replacement requires the same ChartScene contract version.');
|
|
1358
|
+
}
|
|
1359
|
+
assertGapAwareSceneSupported(candidate);
|
|
1322
1360
|
const paneShape = (scene) => JSON.stringify(scene.panes.map((pane) => ({
|
|
1323
1361
|
id: pane.id,
|
|
1324
1362
|
kind: pane.kind,
|
|
@@ -1343,7 +1381,7 @@ export class KLineChartsSceneAdapter {
|
|
|
1343
1381
|
this.#historicalDataLoading = { hasMore: true };
|
|
1344
1382
|
}
|
|
1345
1383
|
this.#chart.setDataLoader(this.#historicalDataLoading === undefined
|
|
1346
|
-
? createStaticDataLoader(candidate
|
|
1384
|
+
? createStaticDataLoader(engineDataForScene(candidate))
|
|
1347
1385
|
: this.#historicalDataLoader(candidate));
|
|
1348
1386
|
this.#chart.resetData();
|
|
1349
1387
|
applyViewport(this.#chart, candidate.viewport);
|
|
@@ -1366,7 +1404,7 @@ export class KLineChartsSceneAdapter {
|
|
|
1366
1404
|
this.#historicalDataLoading = { hasMore: previousHistoricalHasMore };
|
|
1367
1405
|
}
|
|
1368
1406
|
this.#chart.setDataLoader(this.#historicalDataLoading === undefined
|
|
1369
|
-
? createStaticDataLoader(previous
|
|
1407
|
+
? createStaticDataLoader(engineDataForScene(previous))
|
|
1370
1408
|
: this.#historicalDataLoader(previous));
|
|
1371
1409
|
this.#chart.resetData();
|
|
1372
1410
|
applyViewport(this.#chart, previous.viewport);
|
|
@@ -1425,10 +1463,15 @@ export class KLineChartsSceneAdapter {
|
|
|
1425
1463
|
this.#pendingHistoricalData = undefined;
|
|
1426
1464
|
this.#historicalDataLoading = { hasMore };
|
|
1427
1465
|
this.#scene = candidate;
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1466
|
+
try {
|
|
1467
|
+
pending.callback(structuredClone(page), {
|
|
1468
|
+
forward: hasMore,
|
|
1469
|
+
backward: false,
|
|
1470
|
+
});
|
|
1471
|
+
}
|
|
1472
|
+
finally {
|
|
1473
|
+
this.#restoreHistoricalScrollIfIdle();
|
|
1474
|
+
}
|
|
1432
1475
|
return {
|
|
1433
1476
|
scene: structuredClone(candidate),
|
|
1434
1477
|
addedCount: page.length,
|
|
@@ -1442,10 +1485,15 @@ export class KLineChartsSceneAdapter {
|
|
|
1442
1485
|
return false;
|
|
1443
1486
|
}
|
|
1444
1487
|
this.#pendingHistoricalData = undefined;
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1488
|
+
try {
|
|
1489
|
+
pending.callback([], {
|
|
1490
|
+
forward: this.#historicalDataLoading?.hasMore ?? false,
|
|
1491
|
+
backward: false,
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
finally {
|
|
1495
|
+
this.#restoreHistoricalScrollIfIdle();
|
|
1496
|
+
}
|
|
1449
1497
|
return true;
|
|
1450
1498
|
}
|
|
1451
1499
|
get sceneKind() {
|
|
@@ -1624,6 +1672,9 @@ export class KLineChartsSceneAdapter {
|
|
|
1624
1672
|
applyMainSeriesPresentation(presentation) {
|
|
1625
1673
|
this.#assertActive();
|
|
1626
1674
|
this.#assertNotTerminated();
|
|
1675
|
+
if (isGapAwareScene(this.#scene)) {
|
|
1676
|
+
throw new MainSeriesPresentationError('MAIN_SERIES_PRESENTATION_UNSUPPORTED', '/chart/candle/type', 'ChartScene v2 main-series switching is disabled until every presentation is Gap-aware.');
|
|
1677
|
+
}
|
|
1627
1678
|
if (presentation.type === 'area') {
|
|
1628
1679
|
const expected = STANDARD_CLOSE_LINE_PRESENTATION;
|
|
1629
1680
|
if (presentation.value !== expected.value ||
|
|
@@ -1913,7 +1964,9 @@ export class KLineChartsSceneAdapter {
|
|
|
1913
1964
|
}
|
|
1914
1965
|
inspect() {
|
|
1915
1966
|
this.#assertActive();
|
|
1916
|
-
const indicators = this.#chart.getIndicators()
|
|
1967
|
+
const indicators = this.#chart.getIndicators()
|
|
1968
|
+
.filter((indicator) => indicator.id !== GAP_AWARE_CANDLE_INDICATOR_ID)
|
|
1969
|
+
.map((indicator) => {
|
|
1917
1970
|
const paneId = this.#idMap.paneFromEngine.get(indicator.paneId);
|
|
1918
1971
|
const yAxisId = this.#idMap.yAxisFromEngine.get(indicator.yAxisId);
|
|
1919
1972
|
if (paneId === undefined || yAxisId === undefined) {
|
|
@@ -1929,7 +1982,9 @@ export class KLineChartsSceneAdapter {
|
|
|
1929
1982
|
return {
|
|
1930
1983
|
engineVersion: this.#engine.version(),
|
|
1931
1984
|
runtimeVersion: this.#scene.runtime.runtimeVersion,
|
|
1932
|
-
dataCount: this.#
|
|
1985
|
+
dataCount: this.#scene.data.length,
|
|
1986
|
+
timelineSlotCount: timelineSlotCount(this.#scene),
|
|
1987
|
+
gapCount: gapCount(this.#scene),
|
|
1933
1988
|
paneIds: this.#scene.panes.map((pane) => pane.id),
|
|
1934
1989
|
indicators,
|
|
1935
1990
|
overlays: this.exportScene().overlays,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"id-map.d.ts","sourceRoot":"","sources":["../../src/conversion/id-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,KAAK,EAAE,KAAK,EAAS,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"id-map.d.ts","sourceRoot":"","sources":["../../src/conversion/id-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,KAAK,EAAE,KAAK,EAAS,MAAM,aAAa,CAAC;AAYhD,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtD;AAMD,gCAAgC;AAChC,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,WAAW,CAyC9E;AAED,wBAAgB,eAAe,CAC9B,GAAG,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACX,MAAM,CAMR"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SceneError } from '@baron1996/kline-scene-schema';
|
|
2
|
+
import { GAP_AWARE_CANDLE_PANE_ID, isGapAwareScene, } from '../gap-aware-series.js';
|
|
2
3
|
function invert(source) {
|
|
3
4
|
return new Map(Array.from(source, ([sceneId, engineId]) => [engineId, sceneId]));
|
|
4
5
|
}
|
|
@@ -11,7 +12,11 @@ export function createEngineIdMap(scene, chart) {
|
|
|
11
12
|
if (pane === undefined) {
|
|
12
13
|
continue;
|
|
13
14
|
}
|
|
14
|
-
const enginePaneId = pane.kind === 'candle'
|
|
15
|
+
const enginePaneId = pane.kind === 'candle'
|
|
16
|
+
? isGapAwareScene(scene)
|
|
17
|
+
? GAP_AWARE_CANDLE_PANE_ID
|
|
18
|
+
: 'candle_pane'
|
|
19
|
+
: `baron_pane_${paneIndex}`;
|
|
15
20
|
paneToEngine.set(pane.id, enginePaneId);
|
|
16
21
|
for (let axisIndex = 0; axisIndex < pane.yAxes.length; axisIndex++) {
|
|
17
22
|
const axis = pane.yAxes[axisIndex];
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAWzC,MAAM,MAAM,iBAAiB,GAAG,cAAc,aAAa,CAAC,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,4CAA4C;IAC5C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAC3C,kCAAkC;IAClC,QAAQ,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACpE,gCAAgC;IAChC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACrE;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAqFD,qCAAqC;AACrC,wBAAsB,YAAY,CACjC,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7C,OAAO,CAAC,YAAY,CAAC,CAyCvB"}
|
package/dist/engine.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SceneError } from '@baron1996/kline-scene-schema';
|
|
2
2
|
import { toKLineChartsOptions } from './conversion/chart-options.js';
|
|
3
3
|
import { createStaticDataLoader } from './static-data-loader.js';
|
|
4
|
+
import { engineDataForScene } from './gap-aware-series.js';
|
|
4
5
|
import { KLINECHARTS_ENGINE_VERSION, KLINECHARTS_RUNTIME_VERSION, SUPPORTED_KLINECHARTS_RUNTIME_VERSIONS, } from './version.js';
|
|
5
6
|
function resolveMouseInteractionDispatch(chart) {
|
|
6
7
|
const chartEvent = chart._chartEvent;
|
|
@@ -62,7 +63,7 @@ export async function createEngine(container, scene, options) {
|
|
|
62
63
|
...(scene.symbol.name === undefined ? {} : { name: scene.symbol.name }),
|
|
63
64
|
});
|
|
64
65
|
chart.setPeriod(structuredClone(scene.period));
|
|
65
|
-
chart.setDataLoader(createStaticDataLoader(scene
|
|
66
|
+
chart.setDataLoader(createStaticDataLoader(engineDataForScene(scene)));
|
|
66
67
|
const mouseInteraction = resolveMouseInteractionDispatch(chart);
|
|
67
68
|
return {
|
|
68
69
|
chart,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ChartScene, MarketData, MarketDataGap } from '@baron1996/kline-scene-schema';
|
|
2
|
+
import type { Chart, IndicatorTemplate, KLineData } from 'klinecharts';
|
|
3
|
+
export declare const GAP_AWARE_CANDLE_INDICATOR_ID = "baron_gap_aware_candle";
|
|
4
|
+
export declare const GAP_AWARE_CANDLE_INDICATOR_NAME = "BARON_GAP_AWARE_CANDLE";
|
|
5
|
+
export declare const GAP_AWARE_CANDLE_PANE_ID = "baron_gap_aware_candle_pane";
|
|
6
|
+
export declare const GAP_AWARE_CANDLE_Y_AXIS_ID = "baron_gap_aware_candle_y_axis";
|
|
7
|
+
export type GapAwareTimelineItem = {
|
|
8
|
+
readonly kind: 'bar';
|
|
9
|
+
readonly bar: MarketData;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: 'gap';
|
|
12
|
+
readonly gap: MarketDataGap;
|
|
13
|
+
};
|
|
14
|
+
export interface GapAwareCarrierData extends KLineData {
|
|
15
|
+
/** 仅供 Adapter 内部绘制与十字线识别,不属于公开 MarketData。 */
|
|
16
|
+
readonly __baronTimelineItem: GapAwareTimelineItem;
|
|
17
|
+
}
|
|
18
|
+
interface GapAwareCandleValue {
|
|
19
|
+
readonly open: number | null;
|
|
20
|
+
readonly high: number | null;
|
|
21
|
+
readonly low: number | null;
|
|
22
|
+
readonly close: number | null;
|
|
23
|
+
}
|
|
24
|
+
interface GapAwareCandleStyles {
|
|
25
|
+
readonly upColor: string;
|
|
26
|
+
readonly downColor: string;
|
|
27
|
+
readonly noChangeColor: string;
|
|
28
|
+
readonly upWickColor: string;
|
|
29
|
+
readonly downWickColor: string;
|
|
30
|
+
readonly noChangeWickColor: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function isGapAwareScene(scene: ChartScene): boolean;
|
|
33
|
+
export declare function timelineSlotCount(scene: ChartScene): number;
|
|
34
|
+
export declare function gapCount(scene: ChartScene): number;
|
|
35
|
+
/** 将真实 Bar 与 Gap 合并为严格时间序的引擎索引载体。 */
|
|
36
|
+
export declare function toGapAwareCarrierData(scene: ChartScene): GapAwareCarrierData[];
|
|
37
|
+
export declare function engineDataForScene(scene: ChartScene): readonly KLineData[];
|
|
38
|
+
export declare function timelineItemOf(data: KLineData | undefined): GapAwareTimelineItem | undefined;
|
|
39
|
+
export declare const gapAwareCandleIndicatorTemplate: IndicatorTemplate<GapAwareCandleValue, never, GapAwareCandleStyles>;
|
|
40
|
+
/** 初始化仅绘制真实 Bar 的主序列;Gap 只保留横轴槽位。 */
|
|
41
|
+
export declare function installGapAwareMainSeries(scene: ChartScene, chart: Chart, registerIndicator: typeof import('klinecharts').registerIndicator): void;
|
|
42
|
+
export declare function assertGapAwareSceneSupported(scene: ChartScene): void;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=gap-aware-series.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gap-aware-series.d.ts","sourceRoot":"","sources":["../src/gap-aware-series.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,UAAU,EACV,aAAa,EACb,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EACX,KAAK,EAEL,iBAAiB,EACjB,SAAS,EACT,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,6BAA6B,2BAA2B,CAAC;AACtE,eAAO,MAAM,+BAA+B,2BAA2B,CAAC;AACxE,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AACtE,eAAO,MAAM,0BAA0B,kCAAkC,CAAC;AAE1E,MAAM,MAAM,oBAAoB,GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAA;CAAE,CAAC;AAEzD,MAAM,WAAW,mBAAoB,SAAQ,SAAS;IACrD,8CAA8C;IAC9C,QAAQ,CAAC,mBAAmB,EAAE,oBAAoB,CAAC;CACnD;AAED,UAAU,mBAAmB;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,UAAU,oBAAoB;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACnC;AAMD,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAE1D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAE3D;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAElD;AAED,qCAAqC;AACrC,wBAAgB,qBAAqB,CACpC,KAAK,EAAE,UAAU,GACf,mBAAmB,EAAE,CAgCvB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,SAAS,EAAE,CAI1E;AAED,wBAAgB,cAAc,CAC7B,IAAI,EAAE,SAAS,GAAG,SAAS,GACzB,oBAAoB,GAAG,SAAS,CAElC;AAkCD,eAAO,MAAM,+BAA+B,EAAE,iBAAiB,CAC9D,mBAAmB,EACnB,KAAK,EACL,oBAAoB,CA4FpB,CAAC;AA4BF,qCAAqC;AACrC,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,KAAK,EACZ,iBAAiB,EAAE,cAAc,aAAa,EAAE,iBAAiB,GAC/D,IAAI,CAkBN;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAgBpE"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { SceneError } from '@baron1996/kline-scene-schema';
|
|
2
|
+
export const GAP_AWARE_CANDLE_INDICATOR_ID = 'baron_gap_aware_candle';
|
|
3
|
+
export const GAP_AWARE_CANDLE_INDICATOR_NAME = 'BARON_GAP_AWARE_CANDLE';
|
|
4
|
+
export const GAP_AWARE_CANDLE_PANE_ID = 'baron_gap_aware_candle_pane';
|
|
5
|
+
export const GAP_AWARE_CANDLE_Y_AXIS_ID = 'baron_gap_aware_candle_y_axis';
|
|
6
|
+
function adapterError(path, message) {
|
|
7
|
+
return new SceneError('RUNTIME_INIT_FAILED', path, message);
|
|
8
|
+
}
|
|
9
|
+
export function isGapAwareScene(scene) {
|
|
10
|
+
return scene.version === 2;
|
|
11
|
+
}
|
|
12
|
+
export function timelineSlotCount(scene) {
|
|
13
|
+
return scene.data.length + (scene.gaps?.length ?? 0);
|
|
14
|
+
}
|
|
15
|
+
export function gapCount(scene) {
|
|
16
|
+
return scene.gaps?.length ?? 0;
|
|
17
|
+
}
|
|
18
|
+
/** 将真实 Bar 与 Gap 合并为严格时间序的引擎索引载体。 */
|
|
19
|
+
export function toGapAwareCarrierData(scene) {
|
|
20
|
+
if (!isGapAwareScene(scene) || scene.gaps === undefined) {
|
|
21
|
+
throw adapterError('/gaps', 'Gap-aware carrier requires a ChartScene v2 gaps array.');
|
|
22
|
+
}
|
|
23
|
+
const carriers = [];
|
|
24
|
+
let barIndex = 0;
|
|
25
|
+
let gapIndex = 0;
|
|
26
|
+
while (barIndex < scene.data.length || gapIndex < scene.gaps.length) {
|
|
27
|
+
const bar = scene.data[barIndex];
|
|
28
|
+
const gap = scene.gaps[gapIndex];
|
|
29
|
+
if (gap === undefined || (bar !== undefined && bar.timestamp < gap.timestamp)) {
|
|
30
|
+
const snapshot = structuredClone(bar);
|
|
31
|
+
carriers.push({
|
|
32
|
+
...snapshot,
|
|
33
|
+
__baronTimelineItem: { kind: 'bar', bar: snapshot },
|
|
34
|
+
});
|
|
35
|
+
barIndex += 1;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const snapshot = structuredClone(gap);
|
|
39
|
+
carriers.push({
|
|
40
|
+
timestamp: snapshot.timestamp,
|
|
41
|
+
open: 0,
|
|
42
|
+
high: 0,
|
|
43
|
+
low: 0,
|
|
44
|
+
close: 0,
|
|
45
|
+
volume: 0,
|
|
46
|
+
__baronTimelineItem: { kind: 'gap', gap: snapshot },
|
|
47
|
+
});
|
|
48
|
+
gapIndex += 1;
|
|
49
|
+
}
|
|
50
|
+
return carriers;
|
|
51
|
+
}
|
|
52
|
+
export function engineDataForScene(scene) {
|
|
53
|
+
return isGapAwareScene(scene)
|
|
54
|
+
? toGapAwareCarrierData(scene)
|
|
55
|
+
: structuredClone(scene.data);
|
|
56
|
+
}
|
|
57
|
+
export function timelineItemOf(data) {
|
|
58
|
+
return data?.__baronTimelineItem;
|
|
59
|
+
}
|
|
60
|
+
function directionOf(value) {
|
|
61
|
+
if (value.close > value.open) {
|
|
62
|
+
return 'up';
|
|
63
|
+
}
|
|
64
|
+
if (value.close < value.open) {
|
|
65
|
+
return 'down';
|
|
66
|
+
}
|
|
67
|
+
return 'flat';
|
|
68
|
+
}
|
|
69
|
+
function bodyColor(styles, direction) {
|
|
70
|
+
return direction === 'up'
|
|
71
|
+
? styles.upColor
|
|
72
|
+
: direction === 'down'
|
|
73
|
+
? styles.downColor
|
|
74
|
+
: styles.noChangeColor;
|
|
75
|
+
}
|
|
76
|
+
function wickColor(styles, direction) {
|
|
77
|
+
return direction === 'up'
|
|
78
|
+
? styles.upWickColor
|
|
79
|
+
: direction === 'down'
|
|
80
|
+
? styles.downWickColor
|
|
81
|
+
: styles.noChangeWickColor;
|
|
82
|
+
}
|
|
83
|
+
export const gapAwareCandleIndicatorTemplate = {
|
|
84
|
+
name: GAP_AWARE_CANDLE_INDICATOR_NAME,
|
|
85
|
+
shortName: '',
|
|
86
|
+
series: 'price',
|
|
87
|
+
shouldOhlc: false,
|
|
88
|
+
shouldFormatBigNumber: false,
|
|
89
|
+
figures: [
|
|
90
|
+
// 只参与 Y 轴范围计算;没有 type 就不会创建引擎 Figure。
|
|
91
|
+
{ key: 'low' },
|
|
92
|
+
{
|
|
93
|
+
key: 'high',
|
|
94
|
+
type: 'bar',
|
|
95
|
+
attrs({ data, coordinate, yAxis }) {
|
|
96
|
+
if (data.current == null || data.current.close === null) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const high = yAxis.convertToPixel(data.current.high);
|
|
100
|
+
const low = yAxis.convertToPixel(data.current.low);
|
|
101
|
+
return {
|
|
102
|
+
x: coordinate.current.x - 0.5,
|
|
103
|
+
y: Math.min(high, low),
|
|
104
|
+
width: 1,
|
|
105
|
+
height: Math.max(1, Math.abs(high - low)),
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
styles({ data, indicator }) {
|
|
109
|
+
if (data.current == null || data.current.close === null) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
style: 'fill',
|
|
114
|
+
color: wickColor(indicator.extendData, directionOf(data.current)),
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
key: 'close',
|
|
120
|
+
type: 'bar',
|
|
121
|
+
attrs({ data, coordinate, barSpace, yAxis }) {
|
|
122
|
+
if (data.current == null || data.current.close === null) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
const width = Math.max(1, barSpace.bar * 0.62);
|
|
126
|
+
const open = yAxis.convertToPixel(data.current.open);
|
|
127
|
+
const close = yAxis.convertToPixel(data.current.close);
|
|
128
|
+
const top = Math.min(open, close);
|
|
129
|
+
return {
|
|
130
|
+
x: coordinate.current.x - width / 2,
|
|
131
|
+
y: top,
|
|
132
|
+
width,
|
|
133
|
+
height: Math.max(1, Math.abs(open - close)),
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
styles({ data, indicator }) {
|
|
137
|
+
if (data.current == null || data.current.close === null) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
const color = bodyColor(indicator.extendData, directionOf(data.current));
|
|
141
|
+
return {
|
|
142
|
+
style: 'fill',
|
|
143
|
+
color,
|
|
144
|
+
borderColor: color,
|
|
145
|
+
borderSize: 0,
|
|
146
|
+
borderRadius: 0,
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
calc(dataList) {
|
|
152
|
+
return dataList.map((data) => {
|
|
153
|
+
const item = timelineItemOf(data);
|
|
154
|
+
if (item?.kind !== 'bar') {
|
|
155
|
+
return { open: null, high: null, low: null, close: null };
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
open: item.bar.open,
|
|
159
|
+
high: item.bar.high,
|
|
160
|
+
low: item.bar.low,
|
|
161
|
+
close: item.bar.close,
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
function indicatorCreate(scene) {
|
|
167
|
+
const candle = scene.chart.candle;
|
|
168
|
+
return {
|
|
169
|
+
id: GAP_AWARE_CANDLE_INDICATOR_ID,
|
|
170
|
+
name: GAP_AWARE_CANDLE_INDICATOR_NAME,
|
|
171
|
+
shortName: '',
|
|
172
|
+
paneId: GAP_AWARE_CANDLE_PANE_ID,
|
|
173
|
+
yAxisId: GAP_AWARE_CANDLE_Y_AXIS_ID,
|
|
174
|
+
precision: scene.symbol.pricePrecision,
|
|
175
|
+
visible: true,
|
|
176
|
+
zLevel: 0,
|
|
177
|
+
extendData: {
|
|
178
|
+
upColor: candle.upColor,
|
|
179
|
+
downColor: candle.downColor,
|
|
180
|
+
noChangeColor: candle.noChangeColor,
|
|
181
|
+
upWickColor: candle.upWickColor,
|
|
182
|
+
downWickColor: candle.downWickColor,
|
|
183
|
+
noChangeWickColor: candle.noChangeWickColor,
|
|
184
|
+
},
|
|
185
|
+
styles: {
|
|
186
|
+
lastValueMark: { show: false },
|
|
187
|
+
tooltip: { showRule: 'none' },
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/** 初始化仅绘制真实 Bar 的主序列;Gap 只保留横轴槽位。 */
|
|
192
|
+
export function installGapAwareMainSeries(scene, chart, registerIndicator) {
|
|
193
|
+
if (!isGapAwareScene(scene)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
assertGapAwareSceneSupported(scene);
|
|
197
|
+
registerIndicator(gapAwareCandleIndicatorTemplate);
|
|
198
|
+
const createdId = chart.createIndicator(indicatorCreate(scene), true);
|
|
199
|
+
if (createdId !== GAP_AWARE_CANDLE_INDICATOR_ID) {
|
|
200
|
+
throw adapterError('/gaps', 'KLineCharts failed to create the Gap-aware main series.');
|
|
201
|
+
}
|
|
202
|
+
chart.setPaneOptions({
|
|
203
|
+
id: 'candle_pane',
|
|
204
|
+
height: 0,
|
|
205
|
+
minHeight: 0,
|
|
206
|
+
order: scene.panes.length,
|
|
207
|
+
state: 'minimize',
|
|
208
|
+
dragEnabled: false,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
export function assertGapAwareSceneSupported(scene) {
|
|
212
|
+
if (!isGapAwareScene(scene)) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (scene.chart.candle.type !== 'candle_solid') {
|
|
216
|
+
throw adapterError('/chart/candle/type', 'ChartScene v2 MVP only supports the candle_solid gap-aware main series.');
|
|
217
|
+
}
|
|
218
|
+
if (scene.panes.some((pane) => pane.indicators.length > 0)) {
|
|
219
|
+
throw adapterError('/panes', 'ChartScene v2 indicators are disabled until their Gap semantics are implemented.');
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { DataLoader, DataLoaderGetBarsParams } from 'klinecharts';
|
|
1
|
+
import type { DataLoader, DataLoaderGetBarsParams, KLineData } from 'klinecharts';
|
|
3
2
|
export type StaticDataLoadType = DataLoaderGetBarsParams['type'];
|
|
4
3
|
/** 创建只读取场景内嵌行情的不可变数据加载器。 */
|
|
5
|
-
export declare function createStaticDataLoader(data: readonly
|
|
4
|
+
export declare function createStaticDataLoader(data: readonly KLineData[]): DataLoader;
|
|
6
5
|
//# sourceMappingURL=static-data-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-data-loader.d.ts","sourceRoot":"","sources":["../src/static-data-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"static-data-loader.d.ts","sourceRoot":"","sources":["../src/static-data-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,uBAAuB,EACvB,SAAS,EACT,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,kBAAkB,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAEjE,4BAA4B;AAC5B,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG,UAAU,CAU7E"}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baron1996/klinecharts-adapter",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.9",
|
|
4
4
|
"description": "Controlled ChartScene adapter for KLineCharts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@baron1996/kline-scene-schema": "0.
|
|
41
|
+
"@baron1996/kline-scene-schema": "0.9.9",
|
|
42
42
|
"klinecharts": "10.0.0"
|
|
43
43
|
}
|
|
44
44
|
}
|