hyperprop-charting-library 0.1.57 → 0.1.58

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.
@@ -962,6 +962,8 @@ function createChart(element, options = {}) {
962
962
  let drawingDragState = null;
963
963
  let drawingsChangeHandler = null;
964
964
  let drawingSelectHandler = null;
965
+ let drawingHoverHandler = null;
966
+ let lastHoveredDrawingId = null;
965
967
  const emitDrawingsChange = () => {
966
968
  drawingsChangeHandler?.(drawings.map((drawing) => serializeDrawing(drawing)));
967
969
  };
@@ -2031,6 +2033,29 @@ function createChart(element, options = {}) {
2031
2033
  ctx.stroke();
2032
2034
  ctx.restore();
2033
2035
  };
2036
+ const drawDrawingLabel = (labelText, anchorX, anchorY, color, angle) => {
2037
+ if (!labelText) return;
2038
+ ctx.save();
2039
+ ctx.translate(anchorX, anchorY);
2040
+ ctx.rotate(angle);
2041
+ ctx.translate(0, -8);
2042
+ const prevFont = ctx.font;
2043
+ ctx.font = `500 12px ${mergedOptions.fontFamily}`;
2044
+ const textWidth = ctx.measureText(labelText).width;
2045
+ const paddingX = 6;
2046
+ const paddingY = 3;
2047
+ const bgWidth = textWidth + paddingX * 2;
2048
+ const bgHeight = 18;
2049
+ ctx.fillStyle = `${color}1f`;
2050
+ fillRoundedRect(-bgWidth / 2, -bgHeight, bgWidth, bgHeight, 4);
2051
+ ctx.fillStyle = color;
2052
+ ctx.textAlign = "center";
2053
+ ctx.textBaseline = "middle";
2054
+ ctx.fillText(labelText, 0, -bgHeight / 2);
2055
+ ctx.font = prevFont;
2056
+ void paddingY;
2057
+ ctx.restore();
2058
+ };
2034
2059
  const drawDrawing = (drawing, draft = false) => {
2035
2060
  if (!drawing.visible) {
2036
2061
  return;
@@ -2050,6 +2075,9 @@ function createChart(element, options = {}) {
2050
2075
  ctx.lineTo(crisp(chartRight), crisp(y));
2051
2076
  ctx.stroke();
2052
2077
  drawDrawingHandle(handleX, y, drawing.color);
2078
+ if (drawing.label) {
2079
+ drawDrawingLabel(drawing.label, chartLeft + 60, y, drawing.color, 0);
2080
+ }
2053
2081
  }
2054
2082
  } else if (drawing.type === "trendline") {
2055
2083
  const first = drawing.points[0];
@@ -2065,6 +2093,12 @@ function createChart(element, options = {}) {
2065
2093
  ctx.stroke();
2066
2094
  drawDrawingHandle(firstX, firstY, drawing.color);
2067
2095
  drawDrawingHandle(secondX, secondY, drawing.color);
2096
+ if (drawing.label) {
2097
+ const midX = (firstX + secondX) / 2;
2098
+ const midY = (firstY + secondY) / 2;
2099
+ const angle = Math.atan2(secondY - firstY, secondX - firstX);
2100
+ drawDrawingLabel(drawing.label, midX, midY, drawing.color, angle);
2101
+ }
2068
2102
  }
2069
2103
  }
2070
2104
  ctx.restore();
@@ -3574,8 +3608,23 @@ function createChart(element, options = {}) {
3574
3608
  const drawingHit = getDrawingHit(point.x, point.y);
3575
3609
  canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
3576
3610
  setCrosshairPoint(null);
3611
+ if (drawingHit && drawingHoverHandler) {
3612
+ if (lastHoveredDrawingId !== drawingHit.drawing.id) {
3613
+ lastHoveredDrawingId = drawingHit.drawing.id;
3614
+ }
3615
+ drawingHoverHandler({
3616
+ drawing: serializeDrawing(drawingHit.drawing),
3617
+ target: drawingHit.target,
3618
+ x: point.x,
3619
+ y: point.y
3620
+ });
3621
+ }
3577
3622
  return;
3578
3623
  }
3624
+ if (lastHoveredDrawingId !== null) {
3625
+ lastHoveredDrawingId = null;
3626
+ drawingHoverHandler?.({ drawing: null, target: null, x: point.x, y: point.y });
3627
+ }
3579
3628
  const hoverRegion = getHitRegion(point.x, point.y);
3580
3629
  if (hoverRegion === "plot") {
3581
3630
  canvas.style.cursor = activeDrawingTool ? "crosshair" : doubleClickEnabled ? "default" : "crosshair";
@@ -4031,6 +4080,9 @@ function createChart(element, options = {}) {
4031
4080
  const onDrawingSelect = (handler) => {
4032
4081
  drawingSelectHandler = handler;
4033
4082
  };
4083
+ const onDrawingHover = (handler) => {
4084
+ drawingHoverHandler = handler;
4085
+ };
4034
4086
  const destroy = () => {
4035
4087
  if (smoothingRafId !== null) {
4036
4088
  cancelAnimationFrame(smoothingRafId);
@@ -4084,6 +4136,7 @@ function createChart(element, options = {}) {
4084
4136
  clearDrawings,
4085
4137
  onDrawingsChange,
4086
4138
  onDrawingSelect,
4139
+ onDrawingHover,
4087
4140
  setDoubleClickEnabled,
4088
4141
  setDoubleClickAction,
4089
4142
  registerIndicator,
@@ -67,6 +67,12 @@ interface DrawingSelectEvent {
67
67
  x: number;
68
68
  y: number;
69
69
  }
70
+ interface DrawingHoverEvent {
71
+ drawing: DrawingObjectOptions | null;
72
+ target: "line" | "handle" | null;
73
+ x: number;
74
+ y: number;
75
+ }
70
76
  interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
71
77
  id?: string;
72
78
  type: string;
@@ -398,6 +404,7 @@ interface ChartInstance {
398
404
  clearDrawings: () => void;
399
405
  onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
400
406
  onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
407
+ onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
401
408
  setDoubleClickEnabled: (enabled: boolean) => void;
402
409
  setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
403
410
  registerIndicator: (plugin: IndicatorPlugin<any>) => void;
@@ -433,4 +440,4 @@ interface ViewportState {
433
440
  }
434
441
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
435
442
 
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 };
443
+ export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingHoverEvent, 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 };
@@ -938,6 +938,8 @@ function createChart(element, options = {}) {
938
938
  let drawingDragState = null;
939
939
  let drawingsChangeHandler = null;
940
940
  let drawingSelectHandler = null;
941
+ let drawingHoverHandler = null;
942
+ let lastHoveredDrawingId = null;
941
943
  const emitDrawingsChange = () => {
942
944
  drawingsChangeHandler?.(drawings.map((drawing) => serializeDrawing(drawing)));
943
945
  };
@@ -2007,6 +2009,29 @@ function createChart(element, options = {}) {
2007
2009
  ctx.stroke();
2008
2010
  ctx.restore();
2009
2011
  };
2012
+ const drawDrawingLabel = (labelText, anchorX, anchorY, color, angle) => {
2013
+ if (!labelText) return;
2014
+ ctx.save();
2015
+ ctx.translate(anchorX, anchorY);
2016
+ ctx.rotate(angle);
2017
+ ctx.translate(0, -8);
2018
+ const prevFont = ctx.font;
2019
+ ctx.font = `500 12px ${mergedOptions.fontFamily}`;
2020
+ const textWidth = ctx.measureText(labelText).width;
2021
+ const paddingX = 6;
2022
+ const paddingY = 3;
2023
+ const bgWidth = textWidth + paddingX * 2;
2024
+ const bgHeight = 18;
2025
+ ctx.fillStyle = `${color}1f`;
2026
+ fillRoundedRect(-bgWidth / 2, -bgHeight, bgWidth, bgHeight, 4);
2027
+ ctx.fillStyle = color;
2028
+ ctx.textAlign = "center";
2029
+ ctx.textBaseline = "middle";
2030
+ ctx.fillText(labelText, 0, -bgHeight / 2);
2031
+ ctx.font = prevFont;
2032
+ void paddingY;
2033
+ ctx.restore();
2034
+ };
2010
2035
  const drawDrawing = (drawing, draft = false) => {
2011
2036
  if (!drawing.visible) {
2012
2037
  return;
@@ -2026,6 +2051,9 @@ function createChart(element, options = {}) {
2026
2051
  ctx.lineTo(crisp(chartRight), crisp(y));
2027
2052
  ctx.stroke();
2028
2053
  drawDrawingHandle(handleX, y, drawing.color);
2054
+ if (drawing.label) {
2055
+ drawDrawingLabel(drawing.label, chartLeft + 60, y, drawing.color, 0);
2056
+ }
2029
2057
  }
2030
2058
  } else if (drawing.type === "trendline") {
2031
2059
  const first = drawing.points[0];
@@ -2041,6 +2069,12 @@ function createChart(element, options = {}) {
2041
2069
  ctx.stroke();
2042
2070
  drawDrawingHandle(firstX, firstY, drawing.color);
2043
2071
  drawDrawingHandle(secondX, secondY, drawing.color);
2072
+ if (drawing.label) {
2073
+ const midX = (firstX + secondX) / 2;
2074
+ const midY = (firstY + secondY) / 2;
2075
+ const angle = Math.atan2(secondY - firstY, secondX - firstX);
2076
+ drawDrawingLabel(drawing.label, midX, midY, drawing.color, angle);
2077
+ }
2044
2078
  }
2045
2079
  }
2046
2080
  ctx.restore();
@@ -3550,8 +3584,23 @@ function createChart(element, options = {}) {
3550
3584
  const drawingHit = getDrawingHit(point.x, point.y);
3551
3585
  canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
3552
3586
  setCrosshairPoint(null);
3587
+ if (drawingHit && drawingHoverHandler) {
3588
+ if (lastHoveredDrawingId !== drawingHit.drawing.id) {
3589
+ lastHoveredDrawingId = drawingHit.drawing.id;
3590
+ }
3591
+ drawingHoverHandler({
3592
+ drawing: serializeDrawing(drawingHit.drawing),
3593
+ target: drawingHit.target,
3594
+ x: point.x,
3595
+ y: point.y
3596
+ });
3597
+ }
3553
3598
  return;
3554
3599
  }
3600
+ if (lastHoveredDrawingId !== null) {
3601
+ lastHoveredDrawingId = null;
3602
+ drawingHoverHandler?.({ drawing: null, target: null, x: point.x, y: point.y });
3603
+ }
3555
3604
  const hoverRegion = getHitRegion(point.x, point.y);
3556
3605
  if (hoverRegion === "plot") {
3557
3606
  canvas.style.cursor = activeDrawingTool ? "crosshair" : doubleClickEnabled ? "default" : "crosshair";
@@ -4007,6 +4056,9 @@ function createChart(element, options = {}) {
4007
4056
  const onDrawingSelect = (handler) => {
4008
4057
  drawingSelectHandler = handler;
4009
4058
  };
4059
+ const onDrawingHover = (handler) => {
4060
+ drawingHoverHandler = handler;
4061
+ };
4010
4062
  const destroy = () => {
4011
4063
  if (smoothingRafId !== null) {
4012
4064
  cancelAnimationFrame(smoothingRafId);
@@ -4060,6 +4112,7 @@ function createChart(element, options = {}) {
4060
4112
  clearDrawings,
4061
4113
  onDrawingsChange,
4062
4114
  onDrawingSelect,
4115
+ onDrawingHover,
4063
4116
  setDoubleClickEnabled,
4064
4117
  setDoubleClickAction,
4065
4118
  registerIndicator,
package/dist/index.cjs CHANGED
@@ -962,6 +962,8 @@ function createChart(element, options = {}) {
962
962
  let drawingDragState = null;
963
963
  let drawingsChangeHandler = null;
964
964
  let drawingSelectHandler = null;
965
+ let drawingHoverHandler = null;
966
+ let lastHoveredDrawingId = null;
965
967
  const emitDrawingsChange = () => {
966
968
  drawingsChangeHandler?.(drawings.map((drawing) => serializeDrawing(drawing)));
967
969
  };
@@ -2031,6 +2033,29 @@ function createChart(element, options = {}) {
2031
2033
  ctx.stroke();
2032
2034
  ctx.restore();
2033
2035
  };
2036
+ const drawDrawingLabel = (labelText, anchorX, anchorY, color, angle) => {
2037
+ if (!labelText) return;
2038
+ ctx.save();
2039
+ ctx.translate(anchorX, anchorY);
2040
+ ctx.rotate(angle);
2041
+ ctx.translate(0, -8);
2042
+ const prevFont = ctx.font;
2043
+ ctx.font = `500 12px ${mergedOptions.fontFamily}`;
2044
+ const textWidth = ctx.measureText(labelText).width;
2045
+ const paddingX = 6;
2046
+ const paddingY = 3;
2047
+ const bgWidth = textWidth + paddingX * 2;
2048
+ const bgHeight = 18;
2049
+ ctx.fillStyle = `${color}1f`;
2050
+ fillRoundedRect(-bgWidth / 2, -bgHeight, bgWidth, bgHeight, 4);
2051
+ ctx.fillStyle = color;
2052
+ ctx.textAlign = "center";
2053
+ ctx.textBaseline = "middle";
2054
+ ctx.fillText(labelText, 0, -bgHeight / 2);
2055
+ ctx.font = prevFont;
2056
+ void paddingY;
2057
+ ctx.restore();
2058
+ };
2034
2059
  const drawDrawing = (drawing, draft = false) => {
2035
2060
  if (!drawing.visible) {
2036
2061
  return;
@@ -2050,6 +2075,9 @@ function createChart(element, options = {}) {
2050
2075
  ctx.lineTo(crisp(chartRight), crisp(y));
2051
2076
  ctx.stroke();
2052
2077
  drawDrawingHandle(handleX, y, drawing.color);
2078
+ if (drawing.label) {
2079
+ drawDrawingLabel(drawing.label, chartLeft + 60, y, drawing.color, 0);
2080
+ }
2053
2081
  }
2054
2082
  } else if (drawing.type === "trendline") {
2055
2083
  const first = drawing.points[0];
@@ -2065,6 +2093,12 @@ function createChart(element, options = {}) {
2065
2093
  ctx.stroke();
2066
2094
  drawDrawingHandle(firstX, firstY, drawing.color);
2067
2095
  drawDrawingHandle(secondX, secondY, drawing.color);
2096
+ if (drawing.label) {
2097
+ const midX = (firstX + secondX) / 2;
2098
+ const midY = (firstY + secondY) / 2;
2099
+ const angle = Math.atan2(secondY - firstY, secondX - firstX);
2100
+ drawDrawingLabel(drawing.label, midX, midY, drawing.color, angle);
2101
+ }
2068
2102
  }
2069
2103
  }
2070
2104
  ctx.restore();
@@ -3574,8 +3608,23 @@ function createChart(element, options = {}) {
3574
3608
  const drawingHit = getDrawingHit(point.x, point.y);
3575
3609
  canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
3576
3610
  setCrosshairPoint(null);
3611
+ if (drawingHit && drawingHoverHandler) {
3612
+ if (lastHoveredDrawingId !== drawingHit.drawing.id) {
3613
+ lastHoveredDrawingId = drawingHit.drawing.id;
3614
+ }
3615
+ drawingHoverHandler({
3616
+ drawing: serializeDrawing(drawingHit.drawing),
3617
+ target: drawingHit.target,
3618
+ x: point.x,
3619
+ y: point.y
3620
+ });
3621
+ }
3577
3622
  return;
3578
3623
  }
3624
+ if (lastHoveredDrawingId !== null) {
3625
+ lastHoveredDrawingId = null;
3626
+ drawingHoverHandler?.({ drawing: null, target: null, x: point.x, y: point.y });
3627
+ }
3579
3628
  const hoverRegion = getHitRegion(point.x, point.y);
3580
3629
  if (hoverRegion === "plot") {
3581
3630
  canvas.style.cursor = activeDrawingTool ? "crosshair" : doubleClickEnabled ? "default" : "crosshair";
@@ -4031,6 +4080,9 @@ function createChart(element, options = {}) {
4031
4080
  const onDrawingSelect = (handler) => {
4032
4081
  drawingSelectHandler = handler;
4033
4082
  };
4083
+ const onDrawingHover = (handler) => {
4084
+ drawingHoverHandler = handler;
4085
+ };
4034
4086
  const destroy = () => {
4035
4087
  if (smoothingRafId !== null) {
4036
4088
  cancelAnimationFrame(smoothingRafId);
@@ -4084,6 +4136,7 @@ function createChart(element, options = {}) {
4084
4136
  clearDrawings,
4085
4137
  onDrawingsChange,
4086
4138
  onDrawingSelect,
4139
+ onDrawingHover,
4087
4140
  setDoubleClickEnabled,
4088
4141
  setDoubleClickAction,
4089
4142
  registerIndicator,
package/dist/index.d.cts CHANGED
@@ -67,6 +67,12 @@ interface DrawingSelectEvent {
67
67
  x: number;
68
68
  y: number;
69
69
  }
70
+ interface DrawingHoverEvent {
71
+ drawing: DrawingObjectOptions | null;
72
+ target: "line" | "handle" | null;
73
+ x: number;
74
+ y: number;
75
+ }
70
76
  interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
71
77
  id?: string;
72
78
  type: string;
@@ -398,6 +404,7 @@ interface ChartInstance {
398
404
  clearDrawings: () => void;
399
405
  onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
400
406
  onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
407
+ onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
401
408
  setDoubleClickEnabled: (enabled: boolean) => void;
402
409
  setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
403
410
  registerIndicator: (plugin: IndicatorPlugin<any>) => void;
@@ -433,4 +440,4 @@ interface ViewportState {
433
440
  }
434
441
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
435
442
 
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 };
443
+ export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingHoverEvent, 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
@@ -67,6 +67,12 @@ interface DrawingSelectEvent {
67
67
  x: number;
68
68
  y: number;
69
69
  }
70
+ interface DrawingHoverEvent {
71
+ drawing: DrawingObjectOptions | null;
72
+ target: "line" | "handle" | null;
73
+ x: number;
74
+ y: number;
75
+ }
70
76
  interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Record<string, unknown>> {
71
77
  id?: string;
72
78
  type: string;
@@ -398,6 +404,7 @@ interface ChartInstance {
398
404
  clearDrawings: () => void;
399
405
  onDrawingsChange: (handler: ((drawings: DrawingObjectOptions[]) => void) | null) => void;
400
406
  onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
407
+ onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
401
408
  setDoubleClickEnabled: (enabled: boolean) => void;
402
409
  setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
403
410
  registerIndicator: (plugin: IndicatorPlugin<any>) => void;
@@ -433,4 +440,4 @@ interface ViewportState {
433
440
  }
434
441
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
435
442
 
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 };
443
+ export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingHoverEvent, 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.js CHANGED
@@ -938,6 +938,8 @@ function createChart(element, options = {}) {
938
938
  let drawingDragState = null;
939
939
  let drawingsChangeHandler = null;
940
940
  let drawingSelectHandler = null;
941
+ let drawingHoverHandler = null;
942
+ let lastHoveredDrawingId = null;
941
943
  const emitDrawingsChange = () => {
942
944
  drawingsChangeHandler?.(drawings.map((drawing) => serializeDrawing(drawing)));
943
945
  };
@@ -2007,6 +2009,29 @@ function createChart(element, options = {}) {
2007
2009
  ctx.stroke();
2008
2010
  ctx.restore();
2009
2011
  };
2012
+ const drawDrawingLabel = (labelText, anchorX, anchorY, color, angle) => {
2013
+ if (!labelText) return;
2014
+ ctx.save();
2015
+ ctx.translate(anchorX, anchorY);
2016
+ ctx.rotate(angle);
2017
+ ctx.translate(0, -8);
2018
+ const prevFont = ctx.font;
2019
+ ctx.font = `500 12px ${mergedOptions.fontFamily}`;
2020
+ const textWidth = ctx.measureText(labelText).width;
2021
+ const paddingX = 6;
2022
+ const paddingY = 3;
2023
+ const bgWidth = textWidth + paddingX * 2;
2024
+ const bgHeight = 18;
2025
+ ctx.fillStyle = `${color}1f`;
2026
+ fillRoundedRect(-bgWidth / 2, -bgHeight, bgWidth, bgHeight, 4);
2027
+ ctx.fillStyle = color;
2028
+ ctx.textAlign = "center";
2029
+ ctx.textBaseline = "middle";
2030
+ ctx.fillText(labelText, 0, -bgHeight / 2);
2031
+ ctx.font = prevFont;
2032
+ void paddingY;
2033
+ ctx.restore();
2034
+ };
2010
2035
  const drawDrawing = (drawing, draft = false) => {
2011
2036
  if (!drawing.visible) {
2012
2037
  return;
@@ -2026,6 +2051,9 @@ function createChart(element, options = {}) {
2026
2051
  ctx.lineTo(crisp(chartRight), crisp(y));
2027
2052
  ctx.stroke();
2028
2053
  drawDrawingHandle(handleX, y, drawing.color);
2054
+ if (drawing.label) {
2055
+ drawDrawingLabel(drawing.label, chartLeft + 60, y, drawing.color, 0);
2056
+ }
2029
2057
  }
2030
2058
  } else if (drawing.type === "trendline") {
2031
2059
  const first = drawing.points[0];
@@ -2041,6 +2069,12 @@ function createChart(element, options = {}) {
2041
2069
  ctx.stroke();
2042
2070
  drawDrawingHandle(firstX, firstY, drawing.color);
2043
2071
  drawDrawingHandle(secondX, secondY, drawing.color);
2072
+ if (drawing.label) {
2073
+ const midX = (firstX + secondX) / 2;
2074
+ const midY = (firstY + secondY) / 2;
2075
+ const angle = Math.atan2(secondY - firstY, secondX - firstX);
2076
+ drawDrawingLabel(drawing.label, midX, midY, drawing.color, angle);
2077
+ }
2044
2078
  }
2045
2079
  }
2046
2080
  ctx.restore();
@@ -3550,8 +3584,23 @@ function createChart(element, options = {}) {
3550
3584
  const drawingHit = getDrawingHit(point.x, point.y);
3551
3585
  canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
3552
3586
  setCrosshairPoint(null);
3587
+ if (drawingHit && drawingHoverHandler) {
3588
+ if (lastHoveredDrawingId !== drawingHit.drawing.id) {
3589
+ lastHoveredDrawingId = drawingHit.drawing.id;
3590
+ }
3591
+ drawingHoverHandler({
3592
+ drawing: serializeDrawing(drawingHit.drawing),
3593
+ target: drawingHit.target,
3594
+ x: point.x,
3595
+ y: point.y
3596
+ });
3597
+ }
3553
3598
  return;
3554
3599
  }
3600
+ if (lastHoveredDrawingId !== null) {
3601
+ lastHoveredDrawingId = null;
3602
+ drawingHoverHandler?.({ drawing: null, target: null, x: point.x, y: point.y });
3603
+ }
3555
3604
  const hoverRegion = getHitRegion(point.x, point.y);
3556
3605
  if (hoverRegion === "plot") {
3557
3606
  canvas.style.cursor = activeDrawingTool ? "crosshair" : doubleClickEnabled ? "default" : "crosshair";
@@ -4007,6 +4056,9 @@ function createChart(element, options = {}) {
4007
4056
  const onDrawingSelect = (handler) => {
4008
4057
  drawingSelectHandler = handler;
4009
4058
  };
4059
+ const onDrawingHover = (handler) => {
4060
+ drawingHoverHandler = handler;
4061
+ };
4010
4062
  const destroy = () => {
4011
4063
  if (smoothingRafId !== null) {
4012
4064
  cancelAnimationFrame(smoothingRafId);
@@ -4060,6 +4112,7 @@ function createChart(element, options = {}) {
4060
4112
  clearDrawings,
4061
4113
  onDrawingsChange,
4062
4114
  onDrawingSelect,
4115
+ onDrawingHover,
4063
4116
  setDoubleClickEnabled,
4064
4117
  setDoubleClickAction,
4065
4118
  registerIndicator,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperprop-charting-library",
3
- "version": "0.1.57",
3
+ "version": "0.1.58",
4
4
  "description": "Lightweight TypeScript charting core",
5
5
  "type": "module",
6
6
  "main": "./dist/hyperprop-charting-library.cjs",