@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,359 @@
1
+ import * as React from "react";
2
+ import { head, last, noop } from "@tradingaction/core";
3
+ import { getXValue } from "@tradingaction/core/lib/utils/ChartDataUtil";
4
+ import { isHover, saveNodeType } from "../utils";
5
+ import { ClickableCircle, HoverTextNearMouse, InteractiveStraightLine, generateLine, Text } from "../components";
6
+ import { getNewXY } from "./EachTrendLine";
7
+
8
+ export interface EachFibRetracementProps {
9
+ readonly x1: any;
10
+ readonly x2: any;
11
+ readonly y1: number;
12
+ readonly y2: number;
13
+ readonly yDisplayFormat: (value: number) => string;
14
+ readonly type: string;
15
+ readonly selected: boolean;
16
+ readonly appearance: {
17
+ readonly strokeStyle: string;
18
+ readonly strokeWidth: number;
19
+ readonly fontFamily: string;
20
+ readonly fontSize: number;
21
+ readonly fontFill: string;
22
+ readonly edgeStroke: string;
23
+ readonly edgeFill: string;
24
+ readonly nsEdgeFill: string;
25
+ readonly edgeStrokeWidth: number;
26
+ readonly r: number;
27
+ };
28
+ readonly interactive: boolean;
29
+ readonly hoverText: {
30
+ readonly enable: boolean;
31
+ readonly fontFamily: string;
32
+ readonly fontSize: number;
33
+ readonly fill: string;
34
+ readonly text: string;
35
+ readonly bgFill: string;
36
+ readonly bgOpacity: number;
37
+ readonly bgWidth: number | string;
38
+ readonly bgHeight: number | string;
39
+ readonly selectedText: string;
40
+ };
41
+ readonly index?: number;
42
+ readonly onDrag: (e: React.MouseEvent, index: number | undefined, moreProps: any) => void;
43
+ readonly onDragComplete?: (e: React.MouseEvent, moreProps: any) => void;
44
+ readonly onDoubleClick?: (e: React.MouseEvent, moreProps: any) => void;
45
+ readonly onClickWhenHover?: (e: React.MouseEvent, moreProps: any) => void;
46
+ readonly onClickOutside?: (e: React.MouseEvent, moreProps: any) => void;
47
+ readonly onContextMenuWhenHover?: (e: React.MouseEvent, moreProps: any) => void;
48
+ }
49
+
50
+ interface EachFibRetracementState {
51
+ hover: boolean;
52
+ }
53
+
54
+ export class EachFibRetracement extends React.Component<EachFibRetracementProps, EachFibRetracementState> {
55
+ public static defaultProps = {
56
+ yDisplayFormat: (d: number) => d.toFixed(2),
57
+ interactive: true,
58
+ appearance: {
59
+ strokeStyle: "#000000",
60
+ strokeWidth: 1,
61
+ fontFamily: "-apple-system, system-ui, Roboto, 'Helvetica Neue', Ubuntu, sans-serif",
62
+ fontSize: 10,
63
+ fontFill: "#000000",
64
+ edgeStroke: "#000000",
65
+ edgeFill: "#FFFFFF",
66
+ nsEdgeFill: "#000000",
67
+ edgeStrokeWidth: 1,
68
+ r: 5,
69
+ },
70
+ selected: false,
71
+ onDrag: noop,
72
+ hoverText: {
73
+ enable: false,
74
+ },
75
+ };
76
+
77
+ private dragStart: any;
78
+ // @ts-ignore
79
+ private isHover: any;
80
+ private saveNodeType: any;
81
+
82
+ public constructor(props: EachFibRetracementProps) {
83
+ super(props);
84
+
85
+ this.isHover = isHover.bind(this);
86
+ this.saveNodeType = saveNodeType.bind(this);
87
+
88
+ this.state = {
89
+ hover: false,
90
+ };
91
+ }
92
+
93
+ public render() {
94
+ const { x1, x2, y1, y2 } = this.props;
95
+ const { interactive, yDisplayFormat, type, appearance } = this.props;
96
+ const { strokeStyle, strokeWidth } = appearance;
97
+ const { fontFamily, fontSize, fontFill } = appearance;
98
+ const { edgeStroke, edgeFill, nsEdgeFill, edgeStrokeWidth, r } = appearance;
99
+ const { hoverText, selected } = this.props;
100
+ const { hover } = this.state;
101
+ const { onDragComplete } = this.props;
102
+ const lines = helper({ x1, x2, y1, y2 });
103
+
104
+ const {
105
+ enable: hoverTextEnabled,
106
+ selectedText: hoverTextSelected,
107
+ text: hoverTextUnselected,
108
+ ...restHoverTextProps
109
+ } = hoverText;
110
+
111
+ const lineType = type === "EXTEND" ? "XLINE" : type === "BOUND" ? "LINE" : "RAY";
112
+ const dir = head(lines).y1 > last(lines).y1 ? 3 : -1.3;
113
+
114
+ return (
115
+ <g>
116
+ {lines.map((line, j) => {
117
+ const text = `${yDisplayFormat(line.y)} (${line.percent.toFixed(2)}%)`;
118
+
119
+ const xyProvider = ({ xScale, chartConfig }: any) => {
120
+ const { yScale } = chartConfig;
121
+ const {
122
+ x1: lineX1,
123
+ y1: lineY1,
124
+ x2: lineX2,
125
+ } = generateLine({
126
+ type: lineType,
127
+ start: [line.x1, line.y],
128
+ end: [line.x2, line.y],
129
+ xScale,
130
+ yScale,
131
+ });
132
+
133
+ const x = xScale(Math.min(lineX1, lineX2)) + 10;
134
+ const y = yScale(lineY1) + dir * 4;
135
+ return [x, y];
136
+ };
137
+
138
+ const firstOrLast = j === 0 || j === lines.length - 1;
139
+
140
+ const interactiveCursorClass = firstOrLast
141
+ ? "react-financial-charts-ns-resize-cursor"
142
+ : "react-financial-charts-move-cursor";
143
+
144
+ const interactiveEdgeCursorClass = firstOrLast
145
+ ? "react-financial-charts-ns-resize-cursor"
146
+ : "react-financial-charts-ew-resize-cursor";
147
+
148
+ const dragHandler =
149
+ j === 0
150
+ ? this.handleLineNSResizeTop
151
+ : j === lines.length - 1
152
+ ? this.handleLineNSResizeBottom
153
+ : this.handleLineMove;
154
+
155
+ const edge1DragHandler =
156
+ j === 0
157
+ ? this.handleLineNSResizeTop
158
+ : j === lines.length - 1
159
+ ? this.handleLineNSResizeBottom
160
+ : this.handleEdge1Drag;
161
+ const edge2DragHandler =
162
+ j === 0
163
+ ? this.handleLineNSResizeTop
164
+ : j === lines.length - 1
165
+ ? this.handleLineNSResizeBottom
166
+ : this.handleEdge2Drag;
167
+
168
+ const hoverHandler = interactive ? { onHover: this.handleHover, onUnHover: this.handleHover } : {};
169
+ return (
170
+ <g key={j}>
171
+ <InteractiveStraightLine
172
+ onContextMenuWhenHover={(e, moreProps) => {
173
+ if (this.props.onContextMenuWhenHover && j == 0) {
174
+ console.log(this.props);
175
+ this.props.onContextMenuWhenHover(e, moreProps);
176
+ }
177
+ }}
178
+ onDoubleClickWhenHover={this.props.onDoubleClick}
179
+ onClickOutside={this.props.onClickOutside}
180
+ onClickWhenHover={this.props.onClickWhenHover}
181
+ ref={this.saveNodeType(`line_${j}`)}
182
+ selected={selected || hover}
183
+ {...hoverHandler}
184
+ type={lineType}
185
+ x1Value={line.x1}
186
+ y1Value={line.y}
187
+ x2Value={line.x2}
188
+ y2Value={line.y}
189
+ strokeStyle={strokeStyle}
190
+ strokeWidth={hover || selected ? strokeWidth + 1 : strokeWidth}
191
+ interactiveCursorClass={interactiveCursorClass}
192
+ onDragStart={this.handleLineDragStart}
193
+ onDrag={dragHandler}
194
+ onDragComplete={onDragComplete}
195
+ />
196
+ <Text
197
+ selected={selected}
198
+ xyProvider={xyProvider}
199
+ fontFamily={fontFamily}
200
+ fontSize={fontSize}
201
+ fillStyle={fontFill}
202
+ >
203
+ {text}
204
+ </Text>
205
+ <ClickableCircle
206
+ ref={this.saveNodeType("edge1")}
207
+ show={selected || hover}
208
+ cx={line.x1}
209
+ cy={line.y}
210
+ r={r}
211
+ fillStyle={firstOrLast ? nsEdgeFill : edgeFill}
212
+ strokeStyle={edgeStroke}
213
+ strokeWidth={edgeStrokeWidth}
214
+ interactiveCursorClass={interactiveEdgeCursorClass}
215
+ onDrag={edge1DragHandler}
216
+ onDragComplete={onDragComplete}
217
+ />
218
+ <ClickableCircle
219
+ ref={this.saveNodeType("edge2")}
220
+ show={selected || hover}
221
+ cx={line.x2}
222
+ cy={line.y}
223
+ r={r}
224
+ fillStyle={firstOrLast ? nsEdgeFill : edgeFill}
225
+ strokeStyle={edgeStroke}
226
+ strokeWidth={edgeStrokeWidth}
227
+ interactiveCursorClass={interactiveEdgeCursorClass}
228
+ onDrag={edge2DragHandler}
229
+ onDragComplete={onDragComplete}
230
+ />
231
+ </g>
232
+ );
233
+ })}
234
+ <HoverTextNearMouse
235
+ show={hoverTextEnabled && hover}
236
+ {...restHoverTextProps}
237
+ text={selected ? hoverTextSelected : hoverTextUnselected}
238
+ />
239
+ </g>
240
+ );
241
+ }
242
+
243
+ private readonly handleEdge2Drag = (e: React.MouseEvent, moreProps: any) => {
244
+ const { index, onDrag, x1, y1, y2 } = this.props;
245
+
246
+ const [x2] = getNewXY(moreProps);
247
+
248
+ onDrag(e, index, {
249
+ x1,
250
+ y1,
251
+ x2,
252
+ y2,
253
+ });
254
+ };
255
+
256
+ private readonly handleEdge1Drag = (e: React.MouseEvent, moreProps: any) => {
257
+ const { index, onDrag, y1, x2, y2 } = this.props;
258
+
259
+ const [x1] = getNewXY(moreProps);
260
+
261
+ onDrag(e, index, {
262
+ x1,
263
+ y1,
264
+ x2,
265
+ y2,
266
+ });
267
+ };
268
+
269
+ private readonly handleLineNSResizeBottom = (e: React.MouseEvent, moreProps: any) => {
270
+ const { index, onDrag, x1, y1, x2 } = this.props;
271
+
272
+ const [, y2] = getNewXY(moreProps);
273
+
274
+ onDrag(e, index, {
275
+ x1,
276
+ y1,
277
+ x2,
278
+ y2,
279
+ });
280
+ };
281
+
282
+ private readonly handleLineNSResizeTop = (e: React.MouseEvent, moreProps: any) => {
283
+ const { index, onDrag, x1, x2, y2 } = this.props;
284
+
285
+ const [, y1] = getNewXY(moreProps);
286
+
287
+ onDrag(e, index, {
288
+ x1,
289
+ y1,
290
+ x2,
291
+ y2,
292
+ });
293
+ };
294
+
295
+ private readonly handleLineMove = (e: React.MouseEvent, moreProps: any) => {
296
+ const { index, onDrag } = this.props;
297
+
298
+ const { x1: x1Value, y1: y1Value, x2: x2Value, y2: y2Value } = this.dragStart;
299
+
300
+ const {
301
+ xScale,
302
+ chartConfig: { yScale },
303
+ xAccessor,
304
+ fullData,
305
+ } = moreProps;
306
+ const { startPos, mouseXY } = moreProps;
307
+
308
+ const x1 = xScale(x1Value);
309
+ const y1 = yScale(y1Value);
310
+ const x2 = xScale(x2Value);
311
+ const y2 = yScale(y2Value);
312
+
313
+ const dx = startPos[0] - mouseXY[0];
314
+ const dy = startPos[1] - mouseXY[1];
315
+
316
+ const newX1Value = getXValue(xScale, xAccessor, [x1 - dx, y1 - dy], fullData);
317
+ const newY1Value = yScale.invert(y1 - dy);
318
+ const newX2Value = getXValue(xScale, xAccessor, [x2 - dx, y2 - dy], fullData);
319
+ const newY2Value = yScale.invert(y2 - dy);
320
+
321
+ onDrag(e, index, {
322
+ x1: newX1Value,
323
+ y1: newY1Value,
324
+ x2: newX2Value,
325
+ y2: newY2Value,
326
+ });
327
+ };
328
+
329
+ private readonly handleLineDragStart = () => {
330
+ const { x1, y1, x2, y2 } = this.props;
331
+
332
+ this.dragStart = {
333
+ x1,
334
+ y1,
335
+ x2,
336
+ y2,
337
+ };
338
+ };
339
+
340
+ private readonly handleHover = (_: React.MouseEvent, moreProps: any) => {
341
+ if (this.state.hover !== moreProps.hovering) {
342
+ this.setState({
343
+ hover: moreProps.hovering,
344
+ });
345
+ }
346
+ };
347
+ }
348
+
349
+ function helper({ x1, y1, x2, y2 }: any) {
350
+ const dy = y2 - y1;
351
+ const retracements = [100, 61.8, 50, 38.2, 23.6, 0].map((each) => ({
352
+ percent: each,
353
+ x1,
354
+ x2,
355
+ y: y2 - (each / 100) * dy,
356
+ }));
357
+
358
+ return retracements;
359
+ }
@@ -0,0 +1,289 @@
1
+ import * as React from "react";
2
+ import { isDefined, noop } from "@tradingaction/core";
3
+ import { getXValue } from "@tradingaction/core/lib/utils/ChartDataUtil";
4
+ import { isHover, saveNodeType } from "../utils";
5
+ import { ClickableCircle, GannFan, HoverTextNearMouse } from "../components";
6
+
7
+ export interface EachGannFanProps {
8
+ readonly startXY: number[];
9
+ readonly endXY: number[];
10
+ readonly dy?: number;
11
+ readonly interactive: boolean;
12
+ readonly selected: boolean;
13
+ readonly appearance: {
14
+ readonly stroke: string;
15
+ readonly strokeWidth: number;
16
+ readonly edgeStroke: string;
17
+ readonly edgeFill: string;
18
+ readonly edgeStrokeWidth: number;
19
+ readonly r: number;
20
+ readonly fill: Array<string>;
21
+ readonly fontFamily: string;
22
+ readonly fontSize: number;
23
+ readonly fontFill: string;
24
+ };
25
+ readonly hoverText: {
26
+ readonly enable: boolean;
27
+ readonly fontFamily: string;
28
+ readonly fontSize: number;
29
+ readonly fill: string;
30
+ readonly text: string;
31
+ readonly bgFill: string;
32
+ readonly bgOpacity: number;
33
+ readonly bgWidth: number | string;
34
+ readonly bgHeight: number | string;
35
+ readonly selectedText: string;
36
+ };
37
+ readonly index?: number;
38
+ readonly onDrag: (e: React.MouseEvent, index: number | undefined, moreProps: any) => void;
39
+ readonly onDragComplete?: (e: React.MouseEvent, moreProps: any) => void;
40
+ }
41
+
42
+ interface EachGannFanState {
43
+ hover: boolean;
44
+ }
45
+
46
+ export class EachGannFan extends React.Component<EachGannFanProps, EachGannFanState> {
47
+ public static defaultProps = {
48
+ yDisplayFormat: (d: number) => d.toFixed(2),
49
+ interactive: true,
50
+ selected: false,
51
+ appearance: {
52
+ stroke: "#000000",
53
+ strokeWidth: 1,
54
+ edgeStroke: "#000000",
55
+ edgeFill: "#FFFFFF",
56
+ edgeStrokeWidth: 1,
57
+ r: 5,
58
+ fill: [
59
+ "rgba(31, 119, 180, 0.2)",
60
+ "rgba(255, 126, 14, 0.2)",
61
+ "rgba(44, 160, 44, 0.2)",
62
+ "rgba(214, 39, 39, 0.2)",
63
+ "rgba(148, 103, 189, 0.2)",
64
+ "rgba(140, 86, 75, 0.2)",
65
+ "rgba(227, 119, 194, 0.2)",
66
+ "rgba(127, 127, 127, 0.2)",
67
+ ],
68
+ fontFamily: "-apple-system, system-ui, Roboto, 'Helvetica Neue', Ubuntu, sans-serif",
69
+ fontSize: 10,
70
+ fontFill: "#000000",
71
+ },
72
+ onDrag: noop,
73
+ hoverText: {
74
+ ...HoverTextNearMouse.defaultProps,
75
+ enable: true,
76
+ bgHeight: 18,
77
+ bgWidth: 120,
78
+ text: "Click to select object",
79
+ },
80
+ };
81
+
82
+ // @ts-ignore
83
+ private isHover: any;
84
+ private dragStart: any;
85
+ private saveNodeType: any;
86
+
87
+ public constructor(props: EachGannFanProps) {
88
+ super(props);
89
+
90
+ this.isHover = isHover.bind(this);
91
+ this.saveNodeType = saveNodeType.bind(this);
92
+
93
+ this.state = {
94
+ hover: false,
95
+ };
96
+ }
97
+
98
+ public render() {
99
+ const { startXY, endXY } = this.props;
100
+ const { interactive, appearance } = this.props;
101
+ const { edgeFill, stroke, strokeWidth, fill } = appearance;
102
+ const { fontFamily, fontSize, fontFill } = appearance;
103
+ const { hoverText, selected } = this.props;
104
+ const { onDragComplete } = this.props;
105
+ const { hover } = this.state;
106
+ const { enable: hoverTextEnabled, ...restHoverTextProps } = hoverText;
107
+
108
+ const hoverHandler = interactive ? { onHover: this.handleHover, onUnHover: this.handleHover } : {};
109
+
110
+ const line1Edge =
111
+ isDefined(startXY) && isDefined(endXY) ? (
112
+ <g>
113
+ {this.getEdgeCircle({
114
+ xy: startXY,
115
+ dragHandler: this.handleLine1Edge1Drag,
116
+ cursor: "react-financial-charts-move-cursor",
117
+ fill: edgeFill,
118
+ edge: "edge1",
119
+ })}
120
+ {this.getEdgeCircle({
121
+ xy: endXY,
122
+ dragHandler: this.handleLine1Edge2Drag,
123
+ cursor: "react-financial-charts-move-cursor",
124
+ fill: edgeFill,
125
+ edge: "edge2",
126
+ })}
127
+ </g>
128
+ ) : null;
129
+
130
+ return (
131
+ <g>
132
+ <GannFan
133
+ ref={this.saveNodeType("fan")}
134
+ selected={hover || selected}
135
+ {...hoverHandler}
136
+ startXY={startXY}
137
+ endXY={endXY}
138
+ strokeStyle={stroke}
139
+ strokeWidth={hover || selected ? strokeWidth + 1 : strokeWidth}
140
+ fillStyle={fill}
141
+ fontFamily={fontFamily}
142
+ fontSize={fontSize}
143
+ fontFill={fontFill}
144
+ interactiveCursorClass="react-financial-charts-move-cursor"
145
+ onDragStart={this.handleDragStart}
146
+ onDrag={this.handleFanDrag}
147
+ onDragComplete={onDragComplete}
148
+ />
149
+ {line1Edge}
150
+ <HoverTextNearMouse show={hoverTextEnabled && hover && !selected} {...restHoverTextProps} />
151
+ </g>
152
+ );
153
+ }
154
+
155
+ private readonly getEdgeCircle = ({ xy, dragHandler, cursor, fill, edge }: any) => {
156
+ const { hover } = this.state;
157
+ const { selected, appearance } = this.props;
158
+ const { edgeStroke, edgeStrokeWidth, r } = appearance;
159
+ const { onDragComplete } = this.props;
160
+
161
+ return (
162
+ <ClickableCircle
163
+ ref={this.saveNodeType(edge)}
164
+ show={selected || hover}
165
+ cx={xy[0]}
166
+ cy={xy[1]}
167
+ r={r}
168
+ fillStyle={fill}
169
+ strokeStyle={edgeStroke}
170
+ strokeWidth={edgeStrokeWidth}
171
+ interactiveCursorClass={cursor}
172
+ onDragStart={this.handleDragStart}
173
+ onDrag={dragHandler}
174
+ onDragComplete={onDragComplete}
175
+ />
176
+ );
177
+ };
178
+
179
+ private readonly handleLine1Edge2Drag = (e: React.MouseEvent, moreProps: any) => {
180
+ const { index, onDrag } = this.props;
181
+ const { endXY } = this.dragStart;
182
+
183
+ const {
184
+ startPos,
185
+ mouseXY,
186
+ xAccessor,
187
+ xScale,
188
+ fullData,
189
+ chartConfig: { yScale },
190
+ } = moreProps;
191
+
192
+ const dx = startPos[0] - mouseXY[0];
193
+ const dy = startPos[1] - mouseXY[1];
194
+
195
+ const x1 = xScale(endXY[0]);
196
+ const y1 = yScale(endXY[1]);
197
+
198
+ const newX1Value = getXValue(xScale, xAccessor, [x1 - dx, y1 - dy], fullData);
199
+ const newY1Value = yScale.invert(y1 - dy);
200
+
201
+ onDrag(e, index, {
202
+ startXY: this.dragStart.startXY,
203
+ endXY: [newX1Value, newY1Value],
204
+ dy: this.dragStart.dy,
205
+ });
206
+ };
207
+
208
+ private readonly handleLine1Edge1Drag = (e: React.MouseEvent, moreProps: any) => {
209
+ const { index, onDrag } = this.props;
210
+ const { startXY } = this.dragStart;
211
+
212
+ const {
213
+ startPos,
214
+ mouseXY,
215
+ xAccessor,
216
+ xScale,
217
+ fullData,
218
+ chartConfig: { yScale },
219
+ } = moreProps;
220
+
221
+ const dx = startPos[0] - mouseXY[0];
222
+ const dy = startPos[1] - mouseXY[1];
223
+
224
+ const x1 = xScale(startXY[0]);
225
+ const y1 = yScale(startXY[1]);
226
+
227
+ const newX1Value = getXValue(xScale, xAccessor, [x1 - dx, y1 - dy], fullData);
228
+ const newY1Value = yScale.invert(y1 - dy);
229
+
230
+ onDrag(e, index, {
231
+ startXY: [newX1Value, newY1Value],
232
+ endXY: this.dragStart.endXY,
233
+ dy: this.dragStart.dy,
234
+ });
235
+ };
236
+
237
+ private readonly handleFanDrag = (e: React.MouseEvent, moreProps: any) => {
238
+ const { index, onDrag } = this.props;
239
+
240
+ const { startXY, endXY } = this.dragStart;
241
+
242
+ const {
243
+ xScale,
244
+ chartConfig: { yScale },
245
+ xAccessor,
246
+ fullData,
247
+ } = moreProps;
248
+ const { startPos, mouseXY } = moreProps;
249
+
250
+ const x1 = xScale(startXY[0]);
251
+ const y1 = yScale(startXY[1]);
252
+ const x2 = xScale(endXY[0]);
253
+ const y2 = yScale(endXY[1]);
254
+
255
+ const dx = startPos[0] - mouseXY[0];
256
+ const dy = startPos[1] - mouseXY[1];
257
+
258
+ const newX1Value = getXValue(xScale, xAccessor, [x1 - dx, y1 - dy], fullData);
259
+ const newY1Value = yScale.invert(y1 - dy);
260
+ const newX2Value = getXValue(xScale, xAccessor, [x2 - dx, y2 - dy], fullData);
261
+ const newY2Value = yScale.invert(y2 - dy);
262
+
263
+ // const newDy = newY2Value - endXY[1] + this.dragStart.dy;
264
+
265
+ onDrag(e, index, {
266
+ startXY: [newX1Value, newY1Value],
267
+ endXY: [newX2Value, newY2Value],
268
+ dy: this.dragStart.dy,
269
+ });
270
+ };
271
+
272
+ private readonly handleDragStart = () => {
273
+ const { startXY, endXY, dy } = this.props;
274
+
275
+ this.dragStart = {
276
+ startXY,
277
+ endXY,
278
+ dy,
279
+ };
280
+ };
281
+
282
+ private readonly handleHover = (moreProps: any) => {
283
+ if (this.state.hover !== moreProps.hovering) {
284
+ this.setState({
285
+ hover: moreProps.hovering,
286
+ });
287
+ }
288
+ };
289
+ }