@tradingaction/interactive 2.0.13

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.
Files changed (135) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +5 -0
  3. package/lib/Brush.d.ts +35 -0
  4. package/lib/Brush.js +103 -0
  5. package/lib/Brush.js.map +1 -0
  6. package/lib/ClickCallback.d.ts +18 -0
  7. package/lib/ClickCallback.js +12 -0
  8. package/lib/ClickCallback.js.map +1 -0
  9. package/lib/DrawingObjectSelector.d.ts +18 -0
  10. package/lib/DrawingObjectSelector.js +73 -0
  11. package/lib/DrawingObjectSelector.js.map +1 -0
  12. package/lib/EquidistantChannel.d.ts +74 -0
  13. package/lib/EquidistantChannel.js +149 -0
  14. package/lib/EquidistantChannel.js.map +1 -0
  15. package/lib/FibonacciRetracement.d.ts +89 -0
  16. package/lib/FibonacciRetracement.js +184 -0
  17. package/lib/FibonacciRetracement.js.map +1 -0
  18. package/lib/GannFan.d.ts +78 -0
  19. package/lib/GannFan.js +128 -0
  20. package/lib/GannFan.js.map +1 -0
  21. package/lib/InteractiveText.d.ts +65 -0
  22. package/lib/InteractiveText.js +83 -0
  23. package/lib/InteractiveText.js.map +1 -0
  24. package/lib/InteractiveYCoordinate.d.ts +122 -0
  25. package/lib/InteractiveYCoordinate.js +100 -0
  26. package/lib/InteractiveYCoordinate.js.map +1 -0
  27. package/lib/StandardDeviationChannel.d.ts +74 -0
  28. package/lib/StandardDeviationChannel.js +125 -0
  29. package/lib/StandardDeviationChannel.js.map +1 -0
  30. package/lib/TrendLine.d.ts +84 -0
  31. package/lib/TrendLine.js +128 -0
  32. package/lib/TrendLine.js.map +1 -0
  33. package/lib/ZoomButtons.d.ts +30 -0
  34. package/lib/ZoomButtons.js +78 -0
  35. package/lib/ZoomButtons.js.map +1 -0
  36. package/lib/components/ChannelWithArea.d.ts +30 -0
  37. package/lib/components/ChannelWithArea.js +126 -0
  38. package/lib/components/ChannelWithArea.js.map +1 -0
  39. package/lib/components/ClickableCircle.d.ts +26 -0
  40. package/lib/components/ClickableCircle.js +48 -0
  41. package/lib/components/ClickableCircle.js.map +1 -0
  42. package/lib/components/ClickableShape.d.ts +33 -0
  43. package/lib/components/ClickableShape.js +64 -0
  44. package/lib/components/ClickableShape.js.map +1 -0
  45. package/lib/components/GannFan.d.ts +32 -0
  46. package/lib/components/GannFan.js +134 -0
  47. package/lib/components/GannFan.js.map +1 -0
  48. package/lib/components/HoverTextNearMouse.d.ts +35 -0
  49. package/lib/components/HoverTextNearMouse.js +113 -0
  50. package/lib/components/HoverTextNearMouse.js.map +1 -0
  51. package/lib/components/InteractiveStraightLine.d.ts +61 -0
  52. package/lib/components/InteractiveStraightLine.js +220 -0
  53. package/lib/components/InteractiveStraightLine.js.map +1 -0
  54. package/lib/components/InteractiveText.d.ts +38 -0
  55. package/lib/components/InteractiveText.js +84 -0
  56. package/lib/components/InteractiveText.js.map +1 -0
  57. package/lib/components/InteractiveYCoordinate.d.ts +46 -0
  58. package/lib/components/InteractiveYCoordinate.js +109 -0
  59. package/lib/components/InteractiveYCoordinate.js.map +1 -0
  60. package/lib/components/LinearRegressionChannelWithArea.d.ts +31 -0
  61. package/lib/components/LinearRegressionChannelWithArea.js +104 -0
  62. package/lib/components/LinearRegressionChannelWithArea.js.map +1 -0
  63. package/lib/components/MouseLocationIndicator.d.ts +34 -0
  64. package/lib/components/MouseLocationIndicator.js +79 -0
  65. package/lib/components/MouseLocationIndicator.js.map +1 -0
  66. package/lib/components/Text.d.ts +17 -0
  67. package/lib/components/Text.js +26 -0
  68. package/lib/components/Text.js.map +1 -0
  69. package/lib/components/index.d.ts +11 -0
  70. package/lib/components/index.js +12 -0
  71. package/lib/components/index.js.map +1 -0
  72. package/lib/index.d.ts +12 -0
  73. package/lib/index.js +13 -0
  74. package/lib/index.js.map +1 -0
  75. package/lib/utils.d.ts +7 -0
  76. package/lib/utils.js +84 -0
  77. package/lib/utils.js.map +1 -0
  78. package/lib/wrapper/EachEquidistantChannel.d.ts +59 -0
  79. package/lib/wrapper/EachEquidistantChannel.js +172 -0
  80. package/lib/wrapper/EachEquidistantChannel.js.map +1 -0
  81. package/lib/wrapper/EachFibRetracement.d.ts +81 -0
  82. package/lib/wrapper/EachFibRetracement.js +202 -0
  83. package/lib/wrapper/EachFibRetracement.js.map +1 -0
  84. package/lib/wrapper/EachGannFan.d.ts +81 -0
  85. package/lib/wrapper/EachGannFan.js +161 -0
  86. package/lib/wrapper/EachGannFan.js.map +1 -0
  87. package/lib/wrapper/EachInteractiveYCoordinate.d.ts +50 -0
  88. package/lib/wrapper/EachInteractiveYCoordinate.js +80 -0
  89. package/lib/wrapper/EachInteractiveYCoordinate.js.map +1 -0
  90. package/lib/wrapper/EachLinearRegressionChannel.d.ts +75 -0
  91. package/lib/wrapper/EachLinearRegressionChannel.js +89 -0
  92. package/lib/wrapper/EachLinearRegressionChannel.js.map +1 -0
  93. package/lib/wrapper/EachText.d.ts +59 -0
  94. package/lib/wrapper/EachText.js +83 -0
  95. package/lib/wrapper/EachText.js.map +1 -0
  96. package/lib/wrapper/EachTrendLine.d.ts +85 -0
  97. package/lib/wrapper/EachTrendLine.js +165 -0
  98. package/lib/wrapper/EachTrendLine.js.map +1 -0
  99. package/lib/wrapper/index.d.ts +7 -0
  100. package/lib/wrapper/index.js +8 -0
  101. package/lib/wrapper/index.js.map +1 -0
  102. package/package.json +53 -0
  103. package/src/Brush.tsx +172 -0
  104. package/src/ClickCallback.tsx +37 -0
  105. package/src/DrawingObjectSelector.tsx +97 -0
  106. package/src/EquidistantChannel.tsx +268 -0
  107. package/src/FibonacciRetracement.tsx +328 -0
  108. package/src/GannFan.tsx +233 -0
  109. package/src/InteractiveText.tsx +182 -0
  110. package/src/InteractiveYCoordinate.tsx +199 -0
  111. package/src/StandardDeviationChannel.tsx +269 -0
  112. package/src/TrendLine.tsx +294 -0
  113. package/src/ZoomButtons.tsx +165 -0
  114. package/src/components/ChannelWithArea.tsx +199 -0
  115. package/src/components/ClickableCircle.tsx +91 -0
  116. package/src/components/ClickableShape.tsx +114 -0
  117. package/src/components/GannFan.tsx +189 -0
  118. package/src/components/HoverTextNearMouse.tsx +174 -0
  119. package/src/components/InteractiveStraightLine.tsx +335 -0
  120. package/src/components/InteractiveText.tsx +146 -0
  121. package/src/components/InteractiveYCoordinate.tsx +200 -0
  122. package/src/components/LinearRegressionChannelWithArea.tsx +169 -0
  123. package/src/components/MouseLocationIndicator.tsx +128 -0
  124. package/src/components/Text.tsx +47 -0
  125. package/src/components/index.ts +11 -0
  126. package/src/index.ts +12 -0
  127. package/src/utils.ts +101 -0
  128. package/src/wrapper/EachEquidistantChannel.tsx +302 -0
  129. package/src/wrapper/EachFibRetracement.tsx +359 -0
  130. package/src/wrapper/EachGannFan.tsx +289 -0
  131. package/src/wrapper/EachInteractiveYCoordinate.tsx +198 -0
  132. package/src/wrapper/EachLinearRegressionChannel.tsx +202 -0
  133. package/src/wrapper/EachText.tsx +190 -0
  134. package/src/wrapper/EachTrendLine.tsx +331 -0
  135. package/src/wrapper/index.ts +7 -0
@@ -0,0 +1,165 @@
1
+ import { ChartContext, last } from "@tradingaction/core";
2
+ import { interpolateNumber } from "d3-interpolate";
3
+ import * as React from "react";
4
+
5
+ export interface ZoomButtonsProps {
6
+ readonly fill: string;
7
+ readonly fillOpacity: number;
8
+ readonly heightFromBase: number;
9
+ readonly onReset?: () => void;
10
+ readonly r: number;
11
+ readonly stroke: string;
12
+ readonly strokeWidth: number;
13
+ readonly textFill: string;
14
+ readonly zoomMultiplier: number;
15
+ }
16
+
17
+ export class ZoomButtons extends React.Component<ZoomButtonsProps> {
18
+ public static defaultProps = {
19
+ fill: "#ffffff",
20
+ fillOpacity: 0.75,
21
+ heightFromBase: 32,
22
+ r: 16,
23
+ stroke: "#e0e3eb",
24
+ strokeWidth: 1,
25
+ textFill: "#000000",
26
+ zoomMultiplier: 1.5,
27
+ };
28
+
29
+ public static contextType = ChartContext;
30
+
31
+ private interval?: number;
32
+
33
+ public render() {
34
+ const { chartConfig } = this.context;
35
+
36
+ const { width, height } = chartConfig;
37
+
38
+ const { heightFromBase, r, fill, fillOpacity, onReset, stroke, strokeWidth, textFill } = this.props;
39
+
40
+ const centerX = Math.round(width / 2);
41
+ const y = height - heightFromBase;
42
+
43
+ const zoomOutX = centerX - 16 - r * 2;
44
+ const zoomInX = centerX - 8;
45
+ const resetX = centerX + 16 + r * 2;
46
+
47
+ return (
48
+ <g className="react-financial-charts-zoom-buttons">
49
+ <circle
50
+ className="react-financial-charts-button"
51
+ cx={zoomOutX - r / 2}
52
+ cy={y + r / 2}
53
+ fill={fill}
54
+ fillOpacity={fillOpacity}
55
+ stroke={stroke}
56
+ strokeWidth={strokeWidth}
57
+ r={r}
58
+ />
59
+ <g transform={`translate (${zoomOutX - 20}, ${y - 8 + r / 4})`}>
60
+ <path d="M19,13H5V11H19V13Z" fill={textFill} />
61
+ </g>
62
+ <circle
63
+ className="react-financial-charts-button"
64
+ cx={zoomInX - r / 2}
65
+ cy={y + r / 2}
66
+ fill={fill}
67
+ fillOpacity={fillOpacity}
68
+ stroke={stroke}
69
+ strokeWidth={strokeWidth}
70
+ r={r}
71
+ />
72
+ <g transform={`translate (${zoomInX - 20}, ${y - 8 + r / 4})`}>
73
+ <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z" fill={textFill} />
74
+ </g>
75
+ <circle
76
+ className="react-financial-charts-button"
77
+ cx={resetX - r / 2}
78
+ cy={y + r / 2}
79
+ fill={fill}
80
+ fillOpacity={fillOpacity}
81
+ stroke={stroke}
82
+ strokeWidth={strokeWidth}
83
+ r={r}
84
+ />
85
+ <g transform={`translate (${resetX - r}, ${y - 4 + r / 4})`}>
86
+ <path
87
+ d="M2.35 2.35A7.958 7.958 0 018 0a8 8 0 110 16c-3.73 0-6.84-2.55-7.73-6h2.08c.82 2.33 3.04 4 5.65 4A6 6 0 108 2c-1.66 0-3.14.69-4.22 1.78L7 7H0V0l2.35 2.35z"
88
+ fill={textFill}
89
+ />
90
+ </g>
91
+ <circle
92
+ className="react-financial-charts-enable-interaction out"
93
+ onClick={this.handleZoomOut}
94
+ cx={zoomOutX - r / 2}
95
+ cy={y + r / 2}
96
+ r={r}
97
+ fill="none"
98
+ />
99
+ <circle
100
+ className="react-financial-charts-enable-interaction in"
101
+ onClick={this.handleZoomIn}
102
+ cx={zoomInX - r / 2}
103
+ cy={y + r / 2}
104
+ r={r}
105
+ fill="none"
106
+ />
107
+ <circle
108
+ className="react-financial-charts-enable-interaction reset"
109
+ onClick={onReset}
110
+ cx={resetX - r / 2}
111
+ cy={y + r / 2}
112
+ r={r}
113
+ fill="none"
114
+ />
115
+ </g>
116
+ );
117
+ }
118
+
119
+ private readonly handleZoomIn = () => {
120
+ if (this.interval) {
121
+ return;
122
+ }
123
+
124
+ this.zoom(-1);
125
+ };
126
+
127
+ private readonly handleZoomOut = () => {
128
+ if (this.interval) {
129
+ return;
130
+ }
131
+
132
+ this.zoom(1);
133
+ };
134
+
135
+ private readonly zoom = (direction: number) => {
136
+ const { xAxisZoom, xScale, plotData, xAccessor } = this.context;
137
+
138
+ const cx = xScale(xAccessor(last(plotData)));
139
+
140
+ const { zoomMultiplier } = this.props;
141
+
142
+ const c = direction > 0 ? 1 * zoomMultiplier : 1 / zoomMultiplier;
143
+
144
+ const [start, end] = xScale.domain();
145
+ const [newStart, newEnd] = xScale
146
+ .range()
147
+ .map((x: number) => cx + (x - cx) * c)
148
+ .map(xScale.invert);
149
+
150
+ const left = interpolateNumber(start, newStart);
151
+ const right = interpolateNumber(end, newEnd);
152
+
153
+ const foo = [0.25, 0.3, 0.5, 0.6, 0.75, 1].map((i) => {
154
+ return [left(i), right(i)];
155
+ });
156
+
157
+ this.interval = window.setInterval(() => {
158
+ xAxisZoom(foo.shift());
159
+ if (foo.length === 0) {
160
+ clearInterval(this.interval);
161
+ delete this.interval;
162
+ }
163
+ }, 10);
164
+ };
165
+ }
@@ -0,0 +1,199 @@
1
+ import * as React from "react";
2
+ import { isDefined, isNotDefined, getMouseCanvas, GenericChartComponent } from "@tradingaction/core";
3
+ import { generateLine, isHovering } from "./InteractiveStraightLine";
4
+
5
+ export interface ChannelWithAreaProps {
6
+ readonly startXY?: number[];
7
+ readonly endXY?: number[];
8
+ readonly dy?: number;
9
+ readonly interactiveCursorClass?: string;
10
+ readonly strokeStyle: string;
11
+ readonly strokeWidth: number;
12
+ readonly fillStyle: string;
13
+ readonly type:
14
+ | "XLINE" // extends from -Infinity to +Infinity
15
+ | "RAY" // extends to +/-Infinity in one direction
16
+ | "LINE"; // extends between the set bounds
17
+ readonly onDragStart?: (e: React.MouseEvent, moreProps: any) => void;
18
+ readonly onDrag?: (e: React.MouseEvent, moreProps: any) => void;
19
+ readonly onDragComplete?: (e: React.MouseEvent, moreProps: any) => void;
20
+ readonly onHover?: (e: React.MouseEvent, moreProps: any) => void;
21
+ readonly onUnHover?: (e: React.MouseEvent, moreProps: any) => void;
22
+ readonly defaultClassName?: string;
23
+ readonly tolerance: number;
24
+ readonly selected: boolean;
25
+ }
26
+
27
+ export class ChannelWithArea extends React.Component<ChannelWithAreaProps> {
28
+ public static defaultProps = {
29
+ type: "LINE",
30
+ strokeWidth: 1,
31
+ tolerance: 4,
32
+ selected: false,
33
+ };
34
+
35
+ public render() {
36
+ const { selected, interactiveCursorClass } = this.props;
37
+ const { onDragStart, onDrag, onDragComplete, onHover, onUnHover } = this.props;
38
+
39
+ return (
40
+ <GenericChartComponent
41
+ isHover={this.isHover}
42
+ canvasToDraw={getMouseCanvas}
43
+ canvasDraw={this.drawOnCanvas}
44
+ interactiveCursorClass={interactiveCursorClass}
45
+ selected={selected}
46
+ onDragStart={onDragStart}
47
+ onDrag={onDrag}
48
+ onDragComplete={onDragComplete}
49
+ onHover={onHover}
50
+ onUnHover={onUnHover}
51
+ drawOn={["mousemove", "mouseleave", "pan", "drag"]}
52
+ />
53
+ );
54
+ }
55
+
56
+ private readonly drawOnCanvas = (ctx: CanvasRenderingContext2D, moreProps: any) => {
57
+ const { strokeStyle, strokeWidth, fillStyle } = this.props;
58
+ const { line1, line2 } = helper(this.props, moreProps);
59
+
60
+ if (line1 !== undefined) {
61
+ const { x1, y1, x2, y2 } = line1;
62
+
63
+ ctx.lineWidth = strokeWidth;
64
+ ctx.strokeStyle = strokeStyle;
65
+
66
+ ctx.beginPath();
67
+ ctx.moveTo(x1, y1);
68
+ ctx.lineTo(x2, y2);
69
+ ctx.stroke();
70
+
71
+ if (line2 !== undefined) {
72
+ const { y1: line2Y1, y2: line2Y2 } = line2;
73
+
74
+ ctx.beginPath();
75
+ ctx.moveTo(x1, line2Y1);
76
+ ctx.lineTo(x2, line2Y2);
77
+ ctx.stroke();
78
+
79
+ ctx.fillStyle = fillStyle;
80
+ ctx.beginPath();
81
+ ctx.moveTo(x1, y1);
82
+
83
+ ctx.lineTo(x2, y2);
84
+ ctx.lineTo(x2, line2Y2);
85
+ ctx.lineTo(x1, line2Y1);
86
+
87
+ ctx.closePath();
88
+ ctx.fill();
89
+ }
90
+ }
91
+ };
92
+
93
+ private readonly isHover = (moreProps: any) => {
94
+ const { tolerance, onHover } = this.props;
95
+
96
+ if (onHover !== undefined) {
97
+ const { line1, line2 } = helper(this.props, moreProps);
98
+
99
+ if (line1 !== undefined && line2 !== undefined) {
100
+ const {
101
+ mouseXY,
102
+ xScale,
103
+ chartConfig: { yScale },
104
+ } = moreProps;
105
+
106
+ const line1Hovering = isHovering({
107
+ x1Value: line1.x1,
108
+ y1Value: line1.y1,
109
+ x2Value: line1.x2,
110
+ y2Value: line1.y2,
111
+ type: "LINE",
112
+ mouseXY,
113
+ tolerance,
114
+ xScale,
115
+ yScale,
116
+ });
117
+
118
+ const line2Hovering = isHovering({
119
+ x1Value: line2.x1,
120
+ y1Value: line2.y1,
121
+ x2Value: line2.x2,
122
+ y2Value: line2.y2,
123
+ type: "LINE",
124
+ mouseXY,
125
+ tolerance,
126
+ xScale,
127
+ yScale,
128
+ });
129
+
130
+ return line1Hovering || line2Hovering;
131
+ }
132
+ }
133
+ return false;
134
+ };
135
+ }
136
+
137
+ function getLines(props: ChannelWithAreaProps, moreProps: any) {
138
+ const { startXY, endXY, dy, type } = props;
139
+ const { xScale } = moreProps;
140
+
141
+ if (isNotDefined(startXY) || isNotDefined(endXY)) {
142
+ return {};
143
+ }
144
+
145
+ const line1 = generateLine({
146
+ type,
147
+ start: startXY,
148
+ end: endXY,
149
+ xScale,
150
+ yScale: undefined,
151
+ });
152
+
153
+ const line2 = isDefined(dy)
154
+ ? {
155
+ ...line1,
156
+ y1: line1.y1 + dy,
157
+ y2: line1.y2 + dy,
158
+ }
159
+ : undefined;
160
+
161
+ return {
162
+ line1,
163
+ line2,
164
+ };
165
+ }
166
+
167
+ function helper(props: ChannelWithAreaProps, moreProps: any) {
168
+ const lines = getLines(props, moreProps);
169
+ const {
170
+ xScale,
171
+ chartConfig: { yScale },
172
+ } = moreProps;
173
+
174
+ const line1 =
175
+ lines.line1 !== undefined
176
+ ? {
177
+ x1: xScale(lines.line1.x1),
178
+ y1: yScale(lines.line1.y1),
179
+ x2: xScale(lines.line1.x2),
180
+ y2: yScale(lines.line1.y2),
181
+ }
182
+ : undefined;
183
+
184
+ const line2 =
185
+ lines.line2 !== undefined
186
+ ? {
187
+ x1: line1!.x1,
188
+ y1: yScale(lines.line2.y1),
189
+ x2: line1!.x2,
190
+ y2: yScale(lines.line2.y2),
191
+ }
192
+ : undefined;
193
+
194
+ return {
195
+ lines,
196
+ line1,
197
+ line2,
198
+ };
199
+ }
@@ -0,0 +1,91 @@
1
+ import * as React from "react";
2
+
3
+ import { getMouseCanvas, GenericChartComponent } from "@tradingaction/core";
4
+
5
+ export interface ClickableCircleProps {
6
+ readonly onDragStart?: (e: React.MouseEvent, moreProps: any) => void;
7
+ readonly onDrag?: (e: React.MouseEvent, moreProps: any) => void;
8
+ readonly onDragComplete?: (e: React.MouseEvent, moreProps: any) => void;
9
+ readonly strokeWidth: number;
10
+ readonly strokeStyle: string;
11
+ readonly fillStyle: string;
12
+ readonly r: number;
13
+ readonly cx?: number;
14
+ readonly cy?: number;
15
+ readonly className: string;
16
+ readonly show: boolean;
17
+ readonly interactiveCursorClass?: string;
18
+ readonly xyProvider?: (moreProps: any) => number[];
19
+ }
20
+
21
+ export class ClickableCircle extends React.Component<ClickableCircleProps> {
22
+ public static defaultProps = {
23
+ className: "react-financial-charts-interactive-line-edge",
24
+ show: false,
25
+ };
26
+
27
+ public render() {
28
+ const { interactiveCursorClass, onDragStart, onDrag, onDragComplete, show } = this.props;
29
+
30
+ if (!show) {
31
+ return null;
32
+ }
33
+
34
+ return (
35
+ <GenericChartComponent
36
+ interactiveCursorClass={interactiveCursorClass}
37
+ selected
38
+ isHover={this.isHover}
39
+ onDragStart={onDragStart}
40
+ onDrag={onDrag}
41
+ onDragComplete={onDragComplete}
42
+ canvasDraw={this.drawOnCanvas}
43
+ canvasToDraw={getMouseCanvas}
44
+ drawOn={["pan", "mousemove", "drag"]}
45
+ />
46
+ );
47
+ }
48
+
49
+ private readonly drawOnCanvas = (ctx: CanvasRenderingContext2D, moreProps: any) => {
50
+ const { strokeStyle, strokeWidth, fillStyle, r } = this.props;
51
+
52
+ ctx.lineWidth = strokeWidth;
53
+ ctx.fillStyle = fillStyle;
54
+ ctx.strokeStyle = strokeStyle;
55
+
56
+ const [x, y] = this.helper(moreProps);
57
+
58
+ ctx.beginPath();
59
+ ctx.arc(x, y, r, 0, 2 * Math.PI, false);
60
+ ctx.fill();
61
+ ctx.stroke();
62
+ };
63
+
64
+ private readonly isHover = (moreProps: any) => {
65
+ const { mouseXY } = moreProps;
66
+ const r = this.props.r + 7;
67
+ const [x, y] = this.helper(moreProps);
68
+
69
+ const [mx, my] = mouseXY;
70
+ const hover = x - r < mx && mx < x + r && y - r < my && my < y + r;
71
+
72
+ return hover;
73
+ };
74
+
75
+ private readonly helper = (moreProps: any) => {
76
+ const { xyProvider, cx, cy } = this.props;
77
+
78
+ if (xyProvider !== undefined) {
79
+ return xyProvider(moreProps);
80
+ }
81
+
82
+ const {
83
+ xScale,
84
+ chartConfig: { yScale },
85
+ } = moreProps;
86
+
87
+ const x = xScale(cx);
88
+ const y = yScale(cy);
89
+ return [x, y];
90
+ };
91
+ }
@@ -0,0 +1,114 @@
1
+ import * as React from "react";
2
+ import { getMouseCanvas, GenericChartComponent } from "@tradingaction/core";
3
+ import { isHovering2 } from "./InteractiveStraightLine";
4
+
5
+ export interface ClickableShapeProps {
6
+ readonly fontWeight: string;
7
+ readonly fontFamily: string;
8
+ readonly fontStyle: string;
9
+ readonly fontSize: number;
10
+ readonly strokeStyle: string;
11
+ readonly strokeWidth: number;
12
+ readonly text: string;
13
+ readonly textBox: {
14
+ readonly closeIcon: any;
15
+ readonly left: number;
16
+ readonly padding: any;
17
+ };
18
+ readonly hovering?: boolean;
19
+ readonly interactiveCursorClass?: string;
20
+ readonly show?: boolean;
21
+ readonly onHover?: (e: React.MouseEvent, moreProps: any) => void;
22
+ readonly onUnHover?: (e: React.MouseEvent, moreProps: any) => void;
23
+ readonly onClick?: (e: React.MouseEvent, moreProps: any) => void;
24
+ readonly yValue: number;
25
+ }
26
+
27
+ export class ClickableShape extends React.Component<ClickableShapeProps> {
28
+ public static defaultProps = {
29
+ show: false,
30
+ strokeWidth: 1,
31
+ };
32
+
33
+ private closeIcon: any;
34
+
35
+ public render() {
36
+ const { interactiveCursorClass, onHover, onUnHover, onClick, show } = this.props;
37
+
38
+ if (!show) {
39
+ return null;
40
+ }
41
+
42
+ return (
43
+ <GenericChartComponent
44
+ interactiveCursorClass={interactiveCursorClass}
45
+ isHover={this.isHover}
46
+ onClickWhenHover={onClick}
47
+ canvasDraw={this.drawOnCanvas}
48
+ canvasToDraw={getMouseCanvas}
49
+ onHover={onHover}
50
+ onUnHover={onUnHover}
51
+ drawOn={["pan", "mousemove", "drag"]}
52
+ />
53
+ );
54
+ }
55
+
56
+ private readonly drawOnCanvas = (ctx: CanvasRenderingContext2D, moreProps: any) => {
57
+ const { strokeStyle, strokeWidth, hovering, textBox } = this.props;
58
+
59
+ const [x, y] = this.helper(this.props, moreProps, ctx);
60
+
61
+ this.closeIcon = { x, y };
62
+ ctx.beginPath();
63
+
64
+ ctx.lineWidth = hovering ? strokeWidth + 1 : strokeWidth;
65
+ ctx.strokeStyle = strokeStyle;
66
+ const halfWidth = textBox.closeIcon.width / 2;
67
+ ctx.moveTo(x - halfWidth, y - halfWidth);
68
+ ctx.lineTo(x + halfWidth, y + halfWidth);
69
+ ctx.moveTo(x - halfWidth, y + halfWidth);
70
+ ctx.lineTo(x + halfWidth, y - halfWidth);
71
+ ctx.stroke();
72
+ };
73
+
74
+ private readonly isHover = (moreProps: any) => {
75
+ const { mouseXY } = moreProps;
76
+ if (this.closeIcon) {
77
+ const { textBox } = this.props;
78
+ const { x, y } = this.closeIcon;
79
+ const halfWidth = textBox.closeIcon.width / 2;
80
+
81
+ const start1 = [x - halfWidth, y - halfWidth];
82
+ const end1 = [x + halfWidth, y + halfWidth];
83
+ const start2 = [x - halfWidth, y + halfWidth];
84
+ const end2 = [x + halfWidth, y - halfWidth];
85
+
86
+ if (isHovering2(start1, end1, mouseXY, 3) || isHovering2(start2, end2, mouseXY, 3)) {
87
+ return true;
88
+ }
89
+ }
90
+ return false;
91
+ };
92
+
93
+ private readonly helper = (props: ClickableShapeProps, moreProps: any, ctx: CanvasRenderingContext2D) => {
94
+ const { yValue, text, textBox } = props;
95
+ const { fontFamily, fontStyle, fontWeight, fontSize } = props;
96
+ ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
97
+
98
+ const {
99
+ chartConfig: { yScale },
100
+ } = moreProps;
101
+
102
+ const x =
103
+ textBox.left +
104
+ textBox.padding.left +
105
+ ctx.measureText(text).width +
106
+ textBox.padding.right +
107
+ textBox.closeIcon.padding.left +
108
+ textBox.closeIcon.width / 2;
109
+
110
+ const y = yScale(yValue);
111
+
112
+ return [x, y];
113
+ };
114
+ }