@tradingaction/core 2.0.0
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/CanvasContainer.d.ts +19 -0
- package/lib/CanvasContainer.js +28 -0
- package/lib/CanvasContainer.js.map +1 -0
- package/lib/Chart.d.ts +32 -0
- package/lib/Chart.js +57 -0
- package/lib/Chart.js.map +1 -0
- package/lib/ChartCanvas.d.ts +235 -0
- package/lib/ChartCanvas.js +810 -0
- package/lib/ChartCanvas.js.map +1 -0
- package/lib/EventCapture.d.ts +131 -0
- package/lib/EventCapture.js +489 -0
- package/lib/EventCapture.js.map +1 -0
- package/lib/GenericChartComponent.d.ts +21 -0
- package/lib/GenericChartComponent.js +75 -0
- package/lib/GenericChartComponent.js.map +1 -0
- package/lib/GenericComponent.d.ts +81 -0
- package/lib/GenericComponent.js +355 -0
- package/lib/GenericComponent.js.map +1 -0
- package/lib/MoreProps.d.ts +16 -0
- package/lib/MoreProps.js +2 -0
- package/lib/MoreProps.js.map +1 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -0
- package/lib/useEvent.d.ts +1 -0
- package/lib/useEvent.js +13 -0
- package/lib/useEvent.js.map +1 -0
- package/lib/utils/ChartDataUtil.d.ts +49 -0
- package/lib/utils/ChartDataUtil.js +205 -0
- package/lib/utils/ChartDataUtil.js.map +1 -0
- package/lib/utils/PureComponent.d.ts +4 -0
- package/lib/utils/PureComponent.js +10 -0
- package/lib/utils/PureComponent.js.map +1 -0
- package/lib/utils/accumulatingWindow.d.ts +15 -0
- package/lib/utils/accumulatingWindow.js +98 -0
- package/lib/utils/accumulatingWindow.js.map +1 -0
- package/lib/utils/barWidth.d.ts +15 -0
- package/lib/utils/barWidth.js +27 -0
- package/lib/utils/barWidth.js.map +1 -0
- package/lib/utils/closestItem.d.ts +5 -0
- package/lib/utils/closestItem.js +45 -0
- package/lib/utils/closestItem.js.map +1 -0
- package/lib/utils/evaluator.d.ts +7 -0
- package/lib/utils/evaluator.js +94 -0
- package/lib/utils/evaluator.js.map +1 -0
- package/lib/utils/identity.d.ts +1 -0
- package/lib/utils/identity.js +2 -0
- package/lib/utils/identity.js.map +1 -0
- package/lib/utils/index.d.ts +46 -0
- package/lib/utils/index.js +126 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/noop.d.ts +1 -0
- package/lib/utils/noop.js +3 -0
- package/lib/utils/noop.js.map +1 -0
- package/lib/utils/shallowEqual.d.ts +1 -0
- package/lib/utils/shallowEqual.js +22 -0
- package/lib/utils/shallowEqual.js.map +1 -0
- package/lib/utils/slidingWindow.d.ts +19 -0
- package/lib/utils/slidingWindow.js +109 -0
- package/lib/utils/slidingWindow.js.map +1 -0
- package/lib/utils/strokeDasharray.d.ts +3 -0
- package/lib/utils/strokeDasharray.js +37 -0
- package/lib/utils/strokeDasharray.js.map +1 -0
- package/lib/utils/zipper.d.ts +7 -0
- package/lib/utils/zipper.js +36 -0
- package/lib/utils/zipper.js.map +1 -0
- package/lib/zoom/index.d.ts +1 -0
- package/lib/zoom/index.js +2 -0
- package/lib/zoom/index.js.map +1 -0
- package/lib/zoom/zoomBehavior.d.ts +10 -0
- package/lib/zoom/zoomBehavior.js +18 -0
- package/lib/zoom/zoomBehavior.js.map +1 -0
- package/package.json +52 -0
- package/src/CanvasContainer.tsx +44 -0
- package/src/Chart.tsx +114 -0
- package/src/ChartCanvas.tsx +1336 -0
- package/src/EventCapture.tsx +709 -0
- package/src/GenericChartComponent.tsx +98 -0
- package/src/GenericComponent.tsx +454 -0
- package/src/MoreProps.ts +17 -0
- package/src/index.ts +7 -0
- package/src/useEvent.ts +14 -0
- package/src/utils/ChartDataUtil.ts +297 -0
- package/src/utils/PureComponent.tsx +12 -0
- package/src/utils/accumulatingWindow.ts +118 -0
- package/src/utils/barWidth.ts +44 -0
- package/src/utils/closestItem.ts +60 -0
- package/src/utils/evaluator.ts +163 -0
- package/src/utils/identity.ts +1 -0
- package/src/utils/index.ts +153 -0
- package/src/utils/noop.ts +2 -0
- package/src/utils/shallowEqual.ts +25 -0
- package/src/utils/slidingWindow.ts +140 -0
- package/src/utils/strokeDasharray.ts +52 -0
- package/src/utils/zipper.ts +45 -0
- package/src/zoom/index.ts +1 -0
- package/src/zoom/zoomBehavior.ts +34 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { GenericComponent } from "./GenericComponent";
|
|
2
|
+
import { isDefined } from "./utils";
|
|
3
|
+
import { ChartContext } from "./Chart";
|
|
4
|
+
|
|
5
|
+
const ALWAYS_TRUE_TYPES = ["drag", "dragend"];
|
|
6
|
+
|
|
7
|
+
export class GenericChartComponent extends GenericComponent {
|
|
8
|
+
public static defaultProps = GenericComponent.defaultProps;
|
|
9
|
+
public static contextType = ChartContext;
|
|
10
|
+
|
|
11
|
+
public constructor(props: any, context: any) {
|
|
12
|
+
super(props, context);
|
|
13
|
+
|
|
14
|
+
this.preCanvasDraw = this.preCanvasDraw.bind(this);
|
|
15
|
+
this.postCanvasDraw = this.postCanvasDraw.bind(this);
|
|
16
|
+
this.shouldTypeProceed = this.shouldTypeProceed.bind(this);
|
|
17
|
+
this.preEvaluate = this.preEvaluate.bind(this);
|
|
18
|
+
this.updateMoreProps = this.updateMoreProps.bind(this);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public preCanvasDraw(ctx: CanvasRenderingContext2D, moreProps: any) {
|
|
22
|
+
super.preCanvasDraw(ctx, moreProps);
|
|
23
|
+
|
|
24
|
+
ctx.save();
|
|
25
|
+
const { margin, ratio } = this.context;
|
|
26
|
+
const {
|
|
27
|
+
chartConfig: { width, height, origin },
|
|
28
|
+
} = moreProps;
|
|
29
|
+
|
|
30
|
+
const canvasOriginX = 0.5 * ratio + origin[0] + margin.left;
|
|
31
|
+
const canvasOriginY = 0.5 * ratio + origin[1] + margin.top;
|
|
32
|
+
|
|
33
|
+
const { clip, edgeClip } = this.props;
|
|
34
|
+
|
|
35
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
36
|
+
ctx.scale(ratio, ratio);
|
|
37
|
+
if (edgeClip) {
|
|
38
|
+
ctx.beginPath();
|
|
39
|
+
ctx.rect(-1, canvasOriginY - 10, width + margin.left + margin.right + 1, height + 20);
|
|
40
|
+
ctx.clip();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
ctx.translate(canvasOriginX, canvasOriginY);
|
|
44
|
+
|
|
45
|
+
if (clip) {
|
|
46
|
+
ctx.beginPath();
|
|
47
|
+
ctx.rect(-1, -1, width + 1, height + 1);
|
|
48
|
+
ctx.clip();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public postCanvasDraw(ctx: CanvasRenderingContext2D, moreProps: any) {
|
|
53
|
+
super.postCanvasDraw(ctx, moreProps);
|
|
54
|
+
ctx.restore();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public updateMoreProps(moreProps: any) {
|
|
58
|
+
super.updateMoreProps(moreProps);
|
|
59
|
+
const { chartConfig: chartConfigList } = moreProps;
|
|
60
|
+
|
|
61
|
+
if (chartConfigList && Array.isArray(chartConfigList)) {
|
|
62
|
+
const { chartId } = this.context;
|
|
63
|
+
const chartConfig = chartConfigList.find((each) => each.id === chartId);
|
|
64
|
+
this.moreProps.chartConfig = chartConfig;
|
|
65
|
+
}
|
|
66
|
+
if (isDefined(this.moreProps.chartConfig)) {
|
|
67
|
+
const {
|
|
68
|
+
origin: [ox, oy],
|
|
69
|
+
} = this.moreProps.chartConfig;
|
|
70
|
+
if (isDefined(moreProps.mouseXY)) {
|
|
71
|
+
const {
|
|
72
|
+
mouseXY: [x, y],
|
|
73
|
+
} = moreProps;
|
|
74
|
+
this.moreProps.mouseXY = [x - ox, y - oy];
|
|
75
|
+
}
|
|
76
|
+
if (isDefined(moreProps.startPos)) {
|
|
77
|
+
const {
|
|
78
|
+
startPos: [x, y],
|
|
79
|
+
} = moreProps;
|
|
80
|
+
this.moreProps.startPos = [x - ox, y - oy];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public preEvaluate(/* type, moreProps */) {
|
|
86
|
+
///
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public shouldTypeProceed(type: string, moreProps: any) {
|
|
90
|
+
if ((type === "mousemove" || type === "click") && this.props.disablePan) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
if (ALWAYS_TRUE_TYPES.indexOf(type) === -1 && isDefined(moreProps) && isDefined(moreProps.currentCharts)) {
|
|
94
|
+
return moreProps.currentCharts.indexOf(this.context.chartId) > -1;
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { functor, identity } from "./utils";
|
|
4
|
+
import { ICanvasContexts } from "./CanvasContainer";
|
|
5
|
+
import { ChartCanvasContext } from "./ChartCanvas";
|
|
6
|
+
|
|
7
|
+
const aliases: Record<string, string> = {
|
|
8
|
+
mouseleave: "mousemove", // to draw interactive after mouse exit
|
|
9
|
+
panend: "pan",
|
|
10
|
+
pinchzoom: "pan",
|
|
11
|
+
mousedown: "mousemove",
|
|
12
|
+
click: "mousemove",
|
|
13
|
+
contextmenu: "mousemove",
|
|
14
|
+
dblclick: "mousemove",
|
|
15
|
+
dragstart: "drag",
|
|
16
|
+
dragend: "drag",
|
|
17
|
+
dragcancel: "drag",
|
|
18
|
+
zoom: "zoom",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
interface GenericComponentProps {
|
|
22
|
+
readonly svgDraw?: (moreProps: any) => React.ReactNode;
|
|
23
|
+
readonly canvasDraw?: (ctx: CanvasRenderingContext2D, moreProps: any) => void;
|
|
24
|
+
readonly canvasToDraw?: (contexts: ICanvasContexts) => CanvasRenderingContext2D | undefined;
|
|
25
|
+
readonly clip?: boolean;
|
|
26
|
+
readonly disablePan?: boolean;
|
|
27
|
+
readonly drawOn: string[];
|
|
28
|
+
readonly edgeClip?: boolean;
|
|
29
|
+
readonly enableDragOnHover?: boolean;
|
|
30
|
+
readonly interactiveCursorClass?: string;
|
|
31
|
+
readonly isHover?: (moreProps: any, e: React.MouseEvent) => boolean;
|
|
32
|
+
readonly onClick?: (e: React.MouseEvent, moreProps: any) => void;
|
|
33
|
+
readonly onClickWhenHover?: (e: React.MouseEvent, moreProps: any) => void;
|
|
34
|
+
readonly onClickOutside?: (e: React.MouseEvent, moreProps: any) => void;
|
|
35
|
+
readonly onPan?: (e: React.MouseEvent, moreProps: any) => void;
|
|
36
|
+
readonly onPanEnd?: (e: React.MouseEvent, moreProps: any) => void;
|
|
37
|
+
readonly onDragStart?: (e: React.MouseEvent, moreProps: any) => void;
|
|
38
|
+
readonly onDrag?: (e: React.MouseEvent, moreProps: any) => void;
|
|
39
|
+
readonly onDragComplete?: (e: React.MouseEvent, moreProps: any) => void;
|
|
40
|
+
readonly onDoubleClick?: (e: React.MouseEvent, moreProps: any) => void;
|
|
41
|
+
readonly onDoubleClickWhenHover?: (e: React.MouseEvent, moreProps: any) => void;
|
|
42
|
+
readonly onContextMenu?: (e: React.MouseEvent, moreProps: any) => void;
|
|
43
|
+
readonly onContextMenuWhenHover?: (e: React.MouseEvent, moreProps: any) => void;
|
|
44
|
+
readonly onMouseMove?: (e: React.MouseEvent, moreProps: any) => void;
|
|
45
|
+
readonly onMouseDown?: (e: React.MouseEvent, moreProps: any) => void;
|
|
46
|
+
readonly onHover?: (e: React.MouseEvent, moreProps: any) => void;
|
|
47
|
+
readonly onUnHover?: (e: React.MouseEvent, moreProps: any) => void;
|
|
48
|
+
readonly selected?: boolean;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface GenericComponentState {
|
|
52
|
+
updateCount: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export class GenericComponent extends React.Component<GenericComponentProps, GenericComponentState> {
|
|
56
|
+
public static defaultProps = {
|
|
57
|
+
svgDraw: functor(null),
|
|
58
|
+
draw: [],
|
|
59
|
+
canvasToDraw: (contexts: ICanvasContexts) => contexts.mouseCoord,
|
|
60
|
+
clip: true,
|
|
61
|
+
edgeClip: false,
|
|
62
|
+
selected: false,
|
|
63
|
+
disablePan: false,
|
|
64
|
+
enableDragOnHover: false,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
public declare context: React.ContextType<typeof ChartCanvasContext>;
|
|
68
|
+
|
|
69
|
+
public moreProps: any = {};
|
|
70
|
+
|
|
71
|
+
private dragInProgress = false;
|
|
72
|
+
private evaluationInProgress = false;
|
|
73
|
+
private iSetTheCursorClass = false;
|
|
74
|
+
private readonly subscriberId: number;
|
|
75
|
+
|
|
76
|
+
public constructor(props: GenericComponentProps, context: any) {
|
|
77
|
+
super(props, context);
|
|
78
|
+
this.drawOnCanvas = this.drawOnCanvas.bind(this);
|
|
79
|
+
this.getMoreProps = this.getMoreProps.bind(this);
|
|
80
|
+
this.draw = this.draw.bind(this);
|
|
81
|
+
this.updateMoreProps = this.updateMoreProps.bind(this);
|
|
82
|
+
this.evaluateType = this.evaluateType.bind(this);
|
|
83
|
+
this.isHover = this.isHover.bind(this);
|
|
84
|
+
this.preCanvasDraw = this.preCanvasDraw.bind(this);
|
|
85
|
+
this.postCanvasDraw = this.postCanvasDraw.bind(this);
|
|
86
|
+
this.getPanConditions = this.getPanConditions.bind(this);
|
|
87
|
+
this.shouldTypeProceed = this.shouldTypeProceed.bind(this);
|
|
88
|
+
this.preEvaluate = this.preEvaluate.bind(this);
|
|
89
|
+
|
|
90
|
+
const { generateSubscriptionId } = context;
|
|
91
|
+
|
|
92
|
+
this.subscriberId = generateSubscriptionId();
|
|
93
|
+
|
|
94
|
+
this.state = {
|
|
95
|
+
updateCount: 0,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public updateMoreProps(moreProps: any) {
|
|
100
|
+
Object.keys(moreProps).forEach((key) => {
|
|
101
|
+
this.moreProps[key] = moreProps[key];
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public shouldTypeProceed(type: string, moreProps: any) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public preEvaluate(type: string, moreProps: any, e: any) {
|
|
110
|
+
/// empty
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public listener = (type: string, moreProps: any, state: any, e: any) => {
|
|
114
|
+
if (moreProps !== undefined) {
|
|
115
|
+
this.updateMoreProps(moreProps);
|
|
116
|
+
}
|
|
117
|
+
this.evaluationInProgress = true;
|
|
118
|
+
this.evaluateType(type, e);
|
|
119
|
+
this.evaluationInProgress = false;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
public evaluateType(type: string, e: any) {
|
|
123
|
+
// @ts-ignore
|
|
124
|
+
const newType = aliases[type] || type;
|
|
125
|
+
const proceed = this.props.drawOn.indexOf(newType) > -1;
|
|
126
|
+
if (!proceed) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this.preEvaluate(type, this.moreProps, e);
|
|
131
|
+
|
|
132
|
+
if (!this.shouldTypeProceed(type, this.moreProps)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
switch (type) {
|
|
137
|
+
case "zoom":
|
|
138
|
+
case "mouseenter":
|
|
139
|
+
// DO NOT DRAW FOR THESE EVENTS
|
|
140
|
+
break;
|
|
141
|
+
case "mouseleave": {
|
|
142
|
+
this.moreProps.hovering = false;
|
|
143
|
+
|
|
144
|
+
if (this.props.onUnHover) {
|
|
145
|
+
this.props.onUnHover(e, this.getMoreProps());
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case "contextmenu": {
|
|
150
|
+
if (this.props.onContextMenu) {
|
|
151
|
+
this.props.onContextMenu(e, this.getMoreProps());
|
|
152
|
+
}
|
|
153
|
+
if (this.moreProps.hovering && this.props.onContextMenuWhenHover) {
|
|
154
|
+
this.props.onContextMenuWhenHover(e, this.getMoreProps());
|
|
155
|
+
}
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case "mousedown": {
|
|
159
|
+
if (this.props.onMouseDown) {
|
|
160
|
+
this.props.onMouseDown(e, this.getMoreProps());
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
case "click": {
|
|
165
|
+
const { onClick, onClickOutside, onClickWhenHover } = this.props;
|
|
166
|
+
const moreProps = this.getMoreProps();
|
|
167
|
+
if (moreProps.hovering && onClickWhenHover !== undefined) {
|
|
168
|
+
onClickWhenHover(e, moreProps);
|
|
169
|
+
} else if (onClickOutside !== undefined) {
|
|
170
|
+
onClickOutside(e, moreProps);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (onClick !== undefined) {
|
|
174
|
+
onClick(e, moreProps);
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
case "mousemove": {
|
|
179
|
+
const prevHover = this.moreProps.hovering;
|
|
180
|
+
this.moreProps.hovering = this.isHover(e);
|
|
181
|
+
|
|
182
|
+
const { amIOnTop, setCursorClass } = this.context;
|
|
183
|
+
|
|
184
|
+
if (
|
|
185
|
+
this.moreProps.hovering &&
|
|
186
|
+
!this.props.selected &&
|
|
187
|
+
/* && !prevHover */
|
|
188
|
+
amIOnTop(this.subscriberId) &&
|
|
189
|
+
this.props.onHover !== undefined
|
|
190
|
+
) {
|
|
191
|
+
setCursorClass("react-financial-charts-pointer-cursor");
|
|
192
|
+
this.iSetTheCursorClass = true;
|
|
193
|
+
} else if (this.moreProps.hovering && this.props.selected && amIOnTop(this.subscriberId)) {
|
|
194
|
+
setCursorClass(this.props.interactiveCursorClass);
|
|
195
|
+
this.iSetTheCursorClass = true;
|
|
196
|
+
} else if (prevHover && !this.moreProps.hovering && this.iSetTheCursorClass) {
|
|
197
|
+
this.iSetTheCursorClass = false;
|
|
198
|
+
setCursorClass(null);
|
|
199
|
+
}
|
|
200
|
+
const moreProps = this.getMoreProps();
|
|
201
|
+
|
|
202
|
+
if (this.moreProps.hovering && !prevHover) {
|
|
203
|
+
if (this.props.onHover) {
|
|
204
|
+
this.props.onHover(e, moreProps);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (prevHover && !this.moreProps.hovering) {
|
|
208
|
+
if (this.props.onUnHover) {
|
|
209
|
+
this.props.onUnHover(e, moreProps);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (this.props.onMouseMove) {
|
|
214
|
+
this.props.onMouseMove(e, moreProps);
|
|
215
|
+
}
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case "dblclick": {
|
|
219
|
+
const moreProps = this.getMoreProps();
|
|
220
|
+
|
|
221
|
+
if (this.props.onDoubleClick) {
|
|
222
|
+
this.props.onDoubleClick(e, moreProps);
|
|
223
|
+
}
|
|
224
|
+
if (this.moreProps.hovering && this.props.onDoubleClickWhenHover) {
|
|
225
|
+
this.props.onDoubleClickWhenHover(e, moreProps);
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
case "pan": {
|
|
230
|
+
this.moreProps.hovering = false;
|
|
231
|
+
if (this.props.onPan) {
|
|
232
|
+
this.props.onPan(e, this.getMoreProps());
|
|
233
|
+
}
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
case "panend": {
|
|
237
|
+
if (this.props.onPanEnd) {
|
|
238
|
+
this.props.onPanEnd(e, this.getMoreProps());
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
case "dragstart": {
|
|
243
|
+
if (this.getPanConditions().draggable) {
|
|
244
|
+
const { amIOnTop } = this.context;
|
|
245
|
+
if (amIOnTop(this.subscriberId)) {
|
|
246
|
+
this.dragInProgress = true;
|
|
247
|
+
if (this.props.onDragStart !== undefined) {
|
|
248
|
+
this.props.onDragStart(e, this.getMoreProps());
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
case "drag": {
|
|
255
|
+
if (this.dragInProgress && this.props.onDrag) {
|
|
256
|
+
this.props.onDrag(e, this.getMoreProps());
|
|
257
|
+
}
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
case "dragend": {
|
|
261
|
+
if (this.dragInProgress && this.props.onDragComplete) {
|
|
262
|
+
this.props.onDragComplete(e, this.getMoreProps());
|
|
263
|
+
}
|
|
264
|
+
this.dragInProgress = false;
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
case "dragcancel": {
|
|
268
|
+
if (this.dragInProgress || this.iSetTheCursorClass) {
|
|
269
|
+
const { setCursorClass } = this.context;
|
|
270
|
+
setCursorClass(null);
|
|
271
|
+
}
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public isHover(e: React.MouseEvent) {
|
|
278
|
+
const { isHover } = this.props;
|
|
279
|
+
if (isHover === undefined) {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return isHover(this.getMoreProps(), e);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
public getPanConditions() {
|
|
287
|
+
const draggable =
|
|
288
|
+
!!(this.props.selected && this.moreProps.hovering) ||
|
|
289
|
+
(this.props.enableDragOnHover && this.moreProps.hovering);
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
draggable,
|
|
293
|
+
panEnabled: !this.props.disablePan,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
public draw({ trigger, force = false }: { force: boolean; trigger: string }) {
|
|
298
|
+
const type = aliases[trigger] || trigger;
|
|
299
|
+
const proceed = this.props.drawOn.indexOf(type) > -1;
|
|
300
|
+
|
|
301
|
+
if (proceed || this.props.selected /* this is to draw as soon as you select */ || force) {
|
|
302
|
+
const { canvasDraw } = this.props;
|
|
303
|
+
if (canvasDraw === undefined) {
|
|
304
|
+
const { updateCount } = this.state;
|
|
305
|
+
this.setState({
|
|
306
|
+
updateCount: updateCount + 1,
|
|
307
|
+
});
|
|
308
|
+
} else {
|
|
309
|
+
this.drawOnCanvas();
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
public UNSAFE_componentWillMount() {
|
|
315
|
+
const { subscribe, chartId } = this.context;
|
|
316
|
+
const { clip, edgeClip } = this.props;
|
|
317
|
+
|
|
318
|
+
subscribe(this.subscriberId, {
|
|
319
|
+
chartId,
|
|
320
|
+
clip,
|
|
321
|
+
edgeClip,
|
|
322
|
+
listener: this.listener,
|
|
323
|
+
draw: this.draw,
|
|
324
|
+
getPanConditions: this.getPanConditions,
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
this.UNSAFE_componentWillReceiveProps(this.props, this.context);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
public componentWillUnmount() {
|
|
331
|
+
const { unsubscribe } = this.context;
|
|
332
|
+
unsubscribe(this.subscriberId);
|
|
333
|
+
if (this.iSetTheCursorClass) {
|
|
334
|
+
const { setCursorClass } = this.context;
|
|
335
|
+
setCursorClass(null);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
public componentDidMount() {
|
|
340
|
+
this.componentDidUpdate(this.props);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
public componentDidUpdate(prevProps: GenericComponentProps) {
|
|
344
|
+
const { canvasDraw, selected, interactiveCursorClass } = this.props;
|
|
345
|
+
|
|
346
|
+
if (prevProps.selected !== selected) {
|
|
347
|
+
const { setCursorClass } = this.context;
|
|
348
|
+
if (selected && this.moreProps.hovering) {
|
|
349
|
+
this.iSetTheCursorClass = true;
|
|
350
|
+
setCursorClass(interactiveCursorClass);
|
|
351
|
+
} else {
|
|
352
|
+
this.iSetTheCursorClass = false;
|
|
353
|
+
setCursorClass(null);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (canvasDraw !== undefined && !this.evaluationInProgress) {
|
|
357
|
+
this.updateMoreProps(this.moreProps);
|
|
358
|
+
this.drawOnCanvas();
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
public UNSAFE_componentWillReceiveProps(nextProps: GenericComponentProps, nextContext: any) {
|
|
363
|
+
const { xScale, plotData, chartConfig, getMutableState } = nextContext;
|
|
364
|
+
|
|
365
|
+
this.moreProps = {
|
|
366
|
+
...this.moreProps,
|
|
367
|
+
...getMutableState(),
|
|
368
|
+
/*
|
|
369
|
+
^ this is so
|
|
370
|
+
mouseXY, currentCharts, currentItem are available to
|
|
371
|
+
newly created components like MouseHoverText which
|
|
372
|
+
is created right after a new interactive object is drawn
|
|
373
|
+
*/
|
|
374
|
+
xScale,
|
|
375
|
+
plotData,
|
|
376
|
+
chartConfig,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
public getMoreProps() {
|
|
381
|
+
const { xScale, plotData, chartConfigs, morePropsDecorator, xAccessor, displayXAccessor, width, height } =
|
|
382
|
+
this.context;
|
|
383
|
+
|
|
384
|
+
const { chartId, fullData } = this.context;
|
|
385
|
+
|
|
386
|
+
const moreProps = {
|
|
387
|
+
xScale,
|
|
388
|
+
plotData,
|
|
389
|
+
chartConfigs,
|
|
390
|
+
xAccessor,
|
|
391
|
+
displayXAccessor,
|
|
392
|
+
width,
|
|
393
|
+
height,
|
|
394
|
+
chartId,
|
|
395
|
+
fullData,
|
|
396
|
+
...this.moreProps,
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
return (morePropsDecorator || identity)(moreProps);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
public preCanvasDraw(ctx: CanvasRenderingContext2D, moreProps: any) {
|
|
403
|
+
// do nothing
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
public postCanvasDraw(ctx: CanvasRenderingContext2D, moreProps: any) {
|
|
407
|
+
// empty
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
public drawOnCanvas() {
|
|
411
|
+
const { canvasDraw, canvasToDraw } = this.props;
|
|
412
|
+
if (canvasDraw === undefined || canvasToDraw === undefined) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const { getCanvasContexts } = this.context;
|
|
417
|
+
|
|
418
|
+
const moreProps = this.getMoreProps();
|
|
419
|
+
|
|
420
|
+
const contexts = getCanvasContexts!()!;
|
|
421
|
+
|
|
422
|
+
const ctx = canvasToDraw(contexts);
|
|
423
|
+
if (ctx !== undefined) {
|
|
424
|
+
this.preCanvasDraw(ctx, moreProps);
|
|
425
|
+
canvasDraw(ctx, moreProps);
|
|
426
|
+
this.postCanvasDraw(ctx, moreProps);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
public render() {
|
|
431
|
+
const { canvasDraw, clip, svgDraw } = this.props;
|
|
432
|
+
if (canvasDraw !== undefined || svgDraw === undefined) {
|
|
433
|
+
return null;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const { chartId } = this.context;
|
|
437
|
+
|
|
438
|
+
const suffix = chartId !== undefined ? "-" + chartId : "";
|
|
439
|
+
|
|
440
|
+
const style = clip ? { clipPath: `url(#chart-area-clip${suffix})` } : undefined;
|
|
441
|
+
|
|
442
|
+
return <g style={style}>{svgDraw(this.getMoreProps())}</g>;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
GenericComponent.contextType = ChartCanvasContext;
|
|
447
|
+
|
|
448
|
+
export const getAxisCanvas = (contexts: ICanvasContexts) => {
|
|
449
|
+
return contexts.axes;
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
export const getMouseCanvas = (contexts: ICanvasContexts) => {
|
|
453
|
+
return contexts.mouseCoord;
|
|
454
|
+
};
|
package/src/MoreProps.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ScaleContinuousNumeric } from "d3-scale";
|
|
2
|
+
import type { ChartConfig } from "./utils/ChartDataUtil";
|
|
3
|
+
|
|
4
|
+
export interface MoreProps {
|
|
5
|
+
chartId: string | number;
|
|
6
|
+
hovering: boolean;
|
|
7
|
+
currentCharts: (string | number)[];
|
|
8
|
+
startPos?: [number, number];
|
|
9
|
+
mouseXY?: [number, number];
|
|
10
|
+
chartConfigs: ChartConfig[];
|
|
11
|
+
chartConfig?: ChartConfig;
|
|
12
|
+
fullData: any[];
|
|
13
|
+
plotData: any[];
|
|
14
|
+
xAccessor: (datum: any) => any;
|
|
15
|
+
xScale: Function;
|
|
16
|
+
yScale?: ScaleContinuousNumeric<number, number>;
|
|
17
|
+
}
|
package/src/index.ts
ADDED
package/src/useEvent.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useCallback, useLayoutEffect, useRef } from "react";
|
|
2
|
+
// Based on https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md#internal-implementation
|
|
3
|
+
export function useEvent<F extends (...args: any[]) => any>(handler: F): (...args: Parameters<F>) => ReturnType<F> {
|
|
4
|
+
const handlerRef = useRef<F>();
|
|
5
|
+
|
|
6
|
+
useLayoutEffect(() => {
|
|
7
|
+
handlerRef.current = handler;
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
return useCallback((...args: Parameters<F>) => {
|
|
11
|
+
const fn = handlerRef.current!;
|
|
12
|
+
return fn(...args);
|
|
13
|
+
}, []);
|
|
14
|
+
}
|