@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.
- package/LICENSE +24 -0
- package/README.md +5 -0
- package/lib/Brush.d.ts +35 -0
- package/lib/Brush.js +103 -0
- package/lib/Brush.js.map +1 -0
- package/lib/ClickCallback.d.ts +18 -0
- package/lib/ClickCallback.js +12 -0
- package/lib/ClickCallback.js.map +1 -0
- package/lib/DrawingObjectSelector.d.ts +18 -0
- package/lib/DrawingObjectSelector.js +73 -0
- package/lib/DrawingObjectSelector.js.map +1 -0
- package/lib/EquidistantChannel.d.ts +74 -0
- package/lib/EquidistantChannel.js +149 -0
- package/lib/EquidistantChannel.js.map +1 -0
- package/lib/FibonacciRetracement.d.ts +89 -0
- package/lib/FibonacciRetracement.js +184 -0
- package/lib/FibonacciRetracement.js.map +1 -0
- package/lib/GannFan.d.ts +78 -0
- package/lib/GannFan.js +128 -0
- package/lib/GannFan.js.map +1 -0
- package/lib/InteractiveText.d.ts +65 -0
- package/lib/InteractiveText.js +83 -0
- package/lib/InteractiveText.js.map +1 -0
- package/lib/InteractiveYCoordinate.d.ts +122 -0
- package/lib/InteractiveYCoordinate.js +100 -0
- package/lib/InteractiveYCoordinate.js.map +1 -0
- package/lib/StandardDeviationChannel.d.ts +74 -0
- package/lib/StandardDeviationChannel.js +125 -0
- package/lib/StandardDeviationChannel.js.map +1 -0
- package/lib/TrendLine.d.ts +84 -0
- package/lib/TrendLine.js +128 -0
- package/lib/TrendLine.js.map +1 -0
- package/lib/ZoomButtons.d.ts +30 -0
- package/lib/ZoomButtons.js +78 -0
- package/lib/ZoomButtons.js.map +1 -0
- package/lib/components/ChannelWithArea.d.ts +30 -0
- package/lib/components/ChannelWithArea.js +126 -0
- package/lib/components/ChannelWithArea.js.map +1 -0
- package/lib/components/ClickableCircle.d.ts +26 -0
- package/lib/components/ClickableCircle.js +48 -0
- package/lib/components/ClickableCircle.js.map +1 -0
- package/lib/components/ClickableShape.d.ts +33 -0
- package/lib/components/ClickableShape.js +64 -0
- package/lib/components/ClickableShape.js.map +1 -0
- package/lib/components/GannFan.d.ts +32 -0
- package/lib/components/GannFan.js +134 -0
- package/lib/components/GannFan.js.map +1 -0
- package/lib/components/HoverTextNearMouse.d.ts +35 -0
- package/lib/components/HoverTextNearMouse.js +113 -0
- package/lib/components/HoverTextNearMouse.js.map +1 -0
- package/lib/components/InteractiveStraightLine.d.ts +61 -0
- package/lib/components/InteractiveStraightLine.js +220 -0
- package/lib/components/InteractiveStraightLine.js.map +1 -0
- package/lib/components/InteractiveText.d.ts +38 -0
- package/lib/components/InteractiveText.js +84 -0
- package/lib/components/InteractiveText.js.map +1 -0
- package/lib/components/InteractiveYCoordinate.d.ts +46 -0
- package/lib/components/InteractiveYCoordinate.js +109 -0
- package/lib/components/InteractiveYCoordinate.js.map +1 -0
- package/lib/components/LinearRegressionChannelWithArea.d.ts +31 -0
- package/lib/components/LinearRegressionChannelWithArea.js +104 -0
- package/lib/components/LinearRegressionChannelWithArea.js.map +1 -0
- package/lib/components/MouseLocationIndicator.d.ts +34 -0
- package/lib/components/MouseLocationIndicator.js +79 -0
- package/lib/components/MouseLocationIndicator.js.map +1 -0
- package/lib/components/Text.d.ts +17 -0
- package/lib/components/Text.js +26 -0
- package/lib/components/Text.js.map +1 -0
- package/lib/components/index.d.ts +11 -0
- package/lib/components/index.js +12 -0
- package/lib/components/index.js.map +1 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +13 -0
- package/lib/index.js.map +1 -0
- package/lib/utils.d.ts +7 -0
- package/lib/utils.js +84 -0
- package/lib/utils.js.map +1 -0
- package/lib/wrapper/EachEquidistantChannel.d.ts +59 -0
- package/lib/wrapper/EachEquidistantChannel.js +172 -0
- package/lib/wrapper/EachEquidistantChannel.js.map +1 -0
- package/lib/wrapper/EachFibRetracement.d.ts +81 -0
- package/lib/wrapper/EachFibRetracement.js +202 -0
- package/lib/wrapper/EachFibRetracement.js.map +1 -0
- package/lib/wrapper/EachGannFan.d.ts +81 -0
- package/lib/wrapper/EachGannFan.js +161 -0
- package/lib/wrapper/EachGannFan.js.map +1 -0
- package/lib/wrapper/EachInteractiveYCoordinate.d.ts +50 -0
- package/lib/wrapper/EachInteractiveYCoordinate.js +80 -0
- package/lib/wrapper/EachInteractiveYCoordinate.js.map +1 -0
- package/lib/wrapper/EachLinearRegressionChannel.d.ts +75 -0
- package/lib/wrapper/EachLinearRegressionChannel.js +89 -0
- package/lib/wrapper/EachLinearRegressionChannel.js.map +1 -0
- package/lib/wrapper/EachText.d.ts +59 -0
- package/lib/wrapper/EachText.js +83 -0
- package/lib/wrapper/EachText.js.map +1 -0
- package/lib/wrapper/EachTrendLine.d.ts +85 -0
- package/lib/wrapper/EachTrendLine.js +165 -0
- package/lib/wrapper/EachTrendLine.js.map +1 -0
- package/lib/wrapper/index.d.ts +7 -0
- package/lib/wrapper/index.js +8 -0
- package/lib/wrapper/index.js.map +1 -0
- package/package.json +53 -0
- package/src/Brush.tsx +172 -0
- package/src/ClickCallback.tsx +37 -0
- package/src/DrawingObjectSelector.tsx +97 -0
- package/src/EquidistantChannel.tsx +268 -0
- package/src/FibonacciRetracement.tsx +328 -0
- package/src/GannFan.tsx +233 -0
- package/src/InteractiveText.tsx +182 -0
- package/src/InteractiveYCoordinate.tsx +199 -0
- package/src/StandardDeviationChannel.tsx +269 -0
- package/src/TrendLine.tsx +294 -0
- package/src/ZoomButtons.tsx +165 -0
- package/src/components/ChannelWithArea.tsx +199 -0
- package/src/components/ClickableCircle.tsx +91 -0
- package/src/components/ClickableShape.tsx +114 -0
- package/src/components/GannFan.tsx +189 -0
- package/src/components/HoverTextNearMouse.tsx +174 -0
- package/src/components/InteractiveStraightLine.tsx +335 -0
- package/src/components/InteractiveText.tsx +146 -0
- package/src/components/InteractiveYCoordinate.tsx +200 -0
- package/src/components/LinearRegressionChannelWithArea.tsx +169 -0
- package/src/components/MouseLocationIndicator.tsx +128 -0
- package/src/components/Text.tsx +47 -0
- package/src/components/index.ts +11 -0
- package/src/index.ts +12 -0
- package/src/utils.ts +101 -0
- package/src/wrapper/EachEquidistantChannel.tsx +302 -0
- package/src/wrapper/EachFibRetracement.tsx +359 -0
- package/src/wrapper/EachGannFan.tsx +289 -0
- package/src/wrapper/EachInteractiveYCoordinate.tsx +198 -0
- package/src/wrapper/EachLinearRegressionChannel.tsx +202 -0
- package/src/wrapper/EachText.tsx +190 -0
- package/src/wrapper/EachTrendLine.tsx +331 -0
- package/src/wrapper/index.ts +7 -0
package/src/GannFan.tsx
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { isDefined, isNotDefined, noop } from "@tradingaction/core";
|
|
3
|
+
import { HoverTextNearMouse, MouseLocationIndicator } from "./components";
|
|
4
|
+
import { isHoverForInteractiveType, saveNodeType, terminate } from "./utils";
|
|
5
|
+
import { EachGannFan } from "./wrapper";
|
|
6
|
+
|
|
7
|
+
export interface GannFanProps {
|
|
8
|
+
readonly enabled: boolean;
|
|
9
|
+
readonly onStart?: () => void;
|
|
10
|
+
readonly onComplete: (e: React.MouseEvent, newfans: any[], moreProps: any) => void;
|
|
11
|
+
readonly onSelect?: (e: React.MouseEvent, interactives: any[], moreProps: any) => void;
|
|
12
|
+
readonly currentPositionStroke?: string;
|
|
13
|
+
readonly currentPositionStrokeWidth?: number;
|
|
14
|
+
readonly currentPositionOpacity?: number;
|
|
15
|
+
readonly currentPositionRadius?: number;
|
|
16
|
+
readonly appearance: {
|
|
17
|
+
readonly stroke: string;
|
|
18
|
+
readonly strokeOpacity: number;
|
|
19
|
+
readonly fillOpacity: number;
|
|
20
|
+
readonly strokeWidth: number;
|
|
21
|
+
readonly edgeStroke: string;
|
|
22
|
+
readonly edgeFill: string;
|
|
23
|
+
readonly edgeStrokeWidth: number;
|
|
24
|
+
readonly r: number;
|
|
25
|
+
readonly fill: string[];
|
|
26
|
+
readonly fontFamily: string;
|
|
27
|
+
readonly fontSize: number;
|
|
28
|
+
readonly fontFill: string;
|
|
29
|
+
};
|
|
30
|
+
readonly hoverText: object;
|
|
31
|
+
readonly fans: any[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface GannFanState {
|
|
35
|
+
current?: any;
|
|
36
|
+
override?: any;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class GannFan extends React.Component<GannFanProps, GannFanState> {
|
|
40
|
+
public static defaultProps = {
|
|
41
|
+
appearance: {
|
|
42
|
+
stroke: "#000000",
|
|
43
|
+
fillOpacity: 0.2,
|
|
44
|
+
strokeOpacity: 1,
|
|
45
|
+
strokeWidth: 1,
|
|
46
|
+
edgeStroke: "#000000",
|
|
47
|
+
edgeFill: "#FFFFFF",
|
|
48
|
+
edgeStrokeWidth: 1,
|
|
49
|
+
r: 5,
|
|
50
|
+
fill: ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33", "#a65628", "#f781bf"],
|
|
51
|
+
fontFamily: "-apple-system, system-ui, Roboto, 'Helvetica Neue', Ubuntu, sans-serif",
|
|
52
|
+
fontSize: 12,
|
|
53
|
+
fontFill: "#000000",
|
|
54
|
+
},
|
|
55
|
+
onSelect: noop,
|
|
56
|
+
currentPositionStroke: "#000000",
|
|
57
|
+
currentPositionOpacity: 1,
|
|
58
|
+
currentPositionStrokeWidth: 3,
|
|
59
|
+
currentPositionRadius: 4,
|
|
60
|
+
hoverText: {
|
|
61
|
+
...HoverTextNearMouse.defaultProps,
|
|
62
|
+
enable: true,
|
|
63
|
+
bgHeight: 18,
|
|
64
|
+
bgWidth: 120,
|
|
65
|
+
text: "Click to select object",
|
|
66
|
+
},
|
|
67
|
+
fans: [],
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
private mouseMoved: any;
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
private getSelectionState: any;
|
|
73
|
+
private saveNodeType: any;
|
|
74
|
+
|
|
75
|
+
// @ts-ignore
|
|
76
|
+
private terminate: any;
|
|
77
|
+
|
|
78
|
+
public constructor(props: GannFanProps) {
|
|
79
|
+
super(props);
|
|
80
|
+
|
|
81
|
+
this.terminate = terminate.bind(this);
|
|
82
|
+
this.saveNodeType = saveNodeType.bind(this);
|
|
83
|
+
|
|
84
|
+
this.getSelectionState = isHoverForInteractiveType("fans").bind(this);
|
|
85
|
+
|
|
86
|
+
this.state = {};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public render() {
|
|
90
|
+
const {
|
|
91
|
+
appearance,
|
|
92
|
+
currentPositionOpacity,
|
|
93
|
+
currentPositionRadius = GannFan.defaultProps.currentPositionRadius,
|
|
94
|
+
currentPositionStroke,
|
|
95
|
+
currentPositionStrokeWidth,
|
|
96
|
+
enabled,
|
|
97
|
+
fans,
|
|
98
|
+
hoverText,
|
|
99
|
+
} = this.props;
|
|
100
|
+
|
|
101
|
+
const { current, override } = this.state;
|
|
102
|
+
const overrideIndex = isDefined(override) ? override.index : null;
|
|
103
|
+
|
|
104
|
+
const tempChannel =
|
|
105
|
+
isDefined(current) && isDefined(current.endXY) ? (
|
|
106
|
+
<EachGannFan interactive={false} {...current} appearance={appearance} hoverText={hoverText} />
|
|
107
|
+
) : null;
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<g>
|
|
111
|
+
{fans.map((each, idx) => {
|
|
112
|
+
const eachAppearance = isDefined(each.appearance)
|
|
113
|
+
? { ...appearance, ...each.appearance }
|
|
114
|
+
: appearance;
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<EachGannFan
|
|
118
|
+
key={idx}
|
|
119
|
+
ref={this.saveNodeType(idx)}
|
|
120
|
+
index={idx}
|
|
121
|
+
selected={each.selected}
|
|
122
|
+
{...(idx === overrideIndex ? override : each)}
|
|
123
|
+
appearance={eachAppearance}
|
|
124
|
+
hoverText={hoverText}
|
|
125
|
+
onDrag={this.handleDragFan}
|
|
126
|
+
onDragComplete={this.handleDragFanComplete}
|
|
127
|
+
/>
|
|
128
|
+
);
|
|
129
|
+
})}
|
|
130
|
+
{tempChannel}
|
|
131
|
+
<MouseLocationIndicator
|
|
132
|
+
enabled={enabled}
|
|
133
|
+
snap={false}
|
|
134
|
+
r={currentPositionRadius}
|
|
135
|
+
stroke={currentPositionStroke}
|
|
136
|
+
opacity={currentPositionOpacity}
|
|
137
|
+
strokeWidth={currentPositionStrokeWidth}
|
|
138
|
+
onMouseDown={this.handleStart}
|
|
139
|
+
onClick={this.handleEnd}
|
|
140
|
+
onMouseMove={this.handleDrawFan}
|
|
141
|
+
/>
|
|
142
|
+
</g>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private readonly handleEnd = (e: React.MouseEvent, _: any, moreProps: any) => {
|
|
147
|
+
const { current } = this.state;
|
|
148
|
+
const { fans, appearance } = this.props;
|
|
149
|
+
|
|
150
|
+
if (this.mouseMoved && isDefined(current) && isDefined(current.startXY)) {
|
|
151
|
+
const newfans = [
|
|
152
|
+
...fans.map((d) => ({ ...d, selected: false })),
|
|
153
|
+
{ ...current, selected: true, appearance },
|
|
154
|
+
];
|
|
155
|
+
this.setState(
|
|
156
|
+
{
|
|
157
|
+
current: null,
|
|
158
|
+
},
|
|
159
|
+
() => {
|
|
160
|
+
const { onComplete } = this.props;
|
|
161
|
+
if (onComplete !== undefined) {
|
|
162
|
+
onComplete(e, newfans, moreProps);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
private readonly handleStart = (_: React.MouseEvent, xyValue: any) => {
|
|
170
|
+
const { current } = this.state;
|
|
171
|
+
|
|
172
|
+
if (isNotDefined(current) || isNotDefined(current.startXY)) {
|
|
173
|
+
this.mouseMoved = false;
|
|
174
|
+
|
|
175
|
+
this.setState(
|
|
176
|
+
{
|
|
177
|
+
current: {
|
|
178
|
+
startXY: xyValue,
|
|
179
|
+
endXY: null,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
() => {
|
|
183
|
+
const { onStart } = this.props;
|
|
184
|
+
if (onStart !== undefined) {
|
|
185
|
+
onStart();
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
private readonly handleDrawFan = (_: React.MouseEvent, xyValue: any) => {
|
|
193
|
+
const { current } = this.state;
|
|
194
|
+
|
|
195
|
+
if (isDefined(current) && isDefined(current.startXY)) {
|
|
196
|
+
this.mouseMoved = true;
|
|
197
|
+
|
|
198
|
+
this.setState({
|
|
199
|
+
current: {
|
|
200
|
+
startXY: current.startXY,
|
|
201
|
+
endXY: xyValue,
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
private readonly handleDragFanComplete = (e: React.MouseEvent, moreProps: any) => {
|
|
208
|
+
const { override } = this.state;
|
|
209
|
+
const { fans } = this.props;
|
|
210
|
+
|
|
211
|
+
if (isDefined(override)) {
|
|
212
|
+
const { index, ...rest } = override;
|
|
213
|
+
const newfans = fans.map((each, idx) => (idx === index ? { ...each, ...rest, selected: true } : each));
|
|
214
|
+
this.setState(
|
|
215
|
+
{
|
|
216
|
+
override: null,
|
|
217
|
+
},
|
|
218
|
+
() => {
|
|
219
|
+
this.props.onComplete(e, newfans, moreProps);
|
|
220
|
+
},
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
private readonly handleDragFan = (_: React.MouseEvent, index: number | undefined, newXYValue: any) => {
|
|
226
|
+
this.setState({
|
|
227
|
+
override: {
|
|
228
|
+
index,
|
|
229
|
+
...newXYValue,
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
};
|
|
233
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ChartContext, GenericChartComponent, getMouseCanvas, isDefined, noop } from "@tradingaction/core";
|
|
3
|
+
import { HoverTextNearMouse } from "./components";
|
|
4
|
+
import { getValueFromOverride, isHoverForInteractiveType, saveNodeType, terminate } from "./utils";
|
|
5
|
+
import { EachText } from "./wrapper";
|
|
6
|
+
|
|
7
|
+
interface InteractiveTextProps {
|
|
8
|
+
readonly onChoosePosition: (e: React.MouseEvent, newText: any, moreProps: any) => void;
|
|
9
|
+
readonly onDragComplete?: (e: React.MouseEvent, newTextList: any[], moreProps: any) => void;
|
|
10
|
+
readonly onSelect?: (e: React.MouseEvent, interactives: any[], moreProps: any) => void;
|
|
11
|
+
readonly onDoubleClick?: (e: React.MouseEvent, moreProps: any) => void; //a1
|
|
12
|
+
readonly defaultText: {
|
|
13
|
+
readonly bgFill: string;
|
|
14
|
+
readonly bgOpacity: number;
|
|
15
|
+
readonly bgStrokeWidth?: number;
|
|
16
|
+
readonly bgStroke?: string;
|
|
17
|
+
readonly textFill: string;
|
|
18
|
+
readonly fontFamily: string;
|
|
19
|
+
readonly fontWeight: string;
|
|
20
|
+
readonly fontStyle: string;
|
|
21
|
+
readonly fontSize: number;
|
|
22
|
+
readonly text: string;
|
|
23
|
+
};
|
|
24
|
+
readonly hoverText: object;
|
|
25
|
+
readonly textList: any[];
|
|
26
|
+
readonly enabled: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface InteractiveTextState {
|
|
30
|
+
current?: any;
|
|
31
|
+
override?: any;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class InteractiveText extends React.Component<InteractiveTextProps, InteractiveTextState> {
|
|
35
|
+
public static defaultProps = {
|
|
36
|
+
onSelect: noop,
|
|
37
|
+
defaultText: {
|
|
38
|
+
bgFill: "#D3D3D3",
|
|
39
|
+
bgOpacity: 1,
|
|
40
|
+
bgStrokeWidth: 1,
|
|
41
|
+
textFill: "#F10040",
|
|
42
|
+
fontFamily: "-apple-system, system-ui, Roboto, 'Helvetica Neue', Ubuntu, sans-serif",
|
|
43
|
+
fontSize: 12,
|
|
44
|
+
fontStyle: "normal",
|
|
45
|
+
fontWeight: "normal",
|
|
46
|
+
text: "Lorem ipsum...",
|
|
47
|
+
},
|
|
48
|
+
hoverText: {
|
|
49
|
+
...HoverTextNearMouse.defaultProps,
|
|
50
|
+
enable: true,
|
|
51
|
+
bgHeight: "auto",
|
|
52
|
+
bgWidth: "auto",
|
|
53
|
+
text: "Click to select object",
|
|
54
|
+
selectedText: "",
|
|
55
|
+
},
|
|
56
|
+
textList: [],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
public static contextType = ChartContext;
|
|
60
|
+
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
private getSelectionState: any;
|
|
63
|
+
private saveNodeType: any;
|
|
64
|
+
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
private terminate: any;
|
|
67
|
+
|
|
68
|
+
public constructor(props: InteractiveTextProps) {
|
|
69
|
+
super(props);
|
|
70
|
+
|
|
71
|
+
this.terminate = terminate.bind(this);
|
|
72
|
+
this.saveNodeType = saveNodeType.bind(this);
|
|
73
|
+
this.getSelectionState = isHoverForInteractiveType("textList").bind(this);
|
|
74
|
+
|
|
75
|
+
this.state = {};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public render() {
|
|
79
|
+
const { textList, defaultText, hoverText, onDoubleClick } = this.props;
|
|
80
|
+
const { override } = this.state;
|
|
81
|
+
return (
|
|
82
|
+
<g>
|
|
83
|
+
{textList.map((each, idx) => {
|
|
84
|
+
const defaultHoverText = InteractiveText.defaultProps.hoverText;
|
|
85
|
+
const props = {
|
|
86
|
+
...defaultText,
|
|
87
|
+
...each,
|
|
88
|
+
hoverText: {
|
|
89
|
+
...defaultHoverText,
|
|
90
|
+
...hoverText,
|
|
91
|
+
...(each.hoverText || {}),
|
|
92
|
+
},
|
|
93
|
+
onDoubleClick,
|
|
94
|
+
};
|
|
95
|
+
return (
|
|
96
|
+
<EachText
|
|
97
|
+
key={idx}
|
|
98
|
+
ref={this.saveNodeType(idx)}
|
|
99
|
+
index={idx}
|
|
100
|
+
{...props}
|
|
101
|
+
selected={each.selected}
|
|
102
|
+
position={getValueFromOverride(override, idx, "position", each.position)}
|
|
103
|
+
onDrag={this.handleDrag}
|
|
104
|
+
onDragComplete={this.handleDragComplete}
|
|
105
|
+
edgeInteractiveCursor="react-financial-charts-move-cursor"
|
|
106
|
+
onDoubleClick={props.onDoubleClick}
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
})}
|
|
110
|
+
<GenericChartComponent
|
|
111
|
+
onClick={this.handleDraw}
|
|
112
|
+
canvasToDraw={getMouseCanvas}
|
|
113
|
+
drawOn={["mousemove", "pan"]}
|
|
114
|
+
/>
|
|
115
|
+
;
|
|
116
|
+
</g>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private readonly handleDraw = (e: React.MouseEvent, moreProps: any) => {
|
|
121
|
+
const { enabled } = this.props;
|
|
122
|
+
if (enabled) {
|
|
123
|
+
const {
|
|
124
|
+
mouseXY: [, mouseY],
|
|
125
|
+
chartConfig: { yScale },
|
|
126
|
+
xAccessor,
|
|
127
|
+
currentItem,
|
|
128
|
+
} = moreProps;
|
|
129
|
+
|
|
130
|
+
const { defaultText, onChoosePosition } = this.props;
|
|
131
|
+
|
|
132
|
+
if (onChoosePosition !== undefined) {
|
|
133
|
+
const xyValue = [xAccessor(currentItem), yScale.invert(mouseY)];
|
|
134
|
+
const newText = {
|
|
135
|
+
...defaultText,
|
|
136
|
+
position: xyValue,
|
|
137
|
+
};
|
|
138
|
+
onChoosePosition(e, newText, moreProps);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
private readonly handleDragComplete = (e: React.MouseEvent, moreProps: any) => {
|
|
144
|
+
const { override } = this.state;
|
|
145
|
+
if (isDefined(override)) {
|
|
146
|
+
const { textList } = this.props;
|
|
147
|
+
const newTextList = textList.map((each, idx) => {
|
|
148
|
+
const selected = idx === override.index;
|
|
149
|
+
return selected
|
|
150
|
+
? {
|
|
151
|
+
...each,
|
|
152
|
+
position: override.position,
|
|
153
|
+
selected,
|
|
154
|
+
}
|
|
155
|
+
: {
|
|
156
|
+
...each,
|
|
157
|
+
selected,
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
this.setState(
|
|
161
|
+
{
|
|
162
|
+
override: null,
|
|
163
|
+
},
|
|
164
|
+
() => {
|
|
165
|
+
const { onDragComplete } = this.props;
|
|
166
|
+
if (onDragComplete !== undefined) {
|
|
167
|
+
onDragComplete(e, newTextList, moreProps);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
private readonly handleDrag = (_: React.MouseEvent, index: any, position: any) => {
|
|
175
|
+
this.setState({
|
|
176
|
+
override: {
|
|
177
|
+
index,
|
|
178
|
+
position,
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { format } from "d3-format";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { ChartContext, isDefined, strokeDashTypes } from "@tradingaction/core";
|
|
4
|
+
import { HoverTextNearMouse } from "./components";
|
|
5
|
+
import { getValueFromOverride, isHoverForInteractiveType, saveNodeType, terminate } from "./utils";
|
|
6
|
+
import { EachInteractiveYCoordinate } from "./wrapper";
|
|
7
|
+
|
|
8
|
+
interface InteractiveYCoordinateProps {
|
|
9
|
+
readonly onChoosePosition: (e: React.MouseEvent, newText: any, moreProps: any) => void;
|
|
10
|
+
readonly onDragComplete: (e: React.MouseEvent, newAlertList: any[], moreProps: any, draggedAlert: any) => void;
|
|
11
|
+
readonly onSelect?: (e: React.MouseEvent, interactives: any[], moreProps: any) => void;
|
|
12
|
+
readonly onDelete?: (e: React.MouseEvent, yCoordinate: any, moreProps: any) => void;
|
|
13
|
+
readonly defaultPriceCoordinate: {
|
|
14
|
+
readonly bgFill: string;
|
|
15
|
+
readonly bgOpacity: number;
|
|
16
|
+
readonly stroke: string;
|
|
17
|
+
readonly strokeDasharray: strokeDashTypes;
|
|
18
|
+
readonly strokeOpacity: number;
|
|
19
|
+
readonly strokeWidth: number;
|
|
20
|
+
readonly textFill: string;
|
|
21
|
+
readonly fontFamily: string;
|
|
22
|
+
readonly fontWeight: string;
|
|
23
|
+
readonly fontStyle: string;
|
|
24
|
+
readonly fontSize: number;
|
|
25
|
+
readonly text: string;
|
|
26
|
+
readonly textBox: {
|
|
27
|
+
readonly height: number;
|
|
28
|
+
readonly left: number;
|
|
29
|
+
readonly padding: {
|
|
30
|
+
left: number;
|
|
31
|
+
right: number;
|
|
32
|
+
};
|
|
33
|
+
readonly closeIcon: {
|
|
34
|
+
padding: {
|
|
35
|
+
left: number;
|
|
36
|
+
right: number;
|
|
37
|
+
};
|
|
38
|
+
width: number;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
readonly edge: {
|
|
42
|
+
readonly stroke: string;
|
|
43
|
+
readonly strokeOpacity: number;
|
|
44
|
+
readonly strokeWidth: number;
|
|
45
|
+
readonly fill: string;
|
|
46
|
+
readonly fillOpacity: number;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
readonly hoverText: object;
|
|
50
|
+
readonly yCoordinateList: any[];
|
|
51
|
+
readonly enabled: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface InteractiveYCoordinateState {
|
|
55
|
+
current?: any;
|
|
56
|
+
override?: any;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class InteractiveYCoordinate extends React.Component<InteractiveYCoordinateProps, InteractiveYCoordinateState> {
|
|
60
|
+
public static defaultProps = {
|
|
61
|
+
defaultPriceCoordinate: {
|
|
62
|
+
bgFill: "#FFFFFF",
|
|
63
|
+
bgOpacity: 1,
|
|
64
|
+
stroke: "#6574CD",
|
|
65
|
+
strokeOpacity: 1,
|
|
66
|
+
strokeDasharray: "ShortDash2",
|
|
67
|
+
strokeWidth: 1,
|
|
68
|
+
textFill: "#6574CD",
|
|
69
|
+
fontFamily: "-apple-system, system-ui, Roboto, 'Helvetica Neue', Ubuntu, sans-serif",
|
|
70
|
+
fontSize: 12,
|
|
71
|
+
fontStyle: "normal",
|
|
72
|
+
fontWeight: "normal",
|
|
73
|
+
text: "Alert",
|
|
74
|
+
textBox: {
|
|
75
|
+
height: 24,
|
|
76
|
+
left: 20,
|
|
77
|
+
padding: { left: 10, right: 5 },
|
|
78
|
+
closeIcon: {
|
|
79
|
+
padding: { left: 5, right: 8 },
|
|
80
|
+
width: 8,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
edge: {
|
|
84
|
+
stroke: "#6574CD",
|
|
85
|
+
strokeOpacity: 1,
|
|
86
|
+
strokeWidth: 1,
|
|
87
|
+
fill: "#FFFFFF",
|
|
88
|
+
fillOpacity: 1,
|
|
89
|
+
orient: "right",
|
|
90
|
+
at: "right",
|
|
91
|
+
arrowWidth: 10,
|
|
92
|
+
dx: 0,
|
|
93
|
+
rectWidth: 50,
|
|
94
|
+
rectHeight: 20,
|
|
95
|
+
displayFormat: format(".2f"),
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
hoverText: {
|
|
99
|
+
...HoverTextNearMouse.defaultProps,
|
|
100
|
+
enable: true,
|
|
101
|
+
bgHeight: 18,
|
|
102
|
+
bgWidth: 175,
|
|
103
|
+
text: "Click and drag the edge circles",
|
|
104
|
+
},
|
|
105
|
+
yCoordinateList: [],
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
public static contextType = ChartContext;
|
|
109
|
+
|
|
110
|
+
// @ts-ignore
|
|
111
|
+
private getSelectionState: any;
|
|
112
|
+
private saveNodeType: any;
|
|
113
|
+
// @ts-ignore
|
|
114
|
+
private terminate: any;
|
|
115
|
+
|
|
116
|
+
public constructor(props: InteractiveYCoordinateProps) {
|
|
117
|
+
super(props);
|
|
118
|
+
|
|
119
|
+
this.terminate = terminate.bind(this);
|
|
120
|
+
this.saveNodeType = saveNodeType.bind(this);
|
|
121
|
+
this.getSelectionState = isHoverForInteractiveType("yCoordinateList").bind(this);
|
|
122
|
+
|
|
123
|
+
this.state = {};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public render() {
|
|
127
|
+
const { yCoordinateList } = this.props;
|
|
128
|
+
const { override } = this.state;
|
|
129
|
+
return (
|
|
130
|
+
<g>
|
|
131
|
+
{yCoordinateList.map((each, idx) => {
|
|
132
|
+
const props = each;
|
|
133
|
+
return (
|
|
134
|
+
<EachInteractiveYCoordinate
|
|
135
|
+
key={each.id}
|
|
136
|
+
ref={this.saveNodeType(idx)}
|
|
137
|
+
index={idx}
|
|
138
|
+
{...props}
|
|
139
|
+
selected={each.selected}
|
|
140
|
+
yValue={getValueFromOverride(override, idx, "yValue", each.yValue)}
|
|
141
|
+
onDelete={this.handleDelete}
|
|
142
|
+
onDrag={this.handleDrag}
|
|
143
|
+
onDragComplete={this.handleDragComplete}
|
|
144
|
+
edgeInteractiveCursor="react-financial-charts-move-cursor"
|
|
145
|
+
/>
|
|
146
|
+
);
|
|
147
|
+
})}
|
|
148
|
+
</g>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private readonly handleDelete = (e: React.MouseEvent, index: number | undefined, moreProps: any) => {
|
|
153
|
+
const { onDelete, yCoordinateList } = this.props;
|
|
154
|
+
if (onDelete !== undefined && index !== undefined) {
|
|
155
|
+
onDelete(e, yCoordinateList[index], moreProps);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
private readonly handleDragComplete = (e: React.MouseEvent, moreProps: any) => {
|
|
160
|
+
const { override } = this.state;
|
|
161
|
+
if (isDefined(override)) {
|
|
162
|
+
const { yCoordinateList } = this.props;
|
|
163
|
+
const newAlertList = yCoordinateList.map((each, idx) => {
|
|
164
|
+
const selected = idx === override.index;
|
|
165
|
+
return selected
|
|
166
|
+
? {
|
|
167
|
+
...each,
|
|
168
|
+
yValue: override.yValue,
|
|
169
|
+
selected,
|
|
170
|
+
}
|
|
171
|
+
: {
|
|
172
|
+
...each,
|
|
173
|
+
selected,
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
const draggedAlert = newAlertList[override.index];
|
|
177
|
+
this.setState(
|
|
178
|
+
{
|
|
179
|
+
override: null,
|
|
180
|
+
},
|
|
181
|
+
() => {
|
|
182
|
+
const { onDragComplete } = this.props;
|
|
183
|
+
if (onDragComplete !== undefined) {
|
|
184
|
+
onDragComplete(e, newAlertList, moreProps, draggedAlert);
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
private readonly handleDrag = (_: React.MouseEvent, index: any, yValue: any) => {
|
|
192
|
+
this.setState({
|
|
193
|
+
override: {
|
|
194
|
+
index,
|
|
195
|
+
yValue,
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
}
|