@baron1996/klinecharts-adapter 0.2.3 → 0.3.0

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.
@@ -1,5 +1,7 @@
1
- import type { ChartConfig } from '@baron1996/kline-scene-schema';
1
+ import type { ChartConfig, TimeSeriesChartConfig } from '@baron1996/kline-scene-schema';
2
2
  import type { Options } from 'klinecharts';
3
3
  /** 将纯数据 ChartConfig 转换为受控的 KLineCharts 初始化选项。 */
4
4
  export declare function toKLineChartsOptions(chart: ChartConfig): Options;
5
+ /** 将 TimeSeriesChartConfig 转换为隐藏 Candle 的受控初始化选项。 */
6
+ export declare function toKLineChartsTimeSeriesOptions(chart: TimeSeriesChartConfig): Options;
5
7
  //# sourceMappingURL=chart-options.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-options.d.ts","sourceRoot":"","sources":["../../src/conversion/chart-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAGX,OAAO,EAEP,MAAM,aAAa,CAAC;AAmGrB,iDAAiD;AACjD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAiChE"}
1
+ {"version":3,"file":"chart-options.d.ts","sourceRoot":"","sources":["../../src/conversion/chart-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,WAAW,EACX,qBAAqB,EACrB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAGX,OAAO,EAEP,MAAM,aAAa,CAAC;AAyIrB,iDAAiD;AACjD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAiChE;AAED,qDAAqD;AACrD,wBAAgB,8BAA8B,CAC7C,KAAK,EAAE,qBAAqB,GAC1B,OAAO,CA+BT"}
@@ -86,6 +86,41 @@ function chartStyles(chart) {
86
86
  yAxis: { tickText: text },
87
87
  };
88
88
  }
89
+ function timeSeriesChartStyles(chart) {
90
+ const text = {
91
+ color: chart.layout.textColor,
92
+ size: chart.layout.fontSize,
93
+ family: chart.layout.fontFamily,
94
+ };
95
+ return {
96
+ grid: {
97
+ horizontal: { show: true, color: chart.grid.horizontalColor },
98
+ vertical: { show: true, color: chart.grid.verticalColor },
99
+ },
100
+ candle: {
101
+ type: 'area',
102
+ area: {
103
+ lineSize: 0,
104
+ lineColor: 'rgba(0, 0, 0, 0)',
105
+ backgroundColor: 'rgba(0, 0, 0, 0)',
106
+ point: { show: false, animation: false },
107
+ },
108
+ priceMark: {
109
+ show: false,
110
+ high: { show: false },
111
+ low: { show: false },
112
+ last: { show: false },
113
+ },
114
+ tooltip: { showRule: 'none' },
115
+ },
116
+ indicator: {
117
+ lastValueMark: { show: false },
118
+ tooltip: { showRule: 'none' },
119
+ },
120
+ xAxis: { tickText: text },
121
+ yAxis: { tickText: text },
122
+ };
123
+ }
89
124
  /** 将纯数据 ChartConfig 转换为受控的 KLineCharts 初始化选项。 */
90
125
  export function toKLineChartsOptions(chart) {
91
126
  return {
@@ -121,3 +156,33 @@ export function toKLineChartsOptions(chart) {
121
156
  },
122
157
  };
123
158
  }
159
+ /** 将 TimeSeriesChartConfig 转换为隐藏 Candle 的受控初始化选项。 */
160
+ export function toKLineChartsTimeSeriesOptions(chart) {
161
+ return {
162
+ locale: chart.locale,
163
+ timezone: chart.timezone,
164
+ styles: timeSeriesChartStyles(chart),
165
+ formatter: {
166
+ formatDate: (params) => formatDate(params, chart.dateFormat),
167
+ formatBigNumber: (value) => formatLargeNumber(value, chart.largeNumberFormat),
168
+ },
169
+ thousandsSeparator: { sign: chart.thousandsSeparator },
170
+ decimalFold: {
171
+ threshold: chart.decimalFold.threshold,
172
+ format: chart.decimalFold.enabled
173
+ ? (value) => {
174
+ const source = String(value);
175
+ const expression = new RegExp(`\\.0{${chart.decimalFold.threshold},}[1-9][0-9]*$`);
176
+ if (!expression.test(source)) {
177
+ return source;
178
+ }
179
+ const [integer, decimal = ''] = source.split('.');
180
+ const zeroCount = decimal.match(/^0*/)?.[0].length ?? 0;
181
+ return `${integer}.0{${zeroCount}}${decimal.slice(zeroCount)}`;
182
+ }
183
+ : (value) => String(value),
184
+ },
185
+ zoomAnchor: chart.zoomAnchor === 'right' ? 'last_bar' : 'cursor',
186
+ hotkey: { enabled: false, exclude: [] },
187
+ };
188
+ }
package/dist/index.d.ts CHANGED
@@ -6,5 +6,6 @@ export * from './interaction/hit-testing.js';
6
6
  export * from './registry/indicators.js';
7
7
  export * from './registry/overlays.js';
8
8
  export * from './static-data-loader.js';
9
+ export * from './time-series/adapter.js';
9
10
  export * from './version.js';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -6,4 +6,5 @@ export * from './interaction/hit-testing.js';
6
6
  export * from './registry/indicators.js';
7
7
  export * from './registry/overlays.js';
8
8
  export * from './static-data-loader.js';
9
+ export * from './time-series/adapter.js';
9
10
  export * from './version.js';
@@ -0,0 +1,18 @@
1
+ import type { TimeSeriesPoint, TimeSeriesScene } from '@baron1996/kline-scene-schema';
2
+ export interface TimeSeriesAdapterCrosshair {
3
+ readonly timestamp: number | null;
4
+ readonly values: Readonly<Record<string, number | null>> | null;
5
+ }
6
+ export type TimeSeriesAdapterCrosshairListener = (event: TimeSeriesAdapterCrosshair) => void;
7
+ /** TimeSeriesScene 与 KLineCharts 之间的唯一受控边界。 */
8
+ export declare class TimeSeriesChartsAdapter {
9
+ #private;
10
+ private constructor();
11
+ static create(container: HTMLElement, value: unknown): Promise<TimeSeriesChartsAdapter>;
12
+ subscribeCrosshair(listener: TimeSeriesAdapterCrosshairListener): () => void;
13
+ setSeriesVisible(seriesId: string, visible: boolean): TimeSeriesScene;
14
+ replaceData(data: readonly TimeSeriesPoint[]): TimeSeriesScene;
15
+ exportScene(): TimeSeriesScene;
16
+ dispose(): void;
17
+ }
18
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/time-series/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,eAAe,EACf,eAAe,EACf,MAAM,+BAA+B,CAAC;AAqBvC,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;CAChE;AAED,MAAM,MAAM,kCAAkC,GAAG,CAChD,KAAK,EAAE,0BAA0B,KAC7B,IAAI,CAAC;AAqFV,+CAA+C;AAC/C,qBAAa,uBAAuB;;IAoBnC,OAAO;WAwBa,MAAM,CACzB,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,OAAO,GACZ,OAAO,CAAC,uBAAuB,CAAC;IA4I5B,kBAAkB,CACxB,QAAQ,EAAE,kCAAkC,GAC1C,MAAM,IAAI;IAMN,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,eAAe;IAqCrE,WAAW,CAAC,IAAI,EAAE,SAAS,eAAe,EAAE,GAAG,eAAe;IA2C9D,WAAW,IAAI,eAAe;IAK9B,OAAO,IAAI,IAAI;CAgBtB"}
@@ -0,0 +1,301 @@
1
+ import { parseTimeSeriesScene, TimeSeriesSceneError, } from '@baron1996/kline-scene-schema';
2
+ import { toKLineChartsTimeSeriesOptions } from '../conversion/chart-options.js';
3
+ import { applyViewport } from '../conversion/viewport.js';
4
+ import { TIME_SERIES_INDICATOR_NAME, TIME_SERIES_PANE_ID, TIME_SERIES_Y_AXIS_ID, timeSeriesIndicatorTemplate, toTimeSeriesIndicatorCreate, } from './indicator.js';
5
+ function carrierData(data) {
6
+ return data.map(({ timestamp, values }) => ({
7
+ timestamp,
8
+ open: 0,
9
+ high: 0,
10
+ low: 0,
11
+ close: 0,
12
+ volume: 0,
13
+ __baronTimeSeriesValues: normalizeValues(values),
14
+ }));
15
+ }
16
+ function normalizeValues(values) {
17
+ const normalized = {};
18
+ for (const [seriesId, value] of Object.entries(values)) {
19
+ if (value === undefined) {
20
+ throw adapterError(`Time Series value ${seriesId} is undefined.`);
21
+ }
22
+ normalized[seriesId] = value;
23
+ }
24
+ return normalized;
25
+ }
26
+ function dataLoader(data) {
27
+ const snapshot = carrierData(data);
28
+ return {
29
+ getBars({ type, callback }) {
30
+ callback(type === 'init' ? structuredClone(snapshot) : [], {
31
+ forward: false,
32
+ backward: false,
33
+ });
34
+ },
35
+ };
36
+ }
37
+ function hasVisibleFiniteValue(scene) {
38
+ const visible = new Set(scene.series.filter((series) => series.visible).map((series) => series.id));
39
+ return scene.data.some((point) => Object.entries(point.values).some(([id, value]) => visible.has(id) && value !== null));
40
+ }
41
+ function adapterError(message) {
42
+ return new TimeSeriesSceneError('TIME_SERIES_ADAPTER_FAILED', '/runtime/adapter', message);
43
+ }
44
+ function dataError(error) {
45
+ const issues = error.issues.map((issue) => ({
46
+ ...issue,
47
+ code: 'TIME_SERIES_DATA_INVALID',
48
+ path: issue.path.startsWith('/data') ? issue.path : '/data',
49
+ }));
50
+ return new TimeSeriesSceneError('TIME_SERIES_DATA_INVALID', '/data', 'Time Series replacement data is invalid.', issues);
51
+ }
52
+ /** TimeSeriesScene 与 KLineCharts 之间的唯一受控边界。 */
53
+ export class TimeSeriesChartsAdapter {
54
+ /** KLineCharts 实例,只能在 Adapter 内使用。 */
55
+ #chart;
56
+ /** 引擎模块,用于版本检查和精确销毁。 */
57
+ #engine;
58
+ /** 当前可导出的规范化 Scene。 */
59
+ #scene;
60
+ /** 按时间戳索引的原始点,保证十字线查询为 O(1)。 */
61
+ #pointByTimestamp;
62
+ /** Adapter 独占的图表容器。 */
63
+ #container;
64
+ /** KLineCharts 交互根节点,用于补全离开绘图区事件。 */
65
+ #interactiveRoot;
66
+ /** 创建前容器背景,销毁后恢复。 */
67
+ #originalBackground;
68
+ /** 十字线纯数据监听器。 */
69
+ #crosshairListeners = new Set();
70
+ /** 防止重复销毁底层引擎。 */
71
+ #disposed = false;
72
+ constructor(container, scene, chart, engine, originalBackground, interactiveRoot) {
73
+ this.#container = container;
74
+ this.#scene = scene;
75
+ this.#pointByTimestamp = new Map(scene.data.map((point) => [point.timestamp, point]));
76
+ this.#chart = chart;
77
+ this.#engine = engine;
78
+ this.#originalBackground = originalBackground;
79
+ this.#interactiveRoot = interactiveRoot;
80
+ this.#chart.subscribeAction('onCrosshairChange', this.#handleCrosshair);
81
+ this.#interactiveRoot.addEventListener('pointerleave', this.#handlePointerLeave);
82
+ }
83
+ static async create(container, value) {
84
+ const scene = parseTimeSeriesScene(value);
85
+ const originalBackground = container.style.backgroundColor;
86
+ const engine = await import('klinecharts');
87
+ let chart = null;
88
+ try {
89
+ if (engine.version() !== scene.runtime.engineVersion) {
90
+ throw adapterError('KLineCharts engine version does not match the Scene.');
91
+ }
92
+ chart = engine.init(container, toKLineChartsTimeSeriesOptions(scene.chart));
93
+ if (chart === null) {
94
+ throw adapterError('KLineCharts returned null while initializing.');
95
+ }
96
+ const root = container.firstElementChild;
97
+ if (!(root instanceof HTMLElement)) {
98
+ throw adapterError('KLineCharts did not create an interactive root.');
99
+ }
100
+ root.style.touchAction = 'none';
101
+ chart.setSymbol({
102
+ ticker: '@baron1996/time-series-scene',
103
+ pricePrecision: scene.series[0].precision,
104
+ volumePrecision: 0,
105
+ });
106
+ chart.setPeriod(structuredClone(scene.period));
107
+ chart.setDataLoader(dataLoader(scene.data));
108
+ engine.registerIndicator(timeSeriesIndicatorTemplate);
109
+ for (const series of scene.series) {
110
+ const expectedId = `baron_time_series_${series.id}`;
111
+ const createdId = chart.createIndicator(toTimeSeriesIndicatorCreate(series), true);
112
+ if (createdId !== expectedId) {
113
+ throw adapterError(`KLineCharts failed to create series ${series.id}.`);
114
+ }
115
+ }
116
+ chart.setPaneOptions({
117
+ id: 'candle_pane',
118
+ height: 0,
119
+ minHeight: 0,
120
+ order: 0,
121
+ state: 'minimize',
122
+ dragEnabled: false,
123
+ });
124
+ chart.setPaneOptions({
125
+ id: TIME_SERIES_PANE_ID,
126
+ height: Math.max(container.clientHeight, 240),
127
+ minHeight: 120,
128
+ order: 1,
129
+ state: 'normal',
130
+ dragEnabled: false,
131
+ });
132
+ const adapter = new TimeSeriesChartsAdapter(container, scene, chart, engine, originalBackground, root);
133
+ adapter.#updateAxisVisibility();
134
+ applyViewport(chart, scene.viewport);
135
+ container.style.backgroundColor = scene.chart.layout.backgroundColor;
136
+ return adapter;
137
+ }
138
+ catch (error) {
139
+ if (chart !== null) {
140
+ engine.dispose(container);
141
+ }
142
+ container.replaceChildren();
143
+ container.style.backgroundColor = originalBackground;
144
+ if (error instanceof TimeSeriesSceneError) {
145
+ throw error;
146
+ }
147
+ throw adapterError('KLineCharts failed to initialize TimeSeriesScene.');
148
+ }
149
+ }
150
+ #assertActive() {
151
+ if (this.#disposed) {
152
+ throw adapterError('The Time Series Adapter has already been disposed.');
153
+ }
154
+ }
155
+ #updateAxisVisibility() {
156
+ const hasValues = hasVisibleFiniteValue(this.#scene);
157
+ this.#chart.overrideYAxis({
158
+ id: TIME_SERIES_Y_AXIS_ID,
159
+ paneId: TIME_SERIES_PANE_ID,
160
+ name: 'normal',
161
+ position: 'right',
162
+ inside: false,
163
+ scrollZoomEnabled: false,
164
+ gap: { top: 0.12, bottom: 0.08 },
165
+ needWidget: hasValues,
166
+ createTicks: ({ defaultTicks }) => hasValues ? defaultTicks : [],
167
+ });
168
+ }
169
+ #handleCrosshair = (value) => {
170
+ if (this.#disposed) {
171
+ return;
172
+ }
173
+ let timestamp = null;
174
+ if (value !== null && typeof value === 'object') {
175
+ if ('timestamp' in value && typeof value.timestamp === 'number') {
176
+ timestamp = value.timestamp;
177
+ }
178
+ else if ('x' in value && typeof value.x === 'number') {
179
+ const converted = this.#chart.convertFromPixel([{ x: value.x, y: 0 }], {
180
+ paneId: TIME_SERIES_PANE_ID,
181
+ yAxisId: TIME_SERIES_Y_AXIS_ID,
182
+ });
183
+ const point = Array.isArray(converted) ? converted[0] : converted;
184
+ timestamp = typeof point?.timestamp === 'number'
185
+ ? point.timestamp
186
+ : null;
187
+ }
188
+ }
189
+ const point = timestamp === null
190
+ ? undefined
191
+ : this.#pointByTimestamp.get(timestamp);
192
+ const event = point === undefined
193
+ ? { timestamp: null, values: null }
194
+ : { timestamp: point.timestamp, values: normalizeValues(point.values) };
195
+ for (const listener of this.#crosshairListeners) {
196
+ listener(structuredClone(event));
197
+ }
198
+ };
199
+ #handlePointerLeave = () => {
200
+ if (this.#disposed) {
201
+ return;
202
+ }
203
+ for (const listener of this.#crosshairListeners) {
204
+ listener({ timestamp: null, values: null });
205
+ }
206
+ };
207
+ subscribeCrosshair(listener) {
208
+ this.#assertActive();
209
+ this.#crosshairListeners.add(listener);
210
+ return () => this.#crosshairListeners.delete(listener);
211
+ }
212
+ setSeriesVisible(seriesId, visible) {
213
+ this.#assertActive();
214
+ const index = this.#scene.series.findIndex((series) => series.id === seriesId);
215
+ if (index < 0) {
216
+ throw new TimeSeriesSceneError('TIME_SERIES_UNKNOWN_SERIES', '/series', `Unknown time series: ${seriesId}.`);
217
+ }
218
+ const series = structuredClone(this.#scene.series);
219
+ series[index] = { ...series[index], visible };
220
+ const candidate = parseTimeSeriesScene({
221
+ ...structuredClone(this.#scene),
222
+ series,
223
+ });
224
+ const indicatorId = `baron_time_series_${seriesId}`;
225
+ const matches = this.#chart.getIndicators({ id: indicatorId });
226
+ if (matches.length !== 1) {
227
+ throw adapterError(`KLineCharts retained ${matches.length} indicators for series ${seriesId}.`);
228
+ }
229
+ this.#chart.overrideIndicator({
230
+ id: indicatorId,
231
+ name: TIME_SERIES_INDICATOR_NAME,
232
+ visible,
233
+ });
234
+ const afterVisible = this.#chart.getIndicators({ id: indicatorId })[0]?.visible;
235
+ if (afterVisible !== visible) {
236
+ throw adapterError(`KLineCharts failed to update series ${seriesId}.`);
237
+ }
238
+ this.#scene = candidate;
239
+ this.#updateAxisVisibility();
240
+ return structuredClone(candidate);
241
+ }
242
+ replaceData(data) {
243
+ this.#assertActive();
244
+ const last = data.at(-1);
245
+ let candidate;
246
+ try {
247
+ candidate = parseTimeSeriesScene({
248
+ ...structuredClone(this.#scene),
249
+ data: structuredClone(data),
250
+ viewport: {
251
+ ...structuredClone(this.#scene.viewport),
252
+ anchorTimestamp: last?.timestamp,
253
+ },
254
+ });
255
+ }
256
+ catch (error) {
257
+ throw error instanceof TimeSeriesSceneError
258
+ ? dataError(error)
259
+ : adapterError('Time Series replacement data validation failed.');
260
+ }
261
+ const previous = this.#scene;
262
+ const previousPointByTimestamp = this.#pointByTimestamp;
263
+ const candidatePointByTimestamp = new Map(candidate.data.map((point) => [point.timestamp, point]));
264
+ try {
265
+ this.#chart.setDataLoader(dataLoader(candidate.data));
266
+ this.#chart.resetData();
267
+ this.#scene = candidate;
268
+ this.#pointByTimestamp = candidatePointByTimestamp;
269
+ this.#updateAxisVisibility();
270
+ applyViewport(this.#chart, candidate.viewport);
271
+ return structuredClone(candidate);
272
+ }
273
+ catch (error) {
274
+ this.#chart.setDataLoader(dataLoader(previous.data));
275
+ this.#chart.resetData();
276
+ this.#scene = previous;
277
+ this.#pointByTimestamp = previousPointByTimestamp;
278
+ this.#updateAxisVisibility();
279
+ throw error instanceof TimeSeriesSceneError
280
+ ? error
281
+ : adapterError('KLineCharts failed to replace Time Series data.');
282
+ }
283
+ }
284
+ exportScene() {
285
+ this.#assertActive();
286
+ return parseTimeSeriesScene(structuredClone(this.#scene));
287
+ }
288
+ dispose() {
289
+ if (this.#disposed) {
290
+ return;
291
+ }
292
+ this.#disposed = true;
293
+ this.#chart.unsubscribeAction('onCrosshairChange', this.#handleCrosshair);
294
+ this.#interactiveRoot.removeEventListener('pointerleave', this.#handlePointerLeave);
295
+ this.#crosshairListeners.clear();
296
+ this.#pointByTimestamp.clear();
297
+ this.#engine.dispose(this.#container);
298
+ this.#container.replaceChildren();
299
+ this.#container.style.backgroundColor = this.#originalBackground;
300
+ }
301
+ }
@@ -0,0 +1,15 @@
1
+ import type { TimeSeriesDefinition } from '@baron1996/kline-scene-schema';
2
+ import type { IndicatorCreate, IndicatorTemplate } from 'klinecharts';
3
+ export declare const TIME_SERIES_INDICATOR_NAME = "BARON_TIME_SERIES_LINE";
4
+ export declare const TIME_SERIES_PANE_ID = "baron_time_series_pane";
5
+ export declare const TIME_SERIES_Y_AXIS_ID = "baron_time_series_y_axis";
6
+ interface TimeSeriesIndicatorResult {
7
+ readonly value: number | null;
8
+ }
9
+ interface TimeSeriesIndicatorExtendData {
10
+ readonly seriesId: string;
11
+ }
12
+ export declare const timeSeriesIndicatorTemplate: IndicatorTemplate<TimeSeriesIndicatorResult, never, TimeSeriesIndicatorExtendData>;
13
+ export declare function toTimeSeriesIndicatorCreate(series: TimeSeriesDefinition): IndicatorCreate;
14
+ export {};
15
+ //# sourceMappingURL=indicator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indicator.d.ts","sourceRoot":"","sources":["../../src/time-series/indicator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EACX,eAAe,EACf,iBAAiB,EAEjB,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AACnE,eAAO,MAAM,mBAAmB,2BAA2B,CAAC;AAC5D,eAAO,MAAM,qBAAqB,6BAA6B,CAAC;AAMhE,UAAU,yBAAyB;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,UAAU,6BAA6B;IACtC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC1B;AAYD,eAAO,MAAM,2BAA2B,EAAE,iBAAiB,CAC1D,yBAAyB,EACzB,KAAK,EACL,6BAA6B,CA2B7B,CAAC;AAEF,wBAAgB,2BAA2B,CAC1C,MAAM,EAAE,oBAAoB,GAC1B,eAAe,CAiBjB"}
@@ -0,0 +1,56 @@
1
+ export const TIME_SERIES_INDICATOR_NAME = 'BARON_TIME_SERIES_LINE';
2
+ export const TIME_SERIES_PANE_ID = 'baron_time_series_pane';
3
+ export const TIME_SERIES_Y_AXIS_ID = 'baron_time_series_y_axis';
4
+ function lineStyle(style) {
5
+ return {
6
+ color: style.color,
7
+ size: style.size,
8
+ style: style.style === 'solid' ? 'solid' : 'dashed',
9
+ dashedValue: style.style === 'dotted' ? [1, 2] : [4, 4],
10
+ smooth: false,
11
+ };
12
+ }
13
+ export const timeSeriesIndicatorTemplate = {
14
+ name: TIME_SERIES_INDICATOR_NAME,
15
+ shortName: '',
16
+ series: 'normal',
17
+ shouldOhlc: false,
18
+ shouldFormatBigNumber: false,
19
+ figures: [{ key: 'value', type: 'line' }],
20
+ shouldUpdate(previous, current) {
21
+ const shouldCalculate = previous.extendData.seriesId !== current.extendData.seriesId ||
22
+ previous.visible !== current.visible;
23
+ return {
24
+ calc: shouldCalculate,
25
+ draw: shouldCalculate || previous.visible !== current.visible,
26
+ };
27
+ },
28
+ calc(dataList, indicator) {
29
+ if (!indicator.visible) {
30
+ return dataList.map(() => ({ value: null }));
31
+ }
32
+ const seriesId = indicator.extendData.seriesId;
33
+ return dataList.map((bar) => {
34
+ const values = bar.__baronTimeSeriesValues;
35
+ return { value: values[seriesId] ?? null };
36
+ });
37
+ },
38
+ };
39
+ export function toTimeSeriesIndicatorCreate(series) {
40
+ return {
41
+ id: `baron_time_series_${series.id}`,
42
+ name: TIME_SERIES_INDICATOR_NAME,
43
+ shortName: series.name,
44
+ paneId: TIME_SERIES_PANE_ID,
45
+ yAxisId: TIME_SERIES_Y_AXIS_ID,
46
+ precision: series.precision,
47
+ visible: series.visible,
48
+ zLevel: 0,
49
+ extendData: { seriesId: series.id },
50
+ styles: {
51
+ lines: [lineStyle(series.style)],
52
+ lastValueMark: { show: false },
53
+ tooltip: { showRule: 'none' },
54
+ },
55
+ };
56
+ }
package/dist/version.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** Adapter 包版本。 */
2
- export declare const ADAPTER_PACKAGE_VERSION: "0.2.3";
2
+ export declare const ADAPTER_PACKAGE_VERSION: "0.3.0";
3
3
  /** 唯一允许加载的 KLineCharts 引擎版本。 */
4
4
  export declare const KLINECHARTS_ENGINE_VERSION: "10.0.0";
5
5
  /** 与 ChartScene 绑定的 Runtime 协议版本。 */
package/dist/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /** Adapter 包版本。 */
2
- export const ADAPTER_PACKAGE_VERSION = '0.2.3';
2
+ export const ADAPTER_PACKAGE_VERSION = '0.3.0';
3
3
  /** 唯一允许加载的 KLineCharts 引擎版本。 */
4
4
  export const KLINECHARTS_ENGINE_VERSION = '10.0.0';
5
5
  /** 与 ChartScene 绑定的 Runtime 协议版本。 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baron1996/klinecharts-adapter",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
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.2.3",
41
+ "@baron1996/kline-scene-schema": "0.3.0",
42
42
  "klinecharts": "10.0.0"
43
43
  }
44
44
  }