@neo4j-ndl/react 3.0.17 → 3.0.18

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.
@@ -24,6 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.Chart = exports.ChartsChartContext = exports.canvasRightPadding = exports.canvasLeftPadding = void 0;
27
+ exports.getPointPixels = getPointPixels;
27
28
  const jsx_runtime_1 = require("react/jsx-runtime");
28
29
  /**
29
30
  *
@@ -45,25 +46,26 @@ const jsx_runtime_1 = require("react/jsx-runtime");
45
46
  * You should have received a copy of the GNU General Public License
46
47
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
47
48
  */
48
- const react_1 = require("react");
49
+ const react_1 = __importStar(require("react"));
49
50
  const d3 = __importStar(require("d3"));
50
51
  const Charts_1 = require("./Charts");
51
52
  const defaultImports_1 = require("../_common/defaultImports");
52
- // import { TopXAxis, BottomXAxis, LeftYAxis, RightYAxis } from './Axis';
53
53
  const Line_1 = require("./Line");
54
- // import { LineThreshold } from './LineThreshold';
55
54
  const Dot_1 = require("./Dot");
56
- // import { da, de, he, set } from 'date-fns/locale';
57
55
  const d3_shape_1 = require("d3-shape");
58
56
  const ChartTooltip_1 = require("./ChartTooltip");
59
57
  const usehooks_ts_1 = require("usehooks-ts");
60
58
  const utils_1 = require("./utils");
59
+ // Used to visualize the voronoi polygons.
60
+ const SHOULD_SHOW_VORONOI_DEBUG = false;
61
+ // Used to throttle calls to on mouse move over the polygons.
62
+ const THROTTLE_MOUSE_MOVE_MILLISECONDS = 100;
61
63
  const defaultChartProps = {
62
64
  scales: {},
63
65
  pointSelectionType: 'single',
64
66
  };
65
- exports.canvasLeftPadding = 8;
66
- exports.canvasRightPadding = 8;
67
+ exports.canvasLeftPadding = 0;
68
+ exports.canvasRightPadding = 0;
67
69
  // eslint-disable-next-line no-redeclare
68
70
  exports.ChartsChartContext = (0, react_1.createContext)({
69
71
  chartRef: null,
@@ -73,36 +75,99 @@ exports.ChartsChartContext = (0, react_1.createContext)({
73
75
  linePointArray: [],
74
76
  mousePositionRef: undefined,
75
77
  });
76
- const ChartComponent = (0, react_1.forwardRef)(function ChartComponent({ children, className,
77
- // scales: textScales = defaultChartProps.scales,
78
- // hoverAreaType = defaultChartProps.hoverAreaType,
79
- scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChartProps.pointSelectionType, }, ref) {
80
- // console.info('Chart.tsx - ChartComponent - initiation');
78
+ function getPointPixels(linePoint, scales) {
79
+ const { accessorXAxis, scaleXAxisId } = linePoint;
80
+ const { accessorYAxis, scaleYAxisId } = linePoint;
81
+ const valueX = linePoint[accessorXAxis];
82
+ const valueY = linePoint[accessorYAxis];
83
+ const scaleXAxisObject = scales[scaleXAxisId];
84
+ const scaleYAxisObject = scales[scaleYAxisId];
85
+ const scaleXAxis = scaleXAxisObject.functionWithContentWidthAsRange;
86
+ const scaleYAxis = scaleYAxisObject.functionWithContentHeightAsRange;
87
+ const pointPixelX = scaleXAxis(valueX);
88
+ const pointPixelY = scaleYAxis(valueY);
89
+ return { pointPixelX, pointPixelY };
90
+ }
91
+ function dotsPropsAreEqual(prevProps, nextProps) {
92
+ const isEqual = JSON.stringify(prevProps.selectedPoints) ==
93
+ JSON.stringify(nextProps.selectedPoints) &&
94
+ JSON.stringify(prevProps.metadata) == JSON.stringify(nextProps.metadata) &&
95
+ prevProps.selectedPointRef.current.dataId ===
96
+ nextProps.selectedPointRef.current.dataId;
97
+ return isEqual;
98
+ }
99
+ const DotsMemoized = react_1.default.memo(function Dots({ selectedPoints, metadata, selectedPointRef, tooltipAnchorRefCallback, scales, }) {
100
+ console.info('DotsMemoized >> render');
101
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: selectedPoints.map((linePoint) => {
102
+ const { key, dataId, pointIndex } = linePoint;
103
+ const { pointPixelX, pointPixelY } = getPointPixels(linePoint, scales);
104
+ const { isVisible, color } = metadata[dataId];
105
+ if (!isVisible)
106
+ return false;
107
+ const shouldAttachTooltipAnchorRef = dataId === selectedPointRef.current.dataId &&
108
+ pointIndex === selectedPointRef.current.pointIndex;
109
+ return ((0, jsx_runtime_1.jsx)(Dot_1.Dot, { ref: shouldAttachTooltipAnchorRef ? tooltipAnchorRefCallback : null, x: pointPixelX, y: pointPixelY, color: color }, `chart-dot-${key}`));
110
+ }) }));
111
+ }, dotsPropsAreEqual);
112
+ function tooltipPropsAreEqual(prevProps, nextProps) {
113
+ console.info(prevProps, nextProps);
114
+ const isEqual = JSON.stringify(prevProps.selectedPoints) ==
115
+ JSON.stringify(nextProps.selectedPoints) &&
116
+ JSON.stringify(prevProps.metadata) == JSON.stringify(nextProps.metadata) &&
117
+ prevProps.tooltipAnchorRef.current === nextProps.tooltipAnchorRef.current;
118
+ console.info('tooltip >>>>>>>>>>>>>>>>>>>', { isEqual });
119
+ return isEqual;
120
+ }
121
+ const TooltipMemoized = react_1.default.memo(function Tooltip({ selectedPoints, metadata, tooltipAnchorRef, }) {
81
122
  var _a, _b;
82
- // useEffect(() => {
83
- // console.info('component rerendered');
84
- // });
123
+ console.info('Tooltip >> render', tooltipAnchorRef);
124
+ return ((0, jsx_runtime_1.jsxs)(ChartTooltip_1.ChartTooltip, { anchorRef: tooltipAnchorRef, isOpen: true, children: [(0, jsx_runtime_1.jsx)(ChartTooltip_1.ChartTooltip.Title, { children: String((_b = selectedPoints[0][(_a = selectedPoints[0]) === null || _a === void 0 ? void 0 : _a.accessorXAxis]) !== null && _b !== void 0 ? _b : '') }), selectedPoints.map((linePoint) => {
125
+ var _a;
126
+ if (linePoint === undefined)
127
+ return null;
128
+ if (metadata[linePoint.dataId].isVisible === false)
129
+ return null;
130
+ const { key, dataId, accessorYAxis } = linePoint;
131
+ const contentKey = `chart-tooltip-content-${key}`;
132
+ console.info(contentKey);
133
+ return ((0, jsx_runtime_1.jsx)(ChartTooltip_1.ChartTooltip.Content, { leftElement: metadata[dataId].label, rightElement: ((_a = linePoint[accessorYAxis]) === null || _a === void 0 ? void 0 : _a.toString()) || '', indentSquareColor: metadata[dataId].color }, contentKey));
134
+ })] }));
135
+ }, tooltipPropsAreEqual);
136
+ const ChartComponent = (0, react_1.forwardRef)(function ChartComponent({ children, className, scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChartProps.pointSelectionType, }, ref) {
137
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
138
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
139
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
140
+ console.info('ChartComponent');
85
141
  const chartsContextValue = (0, react_1.useContext)(Charts_1.ChartsContext);
86
142
  const { data, metadata } = chartsContextValue;
87
143
  const chartRef = (0, react_1.useRef)(null);
88
144
  const contentRef = (0, react_1.useRef)(null);
89
- const tooltipAnchorRef = (0, react_1.useRef)(null);
145
+ // const tooltipAnchorRef = useRef<SVGSVGElement | null>(null);
146
+ const [tooltipAnchorRef, setTooltipAnchorRef] = (0, react_1.useState)(null);
147
+ const tooltipAnchorRefCallback = (0, react_1.useCallback)((node) => {
148
+ console.info('useCallback - dep: - set: setTooltipAnchorRef', node);
149
+ setTooltipAnchorRef({
150
+ current: node,
151
+ });
152
+ }, []);
90
153
  const horizontalIntersectionLineRef = (0, react_1.useRef)(null);
91
154
  const mousePositionRef = (0, react_1.useRef)({ x: 0, y: 0 });
155
+ const [draggingPosition, setDraggingPosition] = (0, react_1.useState)(undefined);
156
+ const [isMouseDown, setIsMouseDown] = (0, react_1.useState)(false);
92
157
  const [hasLines, setHasLines] = (0, react_1.useState)(false);
93
158
  const [contentSize, setContentSize] = (0, react_1.useState)(undefined);
94
159
  // The svg paths calculated for the voronoi polygons, includes
95
160
  // the assigned line point for the section for the onHover event.
96
- const [voroniPolygonPaths, setVoroniPolygonPaths] = (0, react_1.useState)();
97
- const [linePointArray, setLinePointArray] = (0, react_1.useState)([]);
98
- // The point where the tooltip will be anchored.
161
+ const [voronoiPolygons, setVoronoiPolygons] = (0, react_1.useState)();
99
162
  const selectedPointRef = (0, react_1.useRef)({});
100
163
  // The points that will display a thumb and be included in the tooltip.
101
- const [selectedPoints, setSelectedPoints] = (0, react_1.useState)([]);
102
- // useMemo:initialScales
164
+ const [selectedPoints, setSelectedPoints] = (0, react_1.useState)(null);
165
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
166
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
167
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
103
168
  const initialScales = (0, react_1.useMemo)(() => {
104
169
  // Map the string scales to actual d3 function scales.
105
- //Will only re-run if the scalesProp changes.
170
+ // Will only re-run if the scalesProp changes.
106
171
  const initialScales = {};
107
172
  Object.entries(scalesProp).forEach(([key, value]) => {
108
173
  switch (value.type) {
@@ -146,38 +211,32 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
146
211
  return initialScales;
147
212
  }, [scalesProp]);
148
213
  const [scales, setScales] = (0, react_1.useState)(initialScales);
149
- // Used to visualize the voronoi polygons.
150
- const shouldShowVoronoiDebug = true;
151
- const pointPixelAxis = pointSelectionType === 'x-axis' || pointSelectionType === 'single'
152
- ? 'pointPixelX'
153
- : 'pointPixelY';
154
- // useEffect:contentSize
214
+ const voronoiScale = (0, react_1.useMemo)(() => {
215
+ const initialVoronoiScale = {
216
+ originalDomain: null,
217
+ functionWithContentWidthAsRange: d3.scaleLinear(),
218
+ functionWithContentHeightAsRange: d3.scaleLinear(),
219
+ function: d3.scaleLinear(),
220
+ };
221
+ return initialVoronoiScale;
222
+ }, []);
155
223
  (0, react_1.useEffect)(() => {
156
224
  // Needs to run after first render to determine size of content container.
157
- // console.info('Chart.tsx - ChartComponent - useEffect - contentSize');
158
225
  if (!contentRef.current)
159
226
  return;
160
- // console.info(
161
- // 'Chart.tsx - ChartComponent - useEffect - contentSize (past guard)',
162
- // );
163
227
  const contentElement = contentRef.current;
164
228
  if (contentElement && contentElement.getBoundingClientRect) {
165
229
  const newContentSize = {
166
230
  width: contentElement.getBoundingClientRect().width,
167
231
  height: contentElement.getBoundingClientRect().height,
168
232
  };
169
- // console.info(
170
- // 'Chart.tsx - ChartComponent - useEffect - setting contentSize',
171
- // );
172
233
  // Will force a re-render, calculations require
173
234
  // width and height of the content container.
174
235
  setContentSize(newContentSize);
175
236
  }
176
237
  }, [contentRef]);
177
238
  const onResize = (0, usehooks_ts_1.useDebounceCallback)(() => {
178
- // console.info(
179
- // 'Chart.tsx - ChartComponent - useResizeObserver/useDebounceCallback - contentSize',
180
- // );
239
+ console.info('useDebounceCallback - set: contentSize');
181
240
  // Timeout to ensure all rendering is done before we get the size.
182
241
  const contentElement = contentRef.current;
183
242
  if (contentElement && contentElement.getBoundingClientRect()) {
@@ -187,9 +246,6 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
187
246
  exports.canvasRightPadding,
188
247
  height: contentElement.getBoundingClientRect().height,
189
248
  };
190
- // console.info(
191
- // 'Chart.tsx - ChartComponent - useResizeObserver/useDebounceCallback - setting contentSize',
192
- // );
193
249
  setContentSize(newContentSize);
194
250
  }
195
251
  }, 200);
@@ -198,28 +254,18 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
198
254
  onResize: onResize,
199
255
  });
200
256
  (0, react_1.useImperativeHandle)(ref, () => {
201
- // console.info('Chart.tsx - ChartComponent - useImperativeHandle - ref');
202
257
  const svgChart = chartRef.current;
203
258
  if (!svgChart) {
204
259
  return null;
205
260
  }
206
261
  return svgChart;
207
262
  });
208
- // useEffect:line
209
- // TODO: We don't need to run this after a render, we want this to run when we
210
- // have the contentRef ref and contentSize state set. This will force a re-render
211
- // when setting the states at the end.
212
- (0, react_1.useEffect)(() => {
213
- // console.info('Chart.tsx - ChartComponent - useEffect - line');
263
+ // The initial line point array is the representation of the full data
264
+ // that came into the component via the prop.
265
+ // useMemo:initialLinePointArray
266
+ const { initialLinePointArray, lineMap } = (0, react_1.useMemo)(() => {
214
267
  if (!data)
215
- return;
216
- if (!contentRef.current)
217
- return;
218
- const width = contentSize === null || contentSize === void 0 ? void 0 : contentSize.width;
219
- const height = contentSize === null || contentSize === void 0 ? void 0 : contentSize.height;
220
- if (!width || !height)
221
- return;
222
- // console.info('Chart.tsx - useEffect - line (past guard)');
268
+ return { initialLinePointArray: [], lineMap: {} };
223
269
  // This use effect is specific for Line components.
224
270
  // If there are no line components then we don't need to do anything.
225
271
  const arrayChildren = react_1.Children.toArray(children);
@@ -227,20 +273,18 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
227
273
  if (!hasLines)
228
274
  return;
229
275
  setHasLines(true);
276
+ const lineMap = {};
277
+ // Used by react for the key properties.
278
+ let key = 0;
230
279
  // Here we are figuring out the min and max values for all the scales.
231
280
  // To do this we need to iterate through all of the lines and assign
232
281
  // each lines designated scale to a min max object specific for that scale.
233
- const tempLinePointArray = [];
234
- let newScales = Object.assign({}, scales);
282
+ const newInitialLinePointArray = [];
235
283
  arrayChildren.forEach((child) => {
236
- var _a, _b, _c, _d;
237
284
  // Per line.
238
285
  if (!(0, react_1.isValidElement)(child) || child.type !== Line_1.Line)
239
286
  return;
240
- const { scaleXAxis: scaleXAxisId, scaleYAxis: scaleYAxisId, accessorXAxis: initialAccessorXAxis, accessorYAxis: initialAccessorYAxis, dataId, seriesInterval, seriesIntervalStartValue, } = child.props;
241
- // If it's not visible, don't include it.
242
- if (metadata[dataId].isVisible === false)
243
- return;
287
+ const { scaleXAxis: scaleXAxisId, scaleYAxis: scaleYAxisId, accessorXAxis: initialAccessorXAxis, accessorYAxis: initialAccessorYAxis, accessorHollowDot, dataId, seriesInterval, seriesIntervalStartValue, } = child.props;
244
288
  // Need to set these values for series type data.
245
289
  const accessorXAxis = seriesInterval
246
290
  ? 'xAxisValue'
@@ -259,17 +303,20 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
259
303
  const seriesLineData = lineData;
260
304
  singleLinePointArray = seriesLineData.data.map((dataPoint, index) => {
261
305
  const newLinePoint = {
306
+ key,
262
307
  dataId,
263
308
  pointIndex: index,
264
309
  dataIndex: lineDataIndex,
265
310
  accessorXAxis,
266
311
  accessorYAxis,
312
+ accessorHollowDot,
267
313
  xAxisValue: dataPoint !== undefined && dataPoint !== null
268
314
  ? seriesIntervalStartValue + seriesInterval * index
269
315
  : null,
270
316
  yAxisValue: dataPoint,
271
317
  scaleXAxisId,
272
318
  scaleYAxisId,
319
+ selectionGroup: null,
273
320
  };
274
321
  return newLinePoint;
275
322
  });
@@ -279,13 +326,16 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
279
326
  const nonSeriesData = lineData;
280
327
  singleLinePointArray = nonSeriesData.data.map((dataPointArray, index) => {
281
328
  const newLinePoint = {
329
+ key,
282
330
  dataId,
283
331
  pointIndex: index,
284
332
  dataIndex: lineDataIndex,
285
333
  accessorXAxis,
286
334
  accessorYAxis,
335
+ accessorHollowDot,
287
336
  scaleXAxisId,
288
337
  scaleYAxisId,
338
+ selectionGroup: null,
289
339
  };
290
340
  dataPointArray.forEach((dataPoint, index) => {
291
341
  newLinePoint[nonSeriesData.metadata[index]] = dataPoint;
@@ -293,19 +343,45 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
293
343
  return newLinePoint;
294
344
  });
295
345
  }
346
+ key += 1;
296
347
  // Add this single line to the array that holds all of the lines.
297
- tempLinePointArray.push(...singleLinePointArray);
348
+ newInitialLinePointArray.push(...singleLinePointArray);
349
+ // Line map for easier access to points from the same line. No need
350
+ // to iterate through the line point array.
351
+ // console.info('setting lineMap', lineMap);
352
+ lineMap[dataId] = singleLinePointArray;
353
+ });
354
+ const initialLinePointArray = newInitialLinePointArray;
355
+ return { initialLinePointArray, lineMap };
356
+ }, [data, children]) || {};
357
+ (0, react_1.useEffect)(() => {
358
+ if (!contentRef.current)
359
+ return;
360
+ const width = contentSize === null || contentSize === void 0 ? void 0 : contentSize.width;
361
+ const height = contentSize === null || contentSize === void 0 ? void 0 : contentSize.height;
362
+ if (!width || !height)
363
+ return;
364
+ if (initialLinePointArray === undefined)
365
+ return;
366
+ // Need to reset the originalDomain for each scale.
367
+ let newScales = {};
368
+ Object.entries(scales).forEach(([key, scale]) => {
369
+ newScales[key] = Object.assign(Object.assign({}, scale), { originalDomain: null });
370
+ });
371
+ initialLinePointArray.forEach((linePoint) => {
372
+ var _a, _b;
373
+ const { accessorXAxis, accessorYAxis, scaleXAxisId, scaleYAxisId } = linePoint;
298
374
  // Get min and max values for both x and y axis from the data point array.
299
- const minValueXAxis = d3.min(tempLinePointArray,
375
+ const minValueXAxis = d3.min(initialLinePointArray,
300
376
  // @ts-expect-error d3 types are not correct
301
377
  (linePoint) => linePoint[accessorXAxis]);
302
- const maxValueXAxis = d3.max(tempLinePointArray,
378
+ const maxValueXAxis = d3.max(initialLinePointArray,
303
379
  // @ts-expect-error d3 types are not correct
304
380
  (linePoint) => linePoint[accessorXAxis]);
305
- const minValueYAxis = d3.min(tempLinePointArray,
381
+ const minValueYAxis = d3.min(initialLinePointArray,
306
382
  // @ts-expect-error d3 types are not correct
307
383
  (linePoint) => linePoint[accessorYAxis]);
308
- const maxValueYAxis = d3.max(tempLinePointArray,
384
+ const maxValueYAxis = d3.max(initialLinePointArray,
309
385
  // @ts-expect-error d3 types are not correct
310
386
  (linePoint) => linePoint[accessorYAxis]);
311
387
  const scaleXAxis = newScales[scaleXAxisId];
@@ -318,24 +394,36 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
318
394
  let scaleYAxisMin = undefined;
319
395
  let scaleYAxisMax = undefined;
320
396
  if (scalesProp[scaleXAxisId].domain !== undefined) {
397
+ // The domain value is set manually.
321
398
  scaleXAxisMin = scalesProp[scaleXAxisId].domain[0];
322
399
  scaleXAxisMax = scalesProp[scaleXAxisId].domain[1];
323
400
  }
324
- else {
401
+ else if (scaleXAxis !== undefined &&
402
+ (scaleXAxis === null || scaleXAxis === void 0 ? void 0 : scaleXAxis.originalDomain) !== null) {
325
403
  //@ts-expect-error d3 types are not correct - it can handle undefined
326
- scaleXAxisMin = d3.min([(_a = scaleXAxis.originalDomain) === null || _a === void 0 ? void 0 : _a[0], minValueXAxis]);
404
+ scaleXAxisMin = d3.min([scaleXAxis.originalDomain[0], minValueXAxis]);
327
405
  //@ts-expect-error d3 types are not correct - it can handle undefined
328
- scaleXAxisMax = d3.max([(_b = scaleXAxis.originalDomain) === null || _b === void 0 ? void 0 : _b[1], maxValueXAxis]);
406
+ scaleXAxisMax = d3.max([scaleXAxis.originalDomain[1], maxValueXAxis]);
407
+ }
408
+ else {
409
+ scaleXAxisMin = minValueXAxis;
410
+ scaleXAxisMax = maxValueXAxis;
329
411
  }
330
412
  if (scalesProp[scaleYAxisId].domain !== undefined) {
413
+ // The domain value is set manually.
331
414
  scaleYAxisMin = scalesProp[scaleYAxisId].domain[0];
332
415
  scaleYAxisMax = scalesProp[scaleYAxisId].domain[1];
333
416
  }
334
- else {
417
+ else if (scaleYAxis !== undefined &&
418
+ scaleXAxis.originalDomain !== null) {
335
419
  //@ts-expect-error d3 types are not correct - it can handle undefined
336
- scaleYAxisMin = d3.min([(_c = scaleYAxis.originalDomain) === null || _c === void 0 ? void 0 : _c[0], minValueYAxis]);
420
+ scaleYAxisMin = d3.min([(_a = scaleYAxis.originalDomain) === null || _a === void 0 ? void 0 : _a[0], minValueYAxis]);
337
421
  //@ts-expect-error d3 types are not correct - it can handle undefined
338
- scaleYAxisMax = d3.max([(_d = scaleYAxis.originalDomain) === null || _d === void 0 ? void 0 : _d[1], maxValueYAxis]);
422
+ scaleYAxisMax = d3.max([(_b = scaleYAxis.originalDomain) === null || _b === void 0 ? void 0 : _b[1], maxValueYAxis]);
423
+ }
424
+ else {
425
+ scaleYAxisMin = minValueYAxis;
426
+ scaleYAxisMax = maxValueYAxis;
339
427
  }
340
428
  // D3 types are not correct it will be the same type as the original domain.
341
429
  // casting it to [number, number] to avoid type errors.
@@ -358,85 +446,265 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
358
446
  // Update the specific scale.
359
447
  newScales = Object.assign(Object.assign({}, newScales), { [scaleXAxisId]: scaleXAxis, [scaleYAxisId]: scaleYAxis });
360
448
  });
361
- // The points must be created after the line points have been created.
362
- // This is because the points are based on the scalers created from the line points.
363
- // The min max values are constantly updated. So looping twice is inevitable.
364
- const newLinePointArray = [];
365
- const delaunayPointArray = [];
366
- tempLinePointArray.forEach((linePoint) => {
367
- const { accessorXAxis, accessorYAxis, scaleXAxisId, scaleYAxisId } = linePoint;
449
+ voronoiScale.function.domain([0, width !== null && width !== void 0 ? width : 0]);
450
+ voronoiScale.originalDomain = [0, width !== null && width !== void 0 ? width : 0];
451
+ voronoiScale.functionWithContentWidthAsRange.domain([0, width !== null && width !== void 0 ? width : 0]);
452
+ voronoiScale.functionWithContentWidthAsRange.range([0, width !== null && width !== void 0 ? width : 0]);
453
+ setScales(newScales);
454
+ }, [contentSize, scalesProp, children, initialLinePointArray]);
455
+ const { linePointArray, pointSelectionGroups } = (0, react_1.useMemo)(() => {
456
+ if (initialLinePointArray === undefined)
457
+ return {};
458
+ // The following is only used for pointSelectionType x-axis and y-axis
459
+ const pointSelectionGroups = {};
460
+ const linePointArray = initialLinePointArray.map((linePoint) => {
461
+ const { pointPixelX, pointPixelY } = getPointPixels(linePoint, scales);
462
+ const pointPixelAxis = pointSelectionType === 'x-axis' || pointSelectionType === 'single'
463
+ ? pointPixelX
464
+ : pointPixelY;
465
+ if (pointPixelAxis === undefined)
466
+ return linePoint;
467
+ linePoint.selectionGroup = pointPixelAxis;
468
+ if (!pointSelectionGroups[pointPixelAxis]) {
469
+ pointSelectionGroups[pointPixelAxis] = [];
470
+ pointSelectionGroups[pointPixelAxis].push(linePoint);
471
+ }
472
+ else {
473
+ // Pixel point already exists.
474
+ pointSelectionGroups[pointPixelAxis].push(linePoint);
475
+ }
476
+ return linePoint;
477
+ });
478
+ return { linePointArray, pointSelectionGroups };
479
+ }, [pointSelectionType, initialLinePointArray, scales]);
480
+ const voronoiPolygonPointsArray = (0, react_1.useMemo)(() => {
481
+ const width = contentSize === null || contentSize === void 0 ? void 0 : contentSize.width;
482
+ const height = contentSize === null || contentSize === void 0 ? void 0 : contentSize.height;
483
+ if (!width || !height)
484
+ return;
485
+ if (lineMap === undefined)
486
+ return;
487
+ if (linePointArray === undefined)
488
+ return;
489
+ const visibleLinePointArray = linePointArray.filter((linePoint) => {
490
+ return metadata[linePoint.dataId].isVisible;
491
+ });
492
+ const delaunay = d3.Delaunay.from(visibleLinePointArray,
493
+ // @ts-expect-error - d3 types are not correct, it can handle null being returned.
494
+ (linePoint) => {
495
+ const { accessorXAxis, scaleXAxisId } = linePoint;
368
496
  const valueX = linePoint[accessorXAxis];
369
- const valueY = linePoint[accessorYAxis];
370
- const scaleXAxisObject = newScales[scaleXAxisId];
371
- const scaleYAxisObject = newScales[scaleYAxisId];
497
+ const scaleXAxisObject = scales[scaleXAxisId];
372
498
  const scaleXAxis = scaleXAxisObject.functionWithContentWidthAsRange;
499
+ const scaleXAxisCopy = scaleXAxis.copy();
500
+ scaleXAxisCopy.domain(scaleXAxisObject.originalDomain);
501
+ const pointPixelX = scaleXAxisCopy(valueX);
502
+ // We must return null otherwise some points won't work with voronoi/tooltips.
503
+ return pointPixelX === undefined ? null : pointPixelX;
504
+ }, (linePoint) => {
505
+ const { accessorYAxis, scaleYAxisId } = linePoint;
506
+ const valueY = linePoint[accessorYAxis];
507
+ const scaleYAxisObject = scales[scaleYAxisId];
373
508
  const scaleYAxis = scaleYAxisObject.functionWithContentHeightAsRange;
374
- const pointPixelX = scaleXAxis(valueX);
509
+ const scaleYAxisCopy = scaleYAxis.copy();
510
+ scaleYAxisCopy.domain(scaleYAxisObject.originalDomain);
375
511
  const pointPixelY = scaleYAxis(valueY);
376
- const newLinePoint = Object.assign(Object.assign({}, linePoint), { pointPixelX,
377
- pointPixelY });
378
- newLinePointArray.push(newLinePoint);
379
- // We diss line points that have null values as they don't require
380
- // an on hover event and therfor polygon paths.
381
- if (valueX === null || valueY === null)
382
- return;
383
- if (pointPixelX === null || pointPixelY === null)
384
- return;
385
- // Calculating the voroni polygons requires knowing the exact
386
- // pixel positions of all the line points.
387
- delaunayPointArray.push([pointPixelX, pointPixelY, newLinePoint]);
512
+ // We must return null otherwise some points won't work with voronoi/tooltips.
513
+ return pointPixelY === undefined ? null : pointPixelY;
388
514
  });
389
- // We have now created the line points and scales.
390
- // From those we can now calculate the on hover voroni polygons.
391
- // This must also be calculated after all updates as the polygon
392
- // paths will change depending on the line points available.
393
- const delaunayPointArrayLike = Object.assign(Object.assign({}, delaunayPointArray), { length: delaunayPointArray.length });
394
- const delaunay = d3.Delaunay.from(delaunayPointArrayLike);
395
515
  const voronoi = delaunay.voronoi([0, 0, width, height]);
396
516
  const voronoiPolygons = voronoi.cellPolygons();
397
517
  const voronoiPolygonPointsArray = Array.from(voronoiPolygons);
518
+ return voronoiPolygonPointsArray;
519
+ }, [metadata, linePointArray]);
520
+ (0, react_1.useEffect)(() => {
521
+ if (isMouseDown)
522
+ return;
523
+ if (voronoiPolygonPointsArray === undefined)
524
+ return;
525
+ if (linePointArray === undefined)
526
+ return;
527
+ const visibleLinePointArray = linePointArray.filter((linePoint) => {
528
+ return metadata[linePoint.dataId].isVisible;
529
+ });
398
530
  const delaunayLineFn = (0, d3_shape_1.line)();
399
- const voroniPolygonPaths = voronoiPolygonPointsArray.map((voronoiPolygonPoints, index) => {
400
- const path = delaunayLineFn(voronoiPolygonPoints);
401
- const linePoint = delaunayPointArray[index][2];
402
- return { path, linePoint };
531
+ const newVoronoiPolygons = voronoiPolygonPointsArray.map((voronoiPolygonPoints) => {
532
+ const newVoronoiPolygonPoints = voronoiPolygonPoints.map((voronoiPolygonPoint) => {
533
+ const [x, y] = voronoiPolygonPoint;
534
+ const scale = voronoiScale.functionWithContentWidthAsRange;
535
+ const newX = scale(x);
536
+ const newVoronoiPolygonPoint = [newX, y];
537
+ return newVoronoiPolygonPoint;
538
+ });
539
+ newVoronoiPolygonPoints.index = voronoiPolygonPoints.index;
540
+ const { index } = newVoronoiPolygonPoints;
541
+ const path = delaunayLineFn(newVoronoiPolygonPoints);
542
+ const linePoint = visibleLinePointArray[index];
543
+ const voronoiIndex = index;
544
+ return {
545
+ path,
546
+ linePoint,
547
+ voronoiIndex,
548
+ };
403
549
  });
404
- setVoroniPolygonPaths(voroniPolygonPaths);
405
- setLinePointArray(newLinePointArray);
406
- setScales(newScales);
407
- // eslint-disable-next-line react-hooks/exhaustive-deps
408
- }, [contentSize, scalesProp, children, data, metadata]);
409
- const handleMouseMove = (event, linePoint) => {
550
+ setVoronoiPolygons(newVoronoiPolygons);
551
+ }, [voronoiPolygonPointsArray, linePointArray, scales, isMouseDown]);
552
+ const handleMouseMove = (event, voronoiPolygon) => {
553
+ const { linePoint } = voronoiPolygon;
410
554
  const [xm, ym] = d3.pointer(event, contentRef.current);
411
555
  const mousePixelX = xm;
412
556
  const mousePixelY = ym;
413
557
  mousePositionRef.current.x = mousePixelX;
414
558
  mousePositionRef.current.y = mousePixelY;
415
- const { pointPixelX, pointPixelY, pointIndex, dataId } = linePoint;
559
+ // Zooming
560
+ if (isMouseDown) {
561
+ // We care about zooming when dragging because we want to fill space
562
+ // showing what is being selected.
563
+ const newDraggingPosition = Object.assign(Object.assign({}, draggingPosition), { endX: mousePixelX });
564
+ setDraggingPosition(newDraggingPosition);
565
+ return;
566
+ }
567
+ const { pointPixelX, pointPixelY } = getPointPixels(linePoint, scales);
568
+ if (pointPixelX === undefined || pointPixelY === undefined)
569
+ return;
570
+ // Line point
571
+ const { pointIndex, dataId } = linePoint;
416
572
  const distance = Math.hypot(pointPixelX - mousePixelX, pointPixelY - mousePixelY);
417
573
  const radius = 32;
418
- const shouldTrigger = distance < radius;
574
+ const shouldTrigger = distance < radius && pointSelectionGroups !== undefined;
419
575
  if (shouldTrigger) {
420
- // console.info('trigger');
421
- const pointPixelAxisValue = linePoint[pointPixelAxis];
422
- const newSelectedPoints = pointSelectionGroups[pointPixelAxisValue];
423
- if (newSelectedPoints !== selectedPoints)
424
- // console.info('set selected points');
576
+ const selectionGroup = linePoint.selectionGroup;
577
+ const hasSelectionGroup = selectionGroup !== null;
578
+ if (!hasSelectionGroup) {
579
+ console.warn('No selection group for point');
580
+ return;
581
+ }
582
+ const newSelectedPoints = pointSelectionGroups[selectionGroup];
583
+ const isNewSelectedPoints = newSelectedPoints !== selectedPoints;
584
+ if (isNewSelectedPoints) {
425
585
  selectedPointRef.current = { dataId, pointIndex };
586
+ }
426
587
  setSelectedPoints(newSelectedPoints);
427
588
  }
428
- else if (selectedPoints.length > 0) {
429
- // console.info('unset selected points');
589
+ else if (selectedPoints !== null && selectedPoints.length > 0) {
430
590
  selectedPointRef.current = {};
431
- setSelectedPoints([]);
591
+ setSelectedPoints(null);
432
592
  }
433
593
  };
434
- const throttledHandleMouseMove = (0, utils_1.useThrottle)(handleMouseMove, 100);
594
+ const throttledHandleMouseMove = (0, utils_1.useThrottle)(handleMouseMove, THROTTLE_MOUSE_MOVE_MILLISECONDS);
435
595
  const handleMouseLeave = () => {
596
+ if (isMouseDown) {
597
+ return;
598
+ }
599
+ setIsMouseDown(false);
600
+ setDraggingPosition(undefined);
436
601
  // Mouse moves outside of the content area.
437
- if (selectedPoints.length > 0)
438
- setSelectedPoints([]);
602
+ if (selectedPoints !== null && selectedPoints.length > 0)
603
+ setSelectedPoints(null);
439
604
  };
605
+ const handleMouseDown = (event) => {
606
+ const amountOfMouseClicks = event.detail;
607
+ const isDoubleClick = amountOfMouseClicks === 2;
608
+ if (isDoubleClick &&
609
+ contentSize !== undefined &&
610
+ contentSize.width !== undefined) {
611
+ // If zoomed in, return to the original view.
612
+ Object.entries(scales).forEach(([scaleId, scale]) => {
613
+ if (scale.originalDomain === null)
614
+ return;
615
+ const newScale = Object.assign({}, scale);
616
+ newScale.function.domain(scale.originalDomain);
617
+ newScale.functionWithContentWidthAsRange.domain(scale.originalDomain);
618
+ scales[scaleId] = newScale;
619
+ });
620
+ voronoiScale.function.domain([0, contentSize.width]);
621
+ voronoiScale.functionWithContentWidthAsRange.domain([
622
+ 0,
623
+ contentSize.width,
624
+ ]);
625
+ }
626
+ // Set start position for dragging.
627
+ const [xm, ym] = d3.pointer(event, contentRef.current);
628
+ const mousePixelX = xm;
629
+ const mousePixelY = ym;
630
+ mousePositionRef.current.x = mousePixelX;
631
+ mousePositionRef.current.y = mousePixelY;
632
+ // Initial dragging position.
633
+ const newDraggingPosition = {
634
+ startX: mousePixelX,
635
+ endX: undefined,
636
+ };
637
+ // Needed for the dragging motion.
638
+ setIsMouseDown(true);
639
+ setDraggingPosition(newDraggingPosition);
640
+ };
641
+ // must attach mouse listener to window
642
+ const handleMouseUp = () => {
643
+ const [xm] = d3.pointer(event, contentRef.current);
644
+ const mousePixelX = xm;
645
+ if ((draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.startX) === mousePixelX) {
646
+ // The user clicked on the same place, no zooming.
647
+ setIsMouseDown(false);
648
+ setDraggingPosition(undefined);
649
+ return;
650
+ }
651
+ const leftX = (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.startX) > (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.endX)
652
+ ? draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.endX
653
+ : draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.startX;
654
+ const rightX = (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.startX) > (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.endX)
655
+ ? draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.startX
656
+ : draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.endX;
657
+ Object.entries(scales).forEach(([scaleId, scale]) => {
658
+ const newScale = Object.assign({}, scale);
659
+ newScale.function.domain([
660
+ newScale.function.invert(leftX),
661
+ newScale.function.invert(rightX),
662
+ ]);
663
+ newScale.functionWithContentWidthAsRange.domain([
664
+ newScale.functionWithContentWidthAsRange.invert(leftX),
665
+ newScale.functionWithContentWidthAsRange.invert(rightX),
666
+ ]);
667
+ scales[scaleId] = newScale;
668
+ });
669
+ // update voronoi scale
670
+ voronoiScale.function.domain([
671
+ voronoiScale.function.invert(leftX),
672
+ voronoiScale.function.invert(rightX),
673
+ ]);
674
+ voronoiScale.functionWithContentWidthAsRange.domain([
675
+ voronoiScale.functionWithContentWidthAsRange.invert(leftX),
676
+ voronoiScale.functionWithContentWidthAsRange.invert(rightX),
677
+ ]);
678
+ setIsMouseDown(false);
679
+ setDraggingPosition(undefined);
680
+ };
681
+ const isCanvasComponent = (child) => {
682
+ return (0, react_1.isValidElement)(child) && child.type === Line_1.Line;
683
+ };
684
+ const width = (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.endX) && (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.startX)
685
+ ? draggingPosition.endX > draggingPosition.startX
686
+ ? draggingPosition.endX - draggingPosition.startX
687
+ : draggingPosition.startX - draggingPosition.endX
688
+ : 1;
689
+ const leftX = (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.endX) && (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.startX)
690
+ ? (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.startX) > (draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.endX)
691
+ ? draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.endX
692
+ : draggingPosition === null || draggingPosition === void 0 ? void 0 : draggingPosition.startX
693
+ : undefined;
694
+ const shouldRenderDots = hasLines &&
695
+ contentSize !== undefined &&
696
+ selectedPoints !== null &&
697
+ selectedPoints.length > 0 &&
698
+ metadata !== undefined;
699
+ const shouldRenderTooltip = hasLines &&
700
+ contentSize !== undefined &&
701
+ selectedPoints !== null &&
702
+ selectedPoints.length > 0 &&
703
+ metadata !== undefined &&
704
+ tooltipAnchorRef !== null &&
705
+ tooltipAnchorRef.current !== null;
706
+ if (linePointArray === undefined)
707
+ return null;
440
708
  const chartContextValue = {
441
709
  chartRef,
442
710
  contentRef,
@@ -446,90 +714,42 @@ scales: scalesProp = defaultChartProps.scales, pointSelectionType = defaultChart
446
714
  mousePositionRef,
447
715
  };
448
716
  const chartClasses = (0, defaultImports_1.classNames)(`ndl-charts-chart`, className);
449
- const contentClasses = (0, defaultImports_1.classNames)(`ndl-charts-chart-content`, className);
450
- // useMemo:pointSelectionGroups
451
- const pointSelectionGroups = (0, react_1.useMemo)(() => {
452
- // console.info('Chart.tsx - ChartComponent - useMemo - pointSelectionGroups');
453
- // The following is only used for pointSelectionType x-axis and y-axis
454
- const pointSelectionGroups = {};
455
- for (let i = 0; i < linePointArray.length; i += 1) {
456
- const linePoint = linePointArray[i];
457
- const pointPixelAxis = pointSelectionType === 'x-axis' || pointSelectionType === 'single'
458
- ? 'pointPixelX'
459
- : 'pointPixelY';
460
- const pointPixelAxisValue = linePoint[pointPixelAxis];
461
- if (pointPixelAxisValue === undefined)
462
- continue;
463
- if (!pointSelectionGroups[pointPixelAxisValue]) {
464
- pointSelectionGroups[pointPixelAxisValue] = [];
465
- pointSelectionGroups[pointPixelAxisValue].push(linePoint);
466
- }
467
- else {
468
- // Pixel point already exists.
469
- pointSelectionGroups[pointPixelAxisValue].push(linePoint);
470
- }
471
- }
472
- return pointSelectionGroups;
473
- }, [pointSelectionType, linePointArray]);
474
- const isCanvasComponent = (child) => {
475
- return (0, react_1.isValidElement)(child) && child.type === Line_1.Line;
476
- };
477
- return ((0, jsx_runtime_1.jsx)(exports.ChartsChartContext.Provider, { value: chartContextValue, children: (0, jsx_runtime_1.jsxs)("div", { ref: chartRef, className: chartClasses, onMouseLeave: handleMouseLeave, children: [(0, jsx_runtime_1.jsxs)("svg", { ref: contentRef, className: contentClasses, children: [(0, jsx_runtime_1.jsxs)("g", { children: [react_1.Children.toArray(children).map((child) => {
717
+ const contentClasses = (0, defaultImports_1.classNames)(`ndl-charts-chart-content`);
718
+ const zoomingClasses = (0, defaultImports_1.classNames)(`ndl-charts-chart-zoom`);
719
+ return ((0, jsx_runtime_1.jsx)(exports.ChartsChartContext.Provider, { value: chartContextValue, children: (0, jsx_runtime_1.jsxs)("div", { ref: chartRef, className: chartClasses, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, children: [(0, jsx_runtime_1.jsxs)("svg", { ref: contentRef, className: contentClasses, children: [(0, jsx_runtime_1.jsxs)("g", { children: [draggingPosition && contentSize && (
720
+ // The zooming rectangle visualizing the selected area.
721
+ (0, jsx_runtime_1.jsx)("g", { children: (0, jsx_runtime_1.jsx)("rect", { className: zoomingClasses, x: leftX, width: width, height: contentSize.height }) })), react_1.Children.toArray(children).map((child) => {
722
+ // Render the lines.
478
723
  return isCanvasComponent(child) ? child : null;
479
724
  }), hasLines &&
480
725
  contentSize &&
481
726
  selectedPoints &&
482
727
  selectedPoints.length > 0 && (
483
728
  // Dotted line for x-axis selection.
484
- (0, jsx_runtime_1.jsx)("line", { ref: horizontalIntersectionLineRef, x1: selectedPoints[0].pointPixelX, x2: selectedPoints[0].pointPixelX, y1: "0", y2: contentSize.height, style: {
729
+ (0, jsx_runtime_1.jsx)("line", { ref: horizontalIntersectionLineRef, x1: getPointPixels(selectedPoints[0], scales).pointPixelX, x2: getPointPixels(selectedPoints[0], scales).pointPixelX, y1: "0", y2: contentSize.height, style: {
485
730
  strokeDasharray: '5,7',
486
731
  stroke: 'rgb(111, 117, 126)',
487
- } })), hasLines &&
488
- contentSize &&
489
- selectedPoints &&
490
- selectedPoints.length > 0 &&
491
- // The point thumb for x-axis selection.
492
- selectedPoints.map((linePoint, index) => {
493
- const { dataId, pointIndex, pointPixelX, pointPixelY } = linePoint;
494
- const { isVisible, color } = metadata[dataId];
495
- if (isVisible) {
496
- // We want to attach the tooltip anchor to the correctly selected point.
497
- const { dataId: selectedPointRefDataId, pointIndex: selectedPointRefPointIndex, } = selectedPointRef.current;
498
- const shouldAttachTooltipAnchorRef = dataId === selectedPointRefDataId &&
499
- pointIndex === selectedPointRefPointIndex;
500
- return ((0, jsx_runtime_1.jsx)(Dot_1.Dot, { ref: shouldAttachTooltipAnchorRef ? tooltipAnchorRef : null, x: pointPixelX, y: pointPixelY, color: color }, index));
501
- }
502
- return false;
503
- })] }), (0, jsx_runtime_1.jsx)("g", { children: hasLines &&
504
- voroniPolygonPaths &&
505
- voroniPolygonPaths.map((voroniPolygonPath, index) => {
506
- const { path, linePoint } = voroniPolygonPath;
507
- return ((0, jsx_runtime_1.jsx)("path", { d: path, className: "action-voronoi", onMouseMove: (event) => {
508
- throttledHandleMouseMove(event, linePoint);
732
+ } })), shouldRenderDots && ((0, jsx_runtime_1.jsx)(DotsMemoized
733
+ // Dots together with tooltip to be rendered
734
+ , {
735
+ // Dots together with tooltip to be rendered
736
+ selectedPoints: selectedPoints, metadata: metadata, selectedPointRef: selectedPointRef, tooltipAnchorRefCallback: tooltipAnchorRefCallback, scales: scales }))] }), (0, jsx_runtime_1.jsx)("g", { children: hasLines &&
737
+ voronoiPolygons &&
738
+ voronoiPolygons.map((voronoiPolygon, index) => {
739
+ // Hover area for each line point.
740
+ const { path } = voronoiPolygon;
741
+ return ((0, jsx_runtime_1.jsx)("path", { d: path, onMouseMove: (event) => {
742
+ throttledHandleMouseMove(event, voronoiPolygon);
509
743
  }, style: {
510
744
  strokeWidth: 1,
511
745
  stroke: 'black',
512
746
  strokeOpacity: 0.5,
513
747
  fill: '#fff',
514
- opacity: shouldShowVoronoiDebug ? 0.5 : 0,
748
+ opacity: SHOULD_SHOW_VORONOI_DEBUG ? 0.5 : 0,
515
749
  } }, index));
516
- }) })] }), (0, jsx_runtime_1.jsx)(ChartTooltip_1.ChartTooltip
517
- //@ts-expect-error SVG element ref will work in this case.
518
- , {
519
- //@ts-expect-error SVG element ref will work in this case.
520
- anchorRef: tooltipAnchorRef, isOpen: Boolean(hasLines &&
521
- contentSize &&
522
- selectedPoints &&
523
- selectedPoints.length > 0), children: hasLines &&
524
- contentSize &&
525
- selectedPoints &&
526
- selectedPoints.length > 0 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ChartTooltip_1.ChartTooltip.Title, { children: String((_b = selectedPoints[0][(_a = selectedPoints[0]) === null || _a === void 0 ? void 0 : _a.accessorXAxis]) !== null && _b !== void 0 ? _b : '') }), selectedPoints.map((linePoint) => {
527
- var _a;
528
- if (linePoint === undefined)
529
- return null;
530
- const { dataId, accessorYAxis } = linePoint;
531
- return ((0, jsx_runtime_1.jsx)(ChartTooltip_1.ChartTooltip.Content, { leftElement: chartsContextValue.metadata[dataId].label, rightElement: ((_a = linePoint[accessorYAxis]) === null || _a === void 0 ? void 0 : _a.toString()) || '', indentSquareColor: chartsContextValue.metadata[dataId].color }, dataId));
532
- })] })) })] }) }));
750
+ }) })] }), shouldRenderTooltip && (
751
+ // Tooltip together with the dots to be rendered
752
+ (0, jsx_runtime_1.jsx)(TooltipMemoized, { selectedPoints: selectedPoints, metadata: metadata, tooltipAnchorRef: tooltipAnchorRef }))] }) }));
533
753
  });
534
754
  // Issue with TypeScript forwardRef and subcomponents: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/34757#issuecomment-894053907
535
755
  const Chart = Object.assign(ChartComponent, {