@neo4j-ndl/react 3.0.16 → 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.
- package/lib/cjs/charts/Chart.js +415 -195
- package/lib/cjs/charts/Chart.js.map +1 -1
- package/lib/cjs/charts/ChartTooltip.js +5 -0
- package/lib/cjs/charts/ChartTooltip.js.map +1 -1
- package/lib/cjs/charts/Charts.js +4 -0
- package/lib/cjs/charts/Charts.js.map +1 -1
- package/lib/cjs/charts/Dot.js +1 -1
- package/lib/cjs/charts/Dot.js.map +1 -1
- package/lib/cjs/charts/HollowDot.js +31 -0
- package/lib/cjs/charts/HollowDot.js.map +1 -0
- package/lib/cjs/charts/Line.js +32 -1
- package/lib/cjs/charts/Line.js.map +1 -1
- package/lib/cjs/data-grid/Components.js +38 -37
- package/lib/cjs/data-grid/Components.js.map +1 -1
- package/lib/esm/charts/Chart.js +416 -202
- package/lib/esm/charts/Chart.js.map +1 -1
- package/lib/esm/charts/ChartTooltip.js +5 -0
- package/lib/esm/charts/ChartTooltip.js.map +1 -1
- package/lib/esm/charts/Charts.js +4 -0
- package/lib/esm/charts/Charts.js.map +1 -1
- package/lib/esm/charts/Dot.js +1 -1
- package/lib/esm/charts/Dot.js.map +1 -1
- package/lib/esm/charts/HollowDot.js +28 -0
- package/lib/esm/charts/HollowDot.js.map +1 -0
- package/lib/esm/charts/Line.js +34 -3
- package/lib/esm/charts/Line.js.map +1 -1
- package/lib/esm/data-grid/Components.js +38 -37
- package/lib/esm/data-grid/Components.js.map +1 -1
- package/lib/types/charts/Chart.d.ts +21 -15
- package/lib/types/charts/ChartTooltip.d.ts +1 -1
- package/lib/types/charts/HollowDot.d.ts +27 -0
- package/lib/types/charts/Line.d.ts +1 -0
- package/package.json +2 -2
package/lib/cjs/charts/Chart.js
CHANGED
|
@@ -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 =
|
|
66
|
-
exports.canvasRightPadding =
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
83
|
-
|
|
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 =
|
|
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 [
|
|
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
|
-
|
|
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
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
209
|
-
//
|
|
210
|
-
//
|
|
211
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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([
|
|
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([
|
|
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([(
|
|
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([(
|
|
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
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
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
|
|
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
|
|
509
|
+
const scaleYAxisCopy = scaleYAxis.copy();
|
|
510
|
+
scaleYAxisCopy.domain(scaleYAxisObject.originalDomain);
|
|
375
511
|
const pointPixelY = scaleYAxis(valueY);
|
|
376
|
-
|
|
377
|
-
|
|
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
|
|
400
|
-
const
|
|
401
|
-
|
|
402
|
-
|
|
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
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
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
|
-
|
|
421
|
-
const
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
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,
|
|
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
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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
|
-
} })),
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
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:
|
|
748
|
+
opacity: SHOULD_SHOW_VORONOI_DEBUG ? 0.5 : 0,
|
|
515
749
|
} }, index));
|
|
516
|
-
}) })] }),
|
|
517
|
-
|
|
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, {
|