@tradingaction/core 2.0.0 → 2.0.2

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 (57) hide show
  1. package/LICENSE +24 -24
  2. package/README.md +5 -5
  3. package/lib/CanvasContainer.d.ts +19 -19
  4. package/lib/CanvasContainer.js +27 -27
  5. package/lib/Chart.d.ts +32 -32
  6. package/lib/Chart.js +56 -56
  7. package/lib/Chart.js.map +1 -1
  8. package/lib/ChartCanvas.d.ts +235 -235
  9. package/lib/ChartCanvas.js +770 -770
  10. package/lib/ChartCanvas.js.map +1 -1
  11. package/lib/EventCapture.d.ts +131 -131
  12. package/lib/EventCapture.js +488 -488
  13. package/lib/GenericChartComponent.d.ts +21 -21
  14. package/lib/GenericChartComponent.js +74 -74
  15. package/lib/GenericComponent.d.ts +81 -81
  16. package/lib/GenericComponent.js +354 -354
  17. package/lib/GenericComponent.js.map +1 -1
  18. package/lib/MoreProps.d.ts +16 -16
  19. package/lib/MoreProps.js +1 -1
  20. package/lib/index.d.ts +7 -7
  21. package/lib/index.js +7 -7
  22. package/lib/useEvent.d.ts +1 -1
  23. package/lib/useEvent.js +12 -12
  24. package/lib/utils/ChartDataUtil.d.ts +49 -49
  25. package/lib/utils/ChartDataUtil.js +204 -204
  26. package/lib/utils/PureComponent.d.ts +4 -4
  27. package/lib/utils/PureComponent.js +9 -9
  28. package/lib/utils/accumulatingWindow.d.ts +15 -15
  29. package/lib/utils/accumulatingWindow.js +97 -97
  30. package/lib/utils/barWidth.d.ts +15 -15
  31. package/lib/utils/barWidth.js +26 -26
  32. package/lib/utils/closestItem.d.ts +5 -5
  33. package/lib/utils/closestItem.js +44 -44
  34. package/lib/utils/evaluator.d.ts +7 -7
  35. package/lib/utils/evaluator.js +93 -93
  36. package/lib/utils/identity.d.ts +1 -1
  37. package/lib/utils/identity.js +1 -1
  38. package/lib/utils/index.d.ts +46 -46
  39. package/lib/utils/index.js +125 -125
  40. package/lib/utils/noop.d.ts +1 -1
  41. package/lib/utils/noop.js +2 -2
  42. package/lib/utils/shallowEqual.d.ts +1 -1
  43. package/lib/utils/shallowEqual.js +21 -21
  44. package/lib/utils/slidingWindow.d.ts +19 -19
  45. package/lib/utils/slidingWindow.js +108 -108
  46. package/lib/utils/strokeDasharray.d.ts +3 -3
  47. package/lib/utils/strokeDasharray.js +36 -36
  48. package/lib/utils/zipper.d.ts +7 -7
  49. package/lib/utils/zipper.js +35 -35
  50. package/lib/zoom/index.d.ts +1 -1
  51. package/lib/zoom/index.js +1 -1
  52. package/lib/zoom/zoomBehavior.d.ts +10 -10
  53. package/lib/zoom/zoomBehavior.js +17 -17
  54. package/package.json +2 -2
  55. package/src/Chart.tsx +2 -2
  56. package/src/ChartCanvas.tsx +1 -1
  57. package/src/GenericComponent.tsx +1 -0
@@ -1,19 +1,19 @@
1
- import { extent as d3Extent, max, min } from "d3-array";
2
- import * as React from "react";
3
- import { clearCanvas, functor, head, identity, isDefined, isNotDefined, last, shallowEqual } from "./utils";
4
- import { mouseBasedZoomAnchor } from "./zoom";
5
- import { getChartConfigWithUpdatedYScales, getCurrentCharts, getCurrentItem, getNewChartConfig, } from "./utils/ChartDataUtil";
6
- import { EventCapture } from "./EventCapture";
7
- import { CanvasContainer } from "./CanvasContainer";
8
- import evaluator from "./utils/evaluator";
9
- const CANDIDATES_FOR_RESET = ["seriesName"];
10
- const shouldResetChart = (thisProps, nextProps) => {
11
- return !CANDIDATES_FOR_RESET.every((key) => {
12
- const result = shallowEqual(thisProps[key], nextProps[key]);
13
- return result;
14
- });
15
- };
16
- const getCursorStyle = () => {
1
+ import { extent as d3Extent, max, min } from "d3-array";
2
+ import * as React from "react";
3
+ import { clearCanvas, functor, head, identity, isDefined, isNotDefined, last, shallowEqual } from "./utils";
4
+ import { mouseBasedZoomAnchor } from "./zoom";
5
+ import { getChartConfigWithUpdatedYScales, getCurrentCharts, getCurrentItem, getNewChartConfig, } from "./utils/ChartDataUtil";
6
+ import { EventCapture } from "./EventCapture";
7
+ import { CanvasContainer } from "./CanvasContainer";
8
+ import evaluator from "./utils/evaluator";
9
+ const CANDIDATES_FOR_RESET = ["seriesName"];
10
+ const shouldResetChart = (thisProps, nextProps) => {
11
+ return !CANDIDATES_FOR_RESET.every((key) => {
12
+ const result = shallowEqual(thisProps[key], nextProps[key]);
13
+ return result;
14
+ });
15
+ };
16
+ const getCursorStyle = () => {
17
17
  const tooltipStyle = `
18
18
  .react-financial-charts-grabbing-cursor {
19
19
  pointer-events: all;
@@ -53,758 +53,758 @@ const getCursorStyle = () => {
53
53
  }
54
54
  .react-financial-charts-ew-resize-cursor {
55
55
  cursor: ew-resize;
56
- }`;
57
- return React.createElement("style", { type: "text/css" }, tooltipStyle);
58
- };
59
- // eslint-disable-next-line @typescript-eslint/no-empty-function
60
- const noop = () => { };
61
- export const chartCanvasContextDefaultValue = {
62
- amIOnTop: () => false,
63
- chartConfigs: [],
64
- chartId: 0,
65
- ratio: 0,
66
- displayXAccessor: () => 0,
67
- fullData: [],
68
- getMutableState: () => ({}),
69
- height: 0,
70
- margin: { top: 0, right: 0, bottom: 0, left: 0 },
71
- plotData: [],
72
- setCursorClass: noop,
73
- subscribe: noop,
74
- unsubscribe: noop,
75
- redraw: noop,
76
- width: 0,
77
- xAccessor: () => 0,
78
- xScale: noop,
79
- };
80
- export const ChartCanvasContext = React.createContext(chartCanvasContextDefaultValue);
81
- const getDimensions = (props) => {
82
- const { margin, height, width } = props;
83
- return {
84
- height: height - margin.top - margin.bottom,
85
- width: width - margin.left - margin.right,
86
- };
87
- };
88
- const getXScaleDirection = (flipXScale) => {
89
- return flipXScale ? -1 : 1;
90
- };
91
- const calculateFullData = (props) => {
92
- const { data: fullData, plotFull, xScale, clamp, pointsPerPxThreshold, flipXScale, xAccessor, displayXAccessor, minPointsPerPxThreshold, } = props;
93
- const useWholeData = plotFull !== undefined ? plotFull : xAccessor === identity;
94
- const { filterData } = evaluator({
95
- xScale,
96
- useWholeData,
97
- clamp,
98
- pointsPerPxThreshold,
99
- minPointsPerPxThreshold,
100
- flipXScale,
101
- });
102
- return {
103
- xAccessor,
104
- displayXAccessor: displayXAccessor !== null && displayXAccessor !== void 0 ? displayXAccessor : xAccessor,
105
- xScale: xScale.copy(),
106
- fullData,
107
- filterData,
108
- };
109
- };
110
- const resetChart = (props) => {
111
- const state = calculateState(props);
112
- const { xAccessor, displayXAccessor, fullData, plotData: initialPlotData, xScale } = state;
113
- const { postCalculator, children } = props;
114
- const plotData = postCalculator !== undefined ? postCalculator(initialPlotData) : initialPlotData;
115
- const dimensions = getDimensions(props);
116
- const chartConfigs = getChartConfigWithUpdatedYScales(getNewChartConfig(dimensions, children), { plotData, xAccessor, displayXAccessor, fullData }, xScale.domain());
117
- return Object.assign(Object.assign({}, state), { xScale,
118
- plotData,
119
- chartConfigs });
120
- };
121
- const updateChart = (newState, initialXScale, props, lastItemWasVisible, initialChartConfig) => {
122
- const { fullData, xScale, xAccessor, displayXAccessor, filterData } = newState;
123
- const lastItem = last(fullData);
124
- const lastXItem = xAccessor(lastItem);
125
- const [start, end] = initialXScale.domain();
126
- const { postCalculator, children, padding, flipXScale, maintainPointsPerPixelOnResize } = props;
127
- const direction = getXScaleDirection(flipXScale);
128
- const dimensions = getDimensions(props);
129
- const updatedXScale = setXRange(xScale, dimensions, padding, direction);
130
- let initialPlotData;
131
- if (!lastItemWasVisible || end >= lastXItem) {
132
- // resize comes here...
133
- // get plotData between [start, end] and do not change the domain
134
- const [rangeStart, rangeEnd] = initialXScale.range();
135
- const [newRangeStart, newRangeEnd] = updatedXScale.range();
136
- const newDomainExtent = ((newRangeEnd - newRangeStart) / (rangeEnd - rangeStart)) * (end.valueOf() - start.valueOf());
137
- const newStart = maintainPointsPerPixelOnResize ? end.valueOf() - newDomainExtent : start;
138
- const lastItemX = initialXScale(lastXItem);
139
- const response = filterData(fullData, [newStart, end], xAccessor, updatedXScale, {
140
- fallbackStart: start,
141
- fallbackEnd: { lastItem, lastItemX },
142
- });
143
- initialPlotData = response.plotData;
144
- updatedXScale.domain(response.domain);
145
- }
146
- else if (lastItemWasVisible && end < lastXItem) {
147
- // this is when a new item is added and last item was visible
148
- // so slide over and show the new item also
149
- // get plotData between [xAccessor(l) - (end - start), xAccessor(l)] and DO change the domain
150
- const dx = initialXScale(lastXItem) - initialXScale.range()[1];
151
- const [newStart, newEnd] = initialXScale
152
- .range()
153
- .map((x) => x + dx)
154
- .map((x) => initialXScale.invert(x));
155
- const response = filterData(fullData, [newStart, newEnd], xAccessor, updatedXScale);
156
- initialPlotData = response.plotData;
157
- updatedXScale.domain(response.domain); // if last item was visible, then shift
158
- }
159
- const plotData = postCalculator(initialPlotData);
160
- const chartConfigs = getChartConfigWithUpdatedYScales(getNewChartConfig(dimensions, children, initialChartConfig), { plotData, xAccessor, displayXAccessor, fullData }, updatedXScale.domain());
161
- return {
162
- xScale: updatedXScale,
163
- xAccessor,
164
- chartConfigs,
165
- plotData,
166
- fullData,
167
- filterData,
168
- };
169
- };
170
- const calculateState = (props) => {
171
- const { xAccessor: inputXAccessor, xExtents: xExtentsProp, data, padding, flipXScale } = props;
172
- const direction = getXScaleDirection(flipXScale);
173
- const dimensions = getDimensions(props);
174
- const extent = typeof xExtentsProp === "function"
175
- ? xExtentsProp(data)
176
- : d3Extent(xExtentsProp.map((d) => functor(d)).map((each) => each(data, inputXAccessor)));
177
- const { xAccessor, displayXAccessor, xScale, fullData, filterData } = calculateFullData(props);
178
- const updatedXScale = setXRange(xScale, dimensions, padding, direction);
179
- const { plotData, domain } = filterData(fullData, extent, inputXAccessor, updatedXScale);
180
- return {
181
- plotData,
182
- xScale: updatedXScale.domain(domain),
183
- xAccessor,
184
- displayXAccessor,
185
- fullData,
186
- filterData,
187
- };
188
- };
189
- const setXRange = (xScale, dimensions, padding, direction = 1) => {
190
- if (xScale.rangeRoundPoints) {
191
- if (isNaN(padding)) {
192
- throw new Error("padding has to be a number for ordinal scale");
193
- }
194
- xScale.rangeRoundPoints([0, dimensions.width], padding);
195
- }
196
- else if (xScale.padding) {
197
- if (isNaN(padding)) {
198
- throw new Error("padding has to be a number for ordinal scale");
199
- }
200
- xScale.range([0, dimensions.width]);
201
- xScale.padding(padding / 2);
202
- }
203
- else {
204
- const { left, right } = isNaN(padding) ? padding : { left: padding, right: padding };
205
- if (direction > 0) {
206
- xScale.range([left, dimensions.width - right]);
207
- }
208
- else {
209
- xScale.range([dimensions.width - right, left]);
210
- }
211
- }
212
- return xScale;
213
- };
214
- const pinchCoordinates = (pinch) => {
215
- const { touch1Pos, touch2Pos } = pinch;
216
- return {
217
- topLeft: [Math.min(touch1Pos[0], touch2Pos[0]), Math.min(touch1Pos[1], touch2Pos[1])],
218
- bottomRight: [Math.max(touch1Pos[0], touch2Pos[0]), Math.max(touch1Pos[1], touch2Pos[1])],
219
- };
220
- };
221
- const isInteractionEnabled = (xScale, xAccessor, data) => {
222
- const interaction = !isNaN(xScale(xAccessor(head(data)))) && isDefined(xScale.invert);
223
- return interaction;
224
- };
225
- export class ChartCanvas extends React.Component {
226
- constructor(props) {
227
- super(props);
228
- this.canvasContainerRef = React.createRef();
229
- this.eventCaptureRef = React.createRef();
230
- this.lastSubscriptionId = 0;
231
- this.mutableState = { mouseXY: [0, 0], currentCharts: [], currentItem: null };
232
- this.panInProgress = false;
233
- this.subscriptions = [];
234
- this.getMutableState = () => {
235
- return this.mutableState;
236
- };
237
- this.getCanvasContexts = () => {
238
- var _a;
239
- return (_a = this.canvasContainerRef.current) === null || _a === void 0 ? void 0 : _a.getCanvasContexts();
240
- };
241
- this.generateSubscriptionId = () => {
242
- this.lastSubscriptionId++;
243
- return this.lastSubscriptionId;
244
- };
245
- this.subscribe = (id, rest) => {
246
- const { getPanConditions = functor({
247
- draggable: false,
248
- panEnabled: true,
249
- }), } = rest;
250
- this.subscriptions = this.subscriptions.concat(Object.assign(Object.assign({ id }, rest), { getPanConditions }));
251
- };
252
- this.unsubscribe = (id) => {
253
- this.subscriptions = this.subscriptions.filter((each) => each.id !== id);
254
- };
255
- this.getAllPanConditions = () => {
256
- return this.subscriptions.map((each) => each.getPanConditions());
257
- };
258
- this.setCursorClass = (className) => {
259
- var _a;
260
- (_a = this.eventCaptureRef.current) === null || _a === void 0 ? void 0 : _a.setCursorClass(className);
261
- };
262
- this.amIOnTop = (id) => {
263
- const dragableComponents = this.subscriptions.filter((each) => each.getPanConditions().draggable);
264
- return dragableComponents.length > 0 && last(dragableComponents).id === id;
265
- };
266
- this.handleContextMenu = (mouseXY, e) => {
267
- const { xAccessor, chartConfigs, plotData, xScale } = this.state;
268
- const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
269
- const currentItem = getCurrentItem(xScale, xAccessor, mouseXY, plotData);
270
- this.triggerEvent("contextmenu", {
271
- mouseXY,
272
- currentItem,
273
- currentCharts,
274
- }, e);
275
- };
276
- this.calculateStateForDomain = (newDomain) => {
277
- const { xAccessor, displayXAccessor, xScale: initialXScale, chartConfigs: initialChartConfig, plotData: initialPlotData, } = this.state;
278
- const { filterData, fullData } = this.state;
279
- const { postCalculator = ChartCanvas.defaultProps.postCalculator } = this.props;
280
- const { plotData: beforePlotData, domain } = filterData(fullData, newDomain, xAccessor, initialXScale, {
281
- currentPlotData: initialPlotData,
282
- currentDomain: initialXScale.domain(),
283
- });
284
- const plotData = postCalculator(beforePlotData);
285
- const updatedScale = initialXScale.copy().domain(domain);
286
- const chartConfigs = getChartConfigWithUpdatedYScales(initialChartConfig, { plotData, xAccessor, displayXAccessor, fullData }, updatedScale.domain());
287
- return {
288
- xScale: updatedScale,
289
- plotData,
290
- chartConfigs,
291
- };
292
- };
293
- this.pinchZoomHelper = (initialPinch, finalPinch) => {
294
- const { xScale: initialPinchXScale } = initialPinch;
295
- const { xScale: initialXScale, chartConfigs: initialChartConfig, plotData: initialPlotData, xAccessor, displayXAccessor, filterData, fullData, } = this.state;
296
- const { postCalculator = ChartCanvas.defaultProps.postCalculator } = this.props;
297
- const { topLeft: iTL, bottomRight: iBR } = pinchCoordinates(initialPinch);
298
- const { topLeft: fTL, bottomRight: fBR } = pinchCoordinates(finalPinch);
299
- const e = initialPinchXScale.range()[1];
300
- const xDash = Math.round(-(iBR[0] * fTL[0] - iTL[0] * fBR[0]) / (iTL[0] - iBR[0]));
301
- const yDash = Math.round(e + ((e - iBR[0]) * (e - fTL[0]) - (e - iTL[0]) * (e - fBR[0])) / (e - iTL[0] - (e - iBR[0])));
302
- const x = Math.round((-xDash * iTL[0]) / (-xDash + fTL[0]));
303
- const y = Math.round(e - ((yDash - e) * (e - iTL[0])) / (yDash + (e - fTL[0])));
304
- const newDomain = [x, y].map(initialPinchXScale.invert);
305
- const { plotData: beforePlotData, domain } = filterData(fullData, newDomain, xAccessor, initialPinchXScale, {
306
- currentPlotData: initialPlotData,
307
- currentDomain: initialXScale.domain(),
308
- });
309
- const plotData = postCalculator(beforePlotData);
310
- const updatedScale = initialXScale.copy().domain(domain);
311
- const mouseXY = finalPinch.touch1Pos;
312
- const chartConfigs = getChartConfigWithUpdatedYScales(initialChartConfig, { plotData, xAccessor, displayXAccessor, fullData }, updatedScale.domain());
313
- const currentItem = getCurrentItem(updatedScale, xAccessor, mouseXY, plotData);
314
- return {
315
- chartConfigs,
316
- xScale: updatedScale,
317
- plotData,
318
- mouseXY,
319
- currentItem,
320
- xAccessor,
321
- fullData,
322
- };
323
- };
324
- this.handlePinchZoom = (initialPinch, finalPinch, e) => {
325
- if (!this.waitingForPinchZoomAnimationFrame) {
326
- this.waitingForPinchZoomAnimationFrame = true;
327
- const state = this.pinchZoomHelper(initialPinch, finalPinch);
328
- this.triggerEvent("pinchzoom", state, e);
329
- this.finalPinch = finalPinch;
330
- requestAnimationFrame(() => {
331
- this.clearBothCanvas();
332
- this.draw({ trigger: "pinchzoom" });
333
- this.waitingForPinchZoomAnimationFrame = false;
334
- });
335
- }
336
- };
337
- this.handlePinchZoomEnd = (initialPinch, e) => {
338
- const { xAccessor = ChartCanvas.defaultProps.xAccessor } = this.state;
339
- if (this.finalPinch) {
340
- const state = this.pinchZoomHelper(initialPinch, this.finalPinch);
341
- const { xScale, fullData } = state;
342
- this.triggerEvent("pinchzoom", state, e);
343
- this.finalPinch = undefined;
344
- this.clearThreeCanvas();
345
- const firstItem = head(fullData);
346
- const scale_start = head(xScale.domain());
347
- const data_start = xAccessor(firstItem);
348
- const lastItem = last(fullData);
349
- const scale_end = last(xScale.domain());
350
- const data_end = xAccessor(lastItem);
351
- const { onLoadAfter, onLoadBefore } = this.props;
352
- this.setState(state, () => {
353
- if (scale_start < data_start) {
354
- if (onLoadBefore !== undefined) {
355
- onLoadBefore(scale_start, data_start);
356
- }
357
- }
358
- if (data_end < scale_end) {
359
- if (onLoadAfter !== undefined) {
360
- onLoadAfter(data_end, scale_end);
361
- }
362
- }
363
- });
364
- }
365
- };
366
- this.handleZoom = (zoomDirection, mouseXY, e) => {
367
- if (this.panInProgress) {
368
- return;
369
- }
370
- const { xAccessor, xScale: initialXScale, plotData: initialPlotData, fullData } = this.state;
371
- const { zoomMultiplier = ChartCanvas.defaultProps.zoomMultiplier, zoomAnchor = ChartCanvas.defaultProps.zoomAnchor, } = this.props;
372
- const item = zoomAnchor({
373
- xScale: initialXScale,
374
- xAccessor: xAccessor,
375
- mouseXY,
376
- plotData: initialPlotData,
377
- });
378
- const cx = initialXScale(item);
379
- const c = zoomDirection > 0 ? 1 * zoomMultiplier : 1 / zoomMultiplier;
380
- const newDomain = initialXScale
381
- .range()
382
- .map((x) => cx + (x - cx) * c)
383
- .map((x) => initialXScale.invert(x));
384
- const { xScale, plotData, chartConfigs } = this.calculateStateForDomain(newDomain);
385
- const currentItem = getCurrentItem(xScale, xAccessor, mouseXY, plotData);
386
- const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
387
- this.clearThreeCanvas();
388
- const firstItem = head(fullData);
389
- const scale_start = head(xScale.domain());
390
- const data_start = xAccessor(firstItem);
391
- const lastItem = last(fullData);
392
- const scale_end = last(xScale.domain());
393
- const data_end = xAccessor(lastItem);
394
- this.mutableState = {
395
- mouseXY,
396
- currentItem,
397
- currentCharts,
398
- };
399
- this.triggerEvent("zoom", {
400
- xScale,
401
- plotData,
402
- chartConfigs,
403
- mouseXY,
404
- currentCharts,
405
- currentItem,
406
- show: true,
407
- }, e);
408
- const { onLoadAfter, onLoadBefore } = this.props;
409
- this.setState({
410
- xScale,
411
- plotData,
412
- chartConfigs,
413
- }, () => {
414
- if (scale_start < data_start) {
415
- if (onLoadBefore !== undefined) {
416
- onLoadBefore(scale_start, data_start);
417
- }
418
- }
419
- if (data_end < scale_end) {
420
- if (onLoadAfter !== undefined) {
421
- onLoadAfter(data_end, scale_end);
422
- }
423
- }
424
- });
425
- };
426
- this.xAxisZoom = (newDomain) => {
427
- const { xScale, plotData, chartConfigs } = this.calculateStateForDomain(newDomain);
428
- this.clearThreeCanvas();
429
- const { xAccessor, fullData } = this.state;
430
- const firstItem = head(fullData);
431
- const scale_start = head(xScale.domain());
432
- const data_start = xAccessor(firstItem);
433
- const lastItem = last(fullData);
434
- const scale_end = last(xScale.domain());
435
- const data_end = xAccessor(lastItem);
436
- const { onLoadAfter, onLoadBefore } = this.props;
437
- this.setState({
438
- xScale,
439
- plotData,
440
- chartConfigs,
441
- }, () => {
442
- if (scale_start < data_start) {
443
- if (onLoadBefore !== undefined) {
444
- onLoadBefore(scale_start, data_start);
445
- }
446
- }
447
- if (data_end < scale_end) {
448
- if (onLoadAfter !== undefined) {
449
- onLoadAfter(data_end, scale_end);
450
- }
451
- }
452
- });
453
- };
454
- this.yAxisZoom = (chartId, newDomain) => {
455
- this.clearThreeCanvas();
456
- const { chartConfigs: initialChartConfig } = this.state;
457
- const chartConfigs = initialChartConfig.map((each) => {
458
- if (each.id === chartId) {
459
- const { yScale } = each;
460
- return Object.assign(Object.assign({}, each), { yScale: yScale.copy().domain(newDomain), yPanEnabled: true });
461
- }
462
- else {
463
- return each;
464
- }
465
- });
466
- this.setState({
467
- chartConfigs,
468
- });
469
- };
470
- this.draw = (props) => {
471
- this.subscriptions.forEach((each) => {
472
- if (isDefined(each.draw)) {
473
- each.draw(props);
474
- }
475
- });
476
- };
477
- this.redraw = () => {
478
- this.clearThreeCanvas();
479
- this.draw({ force: true });
480
- };
481
- this.panHelper = (mouseXY, initialXScale, { dx, dy }, chartsToPan) => {
482
- const { xAccessor, displayXAccessor, chartConfigs: initialChartConfig, filterData, fullData } = this.state;
483
- const { postCalculator = ChartCanvas.defaultProps.postCalculator } = this.props;
484
- const newDomain = initialXScale
485
- .range()
486
- .map((x) => x - dx)
487
- .map((x) => initialXScale.invert(x));
488
- const { plotData: beforePlotData, domain } = filterData(fullData, newDomain, xAccessor, initialXScale, {
489
- currentPlotData: this.hackyWayToStopPanBeyondBounds__plotData,
490
- currentDomain: this.hackyWayToStopPanBeyondBounds__domain,
491
- ignoreThresholds: true,
492
- });
493
- const updatedScale = initialXScale.copy().domain(domain);
494
- const plotData = postCalculator(beforePlotData);
495
- const currentItem = getCurrentItem(updatedScale, xAccessor, mouseXY, plotData);
496
- const chartConfigs = getChartConfigWithUpdatedYScales(initialChartConfig, { plotData, xAccessor, displayXAccessor, fullData }, updatedScale.domain(), dy, chartsToPan);
497
- const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
498
- return {
499
- xScale: updatedScale,
500
- plotData,
501
- chartConfigs,
502
- mouseXY,
503
- currentCharts,
504
- currentItem,
505
- };
506
- };
507
- this.handlePan = (mousePosition, panStartXScale, dxdy, chartsToPan, e) => {
508
- var _a, _b;
509
- if (this.waitingForPanAnimationFrame) {
510
- return;
511
- }
512
- this.waitingForPanAnimationFrame = true;
513
- this.hackyWayToStopPanBeyondBounds__plotData =
514
- (_a = this.hackyWayToStopPanBeyondBounds__plotData) !== null && _a !== void 0 ? _a : this.state.plotData;
515
- this.hackyWayToStopPanBeyondBounds__domain =
516
- (_b = this.hackyWayToStopPanBeyondBounds__domain) !== null && _b !== void 0 ? _b : this.state.xScale.domain();
517
- const newState = this.panHelper(mousePosition, panStartXScale, dxdy, chartsToPan);
518
- this.hackyWayToStopPanBeyondBounds__plotData = newState.plotData;
519
- this.hackyWayToStopPanBeyondBounds__domain = newState.xScale.domain();
520
- this.panInProgress = true;
521
- this.triggerEvent("pan", newState, e);
522
- this.mutableState = {
523
- mouseXY: newState.mouseXY,
524
- currentItem: newState.currentItem,
525
- currentCharts: newState.currentCharts,
526
- };
527
- requestAnimationFrame(() => {
528
- this.waitingForPanAnimationFrame = false;
529
- this.clearBothCanvas();
530
- this.draw({ trigger: "pan" });
531
- });
532
- };
533
- this.handlePanEnd = (mousePosition, panStartXScale, dxdy, chartsToPan, e) => {
534
- const state = this.panHelper(mousePosition, panStartXScale, dxdy, chartsToPan);
535
- this.hackyWayToStopPanBeyondBounds__plotData = null;
536
- this.hackyWayToStopPanBeyondBounds__domain = null;
537
- this.panInProgress = false;
538
- const { xScale, plotData, chartConfigs } = state;
539
- this.triggerEvent("panend", state, e);
540
- requestAnimationFrame(() => {
541
- const { xAccessor, fullData } = this.state;
542
- const firstItem = head(fullData);
543
- const scale_start = head(xScale.domain());
544
- const data_start = xAccessor(firstItem);
545
- const lastItem = last(fullData);
546
- const scale_end = last(xScale.domain());
547
- const data_end = xAccessor(lastItem);
548
- const { onLoadAfter, onLoadBefore } = this.props;
549
- this.clearThreeCanvas();
550
- this.setState({
551
- xScale,
552
- plotData,
553
- chartConfigs,
554
- }, () => {
555
- if (scale_start < data_start) {
556
- if (onLoadBefore !== undefined) {
557
- onLoadBefore(scale_start, data_start);
558
- }
559
- }
560
- if (data_end < scale_end) {
561
- if (onLoadAfter !== undefined) {
562
- onLoadAfter(data_end, scale_end);
563
- }
564
- }
565
- });
566
- });
567
- };
568
- this.handleMouseDown = (_, __, e) => {
569
- this.triggerEvent("mousedown", this.mutableState, e);
570
- };
571
- this.handleMouseEnter = (e) => {
572
- this.triggerEvent("mouseenter", {
573
- show: true,
574
- }, e);
575
- };
576
- this.handleMouseMove = (mouseXY, _, e) => {
577
- if (this.waitingForMouseMoveAnimationFrame) {
578
- return;
579
- }
580
- this.waitingForMouseMoveAnimationFrame = true;
581
- const { chartConfigs, plotData, xScale, xAccessor } = this.state;
582
- const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
583
- const currentItem = getCurrentItem(xScale, xAccessor, mouseXY, plotData);
584
- this.triggerEvent("mousemove", {
585
- show: true,
586
- mouseXY,
587
- // prevMouseXY is used in interactive components
588
- prevMouseXY: this.prevMouseXY,
589
- currentItem,
590
- currentCharts,
591
- }, e);
592
- this.prevMouseXY = mouseXY;
593
- this.mutableState = {
594
- mouseXY,
595
- currentItem,
596
- currentCharts,
597
- };
598
- requestAnimationFrame(() => {
599
- this.clearMouseCanvas();
600
- this.draw({ trigger: "mousemove" });
601
- this.waitingForMouseMoveAnimationFrame = false;
602
- });
603
- };
604
- this.handleMouseLeave = (e) => {
605
- this.triggerEvent("mouseleave", { show: false }, e);
606
- this.clearMouseCanvas();
607
- this.draw({ trigger: "mouseleave" });
608
- };
609
- this.handleDragStart = ({ startPos }, e) => {
610
- this.triggerEvent("dragstart", { startPos }, e);
611
- };
612
- this.handleDrag = ({ startPos, mouseXY }, e) => {
613
- const { chartConfigs, plotData, xScale, xAccessor } = this.state;
614
- const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
615
- const currentItem = getCurrentItem(xScale, xAccessor, mouseXY, plotData);
616
- this.triggerEvent("drag", {
617
- startPos,
618
- mouseXY,
619
- currentItem,
620
- currentCharts,
621
- }, e);
622
- this.mutableState = {
623
- mouseXY,
624
- currentItem,
625
- currentCharts,
626
- };
627
- requestAnimationFrame(() => {
628
- this.clearMouseCanvas();
629
- this.draw({ trigger: "drag" });
630
- });
631
- };
632
- this.handleDragEnd = ({ mouseXY }, e) => {
633
- this.triggerEvent("dragend", { mouseXY }, e);
634
- requestAnimationFrame(() => {
635
- this.clearMouseCanvas();
636
- this.draw({ trigger: "dragend" });
637
- });
638
- };
639
- this.handleClick = (_, e) => {
640
- this.triggerEvent("click", this.mutableState, e);
641
- requestAnimationFrame(() => {
642
- this.clearMouseCanvas();
643
- this.draw({ trigger: "click" });
644
- });
645
- };
646
- this.handleDoubleClick = (_, e) => {
647
- this.triggerEvent("dblclick", {}, e);
648
- };
649
- this.resetYDomain = (chartId) => {
650
- const { chartConfigs } = this.state;
651
- let changed = false;
652
- const newChartConfig = chartConfigs.map((each) => {
653
- if ((isNotDefined(chartId) || each.id === chartId) &&
654
- !shallowEqual(each.yScale.domain(), each.realYDomain)) {
655
- changed = true;
656
- return Object.assign(Object.assign({}, each), { yScale: each.yScale.domain(each.realYDomain), yPanEnabled: false });
657
- }
658
- return each;
659
- });
660
- if (changed) {
661
- this.clearThreeCanvas();
662
- this.setState({
663
- chartConfigs: newChartConfig,
664
- });
665
- }
666
- };
667
- this.state = resetChart(props);
668
- }
669
- static getDerivedStateFromProps(props, state) {
670
- var _a;
671
- const { chartConfigs: initialChartConfig, plotData, xAccessor, xScale } = state;
672
- const interaction = isInteractionEnabled(xScale, xAccessor, plotData);
673
- const shouldReset = shouldResetChart(state.lastProps || {}, props);
674
- let newState;
675
- if (!interaction || shouldReset || !shallowEqual((_a = state.lastProps) === null || _a === void 0 ? void 0 : _a.xExtents, props.xExtents)) {
676
- // do reset
677
- newState = resetChart(props);
678
- }
679
- else {
680
- const [start, end] = xScale.domain();
681
- const prevLastItem = last(state.fullData);
682
- const calculatedState = calculateFullData(props);
683
- const { xAccessor } = calculatedState;
684
- const previousX = xAccessor(prevLastItem);
685
- const lastItemWasVisible = previousX <= end && previousX >= start;
686
- newState = updateChart(calculatedState, xScale, props, lastItemWasVisible, initialChartConfig);
687
- }
688
- return Object.assign(Object.assign({}, newState), { lastProps: props, propIteration: (state.propIteration || 0) + 1 });
689
- }
690
- getSnapshotBeforeUpdate(prevProps, prevState) {
691
- // propIteration is incremented when the props change to differentiate between state updates
692
- // and prop updates
693
- if (prevState.propIteration !== this.state.propIteration && !this.panInProgress) {
694
- this.clearThreeCanvas();
695
- }
696
- return null;
697
- }
698
- componentDidUpdate(prevProps) {
699
- if (prevProps.data !== this.props.data) {
700
- this.triggerEvent("dataupdated", {
701
- chartConfigs: this.state.chartConfigs,
702
- xScale: this.state.xScale,
703
- plotData: this.state.plotData,
704
- });
705
- }
706
- }
707
- clearBothCanvas() {
708
- const canvases = this.getCanvasContexts();
709
- if (canvases && canvases.axes && canvases.mouseCoord) {
710
- clearCanvas([canvases.axes, canvases.mouseCoord], this.props.ratio);
711
- }
712
- }
713
- clearMouseCanvas() {
714
- const canvases = this.getCanvasContexts();
715
- if (canvases && canvases.mouseCoord) {
716
- clearCanvas([canvases.mouseCoord], this.props.ratio);
717
- }
718
- }
719
- clearThreeCanvas() {
720
- const canvases = this.getCanvasContexts();
721
- if (canvases && canvases.axes && canvases.mouseCoord && canvases.bg) {
722
- clearCanvas([canvases.axes, canvases.mouseCoord, canvases.bg], this.props.ratio);
723
- }
724
- }
725
- cancelDrag() {
726
- var _a;
727
- (_a = this.eventCaptureRef.current) === null || _a === void 0 ? void 0 : _a.cancelDrag();
728
- this.triggerEvent("dragcancel");
729
- }
730
- triggerEvent(type, props, e) {
731
- this.subscriptions.forEach((each) => {
732
- const state = Object.assign(Object.assign({}, this.state), { subscriptions: this.subscriptions });
733
- each.listener(type, props, state, e);
734
- });
735
- }
736
- // TODO: Memoize this
737
- getContextValues() {
738
- const dimensions = getDimensions(this.props);
739
- return {
740
- chartId: -1,
741
- fullData: this.state.fullData,
742
- plotData: this.state.plotData,
743
- width: dimensions.width,
744
- height: dimensions.height,
745
- chartConfigs: this.state.chartConfigs,
746
- xScale: this.state.xScale,
747
- xAccessor: this.state.xAccessor,
748
- displayXAccessor: this.state.displayXAccessor,
749
- margin: this.props.margin,
750
- ratio: this.props.ratio,
751
- xAxisZoom: this.xAxisZoom,
752
- yAxisZoom: this.yAxisZoom,
753
- getCanvasContexts: this.getCanvasContexts,
754
- redraw: this.redraw,
755
- subscribe: this.subscribe,
756
- unsubscribe: this.unsubscribe,
757
- generateSubscriptionId: this.generateSubscriptionId,
758
- getMutableState: this.getMutableState,
759
- amIOnTop: this.amIOnTop,
760
- setCursorClass: this.setCursorClass,
761
- };
762
- }
763
- shouldComponentUpdate() {
764
- return !this.panInProgress;
765
- }
766
- render() {
767
- const { disableInteraction, disablePan, disableZoom, useCrossHairStyleCursor, onClick, onDoubleClick, height, width, margin = ChartCanvas.defaultProps.margin, className, zIndex = ChartCanvas.defaultProps.zIndex, defaultFocus, ratio, mouseMoveEvent, } = this.props;
768
- const { plotData, xScale, xAccessor, chartConfigs } = this.state;
769
- const dimensions = getDimensions(this.props);
770
- const interaction = isInteractionEnabled(xScale, xAccessor, plotData);
771
- const cursorStyle = useCrossHairStyleCursor && interaction;
772
- const cursor = getCursorStyle();
773
- return (React.createElement(ChartCanvasContext.Provider, { value: this.getContextValues() },
774
- React.createElement("div", { style: { position: "relative", width, height }, className: className, onClick: onClick, onDoubleClick: onDoubleClick },
775
- React.createElement(CanvasContainer, { ref: this.canvasContainerRef, ratio: ratio, width: width, height: height, style: { height, zIndex, width } }),
776
- React.createElement("svg", { className: className, width: width, height: height, style: { position: "absolute", zIndex: zIndex + 5 } },
777
- cursor,
778
- React.createElement("defs", null,
779
- React.createElement("clipPath", { id: "chart-area-clip" },
780
- React.createElement("rect", { x: "0", y: "0", width: dimensions.width, height: dimensions.height })),
781
- chartConfigs.map((each, idx) => (React.createElement("clipPath", { key: idx, id: `chart-area-clip-${each.id}` },
782
- React.createElement("rect", { x: "0", y: "0", width: each.width, height: each.height }))))),
783
- React.createElement("g", { transform: `translate(${margin.left + 0.5}, ${margin.top + 0.5})` },
784
- React.createElement(EventCapture, { ref: this.eventCaptureRef, useCrossHairStyleCursor: cursorStyle, mouseMove: mouseMoveEvent && interaction, zoom: !disableZoom && interaction, pan: !disablePan && interaction, width: dimensions.width, height: dimensions.height, chartConfig: chartConfigs, xScale: xScale, xAccessor: xAccessor, focus: defaultFocus, disableInteraction: disableInteraction, getAllPanConditions: this.getAllPanConditions, onContextMenu: this.handleContextMenu, onClick: this.handleClick, onDoubleClick: this.handleDoubleClick, onMouseDown: this.handleMouseDown, onMouseMove: this.handleMouseMove, onMouseEnter: this.handleMouseEnter, onMouseLeave: this.handleMouseLeave, onDragStart: this.handleDragStart, onDrag: this.handleDrag, onDragComplete: this.handleDragEnd, onZoom: this.handleZoom, onPinchZoom: this.handlePinchZoom, onPinchZoomEnd: this.handlePinchZoomEnd, onPan: this.handlePan, onPanEnd: this.handlePanEnd }),
785
- React.createElement("g", { className: "react-financial-charts-avoid-interaction" }, this.props.children))))));
786
- }
787
- }
788
- ChartCanvas.defaultProps = {
789
- clamp: false,
790
- className: "react-financial-charts",
791
- defaultFocus: true,
792
- disablePan: false,
793
- disableInteraction: false,
794
- disableZoom: false,
795
- flipXScale: false,
796
- maintainPointsPerPixelOnResize: true,
797
- margin: { top: 0, right: 40, bottom: 40, left: 0 },
798
- minPointsPerPxThreshold: 1 / 100,
799
- mouseMoveEvent: true,
800
- postCalculator: identity,
801
- padding: 0,
802
- pointsPerPxThreshold: 2,
803
- useCrossHairStyleCursor: true,
804
- xAccessor: identity,
805
- xExtents: [min, max],
806
- zIndex: 1,
807
- zoomAnchor: mouseBasedZoomAnchor,
808
- zoomMultiplier: 1.1,
809
- };
56
+ }`;
57
+ return React.createElement("style", { type: "text/css" }, tooltipStyle);
58
+ };
59
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
60
+ const noop = () => { };
61
+ export const chartCanvasContextDefaultValue = {
62
+ amIOnTop: () => false,
63
+ chartConfigs: [],
64
+ chartId: 0,
65
+ ratio: 0,
66
+ displayXAccessor: () => 0,
67
+ fullData: [],
68
+ getMutableState: () => ({}),
69
+ height: 0,
70
+ margin: { top: 0, right: 0, bottom: 0, left: 0 },
71
+ plotData: [],
72
+ setCursorClass: noop,
73
+ subscribe: noop,
74
+ unsubscribe: noop,
75
+ redraw: noop,
76
+ width: 0,
77
+ xAccessor: () => 0,
78
+ xScale: noop,
79
+ };
80
+ export const ChartCanvasContext = React.createContext(chartCanvasContextDefaultValue);
81
+ const getDimensions = (props) => {
82
+ const { margin, height, width } = props;
83
+ return {
84
+ height: height - margin.top - margin.bottom,
85
+ width: width - margin.left - margin.right,
86
+ };
87
+ };
88
+ const getXScaleDirection = (flipXScale) => {
89
+ return flipXScale ? -1 : 1;
90
+ };
91
+ const calculateFullData = (props) => {
92
+ const { data: fullData, plotFull, xScale, clamp, pointsPerPxThreshold, flipXScale, xAccessor, displayXAccessor, minPointsPerPxThreshold, } = props;
93
+ const useWholeData = plotFull !== undefined ? plotFull : xAccessor === identity;
94
+ const { filterData } = evaluator({
95
+ xScale,
96
+ useWholeData,
97
+ clamp,
98
+ pointsPerPxThreshold,
99
+ minPointsPerPxThreshold,
100
+ flipXScale,
101
+ });
102
+ return {
103
+ xAccessor,
104
+ displayXAccessor: displayXAccessor !== null && displayXAccessor !== void 0 ? displayXAccessor : xAccessor,
105
+ xScale: xScale.copy(),
106
+ fullData,
107
+ filterData,
108
+ };
109
+ };
110
+ const resetChart = (props) => {
111
+ const state = calculateState(props);
112
+ const { xAccessor, displayXAccessor, fullData, plotData: initialPlotData, xScale } = state;
113
+ const { postCalculator, children } = props;
114
+ const plotData = postCalculator !== undefined ? postCalculator(initialPlotData) : initialPlotData;
115
+ const dimensions = getDimensions(props);
116
+ const chartConfigs = getChartConfigWithUpdatedYScales(getNewChartConfig(dimensions, children), { plotData, xAccessor, displayXAccessor, fullData }, xScale.domain());
117
+ return Object.assign(Object.assign({}, state), { xScale,
118
+ plotData,
119
+ chartConfigs });
120
+ };
121
+ const updateChart = (newState, initialXScale, props, lastItemWasVisible, initialChartConfig) => {
122
+ const { fullData, xScale, xAccessor, displayXAccessor, filterData } = newState;
123
+ const lastItem = last(fullData);
124
+ const lastXItem = xAccessor(lastItem);
125
+ const [start, end] = initialXScale.domain();
126
+ const { postCalculator, children, padding, flipXScale, maintainPointsPerPixelOnResize } = props;
127
+ const direction = getXScaleDirection(flipXScale);
128
+ const dimensions = getDimensions(props);
129
+ const updatedXScale = setXRange(xScale, dimensions, padding, direction);
130
+ let initialPlotData;
131
+ if (!lastItemWasVisible || end >= lastXItem) {
132
+ // resize comes here...
133
+ // get plotData between [start, end] and do not change the domain
134
+ const [rangeStart, rangeEnd] = initialXScale.range();
135
+ const [newRangeStart, newRangeEnd] = updatedXScale.range();
136
+ const newDomainExtent = ((newRangeEnd - newRangeStart) / (rangeEnd - rangeStart)) * (end.valueOf() - start.valueOf());
137
+ const newStart = maintainPointsPerPixelOnResize ? end.valueOf() - newDomainExtent : start;
138
+ const lastItemX = initialXScale(lastXItem);
139
+ const response = filterData(fullData, [newStart, end], xAccessor, updatedXScale, {
140
+ fallbackStart: start,
141
+ fallbackEnd: { lastItem, lastItemX },
142
+ });
143
+ initialPlotData = response.plotData;
144
+ updatedXScale.domain(response.domain);
145
+ }
146
+ else if (lastItemWasVisible && end < lastXItem) {
147
+ // this is when a new item is added and last item was visible
148
+ // so slide over and show the new item also
149
+ // get plotData between [xAccessor(l) - (end - start), xAccessor(l)] and DO change the domain
150
+ const dx = initialXScale(lastXItem) - initialXScale.range()[1];
151
+ const [newStart, newEnd] = initialXScale
152
+ .range()
153
+ .map((x) => x + dx)
154
+ .map((x) => initialXScale.invert(x));
155
+ const response = filterData(fullData, [newStart, newEnd], xAccessor, updatedXScale);
156
+ initialPlotData = response.plotData;
157
+ updatedXScale.domain(response.domain); // if last item was visible, then shift
158
+ }
159
+ const plotData = postCalculator(initialPlotData);
160
+ const chartConfigs = getChartConfigWithUpdatedYScales(getNewChartConfig(dimensions, children, initialChartConfig), { plotData, xAccessor, displayXAccessor, fullData }, updatedXScale.domain());
161
+ return {
162
+ xScale: updatedXScale,
163
+ xAccessor,
164
+ chartConfigs,
165
+ plotData,
166
+ fullData,
167
+ filterData,
168
+ };
169
+ };
170
+ const calculateState = (props) => {
171
+ const { xAccessor: inputXAccessor, xExtents: xExtentsProp, data, padding, flipXScale } = props;
172
+ const direction = getXScaleDirection(flipXScale);
173
+ const dimensions = getDimensions(props);
174
+ const extent = typeof xExtentsProp === "function"
175
+ ? xExtentsProp(data)
176
+ : d3Extent(xExtentsProp.map((d) => functor(d)).map((each) => each(data, inputXAccessor)));
177
+ const { xAccessor, displayXAccessor, xScale, fullData, filterData } = calculateFullData(props);
178
+ const updatedXScale = setXRange(xScale, dimensions, padding, direction);
179
+ const { plotData, domain } = filterData(fullData, extent, inputXAccessor, updatedXScale);
180
+ return {
181
+ plotData,
182
+ xScale: updatedXScale.domain(domain),
183
+ xAccessor,
184
+ displayXAccessor,
185
+ fullData,
186
+ filterData,
187
+ };
188
+ };
189
+ const setXRange = (xScale, dimensions, padding, direction = 1) => {
190
+ if (xScale.rangeRoundPoints) {
191
+ if (isNaN(padding)) {
192
+ throw new Error("padding has to be a number for ordinal scale");
193
+ }
194
+ xScale.rangeRoundPoints([0, dimensions.width], padding);
195
+ }
196
+ else if (xScale.padding) {
197
+ if (isNaN(padding)) {
198
+ throw new Error("padding has to be a number for ordinal scale");
199
+ }
200
+ xScale.range([0, dimensions.width]);
201
+ xScale.padding(padding / 2);
202
+ }
203
+ else {
204
+ const { left, right } = isNaN(padding) ? padding : { left: padding, right: padding };
205
+ if (direction > 0) {
206
+ xScale.range([left, dimensions.width - right]);
207
+ }
208
+ else {
209
+ xScale.range([dimensions.width - right, left]);
210
+ }
211
+ }
212
+ return xScale;
213
+ };
214
+ const pinchCoordinates = (pinch) => {
215
+ const { touch1Pos, touch2Pos } = pinch;
216
+ return {
217
+ topLeft: [Math.min(touch1Pos[0], touch2Pos[0]), Math.min(touch1Pos[1], touch2Pos[1])],
218
+ bottomRight: [Math.max(touch1Pos[0], touch2Pos[0]), Math.max(touch1Pos[1], touch2Pos[1])],
219
+ };
220
+ };
221
+ const isInteractionEnabled = (xScale, xAccessor, data) => {
222
+ const interaction = !isNaN(xScale(xAccessor(head(data)))) && isDefined(xScale.invert);
223
+ return interaction;
224
+ };
225
+ export class ChartCanvas extends React.Component {
226
+ constructor(props) {
227
+ super(props);
228
+ this.canvasContainerRef = React.createRef();
229
+ this.eventCaptureRef = React.createRef();
230
+ this.lastSubscriptionId = 0;
231
+ this.mutableState = { mouseXY: [0, 0], currentCharts: [], currentItem: null };
232
+ this.panInProgress = false;
233
+ this.subscriptions = [];
234
+ this.getMutableState = () => {
235
+ return this.mutableState;
236
+ };
237
+ this.getCanvasContexts = () => {
238
+ var _a;
239
+ return (_a = this.canvasContainerRef.current) === null || _a === void 0 ? void 0 : _a.getCanvasContexts();
240
+ };
241
+ this.generateSubscriptionId = () => {
242
+ this.lastSubscriptionId++;
243
+ return this.lastSubscriptionId;
244
+ };
245
+ this.subscribe = (id, rest) => {
246
+ const { getPanConditions = functor({
247
+ draggable: false,
248
+ panEnabled: true,
249
+ }), } = rest;
250
+ this.subscriptions = this.subscriptions.concat(Object.assign(Object.assign({ id }, rest), { getPanConditions }));
251
+ };
252
+ this.unsubscribe = (id) => {
253
+ this.subscriptions = this.subscriptions.filter((each) => each.id !== id);
254
+ };
255
+ this.getAllPanConditions = () => {
256
+ return this.subscriptions.map((each) => each.getPanConditions());
257
+ };
258
+ this.setCursorClass = (className) => {
259
+ var _a;
260
+ (_a = this.eventCaptureRef.current) === null || _a === void 0 ? void 0 : _a.setCursorClass(className);
261
+ };
262
+ this.amIOnTop = (id) => {
263
+ const dragableComponents = this.subscriptions.filter((each) => each.getPanConditions().draggable);
264
+ return dragableComponents.length > 0 && last(dragableComponents).id === id;
265
+ };
266
+ this.handleContextMenu = (mouseXY, e) => {
267
+ const { xAccessor, chartConfigs, plotData, xScale } = this.state;
268
+ const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
269
+ const currentItem = getCurrentItem(xScale, xAccessor, mouseXY, plotData);
270
+ this.triggerEvent("contextmenu", {
271
+ mouseXY,
272
+ currentItem,
273
+ currentCharts,
274
+ }, e);
275
+ };
276
+ this.calculateStateForDomain = (newDomain) => {
277
+ const { xAccessor, displayXAccessor, xScale: initialXScale, chartConfigs: initialChartConfig, plotData: initialPlotData, } = this.state;
278
+ const { filterData, fullData } = this.state;
279
+ const { postCalculator = ChartCanvas.defaultProps.postCalculator } = this.props;
280
+ const { plotData: beforePlotData, domain } = filterData(fullData, newDomain, xAccessor, initialXScale, {
281
+ currentPlotData: initialPlotData,
282
+ currentDomain: initialXScale.domain(),
283
+ });
284
+ const plotData = postCalculator(beforePlotData);
285
+ const updatedScale = initialXScale.copy().domain(domain);
286
+ const chartConfigs = getChartConfigWithUpdatedYScales(initialChartConfig, { plotData, xAccessor, displayXAccessor, fullData }, updatedScale.domain());
287
+ return {
288
+ xScale: updatedScale,
289
+ plotData,
290
+ chartConfigs,
291
+ };
292
+ };
293
+ this.pinchZoomHelper = (initialPinch, finalPinch) => {
294
+ const { xScale: initialPinchXScale } = initialPinch;
295
+ const { xScale: initialXScale, chartConfigs: initialChartConfig, plotData: initialPlotData, xAccessor, displayXAccessor, filterData, fullData, } = this.state;
296
+ const { postCalculator = ChartCanvas.defaultProps.postCalculator } = this.props;
297
+ const { topLeft: iTL, bottomRight: iBR } = pinchCoordinates(initialPinch);
298
+ const { topLeft: fTL, bottomRight: fBR } = pinchCoordinates(finalPinch);
299
+ const e = initialPinchXScale.range()[1];
300
+ const xDash = Math.round(-(iBR[0] * fTL[0] - iTL[0] * fBR[0]) / (iTL[0] - iBR[0]));
301
+ const yDash = Math.round(e + ((e - iBR[0]) * (e - fTL[0]) - (e - iTL[0]) * (e - fBR[0])) / (e - iTL[0] - (e - iBR[0])));
302
+ const x = Math.round((-xDash * iTL[0]) / (-xDash + fTL[0]));
303
+ const y = Math.round(e - ((yDash - e) * (e - iTL[0])) / (yDash + (e - fTL[0])));
304
+ const newDomain = [x, y].map(initialPinchXScale.invert);
305
+ const { plotData: beforePlotData, domain } = filterData(fullData, newDomain, xAccessor, initialPinchXScale, {
306
+ currentPlotData: initialPlotData,
307
+ currentDomain: initialXScale.domain(),
308
+ });
309
+ const plotData = postCalculator(beforePlotData);
310
+ const updatedScale = initialXScale.copy().domain(domain);
311
+ const mouseXY = finalPinch.touch1Pos;
312
+ const chartConfigs = getChartConfigWithUpdatedYScales(initialChartConfig, { plotData, xAccessor, displayXAccessor, fullData }, updatedScale.domain());
313
+ const currentItem = getCurrentItem(updatedScale, xAccessor, mouseXY, plotData);
314
+ return {
315
+ chartConfigs,
316
+ xScale: updatedScale,
317
+ plotData,
318
+ mouseXY,
319
+ currentItem,
320
+ xAccessor,
321
+ fullData,
322
+ };
323
+ };
324
+ this.handlePinchZoom = (initialPinch, finalPinch, e) => {
325
+ if (!this.waitingForPinchZoomAnimationFrame) {
326
+ this.waitingForPinchZoomAnimationFrame = true;
327
+ const state = this.pinchZoomHelper(initialPinch, finalPinch);
328
+ this.triggerEvent("pinchzoom", state, e);
329
+ this.finalPinch = finalPinch;
330
+ requestAnimationFrame(() => {
331
+ this.clearBothCanvas();
332
+ this.draw({ trigger: "pinchzoom" });
333
+ this.waitingForPinchZoomAnimationFrame = false;
334
+ });
335
+ }
336
+ };
337
+ this.handlePinchZoomEnd = (initialPinch, e) => {
338
+ const { xAccessor = ChartCanvas.defaultProps.xAccessor } = this.state;
339
+ if (this.finalPinch) {
340
+ const state = this.pinchZoomHelper(initialPinch, this.finalPinch);
341
+ const { xScale, fullData } = state;
342
+ this.triggerEvent("pinchzoom", state, e);
343
+ this.finalPinch = undefined;
344
+ this.clearThreeCanvas();
345
+ const firstItem = head(fullData);
346
+ const scale_start = head(xScale.domain());
347
+ const data_start = xAccessor(firstItem);
348
+ const lastItem = last(fullData);
349
+ const scale_end = last(xScale.domain());
350
+ const data_end = xAccessor(lastItem);
351
+ const { onLoadAfter, onLoadBefore } = this.props;
352
+ this.setState(state, () => {
353
+ if (scale_start < data_start) {
354
+ if (onLoadBefore !== undefined) {
355
+ onLoadBefore(scale_start, data_start);
356
+ }
357
+ }
358
+ if (data_end < scale_end) {
359
+ if (onLoadAfter !== undefined) {
360
+ onLoadAfter(data_end, scale_end);
361
+ }
362
+ }
363
+ });
364
+ }
365
+ };
366
+ this.handleZoom = (zoomDirection, mouseXY, e) => {
367
+ if (this.panInProgress) {
368
+ return;
369
+ }
370
+ const { xAccessor, xScale: initialXScale, plotData: initialPlotData, fullData } = this.state;
371
+ const { zoomMultiplier = ChartCanvas.defaultProps.zoomMultiplier, zoomAnchor = ChartCanvas.defaultProps.zoomAnchor, } = this.props;
372
+ const item = zoomAnchor({
373
+ xScale: initialXScale,
374
+ xAccessor: xAccessor,
375
+ mouseXY,
376
+ plotData: initialPlotData,
377
+ });
378
+ const cx = initialXScale(item);
379
+ const c = zoomDirection > 0 ? 1 * zoomMultiplier : 1 / zoomMultiplier;
380
+ const newDomain = initialXScale
381
+ .range()
382
+ .map((x) => cx + (x - cx) * c)
383
+ .map((x) => initialXScale.invert(x));
384
+ const { xScale, plotData, chartConfigs } = this.calculateStateForDomain(newDomain);
385
+ const currentItem = getCurrentItem(xScale, xAccessor, mouseXY, plotData);
386
+ const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
387
+ this.clearThreeCanvas();
388
+ const firstItem = head(fullData);
389
+ const scale_start = head(xScale.domain());
390
+ const data_start = xAccessor(firstItem);
391
+ const lastItem = last(fullData);
392
+ const scale_end = last(xScale.domain());
393
+ const data_end = xAccessor(lastItem);
394
+ this.mutableState = {
395
+ mouseXY,
396
+ currentItem,
397
+ currentCharts,
398
+ };
399
+ this.triggerEvent("zoom", {
400
+ xScale,
401
+ plotData,
402
+ chartConfigs,
403
+ mouseXY,
404
+ currentCharts,
405
+ currentItem,
406
+ show: true,
407
+ }, e);
408
+ const { onLoadAfter, onLoadBefore } = this.props;
409
+ this.setState({
410
+ xScale,
411
+ plotData,
412
+ chartConfigs,
413
+ }, () => {
414
+ if (scale_start < data_start) {
415
+ if (onLoadBefore !== undefined) {
416
+ onLoadBefore(scale_start, data_start);
417
+ }
418
+ }
419
+ if (data_end < scale_end) {
420
+ if (onLoadAfter !== undefined) {
421
+ onLoadAfter(data_end, scale_end);
422
+ }
423
+ }
424
+ });
425
+ };
426
+ this.xAxisZoom = (newDomain) => {
427
+ const { xScale, plotData, chartConfigs } = this.calculateStateForDomain(newDomain);
428
+ this.clearThreeCanvas();
429
+ const { xAccessor, fullData } = this.state;
430
+ const firstItem = head(fullData);
431
+ const scale_start = head(xScale.domain());
432
+ const data_start = xAccessor(firstItem);
433
+ const lastItem = last(fullData);
434
+ const scale_end = last(xScale.domain());
435
+ const data_end = xAccessor(lastItem);
436
+ const { onLoadAfter, onLoadBefore } = this.props;
437
+ this.setState({
438
+ xScale,
439
+ plotData,
440
+ chartConfigs,
441
+ }, () => {
442
+ if (scale_start < data_start) {
443
+ if (onLoadBefore !== undefined) {
444
+ onLoadBefore(scale_start, data_start);
445
+ }
446
+ }
447
+ if (data_end < scale_end) {
448
+ if (onLoadAfter !== undefined) {
449
+ onLoadAfter(data_end, scale_end);
450
+ }
451
+ }
452
+ });
453
+ };
454
+ this.yAxisZoom = (chartId, newDomain) => {
455
+ this.clearThreeCanvas();
456
+ const { chartConfigs: initialChartConfig } = this.state;
457
+ const chartConfigs = initialChartConfig.map((each) => {
458
+ if (each.id === chartId) {
459
+ const { yScale } = each;
460
+ return Object.assign(Object.assign({}, each), { yScale: yScale.copy().domain(newDomain), yPanEnabled: true });
461
+ }
462
+ else {
463
+ return each;
464
+ }
465
+ });
466
+ this.setState({
467
+ chartConfigs,
468
+ });
469
+ };
470
+ this.draw = (props) => {
471
+ this.subscriptions.forEach((each) => {
472
+ if (isDefined(each.draw)) {
473
+ each.draw(props);
474
+ }
475
+ });
476
+ };
477
+ this.redraw = () => {
478
+ this.clearThreeCanvas();
479
+ this.draw({ force: true });
480
+ };
481
+ this.panHelper = (mouseXY, initialXScale, { dx, dy }, chartsToPan) => {
482
+ const { xAccessor, displayXAccessor, chartConfigs: initialChartConfig, filterData, fullData } = this.state;
483
+ const { postCalculator = ChartCanvas.defaultProps.postCalculator } = this.props;
484
+ const newDomain = initialXScale
485
+ .range()
486
+ .map((x) => x - dx)
487
+ .map((x) => initialXScale.invert(x));
488
+ const { plotData: beforePlotData, domain } = filterData(fullData, newDomain, xAccessor, initialXScale, {
489
+ currentPlotData: this.hackyWayToStopPanBeyondBounds__plotData,
490
+ currentDomain: this.hackyWayToStopPanBeyondBounds__domain,
491
+ ignoreThresholds: true,
492
+ });
493
+ const updatedScale = initialXScale.copy().domain(domain);
494
+ const plotData = postCalculator(beforePlotData);
495
+ const currentItem = getCurrentItem(updatedScale, xAccessor, mouseXY, plotData);
496
+ const chartConfigs = getChartConfigWithUpdatedYScales(initialChartConfig, { plotData, xAccessor, displayXAccessor, fullData }, updatedScale.domain(), dy, chartsToPan);
497
+ const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
498
+ return {
499
+ xScale: updatedScale,
500
+ plotData,
501
+ chartConfigs,
502
+ mouseXY,
503
+ currentCharts,
504
+ currentItem,
505
+ };
506
+ };
507
+ this.handlePan = (mousePosition, panStartXScale, dxdy, chartsToPan, e) => {
508
+ var _a, _b;
509
+ if (this.waitingForPanAnimationFrame) {
510
+ return;
511
+ }
512
+ this.waitingForPanAnimationFrame = true;
513
+ this.hackyWayToStopPanBeyondBounds__plotData =
514
+ (_a = this.hackyWayToStopPanBeyondBounds__plotData) !== null && _a !== void 0 ? _a : this.state.plotData;
515
+ this.hackyWayToStopPanBeyondBounds__domain =
516
+ (_b = this.hackyWayToStopPanBeyondBounds__domain) !== null && _b !== void 0 ? _b : this.state.xScale.domain();
517
+ const newState = this.panHelper(mousePosition, panStartXScale, dxdy, chartsToPan);
518
+ this.hackyWayToStopPanBeyondBounds__plotData = newState.plotData;
519
+ this.hackyWayToStopPanBeyondBounds__domain = newState.xScale.domain();
520
+ this.panInProgress = true;
521
+ this.triggerEvent("pan", newState, e);
522
+ this.mutableState = {
523
+ mouseXY: newState.mouseXY,
524
+ currentItem: newState.currentItem,
525
+ currentCharts: newState.currentCharts,
526
+ };
527
+ requestAnimationFrame(() => {
528
+ this.waitingForPanAnimationFrame = false;
529
+ this.clearBothCanvas();
530
+ this.draw({ trigger: "pan" });
531
+ });
532
+ };
533
+ this.handlePanEnd = (mousePosition, panStartXScale, dxdy, chartsToPan, e) => {
534
+ const state = this.panHelper(mousePosition, panStartXScale, dxdy, chartsToPan);
535
+ this.hackyWayToStopPanBeyondBounds__plotData = null;
536
+ this.hackyWayToStopPanBeyondBounds__domain = null;
537
+ this.panInProgress = false;
538
+ const { xScale, plotData, chartConfigs } = state;
539
+ this.triggerEvent("panend", state, e);
540
+ requestAnimationFrame(() => {
541
+ const { xAccessor, fullData } = this.state;
542
+ const firstItem = head(fullData);
543
+ const scale_start = head(xScale.domain());
544
+ const data_start = xAccessor(firstItem);
545
+ const lastItem = last(fullData);
546
+ const scale_end = last(xScale.domain());
547
+ const data_end = xAccessor(lastItem);
548
+ const { onLoadAfter, onLoadBefore } = this.props;
549
+ this.clearThreeCanvas();
550
+ this.setState({
551
+ xScale,
552
+ plotData,
553
+ chartConfigs,
554
+ }, () => {
555
+ if (scale_start < data_start) {
556
+ if (onLoadBefore !== undefined) {
557
+ onLoadBefore(scale_start, data_start);
558
+ }
559
+ }
560
+ if (data_end < scale_end) {
561
+ if (onLoadAfter !== undefined) {
562
+ onLoadAfter(data_end, scale_end);
563
+ }
564
+ }
565
+ });
566
+ });
567
+ };
568
+ this.handleMouseDown = (_, __, e) => {
569
+ this.triggerEvent("mousedown", this.mutableState, e);
570
+ };
571
+ this.handleMouseEnter = (e) => {
572
+ this.triggerEvent("mouseenter", {
573
+ show: true,
574
+ }, e);
575
+ };
576
+ this.handleMouseMove = (mouseXY, _, e) => {
577
+ if (this.waitingForMouseMoveAnimationFrame) {
578
+ return;
579
+ }
580
+ this.waitingForMouseMoveAnimationFrame = true;
581
+ const { chartConfigs, plotData, xScale, xAccessor } = this.state;
582
+ const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
583
+ const currentItem = getCurrentItem(xScale, xAccessor, mouseXY, plotData);
584
+ this.triggerEvent("mousemove", {
585
+ show: true,
586
+ mouseXY,
587
+ // prevMouseXY is used in interactive components
588
+ prevMouseXY: this.prevMouseXY,
589
+ currentItem,
590
+ currentCharts,
591
+ }, e);
592
+ this.prevMouseXY = mouseXY;
593
+ this.mutableState = {
594
+ mouseXY,
595
+ currentItem,
596
+ currentCharts,
597
+ };
598
+ requestAnimationFrame(() => {
599
+ this.clearMouseCanvas();
600
+ this.draw({ trigger: "mousemove" });
601
+ this.waitingForMouseMoveAnimationFrame = false;
602
+ });
603
+ };
604
+ this.handleMouseLeave = (e) => {
605
+ this.triggerEvent("mouseleave", { show: false }, e);
606
+ this.clearMouseCanvas();
607
+ this.draw({ trigger: "mouseleave" });
608
+ };
609
+ this.handleDragStart = ({ startPos }, e) => {
610
+ this.triggerEvent("dragstart", { startPos }, e);
611
+ };
612
+ this.handleDrag = ({ startPos, mouseXY }, e) => {
613
+ const { chartConfigs, plotData, xScale, xAccessor } = this.state;
614
+ const currentCharts = getCurrentCharts(chartConfigs, mouseXY);
615
+ const currentItem = getCurrentItem(xScale, xAccessor, mouseXY, plotData);
616
+ this.triggerEvent("drag", {
617
+ startPos,
618
+ mouseXY,
619
+ currentItem,
620
+ currentCharts,
621
+ }, e);
622
+ this.mutableState = {
623
+ mouseXY,
624
+ currentItem,
625
+ currentCharts,
626
+ };
627
+ requestAnimationFrame(() => {
628
+ this.clearMouseCanvas();
629
+ this.draw({ trigger: "drag" });
630
+ });
631
+ };
632
+ this.handleDragEnd = ({ mouseXY }, e) => {
633
+ this.triggerEvent("dragend", { mouseXY }, e);
634
+ requestAnimationFrame(() => {
635
+ this.clearMouseCanvas();
636
+ this.draw({ trigger: "dragend" });
637
+ });
638
+ };
639
+ this.handleClick = (_, e) => {
640
+ this.triggerEvent("click", this.mutableState, e);
641
+ requestAnimationFrame(() => {
642
+ this.clearMouseCanvas();
643
+ this.draw({ trigger: "click" });
644
+ });
645
+ };
646
+ this.handleDoubleClick = (_, e) => {
647
+ this.triggerEvent("dblclick", {}, e);
648
+ };
649
+ this.resetYDomain = (chartId) => {
650
+ const { chartConfigs } = this.state;
651
+ let changed = false;
652
+ const newChartConfig = chartConfigs.map((each) => {
653
+ if ((isNotDefined(chartId) || each.id === chartId) &&
654
+ !shallowEqual(each.yScale.domain(), each.realYDomain)) {
655
+ changed = true;
656
+ return Object.assign(Object.assign({}, each), { yScale: each.yScale.domain(each.realYDomain), yPanEnabled: false });
657
+ }
658
+ return each;
659
+ });
660
+ if (changed) {
661
+ this.clearThreeCanvas();
662
+ this.setState({
663
+ chartConfigs: newChartConfig,
664
+ });
665
+ }
666
+ };
667
+ this.state = resetChart(props);
668
+ }
669
+ static getDerivedStateFromProps(props, state) {
670
+ var _a;
671
+ const { chartConfigs: initialChartConfig, plotData, xAccessor, xScale } = state;
672
+ const interaction = isInteractionEnabled(xScale, xAccessor, plotData);
673
+ const shouldReset = shouldResetChart(state.lastProps || {}, props);
674
+ let newState;
675
+ if (!interaction || shouldReset || !shallowEqual((_a = state.lastProps) === null || _a === void 0 ? void 0 : _a.xExtents, props.xExtents)) {
676
+ // do reset
677
+ newState = resetChart(props);
678
+ }
679
+ else {
680
+ const [start, end] = xScale.domain();
681
+ const prevLastItem = last(state.fullData);
682
+ const calculatedState = calculateFullData(props);
683
+ const { xAccessor } = calculatedState;
684
+ const previousX = xAccessor(prevLastItem);
685
+ const lastItemWasVisible = previousX <= end && previousX >= start;
686
+ newState = updateChart(calculatedState, xScale, props, lastItemWasVisible, initialChartConfig);
687
+ }
688
+ return Object.assign(Object.assign({}, newState), { lastProps: props, propIteration: (state.propIteration || 0) + 1 });
689
+ }
690
+ getSnapshotBeforeUpdate(prevProps, prevState) {
691
+ // propIteration is incremented when the props change to differentiate between state updates
692
+ // and prop updates
693
+ if (prevState.propIteration !== this.state.propIteration && !this.panInProgress) {
694
+ this.clearThreeCanvas();
695
+ }
696
+ return null;
697
+ }
698
+ componentDidUpdate(prevProps) {
699
+ if (prevProps.data !== this.props.data) {
700
+ this.triggerEvent("dataupdated", {
701
+ chartConfigs: this.state.chartConfigs,
702
+ xScale: this.state.xScale,
703
+ plotData: this.state.plotData,
704
+ });
705
+ }
706
+ }
707
+ clearBothCanvas() {
708
+ const canvases = this.getCanvasContexts();
709
+ if (canvases && canvases.axes && canvases.mouseCoord) {
710
+ clearCanvas([canvases.axes, canvases.mouseCoord], this.props.ratio);
711
+ }
712
+ }
713
+ clearMouseCanvas() {
714
+ const canvases = this.getCanvasContexts();
715
+ if (canvases && canvases.mouseCoord) {
716
+ clearCanvas([canvases.mouseCoord], this.props.ratio);
717
+ }
718
+ }
719
+ clearThreeCanvas() {
720
+ const canvases = this.getCanvasContexts();
721
+ if (canvases && canvases.axes && canvases.mouseCoord && canvases.bg) {
722
+ clearCanvas([canvases.axes, canvases.mouseCoord, canvases.bg], this.props.ratio);
723
+ }
724
+ }
725
+ cancelDrag() {
726
+ var _a;
727
+ (_a = this.eventCaptureRef.current) === null || _a === void 0 ? void 0 : _a.cancelDrag();
728
+ this.triggerEvent("dragcancel");
729
+ }
730
+ triggerEvent(type, props, e) {
731
+ this.subscriptions.forEach((each) => {
732
+ const state = Object.assign(Object.assign({}, this.state), { subscriptions: this.subscriptions });
733
+ each.listener(type, props, state, e);
734
+ });
735
+ }
736
+ // TODO: Memoize this
737
+ getContextValues() {
738
+ const dimensions = getDimensions(this.props);
739
+ return {
740
+ chartId: -1,
741
+ fullData: this.state.fullData,
742
+ plotData: this.state.plotData,
743
+ width: dimensions.width,
744
+ height: dimensions.height,
745
+ chartConfigs: this.state.chartConfigs,
746
+ xScale: this.state.xScale,
747
+ xAccessor: this.state.xAccessor,
748
+ displayXAccessor: this.state.displayXAccessor,
749
+ margin: this.props.margin,
750
+ ratio: this.props.ratio,
751
+ xAxisZoom: this.xAxisZoom,
752
+ yAxisZoom: this.yAxisZoom,
753
+ getCanvasContexts: this.getCanvasContexts,
754
+ redraw: this.redraw,
755
+ subscribe: this.subscribe,
756
+ unsubscribe: this.unsubscribe,
757
+ generateSubscriptionId: this.generateSubscriptionId,
758
+ getMutableState: this.getMutableState,
759
+ amIOnTop: this.amIOnTop,
760
+ setCursorClass: this.setCursorClass,
761
+ };
762
+ }
763
+ shouldComponentUpdate() {
764
+ return !this.panInProgress;
765
+ }
766
+ render() {
767
+ const { disableInteraction, disablePan, disableZoom, useCrossHairStyleCursor, onClick, onDoubleClick, height, width, margin = ChartCanvas.defaultProps.margin, className, zIndex = ChartCanvas.defaultProps.zIndex, defaultFocus, ratio, mouseMoveEvent, } = this.props;
768
+ const { plotData, xScale, xAccessor, chartConfigs } = this.state;
769
+ const dimensions = getDimensions(this.props);
770
+ const interaction = isInteractionEnabled(xScale, xAccessor, plotData);
771
+ const cursorStyle = useCrossHairStyleCursor && interaction;
772
+ const cursor = getCursorStyle();
773
+ return (React.createElement(ChartCanvasContext.Provider, { value: this.getContextValues() },
774
+ React.createElement("div", { style: { position: "relative", width, height }, className: className, onClick: onClick, onDoubleClick: onDoubleClick },
775
+ React.createElement(CanvasContainer, { ref: this.canvasContainerRef, ratio: ratio, width: width, height: height, style: { height, zIndex, width } }),
776
+ React.createElement("svg", { className: className, width: width, height: height, style: { position: "absolute", zIndex: zIndex + 5 } },
777
+ cursor,
778
+ React.createElement("defs", null,
779
+ React.createElement("clipPath", { id: "chart-area-clip" },
780
+ React.createElement("rect", { x: "0", y: "0", width: dimensions.width, height: dimensions.height })),
781
+ chartConfigs.map((each, idx) => (React.createElement("clipPath", { key: idx, id: `chart-area-clip-${each.id}` },
782
+ React.createElement("rect", { x: "0", y: "0", width: each.width, height: each.height }))))),
783
+ React.createElement("g", { transform: `translate(${margin.left + 0.5}, ${margin.top + 0.5})` },
784
+ React.createElement(EventCapture, { ref: this.eventCaptureRef, useCrossHairStyleCursor: cursorStyle, mouseMove: mouseMoveEvent && interaction, zoom: !disableZoom && interaction, pan: !disablePan && interaction, width: dimensions.width, height: dimensions.height, chartConfig: chartConfigs, xScale: xScale, xAccessor: xAccessor, focus: defaultFocus, disableInteraction: disableInteraction, getAllPanConditions: this.getAllPanConditions, onContextMenu: this.handleContextMenu, onClick: this.handleClick, onDoubleClick: this.handleDoubleClick, onMouseDown: this.handleMouseDown, onMouseMove: this.handleMouseMove, onMouseEnter: this.handleMouseEnter, onMouseLeave: this.handleMouseLeave, onDragStart: this.handleDragStart, onDrag: this.handleDrag, onDragComplete: this.handleDragEnd, onZoom: this.handleZoom, onPinchZoom: this.handlePinchZoom, onPinchZoomEnd: this.handlePinchZoomEnd, onPan: this.handlePan, onPanEnd: this.handlePanEnd }),
785
+ React.createElement("g", { className: "react-financial-charts-avoid-interaction" }, this.props.children))))));
786
+ }
787
+ }
788
+ ChartCanvas.defaultProps = {
789
+ clamp: false,
790
+ className: "react-financial-charts-ta",
791
+ defaultFocus: true,
792
+ disablePan: false,
793
+ disableInteraction: false,
794
+ disableZoom: false,
795
+ flipXScale: false,
796
+ maintainPointsPerPixelOnResize: true,
797
+ margin: { top: 0, right: 40, bottom: 40, left: 0 },
798
+ minPointsPerPxThreshold: 1 / 100,
799
+ mouseMoveEvent: true,
800
+ postCalculator: identity,
801
+ padding: 0,
802
+ pointsPerPxThreshold: 2,
803
+ useCrossHairStyleCursor: true,
804
+ xAccessor: identity,
805
+ xExtents: [min, max],
806
+ zIndex: 1,
807
+ zoomAnchor: mouseBasedZoomAnchor,
808
+ zoomMultiplier: 1.1,
809
+ };
810
810
  //# sourceMappingURL=ChartCanvas.js.map