@baron1996/klinecharts-adapter 0.2.3 → 0.4.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.
- package/dist/adapter.d.ts +27 -2
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +638 -26
- package/dist/conversion/chart-options.d.ts +3 -1
- package/dist/conversion/chart-options.d.ts.map +1 -1
- package/dist/conversion/chart-options.js +71 -0
- package/dist/conversion/overlays.d.ts +2 -1
- package/dist/conversion/overlays.d.ts.map +1 -1
- package/dist/conversion/overlays.js +1 -1
- package/dist/conversion/price.d.ts.map +1 -1
- package/dist/conversion/price.js +10 -39
- package/dist/drawing/engine-port.d.ts +71 -0
- package/dist/drawing/engine-port.d.ts.map +1 -0
- package/dist/drawing/engine-port.js +1 -0
- package/dist/drawing/interaction-normalization.d.ts +18 -0
- package/dist/drawing/interaction-normalization.d.ts.map +1 -0
- package/dist/drawing/interaction-normalization.js +61 -0
- package/dist/drawing/kline-projection-policy.d.ts +8 -0
- package/dist/drawing/kline-projection-policy.d.ts.map +1 -0
- package/dist/drawing/kline-projection-policy.js +69 -0
- package/dist/drawing/overlay-conversion.d.ts +9 -0
- package/dist/drawing/overlay-conversion.d.ts.map +1 -0
- package/dist/drawing/overlay-conversion.js +245 -0
- package/dist/drawing/projection-policy.d.ts +34 -0
- package/dist/drawing/projection-policy.d.ts.map +1 -0
- package/dist/drawing/projection-policy.js +10 -0
- package/dist/drawing/time-series-projection-policy.d.ts +6 -0
- package/dist/drawing/time-series-projection-policy.d.ts.map +1 -0
- package/dist/drawing/time-series-projection-policy.js +28 -0
- package/dist/extensions/price-measurement.d.ts +1 -1
- package/dist/extensions/price-measurement.d.ts.map +1 -1
- package/dist/extensions/price-measurement.js +8 -2
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/main-series-presentation.d.ts +35 -0
- package/dist/main-series-presentation.d.ts.map +1 -0
- package/dist/main-series-presentation.js +52 -0
- package/dist/time-series/adapter.d.ts +41 -0
- package/dist/time-series/adapter.d.ts.map +1 -0
- package/dist/time-series/adapter.js +1189 -0
- package/dist/time-series/indicator.d.ts +15 -0
- package/dist/time-series/indicator.d.ts.map +1 -0
- package/dist/time-series/indicator.js +56 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drawing 业务几何 ↔ 旧 SceneOverlay 兼容几何的纯数据映射。
|
|
3
|
+
* 不写回 dataIndex、paneId、yAxisId 或任何引擎内部 ID。
|
|
4
|
+
*/
|
|
5
|
+
export function drawingToSceneOverlay(drawing, paneId) {
|
|
6
|
+
const base = {
|
|
7
|
+
id: drawing.id,
|
|
8
|
+
type: drawing.type,
|
|
9
|
+
paneId,
|
|
10
|
+
visible: drawing.visible,
|
|
11
|
+
locked: drawing.locked,
|
|
12
|
+
zLevel: drawing.zLevel,
|
|
13
|
+
mode: drawing.mode,
|
|
14
|
+
styles: structuredClone(drawing.styles),
|
|
15
|
+
};
|
|
16
|
+
if (drawing.groupId !== undefined) {
|
|
17
|
+
base.groupId = drawing.groupId;
|
|
18
|
+
}
|
|
19
|
+
if (drawing.metadata !== undefined) {
|
|
20
|
+
base.metadata = structuredClone(drawing.metadata);
|
|
21
|
+
}
|
|
22
|
+
switch (drawing.type) {
|
|
23
|
+
case 'horizontalStraightLine':
|
|
24
|
+
case 'priceLine':
|
|
25
|
+
return { ...base, anchor: { value: drawing.geometry.value } };
|
|
26
|
+
case 'simpleTag':
|
|
27
|
+
return {
|
|
28
|
+
...base,
|
|
29
|
+
anchor: { value: drawing.geometry.value },
|
|
30
|
+
text: drawing.geometry.text,
|
|
31
|
+
};
|
|
32
|
+
case 'verticalStraightLine':
|
|
33
|
+
return { ...base, anchor: { timestamp: drawing.geometry.time } };
|
|
34
|
+
case 'horizontalRayLine':
|
|
35
|
+
case 'horizontalSegment':
|
|
36
|
+
return {
|
|
37
|
+
...base,
|
|
38
|
+
value: drawing.geometry.value,
|
|
39
|
+
startTimestamp: drawing.geometry.startTime,
|
|
40
|
+
endTimestamp: drawing.geometry.endTime,
|
|
41
|
+
};
|
|
42
|
+
case 'verticalRayLine':
|
|
43
|
+
case 'verticalSegment':
|
|
44
|
+
return {
|
|
45
|
+
...base,
|
|
46
|
+
timestamp: drawing.geometry.time,
|
|
47
|
+
startValue: drawing.geometry.startValue,
|
|
48
|
+
endValue: drawing.geometry.endValue,
|
|
49
|
+
};
|
|
50
|
+
case 'rayLine':
|
|
51
|
+
case 'segment':
|
|
52
|
+
case 'straightLine':
|
|
53
|
+
case 'fibonacciLine':
|
|
54
|
+
case 'priceChannelLine':
|
|
55
|
+
case 'parallelStraightLine':
|
|
56
|
+
case 'brush':
|
|
57
|
+
return {
|
|
58
|
+
...base,
|
|
59
|
+
points: drawing.geometry.points.map((point) => ({
|
|
60
|
+
timestamp: point.timestamp,
|
|
61
|
+
value: point.value,
|
|
62
|
+
})),
|
|
63
|
+
};
|
|
64
|
+
case 'simpleAnnotation':
|
|
65
|
+
case 'callout':
|
|
66
|
+
case 'text':
|
|
67
|
+
return {
|
|
68
|
+
...base,
|
|
69
|
+
point: {
|
|
70
|
+
timestamp: drawing.geometry.point.timestamp,
|
|
71
|
+
value: drawing.geometry.point.value,
|
|
72
|
+
},
|
|
73
|
+
text: drawing.geometry.text,
|
|
74
|
+
};
|
|
75
|
+
case 'crossLine':
|
|
76
|
+
return {
|
|
77
|
+
...base,
|
|
78
|
+
point: {
|
|
79
|
+
timestamp: drawing.geometry.point.timestamp,
|
|
80
|
+
value: drawing.geometry.point.value,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
case 'rectangle':
|
|
84
|
+
case 'arrow':
|
|
85
|
+
case 'priceMeasurement':
|
|
86
|
+
return {
|
|
87
|
+
...base,
|
|
88
|
+
start: {
|
|
89
|
+
timestamp: drawing.geometry.start.timestamp,
|
|
90
|
+
value: drawing.geometry.start.value,
|
|
91
|
+
},
|
|
92
|
+
end: {
|
|
93
|
+
timestamp: drawing.geometry.end.timestamp,
|
|
94
|
+
value: drawing.geometry.end.value,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function drawingText(drawing) {
|
|
100
|
+
switch (drawing.type) {
|
|
101
|
+
case 'simpleTag':
|
|
102
|
+
case 'simpleAnnotation':
|
|
103
|
+
case 'callout':
|
|
104
|
+
case 'text':
|
|
105
|
+
return drawing.geometry.text;
|
|
106
|
+
default:
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** 用引擎归一化后的 SceneOverlay 几何重建 Drawing;granularity 从源 Drawing 恢复。 */
|
|
111
|
+
export function sceneOverlayToDrawing(overlay, source) {
|
|
112
|
+
const text = overlay.type === 'simpleTag'
|
|
113
|
+
|| overlay.type === 'simpleAnnotation'
|
|
114
|
+
|| overlay.type === 'callout'
|
|
115
|
+
|| overlay.type === 'text'
|
|
116
|
+
? overlay.text
|
|
117
|
+
: drawingText(source);
|
|
118
|
+
const result = {
|
|
119
|
+
id: overlay.id,
|
|
120
|
+
target: structuredClone(source.target),
|
|
121
|
+
visible: overlay.visible,
|
|
122
|
+
locked: overlay.locked,
|
|
123
|
+
zLevel: overlay.zLevel,
|
|
124
|
+
mode: overlay.mode,
|
|
125
|
+
styles: structuredClone(overlay.styles),
|
|
126
|
+
type: overlay.type,
|
|
127
|
+
};
|
|
128
|
+
if (overlay.groupId !== undefined) {
|
|
129
|
+
result.groupId = overlay.groupId;
|
|
130
|
+
}
|
|
131
|
+
if (overlay.metadata !== undefined) {
|
|
132
|
+
result.metadata = structuredClone(overlay.metadata);
|
|
133
|
+
}
|
|
134
|
+
switch (overlay.type) {
|
|
135
|
+
case 'horizontalStraightLine':
|
|
136
|
+
case 'priceLine':
|
|
137
|
+
result.geometry = { value: overlay.anchor.value };
|
|
138
|
+
break;
|
|
139
|
+
case 'simpleTag':
|
|
140
|
+
result.geometry = {
|
|
141
|
+
value: overlay.anchor.value,
|
|
142
|
+
text: overlay.text ?? '',
|
|
143
|
+
};
|
|
144
|
+
break;
|
|
145
|
+
case 'verticalStraightLine':
|
|
146
|
+
result.geometry = {
|
|
147
|
+
time: overlay.anchor.timestamp,
|
|
148
|
+
};
|
|
149
|
+
break;
|
|
150
|
+
case 'horizontalRayLine':
|
|
151
|
+
case 'horizontalSegment':
|
|
152
|
+
result.geometry = {
|
|
153
|
+
value: overlay.value,
|
|
154
|
+
startTime: overlay.startTimestamp,
|
|
155
|
+
endTime: overlay.endTimestamp,
|
|
156
|
+
};
|
|
157
|
+
break;
|
|
158
|
+
case 'verticalRayLine':
|
|
159
|
+
case 'verticalSegment':
|
|
160
|
+
result.geometry = {
|
|
161
|
+
time: overlay.timestamp,
|
|
162
|
+
startValue: overlay.startValue,
|
|
163
|
+
endValue: overlay.endValue,
|
|
164
|
+
};
|
|
165
|
+
break;
|
|
166
|
+
case 'rayLine':
|
|
167
|
+
case 'segment':
|
|
168
|
+
case 'straightLine':
|
|
169
|
+
case 'fibonacciLine':
|
|
170
|
+
case 'priceChannelLine':
|
|
171
|
+
case 'parallelStraightLine':
|
|
172
|
+
case 'brush':
|
|
173
|
+
result.geometry = {
|
|
174
|
+
points: overlay.points.map((point, index) => ({
|
|
175
|
+
timestamp: point.timestamp,
|
|
176
|
+
value: point.value,
|
|
177
|
+
granularity: structuredClone(pointGranularity(source, index)),
|
|
178
|
+
})),
|
|
179
|
+
};
|
|
180
|
+
break;
|
|
181
|
+
case 'simpleAnnotation':
|
|
182
|
+
case 'callout':
|
|
183
|
+
case 'text':
|
|
184
|
+
result.geometry = {
|
|
185
|
+
point: {
|
|
186
|
+
timestamp: overlay.point.timestamp,
|
|
187
|
+
value: overlay.point.value,
|
|
188
|
+
granularity: structuredClone(pointGranularity(source, 0)),
|
|
189
|
+
},
|
|
190
|
+
text: overlay.text ?? '',
|
|
191
|
+
};
|
|
192
|
+
break;
|
|
193
|
+
case 'crossLine':
|
|
194
|
+
result.geometry = {
|
|
195
|
+
point: {
|
|
196
|
+
timestamp: overlay.point.timestamp,
|
|
197
|
+
value: overlay.point.value,
|
|
198
|
+
granularity: structuredClone(pointGranularity(source, 0)),
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
break;
|
|
202
|
+
case 'rectangle':
|
|
203
|
+
case 'arrow':
|
|
204
|
+
case 'priceMeasurement':
|
|
205
|
+
result.geometry = {
|
|
206
|
+
start: {
|
|
207
|
+
timestamp: overlay.start.timestamp,
|
|
208
|
+
value: overlay.start.value,
|
|
209
|
+
granularity: structuredClone(pointGranularity(source, 0)),
|
|
210
|
+
},
|
|
211
|
+
end: {
|
|
212
|
+
timestamp: overlay.end.timestamp,
|
|
213
|
+
value: overlay.end.value,
|
|
214
|
+
granularity: structuredClone(pointGranularity(source, 1)),
|
|
215
|
+
},
|
|
216
|
+
};
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
function pointGranularity(source, index) {
|
|
222
|
+
if (source.type === 'rayLine' ||
|
|
223
|
+
source.type === 'segment' ||
|
|
224
|
+
source.type === 'straightLine' ||
|
|
225
|
+
source.type === 'fibonacciLine' ||
|
|
226
|
+
source.type === 'priceChannelLine' ||
|
|
227
|
+
source.type === 'parallelStraightLine' ||
|
|
228
|
+
source.type === 'brush') {
|
|
229
|
+
const point = source.geometry.points[index] ?? source.geometry.points[0];
|
|
230
|
+
return structuredClone(point?.granularity ?? { type: 'day', span: 1 });
|
|
231
|
+
}
|
|
232
|
+
if (source.type === 'simpleAnnotation' ||
|
|
233
|
+
source.type === 'callout' ||
|
|
234
|
+
source.type === 'text' ||
|
|
235
|
+
source.type === 'crossLine') {
|
|
236
|
+
return structuredClone(source.geometry.point.granularity);
|
|
237
|
+
}
|
|
238
|
+
if (source.type === 'rectangle' ||
|
|
239
|
+
source.type === 'arrow' ||
|
|
240
|
+
source.type === 'priceMeasurement') {
|
|
241
|
+
const anchor = index === 0 ? source.geometry.start : source.geometry.end;
|
|
242
|
+
return structuredClone(anchor.granularity);
|
|
243
|
+
}
|
|
244
|
+
return { type: 'day', span: 1 };
|
|
245
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ChartScene, Drawing, TimeSeriesScene, ValueAxis } from '@baron1996/kline-scene-schema';
|
|
2
|
+
export type DrawingProjectionErrorCode = 'DRAWING_TARGET_INVALID' | 'DRAWING_PROJECTION_INVALID' | 'VALUE_AXIS_SCALE_UNSUPPORTED';
|
|
3
|
+
export declare class DrawingProjectionError extends Error {
|
|
4
|
+
readonly code: DrawingProjectionErrorCode;
|
|
5
|
+
readonly path: string;
|
|
6
|
+
constructor(code: DrawingProjectionErrorCode, path: string, message: string);
|
|
7
|
+
}
|
|
8
|
+
export type ProjectionScene = {
|
|
9
|
+
readonly kind: 'chart';
|
|
10
|
+
readonly document: ChartScene;
|
|
11
|
+
} | {
|
|
12
|
+
readonly kind: 'time-series';
|
|
13
|
+
readonly document: TimeSeriesScene;
|
|
14
|
+
};
|
|
15
|
+
export interface ResolvedAxisBinding {
|
|
16
|
+
readonly paneRole: string;
|
|
17
|
+
readonly yAxisRole: 'primary';
|
|
18
|
+
readonly valuePrecision: number;
|
|
19
|
+
readonly scale: 'linear' | 'logarithmic';
|
|
20
|
+
}
|
|
21
|
+
export interface ResolveAxisBindingInput {
|
|
22
|
+
readonly scene: ProjectionScene;
|
|
23
|
+
readonly drawing: Drawing;
|
|
24
|
+
readonly valueAxes: readonly ValueAxis[];
|
|
25
|
+
readonly path: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 纯 Drawing 轴绑定策略:只解析 paneRole/yAxisRole/valuePrecision/scale,
|
|
29
|
+
* 不持有引擎、不实现时间/几何算法,不接收引擎实例或像素输入。
|
|
30
|
+
*/
|
|
31
|
+
export interface DrawingProjectionPolicy {
|
|
32
|
+
resolveAxisBinding(input: ResolveAxisBindingInput): ResolvedAxisBinding;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=projection-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection-policy.d.ts","sourceRoot":"","sources":["../../src/drawing/projection-policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,OAAO,EACP,eAAe,EACf,SAAS,EACT,MAAM,+BAA+B,CAAC;AAEvC,MAAM,MAAM,0BAA0B,GACnC,wBAAwB,GACxB,4BAA4B,GAC5B,8BAA8B,CAAC;AAElC,qBAAa,sBAAuB,SAAQ,KAAK;IAChD,SAAgB,IAAI,EAAE,0BAA0B,CAAC;IACjD,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,0BAA0B,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAMlF;AAED,MAAM,MAAM,eAAe,GACxB;IACA,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;CAC7B,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CAClC,CAAC;AAEL,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,aAAa,CAAC;CACzC;AAED,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,SAAS,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACvC,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,mBAAmB,CAAC;CACxE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type DrawingProjectionPolicy, type ResolveAxisBindingInput, type ResolvedAxisBinding } from './projection-policy.js';
|
|
2
|
+
/** 时间序列场景薄绑定策略;只接受公共 time-series / primary 轴。 */
|
|
3
|
+
export declare class TimeSeriesDrawingProjectionPolicy implements DrawingProjectionPolicy {
|
|
4
|
+
resolveAxisBinding(input: ResolveAxisBindingInput): ResolvedAxisBinding;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=time-series-projection-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-series-projection-policy.d.ts","sourceRoot":"","sources":["../../src/drawing/time-series-projection-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,MAAM,wBAAwB,CAAC;AAEhC,iDAAiD;AACjD,qBAAa,iCAAkC,YAAW,uBAAuB;IACzE,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,GAAG,mBAAmB;CA2C9E"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DrawingProjectionError, } from './projection-policy.js';
|
|
2
|
+
/** 时间序列场景薄绑定策略;只接受公共 time-series / primary 轴。 */
|
|
3
|
+
export class TimeSeriesDrawingProjectionPolicy {
|
|
4
|
+
resolveAxisBinding(input) {
|
|
5
|
+
const { scene, drawing, valueAxes, path } = input;
|
|
6
|
+
if (scene.kind !== 'time-series') {
|
|
7
|
+
throw new DrawingProjectionError('DRAWING_PROJECTION_INVALID', path, 'TimeSeriesDrawingProjectionPolicy requires a time-series Scene.');
|
|
8
|
+
}
|
|
9
|
+
const target = drawing.target;
|
|
10
|
+
if (target.paneRole !== 'time-series' ||
|
|
11
|
+
target.yAxisRole !== 'primary') {
|
|
12
|
+
throw new DrawingProjectionError('DRAWING_TARGET_INVALID', `${path}/target`, 'TimeSeries drawings must target time-series / primary.');
|
|
13
|
+
}
|
|
14
|
+
const sharedPrecision = scene.document.series[0]?.precision;
|
|
15
|
+
const axis = valueAxes.find((candidate) => candidate.paneRole === 'time-series' &&
|
|
16
|
+
candidate.yAxisRole === 'primary');
|
|
17
|
+
if (axis === undefined ||
|
|
18
|
+
axis.valuePrecision !== sharedPrecision) {
|
|
19
|
+
throw new DrawingProjectionError('DRAWING_TARGET_INVALID', `${path}/target`, 'TimeSeries primary binding precision must equal the shared series precision.');
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
paneRole: 'time-series',
|
|
23
|
+
yAxisRole: 'primary',
|
|
24
|
+
valuePrecision: axis.valuePrecision,
|
|
25
|
+
scale: 'linear',
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -2,7 +2,7 @@ import type { registerOverlay } from 'klinecharts';
|
|
|
2
2
|
type KLineOverlayTemplate = Parameters<typeof registerOverlay>[0];
|
|
3
3
|
export interface PriceMeasurementDisplay {
|
|
4
4
|
readonly absoluteChange: number;
|
|
5
|
-
readonly percentageChange: number;
|
|
5
|
+
readonly percentageChange: number | null;
|
|
6
6
|
readonly label: string;
|
|
7
7
|
}
|
|
8
8
|
/** 仅派生显示值;绝对变化、百分比和 label 永不写入 Scene。 */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"price-measurement.d.ts","sourceRoot":"","sources":["../../src/extensions/price-measurement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AAOlE,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"price-measurement.d.ts","sourceRoot":"","sources":["../../src/extensions/price-measurement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;AAOlE,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED,yCAAyC;AACzC,wBAAgB,6BAA6B,CAC5C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACpB,uBAAuB,CA4BzB;AAED,wCAAwC;AACxC,eAAO,MAAM,uBAAuB,EAAE,oBA6CrC,CAAC"}
|
|
@@ -7,13 +7,19 @@ function signedFixed(value, precision) {
|
|
|
7
7
|
export function derivePriceMeasurementDisplay(startValue, endValue, pricePrecision) {
|
|
8
8
|
if (!Number.isFinite(startValue) ||
|
|
9
9
|
!Number.isFinite(endValue) ||
|
|
10
|
-
startValue <= 0 ||
|
|
11
10
|
!Number.isInteger(pricePrecision) ||
|
|
12
11
|
pricePrecision < 0 ||
|
|
13
12
|
pricePrecision > 16) {
|
|
14
|
-
throw new SceneError('SCENE_SCHEMA_INVALID', '/overlays/priceMeasurement', 'Price measurement display inputs must be
|
|
13
|
+
throw new SceneError('SCENE_SCHEMA_INVALID', '/overlays/priceMeasurement', 'Price measurement display inputs must be finite numbers and a 0..16 precision.');
|
|
15
14
|
}
|
|
16
15
|
const absoluteChange = endValue - startValue;
|
|
16
|
+
if (startValue === 0) {
|
|
17
|
+
return {
|
|
18
|
+
absoluteChange,
|
|
19
|
+
percentageChange: null,
|
|
20
|
+
label: `${signedFixed(absoluteChange, pricePrecision)} (—%)`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
17
23
|
const percentageChange = absoluteChange / startValue * 100;
|
|
18
24
|
return {
|
|
19
25
|
absoluteChange,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
export * from './adapter.js';
|
|
2
|
+
export * from './drawing/kline-projection-policy.js';
|
|
3
|
+
export * from './drawing/engine-port.js';
|
|
4
|
+
export * from './drawing/interaction-normalization.js';
|
|
5
|
+
export * from './drawing/overlay-conversion.js';
|
|
6
|
+
export * from './drawing/projection-policy.js';
|
|
7
|
+
export * from './drawing/time-series-projection-policy.js';
|
|
2
8
|
export * from './errors.js';
|
|
9
|
+
export * from './main-series-presentation.js';
|
|
3
10
|
export * from './extensions/register.js';
|
|
4
11
|
export * from './interaction/dragging.js';
|
|
5
12
|
export * from './interaction/hit-testing.js';
|
|
6
13
|
export * from './registry/indicators.js';
|
|
7
14
|
export * from './registry/overlays.js';
|
|
8
15
|
export * from './static-data-loader.js';
|
|
16
|
+
export * from './time-series/adapter.js';
|
|
9
17
|
export * from './version.js';
|
|
10
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,sCAAsC,CAAC;AACrD,cAAc,0BAA0B,CAAC;AACzC,cAAc,wCAAwC,CAAC;AACvD,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,aAAa,CAAC;AAC5B,cAAc,+BAA+B,CAAC;AAC9C,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
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
export * from './adapter.js';
|
|
2
|
+
export * from './drawing/kline-projection-policy.js';
|
|
3
|
+
export * from './drawing/engine-port.js';
|
|
4
|
+
export * from './drawing/interaction-normalization.js';
|
|
5
|
+
export * from './drawing/overlay-conversion.js';
|
|
6
|
+
export * from './drawing/projection-policy.js';
|
|
7
|
+
export * from './drawing/time-series-projection-policy.js';
|
|
2
8
|
export * from './errors.js';
|
|
9
|
+
export * from './main-series-presentation.js';
|
|
3
10
|
export * from './extensions/register.js';
|
|
4
11
|
export * from './interaction/dragging.js';
|
|
5
12
|
export * from './interaction/hit-testing.js';
|
|
6
13
|
export * from './registry/indicators.js';
|
|
7
14
|
export * from './registry/overlays.js';
|
|
8
15
|
export * from './static-data-loader.js';
|
|
16
|
+
export * from './time-series/adapter.js';
|
|
9
17
|
export * from './version.js';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ChartScene } from '@baron1996/kline-scene-schema';
|
|
2
|
+
export type MainSeriesPresentationErrorCode = 'MAIN_SERIES_PRESENTATION_INVALID' | 'MAIN_SERIES_PRESENTATION_UNSUPPORTED' | 'MAIN_SERIES_PRESENTATION_APPLY_FAILED' | 'MAIN_SERIES_PRESENTATION_ROLLBACK_FAILED';
|
|
3
|
+
export declare class MainSeriesPresentationError extends Error {
|
|
4
|
+
readonly code: MainSeriesPresentationErrorCode;
|
|
5
|
+
readonly path: string;
|
|
6
|
+
constructor(code: MainSeriesPresentationErrorCode, path: string, message: string);
|
|
7
|
+
}
|
|
8
|
+
/** 产品唯一 area 收盘价折线展示配置;值来源固定为 close。 */
|
|
9
|
+
export declare const STANDARD_CLOSE_LINE_PRESENTATION: {
|
|
10
|
+
readonly type: "area";
|
|
11
|
+
readonly value: "close";
|
|
12
|
+
readonly line: {
|
|
13
|
+
readonly color: "rgba(41, 98, 255, 1)";
|
|
14
|
+
readonly size: 2;
|
|
15
|
+
};
|
|
16
|
+
readonly backgroundColor: "rgba(0, 0, 0, 0)";
|
|
17
|
+
readonly smooth: false;
|
|
18
|
+
readonly pointVisible: false;
|
|
19
|
+
};
|
|
20
|
+
export type MainSeriesPresentation = {
|
|
21
|
+
readonly type: 'candle_solid' | 'candle_stroke' | 'candle_up_stroke' | 'candle_down_stroke' | 'ohlc';
|
|
22
|
+
} | typeof STANDARD_CLOSE_LINE_PRESENTATION;
|
|
23
|
+
export type ActiveMainSeriesType = 'candle_solid' | 'candle_stroke' | 'candle_up_stroke' | 'candle_down_stroke' | 'ohlc' | 'area';
|
|
24
|
+
export interface MainSeriesPresentationResult {
|
|
25
|
+
readonly activeType: ActiveMainSeriesType;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 主序列展示端口;只由 K 线 Adapter 实现,与 Drawing 引擎端口分离。
|
|
29
|
+
* 输入必须是完整 discriminated union,禁止从其他字段或引擎默认值兜底。
|
|
30
|
+
*/
|
|
31
|
+
export interface MainSeriesPresentationPort {
|
|
32
|
+
applyMainSeriesPresentation(presentation: MainSeriesPresentation): MainSeriesPresentationResult;
|
|
33
|
+
}
|
|
34
|
+
export declare function presentationToSceneCandle(scene: ChartScene, presentation: MainSeriesPresentation): ChartScene;
|
|
35
|
+
//# sourceMappingURL=main-series-presentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-series-presentation.d.ts","sourceRoot":"","sources":["../src/main-series-presentation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE,MAAM,MAAM,+BAA+B,GACxC,kCAAkC,GAClC,sCAAsC,GACtC,uCAAuC,GACvC,0CAA0C,CAAC;AAE9C,qBAAa,2BAA4B,SAAQ,KAAK;IACrD,SAAgB,IAAI,EAAE,+BAA+B,CAAC;IACtD,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAG5B,IAAI,EAAE,+BAA+B,EACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM;CAOhB;AAED,wCAAwC;AACxC,eAAO,MAAM,gCAAgC;;;;;;;;;;CAOnC,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAC/B;IACA,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,eAAe,GAAG,kBAAkB,GACjE,oBAAoB,GAAG,MAAM,CAAC;CAChC,GACD,OAAO,gCAAgC,CAAC;AAE3C,MAAM,MAAM,oBAAoB,GAC7B,cAAc,GACd,eAAe,GACf,kBAAkB,GAClB,oBAAoB,GACpB,MAAM,GACN,MAAM,CAAC;AAEV,MAAM,WAAW,4BAA4B;IAC5C,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC;CAC1C;AAED;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IAC1C,2BAA2B,CAC1B,YAAY,EAAE,sBAAsB,GAClC,4BAA4B,CAAC;CAChC;AAED,wBAAgB,yBAAyB,CACxC,KAAK,EAAE,UAAU,EACjB,YAAY,EAAE,sBAAsB,GAClC,UAAU,CAgCZ"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export class MainSeriesPresentationError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
path;
|
|
4
|
+
constructor(code, path, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'MainSeriesPresentationError';
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.path = path;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** 产品唯一 area 收盘价折线展示配置;值来源固定为 close。 */
|
|
12
|
+
export const STANDARD_CLOSE_LINE_PRESENTATION = {
|
|
13
|
+
type: 'area',
|
|
14
|
+
value: 'close',
|
|
15
|
+
line: { color: 'rgba(41, 98, 255, 1)', size: 2 },
|
|
16
|
+
backgroundColor: 'rgba(0, 0, 0, 0)',
|
|
17
|
+
smooth: false,
|
|
18
|
+
pointVisible: false,
|
|
19
|
+
};
|
|
20
|
+
export function presentationToSceneCandle(scene, presentation) {
|
|
21
|
+
if (presentation.type === 'area') {
|
|
22
|
+
return {
|
|
23
|
+
...structuredClone(scene),
|
|
24
|
+
chart: {
|
|
25
|
+
...structuredClone(scene.chart),
|
|
26
|
+
candle: {
|
|
27
|
+
...structuredClone(scene.chart.candle),
|
|
28
|
+
type: 'area',
|
|
29
|
+
area: {
|
|
30
|
+
value: presentation.value,
|
|
31
|
+
line: {
|
|
32
|
+
color: presentation.line.color,
|
|
33
|
+
size: presentation.line.size,
|
|
34
|
+
},
|
|
35
|
+
backgroundColor: presentation.backgroundColor,
|
|
36
|
+
smooth: presentation.smooth,
|
|
37
|
+
pointVisible: presentation.pointVisible,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const candle = structuredClone(scene.chart.candle);
|
|
44
|
+
delete candle.area;
|
|
45
|
+
return {
|
|
46
|
+
...structuredClone(scene),
|
|
47
|
+
chart: {
|
|
48
|
+
...structuredClone(scene.chart),
|
|
49
|
+
candle: { ...candle, type: presentation.type },
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Drawing, TimeSeriesPoint, TimeSeriesScene } from '@baron1996/kline-scene-schema';
|
|
2
|
+
import type { DrawingEnginePort, EngineDrawingEvent, EngineDrawingSnapshot, EngineDrawingStartRequest, EnginePixelCoordinate, EnginePointProjection } from '../drawing/engine-port.js';
|
|
3
|
+
export interface TimeSeriesAdapterCrosshair {
|
|
4
|
+
readonly timestamp: number | null;
|
|
5
|
+
readonly values: Readonly<Record<string, number | null>> | null;
|
|
6
|
+
}
|
|
7
|
+
export type TimeSeriesAdapterCrosshairListener = (event: TimeSeriesAdapterCrosshair) => void;
|
|
8
|
+
/** TimeSeriesScene 与 KLineCharts 之间的唯一受控边界。 */
|
|
9
|
+
export declare class TimeSeriesChartsAdapter implements DrawingEnginePort {
|
|
10
|
+
#private;
|
|
11
|
+
private constructor();
|
|
12
|
+
static create(container: HTMLElement, value: unknown): Promise<TimeSeriesChartsAdapter>;
|
|
13
|
+
/** 显式 Workspace factory:时间序列场景 + DrawingDocument。 */
|
|
14
|
+
static createWorkspace(container: HTMLElement, value: unknown): Promise<TimeSeriesChartsAdapter>;
|
|
15
|
+
get sceneKind(): 'chart' | 'time-series';
|
|
16
|
+
restoreDrawings(drawings: readonly EngineDrawingSnapshot[]): void;
|
|
17
|
+
startDrawing(request: EngineDrawingStartRequest): string;
|
|
18
|
+
listDrawings(): readonly EngineDrawingSnapshot[];
|
|
19
|
+
getDrawing(id: string): EngineDrawingSnapshot | undefined;
|
|
20
|
+
updateDrawingStyles(id: string, styles: Drawing['styles']): EngineDrawingSnapshot;
|
|
21
|
+
updateDrawingText(id: string, text: string): EngineDrawingSnapshot;
|
|
22
|
+
removeDrawing(id: string): boolean;
|
|
23
|
+
restoreDrawing(snapshot: EngineDrawingSnapshot): void;
|
|
24
|
+
selectDrawing(id: string | null): void;
|
|
25
|
+
hitTestDrawing(point: EnginePixelCoordinate): string | null;
|
|
26
|
+
projectToPixel(anchor: {
|
|
27
|
+
readonly timestamp?: number;
|
|
28
|
+
readonly value?: number;
|
|
29
|
+
}, _paneRole: string): EnginePointProjection;
|
|
30
|
+
unprojectFromPixel(point: EnginePixelCoordinate, _paneRole: string): EnginePointProjection;
|
|
31
|
+
setMutationsEnabled(enabled: boolean): void;
|
|
32
|
+
subscribeDrawingEvents(listener: (event: EngineDrawingEvent) => void): () => void;
|
|
33
|
+
subscribeCrosshair(listener: TimeSeriesAdapterCrosshairListener): () => void;
|
|
34
|
+
setSeriesVisible(seriesId: string, visible: boolean): TimeSeriesScene;
|
|
35
|
+
replaceData(data: readonly TimeSeriesPoint[]): TimeSeriesScene;
|
|
36
|
+
/** 同结构场景替换:period/data/viewport 原子更新,series 结构必须一致。 */
|
|
37
|
+
replaceScene(value: TimeSeriesScene): TimeSeriesScene;
|
|
38
|
+
exportScene(): TimeSeriesScene;
|
|
39
|
+
dispose(): void;
|
|
40
|
+
}
|
|
41
|
+
//# 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,OAAO,EAEP,eAAe,EACf,eAAe,EAEf,MAAM,+BAA+B,CAAC;AAsCvC,OAAO,KAAK,EACX,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,qBAAqB,EACrB,MAAM,2BAA2B,CAAC;AAUnC,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;AAoIV,+CAA+C;AAC/C,qBAAa,uBAAwB,YAAW,iBAAiB;;IA+ChE,OAAO;WA4Ba,MAAM,CACzB,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,OAAO,GACZ,OAAO,CAAC,uBAAuB,CAAC;IA8EnC,qDAAqD;WACjC,eAAe,CAClC,SAAS,EAAE,WAAW,EACtB,KAAK,EAAE,OAAO,GACZ,OAAO,CAAC,uBAAuB,CAAC;IA6vBnC,IAAW,SAAS,IAAI,OAAO,GAAG,aAAa,CAE9C;IAEM,eAAe,CACrB,QAAQ,EAAE,SAAS,qBAAqB,EAAE,GACxC,IAAI;IAQA,YAAY,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM;IA6BxD,YAAY,IAAI,SAAS,qBAAqB,EAAE;IAQhD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAMzD,mBAAmB,CACzB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,GACvB,qBAAqB;IA8BjB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,qBAAqB;IA2BlE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAKlC,cAAc,CAAC,QAAQ,EAAE,qBAAqB,GAAG,IAAI;IAiCrD,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKtC,cAAc,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,GAAG,IAAI;IAM3D,cAAc,CACpB,MAAM,EAAE;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAChE,SAAS,EAAE,MAAM,GACf,qBAAqB;IAKjB,kBAAkB,CACxB,KAAK,EAAE,qBAAqB,EAC5B,SAAS,EAAE,MAAM,GACf,qBAAqB;IAKjB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAK3C,sBAAsB,CAC5B,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAC3C,MAAM,IAAI;IAON,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;IA2CrE,uDAAuD;IAChD,YAAY,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe;IA6CrD,WAAW,IAAI,eAAe;IAK9B,OAAO,IAAI,IAAI;CAmBtB"}
|