@redsift/charts 11.5.0 → 11.6.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/_internal/Arc.js +2 -0
  2. package/_internal/Arc.js.map +1 -0
  3. package/_internal/Arc2.js +117 -0
  4. package/_internal/Arc2.js.map +1 -0
  5. package/_internal/Arcs.js +2 -0
  6. package/_internal/Arcs.js.map +1 -0
  7. package/_internal/Arcs2.js +94 -0
  8. package/_internal/Arcs2.js.map +1 -0
  9. package/_internal/Axis.js +2 -0
  10. package/_internal/Axis.js.map +1 -0
  11. package/_internal/Axis2.js +388 -0
  12. package/_internal/Axis2.js.map +1 -0
  13. package/_internal/Bar.js +2 -0
  14. package/_internal/Bar.js.map +1 -0
  15. package/_internal/Bar2.js +170 -0
  16. package/_internal/Bar2.js.map +1 -0
  17. package/_internal/BarChart.js +2 -0
  18. package/_internal/BarChart.js.map +1 -0
  19. package/_internal/BarChart2.js +1419 -0
  20. package/_internal/BarChart2.js.map +1 -0
  21. package/_internal/ChartContainer.js +2 -0
  22. package/_internal/ChartContainer.js.map +1 -0
  23. package/_internal/ChartContainer2.js +266 -0
  24. package/_internal/ChartContainer2.js.map +1 -0
  25. package/_internal/DataPoint.js +2 -0
  26. package/_internal/DataPoint.js.map +1 -0
  27. package/_internal/DataPoint2.js +110 -0
  28. package/_internal/DataPoint2.js.map +1 -0
  29. package/_internal/Dot.js +2 -0
  30. package/_internal/Dot.js.map +1 -0
  31. package/_internal/Dot2.js +110 -0
  32. package/_internal/Dot2.js.map +1 -0
  33. package/_internal/Legend.js +2 -0
  34. package/_internal/Legend.js.map +1 -0
  35. package/_internal/Legend3.js +84 -0
  36. package/_internal/Legend3.js.map +1 -0
  37. package/_internal/LegendItem.js +2 -0
  38. package/_internal/LegendItem.js.map +1 -0
  39. package/_internal/LegendItem2.js +153 -0
  40. package/_internal/LegendItem2.js.map +1 -0
  41. package/_internal/Line.js +2 -0
  42. package/_internal/Line.js.map +1 -0
  43. package/_internal/Line2.js +59 -0
  44. package/_internal/Line2.js.map +1 -0
  45. package/_internal/LineChart.js +2 -0
  46. package/_internal/LineChart.js.map +1 -0
  47. package/_internal/LineChart2.js +669 -0
  48. package/_internal/LineChart2.js.map +1 -0
  49. package/_internal/PieChart.js +2 -0
  50. package/_internal/PieChart.js.map +1 -0
  51. package/_internal/PieChart2.js +605 -0
  52. package/_internal/PieChart2.js.map +1 -0
  53. package/_internal/ScatterPlot.js +2 -0
  54. package/_internal/ScatterPlot.js.map +1 -0
  55. package/_internal/ScatterPlot2.js +744 -0
  56. package/_internal/ScatterPlot2.js.map +1 -0
  57. package/_internal/_rollupPluginBabelHelpers.js +93 -0
  58. package/_internal/_rollupPluginBabelHelpers.js.map +1 -0
  59. package/_internal/config.js +13 -0
  60. package/_internal/config.js.map +1 -0
  61. package/_internal/legend2.js +21 -0
  62. package/_internal/legend2.js.map +1 -0
  63. package/_internal/scheme.js +47 -0
  64. package/_internal/scheme.js.map +1 -0
  65. package/_internal/theme.js +79 -0
  66. package/_internal/theme.js.map +1 -0
  67. package/_internal/useFormatCategoricalData.js +56 -0
  68. package/_internal/useFormatCategoricalData.js.map +1 -0
  69. package/index.js +17 -5118
  70. package/index.js.map +1 -1
  71. package/index2.js +16 -0
  72. package/index2.js.map +1 -0
  73. package/package.json +4 -4
@@ -0,0 +1,744 @@
1
+ import { _ as _objectWithoutProperties, a as _extends, b as _objectSpread2 } from './_rollupPluginBabelHelpers.js';
2
+ import React__default, { useRef, useEffect, useState, forwardRef } from 'react';
3
+ import classNames from 'classnames';
4
+ import { useTheme, useMessageFormatter, Flexbox, Button, Text, useId } from '@redsift/design-system';
5
+ import { L as LegendVariant, T as TooltipVariant } from './legend2.js';
6
+ import { C as ChartSize, g as getSortingMethod, u as useColor, m as mergeLegends, a as ColorTheme } from './theme.js';
7
+ import styled from 'styled-components';
8
+ import { C as ChartContainer } from './ChartContainer2.js';
9
+ import { brush, select, zoom, interpolateRound, scaleLinear, min, extent, descending, scaleSqrt, max } from 'd3';
10
+ import { A as Axis, a as AxisVariant } from './Axis2.js';
11
+ import { Popover } from '@redsift/popovers';
12
+ import { D as Dot } from './Dot2.js';
13
+ import { L as Legend } from './Legend3.js';
14
+
15
+ const getRoundedIntermediaryPoint = (selection, scaleX, scaleY) => {
16
+ if (!selection) {
17
+ return null;
18
+ }
19
+ const xTicks = scaleX.ticks(20);
20
+ const xDelta = xTicks[1] - xTicks[0];
21
+ const yTicks = scaleY.ticks(20);
22
+ const yDelta = yTicks[1] - yTicks[0];
23
+ return [[scaleX(Math.round(scaleX.invert(selection[0][0]) / xDelta) * xDelta - xDelta / 2), scaleY(Math.round(scaleY.invert(selection[0][1]) / yDelta) * yDelta - yDelta / 2)], [scaleX(Math.round(scaleX.invert(selection[1][0]) / xDelta) * xDelta - xDelta / 2), scaleY(Math.round(scaleY.invert(selection[1][1]) / yDelta) * yDelta - yDelta / 2)]];
24
+ };
25
+ const useBrush = _ref => {
26
+ let {
27
+ brushRef: propsBrushRef,
28
+ svgRef,
29
+ extent,
30
+ scaleX,
31
+ scaleY,
32
+ isBrushable,
33
+ isGridded,
34
+ onBrush,
35
+ onBrushEnd
36
+ } = _ref;
37
+ const brushRef = propsBrushRef || useRef();
38
+ useEffect(() => {
39
+ if (svgRef.current && isBrushable) {
40
+ brushRef.current = brush().extent(extent).keyModifiers(false).filter(event => event.shiftKey).on('brush', event => {
41
+ if (!event.sourceEvent || !brushRef.current || !svgRef.current) return;
42
+ if (isGridded) {
43
+ const selection = getRoundedIntermediaryPoint(event.selection, scaleX, scaleY);
44
+ select(svgRef.current).call(brushRef.current.move, selection);
45
+ onBrush === null || onBrush === void 0 ? void 0 : onBrush(selection, scaleX, scaleY);
46
+ } else {
47
+ onBrush === null || onBrush === void 0 ? void 0 : onBrush(event.selection, scaleX, scaleY);
48
+ }
49
+ }).on('end', event => {
50
+ if (!event.sourceEvent || !brushRef.current || !svgRef.current) return;
51
+ onBrushEnd === null || onBrushEnd === void 0 ? void 0 : onBrushEnd(event.selection, scaleX, scaleY);
52
+ });
53
+ select(svgRef.current).call(brushRef.current);
54
+ }
55
+ });
56
+ };
57
+
58
+ const useZoom = _ref => {
59
+ let {
60
+ svgRef,
61
+ scaleX,
62
+ scaleY,
63
+ defaultTransform = {
64
+ k: 1,
65
+ x: 0,
66
+ y: 0
67
+ },
68
+ size,
69
+ onZoom
70
+ } = _ref;
71
+ const zx = useRef(scaleX);
72
+ const zy = useRef(scaleY);
73
+ const [transform, setTransform] = useState(defaultTransform);
74
+ useEffect(() => {
75
+ if (svgRef.current) {
76
+ const zoom$1 = zoom().filter(event => !event.shiftKey).scaleExtent([1 / 2 ** 3, 2 ** 3]).on('zoom', event => {
77
+ onZoom === null || onZoom === void 0 ? void 0 : onZoom();
78
+ zx.current = event.transform.rescaleX(scaleX).interpolate(interpolateRound);
79
+ zy.current = event.transform.rescaleY(scaleY).interpolate(interpolateRound);
80
+ setTransform(event.transform);
81
+ });
82
+ select(svgRef.current).call(zoom$1);
83
+ }
84
+ }, [svgRef.current, size]);
85
+ return {
86
+ transform,
87
+ scaleX: zx.current,
88
+ scaleY: zy.current
89
+ };
90
+ };
91
+
92
+ /**
93
+ * Component variant.
94
+ */
95
+ const ScatterPlotVariant = {
96
+ default: 'default',
97
+ gridded: 'gridded'
98
+ };
99
+ /**
100
+ * Component's labels variant.
101
+ */
102
+ const ScatterPlotLegendVariant = {
103
+ none: 'none',
104
+ externalLabel: 'externalLabel',
105
+ externalLabelValue: 'externalLabelValue',
106
+ externalLabelPercent: 'externalLabelPercent',
107
+ custom: 'custom'
108
+ };
109
+
110
+ /**
111
+ * Component props.
112
+ */
113
+
114
+ /**
115
+ * Component style.
116
+ */
117
+ const StyledScatterPlot = styled(ChartContainer)``;
118
+ const StyledScatterPlotEmptyText = styled.div`
119
+ position: absolute;
120
+ top: 0;
121
+ left: 0;
122
+ height: 100%;
123
+ width: 100%;
124
+ display: flex;
125
+ flex-direction: column;
126
+ justify-content: center;
127
+ align-items: center;
128
+ pointer-events: none;
129
+
130
+ > * {
131
+ max-width: ${_ref => {
132
+ let {
133
+ $maxWidth
134
+ } = _ref;
135
+ return $maxWidth;
136
+ }}px;
137
+ }
138
+
139
+ > span {
140
+ font-family: var(--redsift-typography-font-family-poppins);
141
+ color: ${_ref2 => {
142
+ let {
143
+ $theme
144
+ } = _ref2;
145
+ return `var(--redsift-color-${$theme}-components-text-primary)`;
146
+ }};
147
+ font-size: ${_ref3 => {
148
+ let {
149
+ $textSize
150
+ } = _ref3;
151
+ return $textSize;
152
+ }}px;
153
+ line-height: ${_ref4 => {
154
+ let {
155
+ $textSize
156
+ } = _ref4;
157
+ return $textSize;
158
+ }}px;
159
+ }
160
+ `;
161
+
162
+ const _excluded$3 = ["className"];
163
+ const LoadingScatterPlot = /*#__PURE__*/forwardRef((props, ref) => {
164
+ const {
165
+ className
166
+ } = props,
167
+ forwardedProps = _objectWithoutProperties(props, _excluded$3);
168
+ return /*#__PURE__*/React__default.createElement(StyledScatterPlot, _extends({}, forwardedProps, {
169
+ className: className,
170
+ ref: ref
171
+ }), "Loading...");
172
+ });
173
+
174
+ const sizeToDimension = size => {
175
+ if (typeof size !== 'string') {
176
+ return size;
177
+ }
178
+ switch (size) {
179
+ case ChartSize.small:
180
+ return {
181
+ width: 600,
182
+ height: 300,
183
+ fontSize: 30
184
+ };
185
+ case ChartSize.medium:
186
+ default:
187
+ return {
188
+ width: 750,
189
+ height: 375,
190
+ fontSize: 34
191
+ };
192
+ case ChartSize.large:
193
+ return {
194
+ width: 900,
195
+ height: 450,
196
+ fontSize: 38
197
+ };
198
+ }
199
+ };
200
+ const BASE_NUMBER_OF_TICKS = 20;
201
+ const getClosestLineIndex = (value, scale) => {
202
+ const ticks = scale.ticks(BASE_NUMBER_OF_TICKS);
203
+ const delta = ticks[1] - ticks[0];
204
+ const index = Math.round(value / delta);
205
+ const roundValue = index * delta;
206
+ return [index, roundValue];
207
+ };
208
+ const group = (data, x, y) => {
209
+ const groupDict = {};
210
+ data.forEach(d => {
211
+ const [i, rx] = getClosestLineIndex(d.key[0], x);
212
+ const [j, ry] = getClosestLineIndex(d.key[1], y);
213
+ const key = `${i}_${j}_${d.key[2]}`;
214
+ if (!(key in groupDict)) {
215
+ groupDict[key] = {
216
+ category: d.key[2],
217
+ x: rx,
218
+ y: ry,
219
+ data: {
220
+ key: d.key,
221
+ value: 0
222
+ },
223
+ points: []
224
+ };
225
+ }
226
+ groupDict[key].points.push(d);
227
+ groupDict[key].data.value += 1;
228
+ });
229
+ return Object.values(groupDict);
230
+ };
231
+ const countBy = (arr, sortingMethod) => {
232
+ const counts = arr.reduce((prev, curr) => (prev[curr.key[2]] = ++prev[curr.key[2]] || 1, prev), {});
233
+ return Object.keys(counts).map(key => ({
234
+ key: key,
235
+ value: counts[key]
236
+ })).sort(getSortingMethod(sortingMethod));
237
+ };
238
+
239
+ const _excluded$2 = ["className", "data", "emptyComponent", "localeText", "size"];
240
+ const EmptyScatterPlot = /*#__PURE__*/forwardRef((props, ref) => {
241
+ const {
242
+ className,
243
+ data: propsData,
244
+ emptyComponent,
245
+ localeText,
246
+ size
247
+ } = props,
248
+ forwardedProps = _objectWithoutProperties(props, _excluded$2);
249
+ const theme = useTheme();
250
+ const cache = useRef();
251
+ const data = propsData;
252
+ useEffect(() => {
253
+ cache.current = data;
254
+ });
255
+ const chartDimensions = sizeToDimension(size);
256
+ const width = chartDimensions.width;
257
+ const height = chartDimensions.height;
258
+ const margins = {
259
+ top: 16,
260
+ left: 48,
261
+ right: 16,
262
+ bottom: 48
263
+ };
264
+ const chartWidth = width - margins.left - margins.right;
265
+ return /*#__PURE__*/React__default.createElement(StyledScatterPlot, _extends({}, forwardedProps, {
266
+ className: className,
267
+ ref: ref
268
+ }), emptyComponent !== null && emptyComponent !== void 0 ? emptyComponent : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(StyledScatterPlotEmptyText, {
269
+ $maxWidth: width,
270
+ $textSize: chartDimensions.fontSize / 2,
271
+ $theme: theme
272
+ }, /*#__PURE__*/React__default.createElement("span", null, localeText === null || localeText === void 0 ? void 0 : localeText.emptyChartText)), /*#__PURE__*/React__default.createElement("svg", {
273
+ width: width,
274
+ height: height
275
+ }, /*#__PURE__*/React__default.createElement("g", {
276
+ transform: `translate(${margins.left},${margins.top})`
277
+ }, /*#__PURE__*/React__default.createElement(Axis, {
278
+ position: "bottom",
279
+ length: width - 32,
280
+ scale: scaleLinear().domain([]).range([0, chartWidth]),
281
+ x: 0,
282
+ y: height,
283
+ tickValues: 4
284
+ })))));
285
+ });
286
+
287
+ var definition = "Linear Scatter Plot with {circleLength} circles.";
288
+ var enUS = {
289
+ "interactive-chart": "Interactive Scatter Plot",
290
+ "static-chart": "Static Scatter Plot",
291
+ definition: definition,
292
+ "definition-with-categories": "Linear Scatter Plot with {categoryLength} categories and {circleLength} circles.",
293
+ "x-axis-definition": "The chart has {numAxis, plural, =0 {0 X axis} =1 {1 X axis} other {# X axes}} displaying numbers from {start, number} to {end, number}.",
294
+ "y-axis-definition": "The chart has {numAxis, plural, =0 {0 Y axis} =1 {1 Y axis} other {# Y axes}} displaying numbers from {start, number} to {end, number}."
295
+ };
296
+
297
+ var frFR = {
298
+ "interactive-chart": "Graphique en courbe interactif",
299
+ "static-chart": "Graphique en courbe statique",
300
+ "definition-linear": "Graphique en courbe contenant {circleLength} points répartis sur un axe linéraire.",
301
+ "definition-linear-with-categories": "Graphique en courbe contenant {categoryLength} courbes et {circleLength} points répartis sur un axe linéraire.",
302
+ "definition-ordinal": "Graphique en courbe contenant {circleLength} points.",
303
+ "x-axis-numbers-definition": "Le graphique a {numAxis, plural, =0 {0 axe X} =1 {1 axe X} other {# axes X}} affichant des nombres allant de {start, number} à {end, number}.",
304
+ "y-axis-numbers-definition": "Le graphique a {numAxis, plural, =0 {0 axe Y} =1 {1 axe Y} other {# axes Y}} affichant des nombres allant de {start, number} à {end, number}.",
305
+ "x-axis-dates-definition": "Le graphique a {numAxis, plural, =0 {0 axe X} =1 {1 axe X} other {# axes X}} affichant des dates allant de {start, date, ::yyyyMMdd} à {end, date, ::yyyyMMdd}.",
306
+ "y-axis-dates-definition": "Le graphique a {numAxis, plural, =0 {0 axe Y} =1 {1 axe Y} other {# axes Y}} affichant des dates allant de {start, date, ::yyyyMMdd} à {end, date, ::yyyyMMdd}.",
307
+ "x-axis-categories-definition": "Le graphique a {numAxis, plural, =0 {0 axe X} =1 {1 axe X} other {# axes X}} affichant des categories.",
308
+ "y-axis-categories-definition": "Le graphique a {numAxis, plural, =0 {0 axe Y} =1 {1 axe Y} other {# axes Y}} affichant des categories.",
309
+ "series-legend": "{category}, courbe {categoryIndex} sur {categoryLength} contenant {circleLength} points"
310
+ };
311
+
312
+ var intlMessages = {
313
+ 'en-US': enUS,
314
+ 'fr-FR': frFR
315
+ };
316
+
317
+ const mdiChevronDown = 'M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z';
318
+
319
+ const mdiChevronRight = 'M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z';
320
+
321
+ const mdiMouse = 'M11,1.07C7.05,1.56 4,4.92 4,9H11M4,15A8,8 0 0,0 12,23A8,8 0 0,0 20,15V11H4M13,1.07V9H20C20,4.92 16.94,1.56 13,1.07Z';
322
+
323
+ const _excluded$1 = ["isBrushable", "className", "data", "dotRole", "disableAnimations", "getDotAnchorProps", "hideControlKeyPanel", "id", "isDotSelected", "labelDecorator", "legendDecorator", "legendVariant", "legendProps", "margins", "onBrush", "onBrushEnd", "onDotClick", "size", "sortingMethod", "colorTheme", "tooltipDecorator", "tooltipVariant", "xAxisVariant", "xAxisPlacement", "xAxisTickFormat", "xAxisTickPadding", "xAxisTickRotation", "xAxisTickSize", "xAxisTickValues", "yAxisVariant", "yAxisPlacement", "yAxisTickFormat", "yAxisTickPadding", "yAxisTickRotation", "yAxisTickSize", "yAxisTickValues", "variant"],
324
+ _excluded2 = ["extraLegendItems"];
325
+ const RenderedScatterPlot = /*#__PURE__*/forwardRef((props, ref) => {
326
+ const {
327
+ isBrushable,
328
+ className,
329
+ data: propsData,
330
+ dotRole,
331
+ disableAnimations,
332
+ getDotAnchorProps,
333
+ hideControlKeyPanel,
334
+ id,
335
+ isDotSelected,
336
+ labelDecorator,
337
+ legendDecorator,
338
+ legendVariant,
339
+ legendProps,
340
+ margins: propsMargins,
341
+ onBrush,
342
+ onBrushEnd,
343
+ onDotClick,
344
+ size,
345
+ sortingMethod,
346
+ colorTheme,
347
+ tooltipDecorator,
348
+ tooltipVariant,
349
+ xAxisVariant,
350
+ xAxisPlacement,
351
+ xAxisTickFormat,
352
+ xAxisTickPadding,
353
+ xAxisTickRotation,
354
+ xAxisTickSize,
355
+ xAxisTickValues,
356
+ yAxisVariant,
357
+ yAxisPlacement,
358
+ yAxisTickFormat,
359
+ yAxisTickPadding,
360
+ yAxisTickRotation,
361
+ yAxisTickSize,
362
+ yAxisTickValues,
363
+ variant
364
+ } = props,
365
+ forwardedProps = _objectWithoutProperties(props, _excluded$1);
366
+ const cache = useRef();
367
+ const theme = useTheme();
368
+ const format = useMessageFormatter(intlMessages);
369
+ const data = propsData.filter(datum => datum.value && typeof datum.key[0] === 'number' && !Number.isNaN(datum.key[0]) && typeof datum.key[1] === 'number' && !Number.isNaN(datum.key[1]));
370
+ useEffect(() => {
371
+ cache.current = data;
372
+ });
373
+ const chartDimensions = sizeToDimension(size);
374
+ const width = chartDimensions.width;
375
+ const height = chartDimensions.height;
376
+ const margins = _objectSpread2({
377
+ top: xAxisVariant === AxisVariant.default || xAxisVariant === AxisVariant.tickValue ? 24 : 8,
378
+ left: yAxisVariant === AxisVariant.default || yAxisVariant === AxisVariant.tickValue ? 48 : 8,
379
+ right: yAxisVariant === AxisVariant.default || yAxisVariant === AxisVariant.tickValue ? 48 : 8,
380
+ bottom: xAxisVariant === AxisVariant.default || xAxisVariant === AxisVariant.tickValue ? 24 : 8
381
+ }, propsMargins);
382
+ const chartHeight = height - margins.top - margins.bottom;
383
+ const chartWidth = width - margins.left - margins.right;
384
+ const minSize = min([chartWidth, chartHeight]);
385
+ const extendedScaleX = (() => {
386
+ const domain = extent(data, d => d.key[0]);
387
+ const gap = domain[1] - domain[0];
388
+ domain[0] -= gap * 0.1;
389
+ domain[1] += gap * 0.1;
390
+ return scaleLinear().domain(domain).range([0, chartWidth]).nice();
391
+ })();
392
+ const extendedScaleY = (() => {
393
+ const domain = extent(data, d => d.key[1]);
394
+ const gap = domain[1] - domain[0];
395
+ domain[0] -= gap * 0.1;
396
+ domain[1] += gap * 0.1;
397
+ return scaleLinear().domain(domain).range([chartHeight, 0]).nice();
398
+ })();
399
+ const hasCategory = data[0] && data[0].key.length >= 3 && data[0].key[2] !== null && data[0].key[2] !== undefined;
400
+ const countsByCategory = hasCategory ? countBy(data, sortingMethod) : undefined;
401
+ const colorScale = useColor({
402
+ data: countsByCategory || data,
403
+ colorTheme: colorTheme,
404
+ category: 'key',
405
+ theme
406
+ });
407
+ const svgRef = useRef();
408
+ const brushRef = useRef();
409
+ const svgBrushRef = useRef();
410
+ const {
411
+ scaleX,
412
+ scaleY,
413
+ transform
414
+ } = useZoom({
415
+ svgRef,
416
+ scaleX: extendedScaleX,
417
+ scaleY: extendedScaleY,
418
+ size,
419
+ onZoom: () => {
420
+ if (brushRef.current && svgBrushRef.current) {
421
+ brushRef.current.clear(select(svgBrushRef.current));
422
+ onBrushEnd === null || onBrushEnd === void 0 ? void 0 : onBrushEnd(null);
423
+ }
424
+ }
425
+ });
426
+ useBrush({
427
+ brushRef,
428
+ svgRef: svgBrushRef,
429
+ extent: [[0, 0], [chartWidth, chartHeight]],
430
+ scaleX,
431
+ scaleY,
432
+ isBrushable,
433
+ isGridded: variant === ScatterPlotVariant.gridded,
434
+ onBrush,
435
+ onBrushEnd
436
+ });
437
+ const circles = variant === ScatterPlotVariant.gridded ? group(data, scaleX, scaleY).sort((a, b) => {
438
+ if (a.y !== b.y) {
439
+ return b.y - a.y;
440
+ }
441
+ if (a.x !== b.x) {
442
+ return a.x - b.x;
443
+ }
444
+ return descending(a.points.length, b.points.length);
445
+ }) : data.map(d => {
446
+ var _d$key$;
447
+ return {
448
+ category: (_d$key$ = d.key[2]) !== null && _d$key$ !== void 0 ? _d$key$ : 'default',
449
+ x: d.key[0],
450
+ y: d.key[1],
451
+ data: {
452
+ key: d.key,
453
+ value: 1
454
+ },
455
+ points: [d]
456
+ };
457
+ });
458
+ const globalSize = variant === ScatterPlotVariant.gridded ? scaleSqrt().domain([1, Math.max(max(circles, d => d.points.length), 1)]).range([3, minSize / BASE_NUMBER_OF_TICKS / 2]) : undefined;
459
+ const legendWidth = useRef();
460
+ if (countsByCategory && !legendWidth.current) {
461
+ legendWidth.current = `${Math.max(...countsByCategory.map(d => d.key.length + String(d.value).length)) * 8 + 32}px`;
462
+ }
463
+ const [isKeyPanelOpen, setIsKeyPanelOpen] = useState(false);
464
+ const categories = [];
465
+ // const pivotedTable = circles.reduce((acc, item) => {
466
+ // const { x, category, y } = item;
467
+ // if (!categories.includes(category)) {
468
+ // categories.push(category);
469
+ // }
470
+ // const formattedKey = xAxisTickFormat ? xAxisTickFormat(x as any) : x.toString();
471
+
472
+ // let entry = acc.find((e) => e.key === formattedKey);
473
+ // if (!entry) {
474
+ // entry = { key: formattedKey };
475
+ // acc.push(entry);
476
+ // }
477
+
478
+ // entry[category] = y;
479
+
480
+ // return acc;
481
+ // }, [] as Array<Record<string, string | number | null | undefined> & { key: string }>);
482
+
483
+ const _ref = legendProps || {},
484
+ {
485
+ extraLegendItems
486
+ } = _ref,
487
+ forwardedLegendProps = _objectWithoutProperties(_ref, _excluded2);
488
+ return /*#__PURE__*/React__default.createElement(StyledScatterPlot, _extends({
489
+ mode: typeof onDotClick === 'function' || typeof getDotAnchorProps === 'function' ? 'interactive' : 'static',
490
+ definition: hasCategory ? format('definition-with-categories', {
491
+ categoryLength: categories.length,
492
+ circleLength: circles.length
493
+ }) : format('definition', {
494
+ circleLength: circles.length
495
+ }),
496
+ xAxisDefinition: format('x-axis-definition', {
497
+ numAxis: xAxisPlacement === 'both' ? 2 : 1,
498
+ start: scaleX.domain()[0],
499
+ end: scaleX.domain()[1]
500
+ }),
501
+ yAxisDefinition: format('y-axis-definition', {
502
+ numAxis: yAxisPlacement === 'both' ? 2 : 1,
503
+ start: scaleY.domain()[0],
504
+ end: scaleY.domain()[1]
505
+ })
506
+ }, forwardedProps, {
507
+ id: id,
508
+ className: className,
509
+ ref: ref
510
+ }), /*#__PURE__*/React__default.createElement(Flexbox, {
511
+ flexDirection: "column",
512
+ alignItems: "center",
513
+ gap: "8"
514
+ }, !hideControlKeyPanel ? /*#__PURE__*/React__default.createElement(Flexbox, {
515
+ width: width,
516
+ position: "absolute"
517
+ }, /*#__PURE__*/React__default.createElement(Flexbox, {
518
+ flexDirection: "column",
519
+ alignItems: "flex-end",
520
+ position: "absolute",
521
+ top: `${margins.top + 16}px`,
522
+ right: `${margins.right + 16}px`
523
+ }, /*#__PURE__*/React__default.createElement(Popover, {
524
+ placement: "bottom-end",
525
+ isOpen: isKeyPanelOpen,
526
+ onOpen: setIsKeyPanelOpen
527
+ }, /*#__PURE__*/React__default.createElement(Popover.Trigger, null, /*#__PURE__*/React__default.createElement(Button, {
528
+ variant: "secondary",
529
+ leftIcon: mdiMouse,
530
+ rightIcon: isKeyPanelOpen ? mdiChevronDown : mdiChevronRight,
531
+ color: "grey",
532
+ style: {
533
+ border: '1px solid var(--redsift-color-neutral-mid-grey)',
534
+ gap: '4px'
535
+ }
536
+ })), /*#__PURE__*/React__default.createElement(Popover.Content, null, /*#__PURE__*/React__default.createElement(Flexbox, {
537
+ flexDirection: "column",
538
+ alignItems: "flex-start"
539
+ }, /*#__PURE__*/React__default.createElement(Text, {
540
+ margin: "8px 16px 0",
541
+ fontSize: "13px"
542
+ }, "Zoom - Mouse wheel"), /*#__PURE__*/React__default.createElement(Text, {
543
+ margin: "0 16px",
544
+ fontSize: "13px"
545
+ }, "Pan - Left click and drag"), /*#__PURE__*/React__default.createElement(Text, {
546
+ margin: "0 16px 8px",
547
+ fontSize: "13px"
548
+ }, "Select - Hold shift, left click and drag")))))) : null, /*#__PURE__*/React__default.createElement("svg", {
549
+ ref: svgRef,
550
+ width: width,
551
+ height: height
552
+ }, /*#__PURE__*/React__default.createElement("g", {
553
+ ref: svgBrushRef,
554
+ transform: `translate(${margins.left},${margins.top})`
555
+ }), /*#__PURE__*/React__default.createElement("g", {
556
+ transform: `translate(${margins.left},${margins.top})`
557
+ }, /*#__PURE__*/React__default.createElement("g", null, circles.map((circle, index) => {
558
+ var _countsByCategory$fin;
559
+ const scaleXDomain = scaleX.domain();
560
+ const scaleYDomain = scaleY.domain();
561
+ if (circle.x < scaleXDomain[0] || circle.x > scaleXDomain[1] || circle.y < scaleYDomain[0] || circle.y > scaleYDomain[1]) {
562
+ return null;
563
+ }
564
+ const to = _objectSpread2(_objectSpread2({}, circle), {}, {
565
+ data: _objectSpread2(_objectSpread2({}, circle.data), {}, {
566
+ percent: circle.category ? circle.data.value / (countsByCategory === null || countsByCategory === void 0 ? void 0 : (_countsByCategory$fin = countsByCategory.find(_ref2 => {
567
+ let {
568
+ key
569
+ } = _ref2;
570
+ return key === circle.category;
571
+ })) === null || _countsByCategory$fin === void 0 ? void 0 : _countsByCategory$fin.value) : undefined
572
+ }),
573
+ r: variant === ScatterPlotVariant.gridded ? globalSize(circle.points.length) / (transform.k < 1 ? transform.k : 1) : 4
574
+ });
575
+ return /*#__PURE__*/React__default.createElement(Dot, {
576
+ color: colorScale === null || colorScale === void 0 ? void 0 : colorScale(circle.category),
577
+ data: to,
578
+ dataset: circles,
579
+ isSelected: Boolean(isDotSelected === null || isDotSelected === void 0 ? void 0 : isDotSelected(to)),
580
+ key: `circle _${index}`,
581
+ labelDecorator: labelDecorator,
582
+ onClick: onDotClick,
583
+ role: dotRole,
584
+ scaleX: scaleX,
585
+ scaleY: scaleY,
586
+ tooltipDecorator: tooltipDecorator,
587
+ tooltipVariant: tooltipVariant
588
+ });
589
+ }))), /*#__PURE__*/React__default.createElement("g", {
590
+ transform: `translate(${margins.left},${margins.top})`
591
+ }, ['bottom', 'both'].includes(xAxisPlacement) ? /*#__PURE__*/React__default.createElement(Axis, {
592
+ disableAnimations: disableAnimations,
593
+ position: "bottom",
594
+ length: chartWidth,
595
+ scale: scaleX,
596
+ x: 0,
597
+ y: chartHeight,
598
+ tickValues: xAxisTickValues !== null && xAxisTickValues !== void 0 ? xAxisTickValues : 8,
599
+ tickPadding: xAxisTickPadding,
600
+ tickRotation: xAxisTickRotation,
601
+ tickSize: xAxisTickSize,
602
+ tickFormat: xAxisTickFormat,
603
+ variant: xAxisVariant
604
+ }) : null, ['top', 'both'].includes(xAxisPlacement) ? /*#__PURE__*/React__default.createElement(Axis, {
605
+ disableAnimations: disableAnimations,
606
+ position: "top",
607
+ length: chartWidth,
608
+ scale: scaleX,
609
+ x: 0,
610
+ y: 0,
611
+ tickValues: xAxisTickValues !== null && xAxisTickValues !== void 0 ? xAxisTickValues : 8,
612
+ tickPadding: xAxisTickPadding,
613
+ tickRotation: xAxisTickRotation,
614
+ tickSize: xAxisTickSize,
615
+ tickFormat: xAxisTickFormat,
616
+ variant: xAxisVariant
617
+ }) : null, ['left', 'both'].includes(yAxisPlacement) ? /*#__PURE__*/React__default.createElement(Axis, {
618
+ disableAnimations: disableAnimations,
619
+ position: "left",
620
+ length: chartHeight,
621
+ scale: scaleY,
622
+ x: 0,
623
+ y: chartHeight,
624
+ tickValues: yAxisTickValues !== null && yAxisTickValues !== void 0 ? yAxisTickValues : 8,
625
+ tickPadding: yAxisTickPadding,
626
+ tickRotation: yAxisTickRotation,
627
+ tickSize: yAxisTickSize,
628
+ tickFormat: yAxisTickFormat,
629
+ variant: yAxisVariant
630
+ }) : null, ['right', 'both'].includes(yAxisPlacement) ? /*#__PURE__*/React__default.createElement(Axis, {
631
+ disableAnimations: disableAnimations,
632
+ position: "right",
633
+ length: chartHeight,
634
+ scale: scaleY,
635
+ x: chartWidth,
636
+ y: chartHeight,
637
+ tickValues: yAxisTickValues !== null && yAxisTickValues !== void 0 ? yAxisTickValues : 8,
638
+ tickPadding: yAxisTickPadding,
639
+ tickRotation: yAxisTickRotation,
640
+ tickSize: yAxisTickSize,
641
+ tickFormat: yAxisTickFormat,
642
+ variant: yAxisVariant
643
+ }) : null))), hasCategory && legendVariant !== ScatterPlotLegendVariant.none ? /*#__PURE__*/React__default.createElement(Legend, _extends({
644
+ data: (extraLegendItems ? mergeLegends(extraLegendItems, countsByCategory).sort(getSortingMethod(sortingMethod)) : countsByCategory).map(d => _objectSpread2(_objectSpread2({}, d), {}, {
645
+ color: colorScale === null || colorScale === void 0 ? void 0 : colorScale(d.key)
646
+ })),
647
+ variant: legendVariant === ScatterPlotLegendVariant.externalLabelValue ? LegendVariant.value : legendVariant === ScatterPlotLegendVariant.externalLabelPercent ? LegendVariant.percent : legendVariant === ScatterPlotLegendVariant.externalLabel ? LegendVariant.label : LegendVariant.custom,
648
+ width: legendWidth.current,
649
+ legendDecorator: legendDecorator ? (datum, props) => legendDecorator(datum, props) : undefined
650
+ }, forwardedLegendProps)) : null);
651
+ });
652
+
653
+ const _excluded = ["className", "colorTheme", "data", "dotRole", "emptyComponent", "hideControlKeyPanel", "id", "isDotSelected", "labelDecorator", "legendDecorator", "legendVariant", "localeText", "onBrush", "onBrushEnd", "onDotClick", "size", "sortingMethod", "tooltipDecorator", "tooltipVariant", "variant", "xAxisPlacement", "xAxisVariant", "yAxisPlacement", "yAxisVariant"];
654
+ const COMPONENT_NAME = 'ScatterPlot';
655
+ const CLASSNAME = 'redsift-scatterplot';
656
+ const ScatterPlot = /*#__PURE__*/forwardRef((props, ref) => {
657
+ const {
658
+ className,
659
+ colorTheme = ColorTheme.default,
660
+ data: propsData,
661
+ dotRole,
662
+ emptyComponent,
663
+ hideControlKeyPanel = false,
664
+ id: propsId,
665
+ isDotSelected,
666
+ labelDecorator,
667
+ legendDecorator,
668
+ legendVariant: propsLegendVariant,
669
+ localeText = {
670
+ emptyChartText: 'No Data'
671
+ },
672
+ onBrush,
673
+ onBrushEnd,
674
+ onDotClick,
675
+ size = ChartSize.medium,
676
+ sortingMethod = 'desc-value',
677
+ tooltipDecorator,
678
+ tooltipVariant = TooltipVariant.none,
679
+ variant = ScatterPlotVariant.default,
680
+ xAxisPlacement = 'bottom',
681
+ xAxisVariant = AxisVariant.default,
682
+ yAxisPlacement = 'left',
683
+ yAxisVariant = AxisVariant.default
684
+ } = props,
685
+ forwardedProps = _objectWithoutProperties(props, _excluded);
686
+ const [_id] = useId();
687
+ const id = propsId !== null && propsId !== void 0 ? propsId : _id;
688
+ const legendVariant = propsLegendVariant !== null && propsLegendVariant !== void 0 ? propsLegendVariant : ScatterPlotLegendVariant.externalLabel;
689
+ if (propsData === undefined || propsData === null) {
690
+ return /*#__PURE__*/React__default.createElement(LoadingScatterPlot, _extends({
691
+ id: id
692
+ }, forwardedProps, {
693
+ ref: ref
694
+ }));
695
+ }
696
+ if (propsData.length === 0) {
697
+ return /*#__PURE__*/React__default.createElement(EmptyScatterPlot, _extends({
698
+ data: propsData,
699
+ emptyComponent: emptyComponent,
700
+ hideControlKeyPanel: hideControlKeyPanel,
701
+ localeText: localeText,
702
+ size: size,
703
+ sortingMethod: sortingMethod,
704
+ xAxisPlacement: xAxisPlacement,
705
+ xAxisVariant: xAxisVariant,
706
+ yAxisPlacement: yAxisPlacement,
707
+ yAxisVariant: yAxisVariant
708
+ }, forwardedProps, {
709
+ ref: ref
710
+ }));
711
+ }
712
+ return /*#__PURE__*/React__default.createElement(RenderedScatterPlot, _extends({
713
+ className: classNames(ScatterPlot.className, className),
714
+ colorTheme: colorTheme,
715
+ data: propsData,
716
+ dotRole: dotRole,
717
+ hideControlKeyPanel: hideControlKeyPanel,
718
+ id: id,
719
+ isDotSelected: isDotSelected,
720
+ labelDecorator: labelDecorator,
721
+ legendDecorator: legendDecorator,
722
+ legendVariant: legendVariant,
723
+ localeText: localeText,
724
+ onBrush: onBrush,
725
+ onBrushEnd: onBrushEnd,
726
+ onDotClick: onDotClick,
727
+ size: size,
728
+ sortingMethod: sortingMethod,
729
+ tooltipDecorator: tooltipDecorator,
730
+ tooltipVariant: tooltipVariant,
731
+ variant: variant,
732
+ xAxisPlacement: xAxisPlacement,
733
+ xAxisVariant: xAxisVariant,
734
+ yAxisPlacement: yAxisPlacement,
735
+ yAxisVariant: yAxisVariant
736
+ }, forwardedProps, {
737
+ ref: ref
738
+ }));
739
+ });
740
+ ScatterPlot.className = CLASSNAME;
741
+ ScatterPlot.displayName = COMPONENT_NAME;
742
+
743
+ export { ScatterPlot as S, useZoom as a, ScatterPlotVariant as b, ScatterPlotLegendVariant as c, StyledScatterPlot as d, StyledScatterPlotEmptyText as e, useBrush as u };
744
+ //# sourceMappingURL=ScatterPlot2.js.map