hyperprop-charting-library 0.1.57 → 0.1.59

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,26 @@ function createChart(element, options = {}) {
2031
2033
  ctx.stroke();
2032
2034
  ctx.restore();
2033
2035
  };
2036
+ const drawDrawingLabel = (labelText, anchorX, anchorY, color) => {
2037
+ if (!labelText) return;
2038
+ ctx.save();
2039
+ const prevFont = ctx.font;
2040
+ ctx.font = `500 12px ${mergedOptions.fontFamily}`;
2041
+ const textWidth = ctx.measureText(labelText).width;
2042
+ const paddingX = 6;
2043
+ const bgWidth = textWidth + paddingX * 2;
2044
+ const bgHeight = 18;
2045
+ const bgX = anchorX - bgWidth / 2;
2046
+ const bgY = anchorY - bgHeight - 6;
2047
+ ctx.fillStyle = `${color}1f`;
2048
+ fillRoundedRect(bgX, bgY, bgWidth, bgHeight, 4);
2049
+ ctx.fillStyle = color;
2050
+ ctx.textAlign = "center";
2051
+ ctx.textBaseline = "middle";
2052
+ ctx.fillText(labelText, anchorX, bgY + bgHeight / 2);
2053
+ ctx.font = prevFont;
2054
+ ctx.restore();
2055
+ };
2034
2056
  const drawDrawing = (drawing, draft = false) => {
2035
2057
  if (!drawing.visible) {
2036
2058
  return;
@@ -2050,6 +2072,10 @@ function createChart(element, options = {}) {
2050
2072
  ctx.lineTo(crisp(chartRight), crisp(y));
2051
2073
  ctx.stroke();
2052
2074
  drawDrawingHandle(handleX, y, drawing.color);
2075
+ if (drawing.label) {
2076
+ const midX = (chartLeft + chartRight) / 2;
2077
+ drawDrawingLabel(drawing.label, midX, y, drawing.color);
2078
+ }
2053
2079
  }
2054
2080
  } else if (drawing.type === "trendline") {
2055
2081
  const first = drawing.points[0];
@@ -2065,6 +2091,11 @@ function createChart(element, options = {}) {
2065
2091
  ctx.stroke();
2066
2092
  drawDrawingHandle(firstX, firstY, drawing.color);
2067
2093
  drawDrawingHandle(secondX, secondY, drawing.color);
2094
+ if (drawing.label) {
2095
+ const midX = (firstX + secondX) / 2;
2096
+ const midY = (firstY + secondY) / 2;
2097
+ drawDrawingLabel(drawing.label, midX, midY, drawing.color);
2098
+ }
2068
2099
  }
2069
2100
  }
2070
2101
  ctx.restore();
@@ -3574,8 +3605,23 @@ function createChart(element, options = {}) {
3574
3605
  const drawingHit = getDrawingHit(point.x, point.y);
3575
3606
  canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
3576
3607
  setCrosshairPoint(null);
3608
+ if (drawingHit && drawingHoverHandler) {
3609
+ if (lastHoveredDrawingId !== drawingHit.drawing.id) {
3610
+ lastHoveredDrawingId = drawingHit.drawing.id;
3611
+ }
3612
+ drawingHoverHandler({
3613
+ drawing: serializeDrawing(drawingHit.drawing),
3614
+ target: drawingHit.target,
3615
+ x: point.x,
3616
+ y: point.y
3617
+ });
3618
+ }
3577
3619
  return;
3578
3620
  }
3621
+ if (lastHoveredDrawingId !== null) {
3622
+ lastHoveredDrawingId = null;
3623
+ drawingHoverHandler?.({ drawing: null, target: null, x: point.x, y: point.y });
3624
+ }
3579
3625
  const hoverRegion = getHitRegion(point.x, point.y);
3580
3626
  if (hoverRegion === "plot") {
3581
3627
  canvas.style.cursor = activeDrawingTool ? "crosshair" : doubleClickEnabled ? "default" : "crosshair";
@@ -4031,6 +4077,9 @@ function createChart(element, options = {}) {
4031
4077
  const onDrawingSelect = (handler) => {
4032
4078
  drawingSelectHandler = handler;
4033
4079
  };
4080
+ const onDrawingHover = (handler) => {
4081
+ drawingHoverHandler = handler;
4082
+ };
4034
4083
  const destroy = () => {
4035
4084
  if (smoothingRafId !== null) {
4036
4085
  cancelAnimationFrame(smoothingRafId);
@@ -4084,6 +4133,7 @@ function createChart(element, options = {}) {
4084
4133
  clearDrawings,
4085
4134
  onDrawingsChange,
4086
4135
  onDrawingSelect,
4136
+ onDrawingHover,
4087
4137
  setDoubleClickEnabled,
4088
4138
  setDoubleClickAction,
4089
4139
  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,26 @@ function createChart(element, options = {}) {
2007
2009
  ctx.stroke();
2008
2010
  ctx.restore();
2009
2011
  };
2012
+ const drawDrawingLabel = (labelText, anchorX, anchorY, color) => {
2013
+ if (!labelText) return;
2014
+ ctx.save();
2015
+ const prevFont = ctx.font;
2016
+ ctx.font = `500 12px ${mergedOptions.fontFamily}`;
2017
+ const textWidth = ctx.measureText(labelText).width;
2018
+ const paddingX = 6;
2019
+ const bgWidth = textWidth + paddingX * 2;
2020
+ const bgHeight = 18;
2021
+ const bgX = anchorX - bgWidth / 2;
2022
+ const bgY = anchorY - bgHeight - 6;
2023
+ ctx.fillStyle = `${color}1f`;
2024
+ fillRoundedRect(bgX, bgY, bgWidth, bgHeight, 4);
2025
+ ctx.fillStyle = color;
2026
+ ctx.textAlign = "center";
2027
+ ctx.textBaseline = "middle";
2028
+ ctx.fillText(labelText, anchorX, bgY + bgHeight / 2);
2029
+ ctx.font = prevFont;
2030
+ ctx.restore();
2031
+ };
2010
2032
  const drawDrawing = (drawing, draft = false) => {
2011
2033
  if (!drawing.visible) {
2012
2034
  return;
@@ -2026,6 +2048,10 @@ function createChart(element, options = {}) {
2026
2048
  ctx.lineTo(crisp(chartRight), crisp(y));
2027
2049
  ctx.stroke();
2028
2050
  drawDrawingHandle(handleX, y, drawing.color);
2051
+ if (drawing.label) {
2052
+ const midX = (chartLeft + chartRight) / 2;
2053
+ drawDrawingLabel(drawing.label, midX, y, drawing.color);
2054
+ }
2029
2055
  }
2030
2056
  } else if (drawing.type === "trendline") {
2031
2057
  const first = drawing.points[0];
@@ -2041,6 +2067,11 @@ function createChart(element, options = {}) {
2041
2067
  ctx.stroke();
2042
2068
  drawDrawingHandle(firstX, firstY, drawing.color);
2043
2069
  drawDrawingHandle(secondX, secondY, drawing.color);
2070
+ if (drawing.label) {
2071
+ const midX = (firstX + secondX) / 2;
2072
+ const midY = (firstY + secondY) / 2;
2073
+ drawDrawingLabel(drawing.label, midX, midY, drawing.color);
2074
+ }
2044
2075
  }
2045
2076
  }
2046
2077
  ctx.restore();
@@ -3550,8 +3581,23 @@ function createChart(element, options = {}) {
3550
3581
  const drawingHit = getDrawingHit(point.x, point.y);
3551
3582
  canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
3552
3583
  setCrosshairPoint(null);
3584
+ if (drawingHit && drawingHoverHandler) {
3585
+ if (lastHoveredDrawingId !== drawingHit.drawing.id) {
3586
+ lastHoveredDrawingId = drawingHit.drawing.id;
3587
+ }
3588
+ drawingHoverHandler({
3589
+ drawing: serializeDrawing(drawingHit.drawing),
3590
+ target: drawingHit.target,
3591
+ x: point.x,
3592
+ y: point.y
3593
+ });
3594
+ }
3553
3595
  return;
3554
3596
  }
3597
+ if (lastHoveredDrawingId !== null) {
3598
+ lastHoveredDrawingId = null;
3599
+ drawingHoverHandler?.({ drawing: null, target: null, x: point.x, y: point.y });
3600
+ }
3555
3601
  const hoverRegion = getHitRegion(point.x, point.y);
3556
3602
  if (hoverRegion === "plot") {
3557
3603
  canvas.style.cursor = activeDrawingTool ? "crosshair" : doubleClickEnabled ? "default" : "crosshair";
@@ -4007,6 +4053,9 @@ function createChart(element, options = {}) {
4007
4053
  const onDrawingSelect = (handler) => {
4008
4054
  drawingSelectHandler = handler;
4009
4055
  };
4056
+ const onDrawingHover = (handler) => {
4057
+ drawingHoverHandler = handler;
4058
+ };
4010
4059
  const destroy = () => {
4011
4060
  if (smoothingRafId !== null) {
4012
4061
  cancelAnimationFrame(smoothingRafId);
@@ -4060,6 +4109,7 @@ function createChart(element, options = {}) {
4060
4109
  clearDrawings,
4061
4110
  onDrawingsChange,
4062
4111
  onDrawingSelect,
4112
+ onDrawingHover,
4063
4113
  setDoubleClickEnabled,
4064
4114
  setDoubleClickAction,
4065
4115
  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,26 @@ function createChart(element, options = {}) {
2031
2033
  ctx.stroke();
2032
2034
  ctx.restore();
2033
2035
  };
2036
+ const drawDrawingLabel = (labelText, anchorX, anchorY, color) => {
2037
+ if (!labelText) return;
2038
+ ctx.save();
2039
+ const prevFont = ctx.font;
2040
+ ctx.font = `500 12px ${mergedOptions.fontFamily}`;
2041
+ const textWidth = ctx.measureText(labelText).width;
2042
+ const paddingX = 6;
2043
+ const bgWidth = textWidth + paddingX * 2;
2044
+ const bgHeight = 18;
2045
+ const bgX = anchorX - bgWidth / 2;
2046
+ const bgY = anchorY - bgHeight - 6;
2047
+ ctx.fillStyle = `${color}1f`;
2048
+ fillRoundedRect(bgX, bgY, bgWidth, bgHeight, 4);
2049
+ ctx.fillStyle = color;
2050
+ ctx.textAlign = "center";
2051
+ ctx.textBaseline = "middle";
2052
+ ctx.fillText(labelText, anchorX, bgY + bgHeight / 2);
2053
+ ctx.font = prevFont;
2054
+ ctx.restore();
2055
+ };
2034
2056
  const drawDrawing = (drawing, draft = false) => {
2035
2057
  if (!drawing.visible) {
2036
2058
  return;
@@ -2050,6 +2072,10 @@ function createChart(element, options = {}) {
2050
2072
  ctx.lineTo(crisp(chartRight), crisp(y));
2051
2073
  ctx.stroke();
2052
2074
  drawDrawingHandle(handleX, y, drawing.color);
2075
+ if (drawing.label) {
2076
+ const midX = (chartLeft + chartRight) / 2;
2077
+ drawDrawingLabel(drawing.label, midX, y, drawing.color);
2078
+ }
2053
2079
  }
2054
2080
  } else if (drawing.type === "trendline") {
2055
2081
  const first = drawing.points[0];
@@ -2065,6 +2091,11 @@ function createChart(element, options = {}) {
2065
2091
  ctx.stroke();
2066
2092
  drawDrawingHandle(firstX, firstY, drawing.color);
2067
2093
  drawDrawingHandle(secondX, secondY, drawing.color);
2094
+ if (drawing.label) {
2095
+ const midX = (firstX + secondX) / 2;
2096
+ const midY = (firstY + secondY) / 2;
2097
+ drawDrawingLabel(drawing.label, midX, midY, drawing.color);
2098
+ }
2068
2099
  }
2069
2100
  }
2070
2101
  ctx.restore();
@@ -3574,8 +3605,23 @@ function createChart(element, options = {}) {
3574
3605
  const drawingHit = getDrawingHit(point.x, point.y);
3575
3606
  canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
3576
3607
  setCrosshairPoint(null);
3608
+ if (drawingHit && drawingHoverHandler) {
3609
+ if (lastHoveredDrawingId !== drawingHit.drawing.id) {
3610
+ lastHoveredDrawingId = drawingHit.drawing.id;
3611
+ }
3612
+ drawingHoverHandler({
3613
+ drawing: serializeDrawing(drawingHit.drawing),
3614
+ target: drawingHit.target,
3615
+ x: point.x,
3616
+ y: point.y
3617
+ });
3618
+ }
3577
3619
  return;
3578
3620
  }
3621
+ if (lastHoveredDrawingId !== null) {
3622
+ lastHoveredDrawingId = null;
3623
+ drawingHoverHandler?.({ drawing: null, target: null, x: point.x, y: point.y });
3624
+ }
3579
3625
  const hoverRegion = getHitRegion(point.x, point.y);
3580
3626
  if (hoverRegion === "plot") {
3581
3627
  canvas.style.cursor = activeDrawingTool ? "crosshair" : doubleClickEnabled ? "default" : "crosshair";
@@ -4031,6 +4077,9 @@ function createChart(element, options = {}) {
4031
4077
  const onDrawingSelect = (handler) => {
4032
4078
  drawingSelectHandler = handler;
4033
4079
  };
4080
+ const onDrawingHover = (handler) => {
4081
+ drawingHoverHandler = handler;
4082
+ };
4034
4083
  const destroy = () => {
4035
4084
  if (smoothingRafId !== null) {
4036
4085
  cancelAnimationFrame(smoothingRafId);
@@ -4084,6 +4133,7 @@ function createChart(element, options = {}) {
4084
4133
  clearDrawings,
4085
4134
  onDrawingsChange,
4086
4135
  onDrawingSelect,
4136
+ onDrawingHover,
4087
4137
  setDoubleClickEnabled,
4088
4138
  setDoubleClickAction,
4089
4139
  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,26 @@ function createChart(element, options = {}) {
2007
2009
  ctx.stroke();
2008
2010
  ctx.restore();
2009
2011
  };
2012
+ const drawDrawingLabel = (labelText, anchorX, anchorY, color) => {
2013
+ if (!labelText) return;
2014
+ ctx.save();
2015
+ const prevFont = ctx.font;
2016
+ ctx.font = `500 12px ${mergedOptions.fontFamily}`;
2017
+ const textWidth = ctx.measureText(labelText).width;
2018
+ const paddingX = 6;
2019
+ const bgWidth = textWidth + paddingX * 2;
2020
+ const bgHeight = 18;
2021
+ const bgX = anchorX - bgWidth / 2;
2022
+ const bgY = anchorY - bgHeight - 6;
2023
+ ctx.fillStyle = `${color}1f`;
2024
+ fillRoundedRect(bgX, bgY, bgWidth, bgHeight, 4);
2025
+ ctx.fillStyle = color;
2026
+ ctx.textAlign = "center";
2027
+ ctx.textBaseline = "middle";
2028
+ ctx.fillText(labelText, anchorX, bgY + bgHeight / 2);
2029
+ ctx.font = prevFont;
2030
+ ctx.restore();
2031
+ };
2010
2032
  const drawDrawing = (drawing, draft = false) => {
2011
2033
  if (!drawing.visible) {
2012
2034
  return;
@@ -2026,6 +2048,10 @@ function createChart(element, options = {}) {
2026
2048
  ctx.lineTo(crisp(chartRight), crisp(y));
2027
2049
  ctx.stroke();
2028
2050
  drawDrawingHandle(handleX, y, drawing.color);
2051
+ if (drawing.label) {
2052
+ const midX = (chartLeft + chartRight) / 2;
2053
+ drawDrawingLabel(drawing.label, midX, y, drawing.color);
2054
+ }
2029
2055
  }
2030
2056
  } else if (drawing.type === "trendline") {
2031
2057
  const first = drawing.points[0];
@@ -2041,6 +2067,11 @@ function createChart(element, options = {}) {
2041
2067
  ctx.stroke();
2042
2068
  drawDrawingHandle(firstX, firstY, drawing.color);
2043
2069
  drawDrawingHandle(secondX, secondY, drawing.color);
2070
+ if (drawing.label) {
2071
+ const midX = (firstX + secondX) / 2;
2072
+ const midY = (firstY + secondY) / 2;
2073
+ drawDrawingLabel(drawing.label, midX, midY, drawing.color);
2074
+ }
2044
2075
  }
2045
2076
  }
2046
2077
  ctx.restore();
@@ -3550,8 +3581,23 @@ function createChart(element, options = {}) {
3550
3581
  const drawingHit = getDrawingHit(point.x, point.y);
3551
3582
  canvas.style.cursor = drawingHit?.drawing.locked ? "pointer" : drawingHit?.target === "handle" ? "grab" : "move";
3552
3583
  setCrosshairPoint(null);
3584
+ if (drawingHit && drawingHoverHandler) {
3585
+ if (lastHoveredDrawingId !== drawingHit.drawing.id) {
3586
+ lastHoveredDrawingId = drawingHit.drawing.id;
3587
+ }
3588
+ drawingHoverHandler({
3589
+ drawing: serializeDrawing(drawingHit.drawing),
3590
+ target: drawingHit.target,
3591
+ x: point.x,
3592
+ y: point.y
3593
+ });
3594
+ }
3553
3595
  return;
3554
3596
  }
3597
+ if (lastHoveredDrawingId !== null) {
3598
+ lastHoveredDrawingId = null;
3599
+ drawingHoverHandler?.({ drawing: null, target: null, x: point.x, y: point.y });
3600
+ }
3555
3601
  const hoverRegion = getHitRegion(point.x, point.y);
3556
3602
  if (hoverRegion === "plot") {
3557
3603
  canvas.style.cursor = activeDrawingTool ? "crosshair" : doubleClickEnabled ? "default" : "crosshair";
@@ -4007,6 +4053,9 @@ function createChart(element, options = {}) {
4007
4053
  const onDrawingSelect = (handler) => {
4008
4054
  drawingSelectHandler = handler;
4009
4055
  };
4056
+ const onDrawingHover = (handler) => {
4057
+ drawingHoverHandler = handler;
4058
+ };
4010
4059
  const destroy = () => {
4011
4060
  if (smoothingRafId !== null) {
4012
4061
  cancelAnimationFrame(smoothingRafId);
@@ -4060,6 +4109,7 @@ function createChart(element, options = {}) {
4060
4109
  clearDrawings,
4061
4110
  onDrawingsChange,
4062
4111
  onDrawingSelect,
4112
+ onDrawingHover,
4063
4113
  setDoubleClickEnabled,
4064
4114
  setDoubleClickAction,
4065
4115
  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.59",
4
4
  "description": "Lightweight TypeScript charting core",
5
5
  "type": "module",
6
6
  "main": "./dist/hyperprop-charting-library.cjs",