hyperprop-charting-library 0.1.54 → 0.1.56

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/index.cjs CHANGED
@@ -214,7 +214,8 @@ var DEFAULT_OPTIONS = {
214
214
  },
215
215
  labels: DEFAULT_LABELS_OPTIONS,
216
216
  dashPatterns: DEFAULT_DASH_PATTERNS,
217
- indicators: []
217
+ indicators: [],
218
+ drawings: []
218
219
  };
219
220
  var mergeChartOptions = (baseOptions, options = {}) => ({
220
221
  ...baseOptions,
@@ -905,6 +906,7 @@ function createChart(element, options = {}) {
905
906
  let generatedPriceLineId = 1;
906
907
  let generatedOrderLineId = 1;
907
908
  let generatedIndicatorId = 1;
909
+ let generatedDrawingId = 1;
908
910
  const indicatorRegistry = /* @__PURE__ */ new Map();
909
911
  for (const indicator of BUILTIN_INDICATORS) {
910
912
  indicatorRegistry.set(indicator.id, indicator);
@@ -927,7 +929,42 @@ function createChart(element, options = {}) {
927
929
  }
928
930
  };
929
931
  };
932
+ const normalizeDrawingState = (drawing) => ({
933
+ id: drawing.id ?? `drawing-${generatedDrawingId++}`,
934
+ type: drawing.type,
935
+ points: drawing.points.map((point) => ({
936
+ index: Number(point.index) || 0,
937
+ price: Number(point.price) || 0,
938
+ ...point.time ? { time: point.time } : {}
939
+ })),
940
+ visible: drawing.visible ?? true,
941
+ color: drawing.color ?? "#94a3b8",
942
+ style: drawing.style ?? "dotted",
943
+ width: Math.max(1, Number(drawing.width) || 1),
944
+ locked: drawing.locked ?? false,
945
+ ...drawing.label === void 0 ? {} : { label: drawing.label }
946
+ });
947
+ const serializeDrawing = (drawing) => ({
948
+ id: drawing.id,
949
+ type: drawing.type,
950
+ points: drawing.points.map((point) => ({ ...point })),
951
+ visible: drawing.visible,
952
+ color: drawing.color,
953
+ style: drawing.style,
954
+ width: drawing.width,
955
+ locked: drawing.locked,
956
+ ...drawing.label === void 0 ? {} : { label: drawing.label }
957
+ });
930
958
  let indicators = (options.indicators ?? []).map((indicator) => normalizeIndicatorState(indicator));
959
+ let drawings = (options.drawings ?? []).map((drawing) => normalizeDrawingState(drawing));
960
+ let activeDrawingTool = null;
961
+ let draftDrawing = null;
962
+ let drawingDragState = null;
963
+ let drawingsChangeHandler = null;
964
+ let drawingSelectHandler = null;
965
+ const emitDrawingsChange = () => {
966
+ drawingsChangeHandler?.(drawings.map((drawing) => serializeDrawing(drawing)));
967
+ };
931
968
  const orderWidgetWidthById = /* @__PURE__ */ new Map();
932
969
  const orderPriceTagWidthById = /* @__PURE__ */ new Map();
933
970
  let xCenter = 0;
@@ -1981,6 +2018,57 @@ function createChart(element, options = {}) {
1981
2018
  const yFromPrice = (price) => {
1982
2019
  return chartBottom - (price - yMin) / yRange * chartHeight;
1983
2020
  };
2021
+ const xFromDrawingPoint = (point) => chartLeft + (point.index + 0.5 - xStart) / xSpan * chartWidth;
2022
+ const drawDrawingHandle = (x, y, color) => {
2023
+ ctx.save();
2024
+ ctx.setLineDash([]);
2025
+ ctx.fillStyle = mergedOptions.backgroundColor;
2026
+ ctx.strokeStyle = color;
2027
+ ctx.lineWidth = 2;
2028
+ ctx.beginPath();
2029
+ ctx.arc(x, y, 5, 0, Math.PI * 2);
2030
+ ctx.fill();
2031
+ ctx.stroke();
2032
+ ctx.restore();
2033
+ };
2034
+ const drawDrawing = (drawing, draft = false) => {
2035
+ if (!drawing.visible) {
2036
+ return;
2037
+ }
2038
+ ctx.save();
2039
+ ctx.strokeStyle = drawing.color;
2040
+ ctx.lineWidth = drawing.width;
2041
+ ctx.globalAlpha = draft ? 0.72 : 1;
2042
+ applyDashPattern(drawing.style, dashPatterns.dotted, dashPatterns.dashed);
2043
+ if (drawing.type === "horizontal-line") {
2044
+ const point = drawing.points[0];
2045
+ if (point) {
2046
+ const y = clamp(yFromPrice(point.price), chartTop + 1, chartBottom - 1);
2047
+ const handleX = chartRight - 14;
2048
+ ctx.beginPath();
2049
+ ctx.moveTo(crisp(chartLeft), crisp(y));
2050
+ ctx.lineTo(crisp(chartRight), crisp(y));
2051
+ ctx.stroke();
2052
+ drawDrawingHandle(handleX, y, drawing.color);
2053
+ }
2054
+ } else if (drawing.type === "trendline") {
2055
+ const first = drawing.points[0];
2056
+ const second = drawing.points[1];
2057
+ if (first && second) {
2058
+ const firstX = xFromDrawingPoint(first);
2059
+ const firstY = yFromPrice(first.price);
2060
+ const secondX = xFromDrawingPoint(second);
2061
+ const secondY = yFromPrice(second.price);
2062
+ ctx.beginPath();
2063
+ ctx.moveTo(firstX, firstY);
2064
+ ctx.lineTo(secondX, secondY);
2065
+ ctx.stroke();
2066
+ drawDrawingHandle(firstX, firstY, drawing.color);
2067
+ drawDrawingHandle(secondX, secondY, drawing.color);
2068
+ }
2069
+ }
2070
+ ctx.restore();
2071
+ };
1984
2072
  if (watermark.visible && watermark.imageSrc.trim().length > 0) {
1985
2073
  ensureWatermarkImage(watermark.imageSrc.trim());
1986
2074
  if (watermarkImageReady && watermarkImage) {
@@ -2152,6 +2240,10 @@ function createChart(element, options = {}) {
2152
2240
  );
2153
2241
  });
2154
2242
  }
2243
+ drawings.forEach((drawing) => drawDrawing(drawing));
2244
+ if (draftDrawing) {
2245
+ drawDrawing(draftDrawing, true);
2246
+ }
2155
2247
  const crosshair = { ...DEFAULT_CROSSHAIR_OPTIONS, ...mergedOptions.crosshair ?? {} };
2156
2248
  if (crosshair.visible && crosshairPoint) {
2157
2249
  const cx = clamp(crosshairPoint.x, chartLeft, chartRight);
@@ -2988,6 +3080,82 @@ function createChart(element, options = {}) {
2988
3080
  const ratio = clamp((drawState.chartBottom - y) / drawState.chartHeight, 0, 1);
2989
3081
  return drawState.yMin + ratio * (drawState.yMax - drawState.yMin);
2990
3082
  };
3083
+ const drawingPointFromCanvas = (x, y) => {
3084
+ if (!drawState) {
3085
+ return null;
3086
+ }
3087
+ const ratio = clamp((x - drawState.chartLeft) / drawState.chartWidth, 0, 1);
3088
+ const index = drawState.xStart + ratio * drawState.xSpan - 0.5;
3089
+ const nearestIndex = Math.round(index);
3090
+ const time = getTimeForIndex(nearestIndex);
3091
+ return {
3092
+ index,
3093
+ price: roundToPricePrecision(priceFromCanvasY(y)),
3094
+ ...time ? { time: time.toISOString() } : {}
3095
+ };
3096
+ };
3097
+ const normalizeDrawingPoint = (index, price) => {
3098
+ const roundedIndex = Math.round(index);
3099
+ const time = getTimeForIndex(roundedIndex);
3100
+ return {
3101
+ index,
3102
+ price: roundToPricePrecision(price),
3103
+ ...time ? { time: time.toISOString() } : {}
3104
+ };
3105
+ };
3106
+ const canvasXFromDrawingPoint = (point) => {
3107
+ if (!drawState) return 0;
3108
+ return drawState.chartLeft + (point.index + 0.5 - drawState.xStart) / drawState.xSpan * drawState.chartWidth;
3109
+ };
3110
+ const canvasYFromDrawingPrice = (price) => {
3111
+ if (!drawState) return 0;
3112
+ const range = drawState.yMax - drawState.yMin || 1;
3113
+ return drawState.chartBottom - (price - drawState.yMin) / range * drawState.chartHeight;
3114
+ };
3115
+ const distanceToSegment = (x, y, x1, y1, x2, y2) => {
3116
+ const dx = x2 - x1;
3117
+ const dy = y2 - y1;
3118
+ const lengthSq = dx * dx + dy * dy;
3119
+ if (lengthSq === 0) return Math.hypot(x - x1, y - y1);
3120
+ const t = clamp(((x - x1) * dx + (y - y1) * dy) / lengthSq, 0, 1);
3121
+ return Math.hypot(x - (x1 + t * dx), y - (y1 + t * dy));
3122
+ };
3123
+ const getDrawingHit = (x, y) => {
3124
+ for (let index = drawings.length - 1; index >= 0; index -= 1) {
3125
+ const drawing = drawings[index];
3126
+ if (!drawing?.visible) continue;
3127
+ if (drawing.type === "horizontal-line") {
3128
+ const point = drawing.points[0];
3129
+ if (!point) continue;
3130
+ const lineY = canvasYFromDrawingPrice(point.price);
3131
+ const handleX = drawState ? drawState.chartRight - 14 : 0;
3132
+ if (Math.hypot(x - handleX, y - lineY) <= 8) {
3133
+ return { drawing, target: "handle", pointIndex: 0 };
3134
+ }
3135
+ if (Math.abs(y - lineY) <= 7) {
3136
+ return { drawing, target: "line" };
3137
+ }
3138
+ } else if (drawing.type === "trendline") {
3139
+ const first = drawing.points[0];
3140
+ const second = drawing.points[1];
3141
+ if (!first || !second) continue;
3142
+ const x1 = canvasXFromDrawingPoint(first);
3143
+ const y1 = canvasYFromDrawingPrice(first.price);
3144
+ const x2 = canvasXFromDrawingPoint(second);
3145
+ const y2 = canvasYFromDrawingPrice(second.price);
3146
+ if (Math.hypot(x - x1, y - y1) <= 8) {
3147
+ return { drawing, target: "handle", pointIndex: 0 };
3148
+ }
3149
+ if (Math.hypot(x - x2, y - y2) <= 8) {
3150
+ return { drawing, target: "handle", pointIndex: 1 };
3151
+ }
3152
+ if (distanceToSegment(x, y, x1, y1, x2, y2) <= 6) {
3153
+ return { drawing, target: "line" };
3154
+ }
3155
+ }
3156
+ }
3157
+ return null;
3158
+ };
2991
3159
  const indexFromCanvasX = (x) => {
2992
3160
  if (!drawState) {
2993
3161
  return null;
@@ -3040,6 +3208,86 @@ function createChart(element, options = {}) {
3040
3208
  }
3041
3209
  return "outside";
3042
3210
  };
3211
+ const handleDrawingToolPointerDown = (x, y) => {
3212
+ if (!activeDrawingTool || !drawState) {
3213
+ return false;
3214
+ }
3215
+ const point = drawingPointFromCanvas(x, y);
3216
+ if (!point) {
3217
+ return false;
3218
+ }
3219
+ if (activeDrawingTool === "horizontal-line") {
3220
+ drawings.push(
3221
+ normalizeDrawingState({
3222
+ type: "horizontal-line",
3223
+ points: [point],
3224
+ color: "#38bdf8",
3225
+ style: "dotted",
3226
+ width: 1
3227
+ })
3228
+ );
3229
+ emitDrawingsChange();
3230
+ draw();
3231
+ return true;
3232
+ }
3233
+ if (activeDrawingTool === "trendline") {
3234
+ if (draftDrawing?.type === "trendline") {
3235
+ const completed = normalizeDrawingState({
3236
+ ...serializeDrawing(draftDrawing),
3237
+ points: [draftDrawing.points[0], point]
3238
+ });
3239
+ drawings.push(completed);
3240
+ draftDrawing = null;
3241
+ activeDrawingTool = null;
3242
+ emitDrawingsChange();
3243
+ draw();
3244
+ return true;
3245
+ }
3246
+ draftDrawing = normalizeDrawingState({
3247
+ type: "trendline",
3248
+ points: [point, point],
3249
+ color: "#2563eb",
3250
+ style: "solid",
3251
+ width: 2
3252
+ });
3253
+ draw();
3254
+ return true;
3255
+ }
3256
+ return false;
3257
+ };
3258
+ const updateDrawingDrag = (x, y) => {
3259
+ if (!drawingDragState) {
3260
+ return false;
3261
+ }
3262
+ const currentPoint = drawingPointFromCanvas(x, y);
3263
+ if (!currentPoint) {
3264
+ return true;
3265
+ }
3266
+ const deltaIndex = currentPoint.index - drawingDragState.startCanvasPoint.index;
3267
+ const deltaPrice = currentPoint.price - drawingDragState.startCanvasPoint.price;
3268
+ drawings = drawings.map((drawing) => {
3269
+ if (drawing.id !== drawingDragState?.drawingId || drawing.locked) {
3270
+ return drawing;
3271
+ }
3272
+ if (drawingDragState.target === "handle") {
3273
+ return {
3274
+ ...drawing,
3275
+ points: drawing.points.map(
3276
+ (point, index) => index === (drawingDragState?.pointIndex ?? 0) ? normalizeDrawingPoint(currentPoint.index, currentPoint.price) : point
3277
+ )
3278
+ };
3279
+ }
3280
+ return {
3281
+ ...drawing,
3282
+ points: drawingDragState.startPoints.map(
3283
+ (point) => normalizeDrawingPoint(point.index + deltaIndex, point.price + deltaPrice)
3284
+ )
3285
+ };
3286
+ });
3287
+ emitDrawingsChange();
3288
+ draw();
3289
+ return true;
3290
+ };
3043
3291
  let isDragging = false;
3044
3292
  let dragMode = null;
3045
3293
  let lastPointerX = 0;
@@ -3079,6 +3327,7 @@ function createChart(element, options = {}) {
3079
3327
  pointerDownInfo = null;
3080
3328
  orderDragState = null;
3081
3329
  actionDragState = null;
3330
+ drawingDragState = null;
3082
3331
  canvas.style.cursor = "default";
3083
3332
  setCrosshairPoint(null);
3084
3333
  };
@@ -3165,6 +3414,40 @@ function createChart(element, options = {}) {
3165
3414
  if (region === "outside") {
3166
3415
  return;
3167
3416
  }
3417
+ if (region === "plot" && !activeDrawingTool) {
3418
+ const drawingHit = getDrawingHit(point.x, point.y);
3419
+ if (drawingHit) {
3420
+ drawingSelectHandler?.({
3421
+ drawing: serializeDrawing(drawingHit.drawing),
3422
+ target: drawingHit.target,
3423
+ ...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
3424
+ x: point.x,
3425
+ y: point.y
3426
+ });
3427
+ if (!drawingHit.drawing.locked) {
3428
+ const startCanvasPoint = drawingPointFromCanvas(point.x, point.y);
3429
+ if (startCanvasPoint) {
3430
+ drawingDragState = {
3431
+ drawingId: drawingHit.drawing.id,
3432
+ target: drawingHit.target,
3433
+ ...drawingHit.pointIndex === void 0 ? {} : { pointIndex: drawingHit.pointIndex },
3434
+ startCanvasPoint,
3435
+ startPoints: drawingHit.drawing.points.map((drawingPoint) => ({ ...drawingPoint }))
3436
+ };
3437
+ activePointerId = event.pointerId;
3438
+ canvas.setPointerCapture(event.pointerId);
3439
+ }
3440
+ }
3441
+ setCrosshairPoint(null);
3442
+ canvas.style.cursor = drawingHit.drawing.locked ? "pointer" : drawingHit.target === "handle" ? "grab" : "move";
3443
+ return;
3444
+ }
3445
+ }
3446
+ if (region === "plot" && handleDrawingToolPointerDown(point.x, point.y)) {
3447
+ setCrosshairPoint(null);
3448
+ canvas.style.cursor = "crosshair";
3449
+ return;
3450
+ }
3168
3451
  isDragging = true;
3169
3452
  dragMode = region;
3170
3453
  activePointerId = event.pointerId;
@@ -3196,6 +3479,27 @@ function createChart(element, options = {}) {
3196
3479
  pointerDownInfo.moved = true;
3197
3480
  }
3198
3481
  }
3482
+ if (drawingDragState) {
3483
+ if (activePointerId !== null && event.pointerId !== activePointerId) {
3484
+ return;
3485
+ }
3486
+ updateDrawingDrag(point.x, point.y);
3487
+ canvas.style.cursor = drawingDragState.target === "handle" ? "grabbing" : "move";
3488
+ setCrosshairPoint(null);
3489
+ return;
3490
+ }
3491
+ if (draftDrawing && activeDrawingTool === "trendline") {
3492
+ const nextPoint = drawingPointFromCanvas(point.x, point.y);
3493
+ if (nextPoint) {
3494
+ draftDrawing = {
3495
+ ...draftDrawing,
3496
+ points: [draftDrawing.points[0], nextPoint]
3497
+ };
3498
+ canvas.style.cursor = "crosshair";
3499
+ draw();
3500
+ return;
3501
+ }
3502
+ }
3199
3503
  if (orderDragState) {
3200
3504
  if (activePointerId !== null && event.pointerId !== activePointerId) {
3201
3505
  return;
@@ -3266,9 +3570,15 @@ function createChart(element, options = {}) {
3266
3570
  setCrosshairPoint(null);
3267
3571
  return;
3268
3572
  }
3573
+ if (!activeDrawingTool && getDrawingHit(point.x, point.y)) {
3574
+ const drawingHit = getDrawingHit(point.x, point.y);
3575
+ canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
3576
+ setCrosshairPoint(null);
3577
+ return;
3578
+ }
3269
3579
  const hoverRegion = getHitRegion(point.x, point.y);
3270
3580
  if (hoverRegion === "plot") {
3271
- canvas.style.cursor = doubleClickEnabled ? "default" : "crosshair";
3581
+ canvas.style.cursor = activeDrawingTool ? "crosshair" : doubleClickEnabled ? "default" : "crosshair";
3272
3582
  setCrosshairPoint(point);
3273
3583
  emitCrosshairMove(point.x, point.y, "plot");
3274
3584
  } else if (hoverRegion === "x-axis") {
@@ -3358,6 +3668,10 @@ function createChart(element, options = {}) {
3358
3668
  }
3359
3669
  actionDragState = null;
3360
3670
  }
3671
+ if (drawingDragState) {
3672
+ drawingDragState = null;
3673
+ emitDrawingsChange();
3674
+ }
3361
3675
  isDragging = false;
3362
3676
  dragMode = null;
3363
3677
  activePointerId = null;
@@ -3667,6 +3981,56 @@ function createChart(element, options = {}) {
3667
3981
  indicators = indicators.filter((indicator) => indicator.id !== id);
3668
3982
  draw();
3669
3983
  };
3984
+ const setActiveDrawingTool = (tool) => {
3985
+ activeDrawingTool = tool;
3986
+ draftDrawing = null;
3987
+ canvas.style.cursor = tool ? "crosshair" : "default";
3988
+ draw();
3989
+ };
3990
+ const getActiveDrawingTool = () => activeDrawingTool;
3991
+ const getDrawings = () => drawings.map((drawing) => serializeDrawing(drawing));
3992
+ const setDrawings = (nextDrawings) => {
3993
+ drawings = nextDrawings.map((drawing) => normalizeDrawingState(drawing));
3994
+ draftDrawing = null;
3995
+ emitDrawingsChange();
3996
+ draw();
3997
+ };
3998
+ const addDrawing = (drawing) => {
3999
+ const next = normalizeDrawingState(drawing);
4000
+ drawings.push(next);
4001
+ emitDrawingsChange();
4002
+ draw();
4003
+ return next.id;
4004
+ };
4005
+ const updateDrawing = (id, patch) => {
4006
+ drawings = drawings.map(
4007
+ (drawing) => drawing.id === id ? normalizeDrawingState({
4008
+ ...serializeDrawing(drawing),
4009
+ ...patch,
4010
+ id,
4011
+ points: patch.points ?? drawing.points
4012
+ }) : drawing
4013
+ );
4014
+ emitDrawingsChange();
4015
+ draw();
4016
+ };
4017
+ const removeDrawing = (id) => {
4018
+ drawings = drawings.filter((drawing) => drawing.id !== id);
4019
+ emitDrawingsChange();
4020
+ draw();
4021
+ };
4022
+ const clearDrawings = () => {
4023
+ drawings = [];
4024
+ draftDrawing = null;
4025
+ emitDrawingsChange();
4026
+ draw();
4027
+ };
4028
+ const onDrawingsChange = (handler) => {
4029
+ drawingsChangeHandler = handler;
4030
+ };
4031
+ const onDrawingSelect = (handler) => {
4032
+ drawingSelectHandler = handler;
4033
+ };
3670
4034
  const destroy = () => {
3671
4035
  if (smoothingRafId !== null) {
3672
4036
  cancelAnimationFrame(smoothingRafId);
@@ -3710,6 +4074,16 @@ function createChart(element, options = {}) {
3710
4074
  getViewport,
3711
4075
  setViewport,
3712
4076
  onViewportChange,
4077
+ setActiveDrawingTool,
4078
+ getActiveDrawingTool,
4079
+ setDrawings,
4080
+ getDrawings,
4081
+ addDrawing,
4082
+ updateDrawing,
4083
+ removeDrawing,
4084
+ clearDrawings,
4085
+ onDrawingsChange,
4086
+ onDrawingSelect,
3713
4087
  setDoubleClickEnabled,
3714
4088
  setDoubleClickAction,
3715
4089
  registerIndicator,
package/dist/index.d.cts CHANGED
@@ -40,8 +40,33 @@ interface ChartOptions {
40
40
  labels?: LabelsOptions;
41
41
  dashPatterns?: Partial<DashPatternOptions>;
42
42
  indicators?: IndicatorInstanceOptions[];
43
+ drawings?: DrawingObjectOptions[];
43
44
  }
44
45
  type IndicatorPane = "overlay" | "separate";
46
+ type DrawingToolType = "horizontal-line" | "trendline";
47
+ interface DrawingPoint {
48
+ index: number;
49
+ price: number;
50
+ time?: string;
51
+ }
52
+ interface DrawingObjectOptions {
53
+ id?: string;
54
+ type: DrawingToolType;
55
+ points: DrawingPoint[];
56
+ visible?: boolean;
57
+ color?: string;
58
+ style?: "solid" | "dotted" | "dashed";
59
+ width?: number;
60
+ label?: string;
61
+ locked?: boolean;
62
+ }
63
+ interface DrawingSelectEvent {
64
+ drawing: DrawingObjectOptions;
65
+ target: "line" | "handle";
66
+ pointIndex?: number;
67
+ x: number;
68
+ y: number;
69
+ }
45
70
  interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
46
71
  id?: string;
47
72
  type: string;
@@ -363,6 +388,16 @@ interface ChartInstance {
363
388
  getViewport: () => ViewportState;
364
389
  setViewport: (viewport: Partial<ViewportState>) => void;
365
390
  onViewportChange: (handler: ((viewport: ViewportState) => void) | null) => void;
391
+ setActiveDrawingTool: (tool: DrawingToolType | null) => void;
392
+ getActiveDrawingTool: () => DrawingToolType | null;
393
+ setDrawings: (nextDrawings: DrawingObjectOptions[]) => void;
394
+ getDrawings: () => DrawingObjectOptions[];
395
+ addDrawing: (drawing: DrawingObjectOptions) => string;
396
+ updateDrawing: (id: string, patch: Partial<DrawingObjectOptions>) => void;
397
+ removeDrawing: (id: string) => void;
398
+ clearDrawings: () => void;
399
+ onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
400
+ onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
366
401
  setDoubleClickEnabled: (enabled: boolean) => void;
367
402
  setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
368
403
  registerIndicator: (plugin: IndicatorPlugin<any>) => void;
@@ -398,4 +433,4 @@ interface ViewportState {
398
433
  }
399
434
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
400
435
 
401
- export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
436
+ export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
package/dist/index.d.ts CHANGED
@@ -40,8 +40,33 @@ interface ChartOptions {
40
40
  labels?: LabelsOptions;
41
41
  dashPatterns?: Partial<DashPatternOptions>;
42
42
  indicators?: IndicatorInstanceOptions[];
43
+ drawings?: DrawingObjectOptions[];
43
44
  }
44
45
  type IndicatorPane = "overlay" | "separate";
46
+ type DrawingToolType = "horizontal-line" | "trendline";
47
+ interface DrawingPoint {
48
+ index: number;
49
+ price: number;
50
+ time?: string;
51
+ }
52
+ interface DrawingObjectOptions {
53
+ id?: string;
54
+ type: DrawingToolType;
55
+ points: DrawingPoint[];
56
+ visible?: boolean;
57
+ color?: string;
58
+ style?: "solid" | "dotted" | "dashed";
59
+ width?: number;
60
+ label?: string;
61
+ locked?: boolean;
62
+ }
63
+ interface DrawingSelectEvent {
64
+ drawing: DrawingObjectOptions;
65
+ target: "line" | "handle";
66
+ pointIndex?: number;
67
+ x: number;
68
+ y: number;
69
+ }
45
70
  interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
46
71
  id?: string;
47
72
  type: string;
@@ -363,6 +388,16 @@ interface ChartInstance {
363
388
  getViewport: () => ViewportState;
364
389
  setViewport: (viewport: Partial<ViewportState>) => void;
365
390
  onViewportChange: (handler: ((viewport: ViewportState) => void) | null) => void;
391
+ setActiveDrawingTool: (tool: DrawingToolType | null) => void;
392
+ getActiveDrawingTool: () => DrawingToolType | null;
393
+ setDrawings: (nextDrawings: DrawingObjectOptions[]) => void;
394
+ getDrawings: () => DrawingObjectOptions[];
395
+ addDrawing: (drawing: DrawingObjectOptions) => string;
396
+ updateDrawing: (id: string, patch: Partial<DrawingObjectOptions>) => void;
397
+ removeDrawing: (id: string) => void;
398
+ clearDrawings: () => void;
399
+ onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
400
+ onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
366
401
  setDoubleClickEnabled: (enabled: boolean) => void;
367
402
  setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
368
403
  registerIndicator: (plugin: IndicatorPlugin<any>) => void;
@@ -398,4 +433,4 @@ interface ViewportState {
398
433
  }
399
434
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
400
435
 
401
- export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
436
+ export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };