@cdc/chart 4.23.1 → 4.23.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdcchart.js +54532 -696
- package/examples/Barchart_with_negative.json +34 -0
- package/examples/box-plot.json +2 -2
- package/examples/dynamic-legends.json +1 -1
- package/examples/example-bar-chart-nonnumeric.json +36 -0
- package/examples/example-bar-chart.json +33 -0
- package/examples/example-combo-bar-nonnumeric.json +105 -0
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +1 -1
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +2 -2
- package/examples/gallery/paired-bar/paired-bar-chart.json +65 -13
- package/examples/line-chart-nonnumeric.json +32 -0
- package/examples/line-chart.json +21 -63
- package/examples/newdata.json +1 -1
- package/examples/planet-combo-example-config.json +143 -20
- package/examples/planet-example-data-nonnumeric.json +56 -0
- package/examples/planet-example-data.json +2 -2
- package/examples/planet-pie-example-config-nonnumeric.json +30 -0
- package/examples/scatterplot-continuous.csv +17 -0
- package/examples/scatterplot.json +136 -0
- package/examples/sparkline-chart-nonnumeric.json +76 -0
- package/examples/stacked-vertical-bar-example-negative.json +154 -0
- package/examples/stacked-vertical-bar-example-nonnumerics.json +154 -0
- package/index.html +74 -0
- package/package.json +29 -23
- package/src/{CdcChart.tsx → CdcChart.jsx} +74 -56
- package/src/components/{BarChart.tsx → BarChart.jsx} +99 -91
- package/src/components/BoxPlot.jsx +88 -0
- package/src/components/{DataTable.tsx → DataTable.jsx} +102 -25
- package/src/components/{EditorPanel.js → EditorPanel.jsx} +228 -14
- package/src/components/{Filters.js → Filters.jsx} +6 -12
- package/src/components/{Legend.js → Legend.jsx} +120 -108
- package/src/components/{LineChart.tsx → LineChart.jsx} +26 -12
- package/src/components/{LinearChart.tsx → LinearChart.jsx} +67 -47
- package/src/components/{PairedBarChart.tsx → PairedBarChart.jsx} +45 -78
- package/src/components/{PieChart.tsx → PieChart.jsx} +17 -32
- package/src/components/ScatterPlot.jsx +48 -0
- package/src/components/{SparkLine.js → SparkLine.jsx} +49 -18
- package/src/components/{useIntersectionObserver.tsx → useIntersectionObserver.jsx} +1 -1
- package/src/data/initial-state.js +33 -3
- package/src/hooks/{useColorPalette.ts → useColorPalette.js} +10 -28
- package/src/hooks/{useReduceData.ts → useReduceData.js} +25 -14
- package/src/hooks/useRightAxis.js +3 -1
- package/src/index.jsx +16 -0
- package/src/scss/DataTable.scss +22 -0
- package/src/scss/main.scss +30 -10
- package/vite.config.js +4 -0
- package/dist/495.js +0 -3
- package/dist/703.js +0 -1
- package/src/components/BoxPlot.js +0 -92
- package/src/index.html +0 -67
- package/src/index.tsx +0 -18
- /package/src/{context.tsx → ConfigContext.jsx} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useContext, useEffect } from 'react'
|
|
2
|
-
import
|
|
2
|
+
import ConfigContext from '../ConfigContext'
|
|
3
3
|
import parse from 'html-react-parser'
|
|
4
4
|
import { LegendOrdinal, LegendItem, LegendLabel } from '@visx/legend'
|
|
5
5
|
import LegendCircle from '@cdc/core/components/LegendCircle'
|
|
@@ -7,7 +7,7 @@ import LegendCircle from '@cdc/core/components/LegendCircle'
|
|
|
7
7
|
import useLegendClasses from './../hooks/useLegendClasses'
|
|
8
8
|
|
|
9
9
|
const Legend = () => {
|
|
10
|
-
const { config, legend, colorScale, seriesHighlight, highlight, highlightReset, setSeriesHighlight, dynamicLegendItems, setDynamicLegendItems, transformedData: data,
|
|
10
|
+
const { config, legend, colorScale, seriesHighlight, highlight, highlightReset, setSeriesHighlight, dynamicLegendItems, setDynamicLegendItems, transformedData: data, colorPalettes, rawData, setConfig, currentViewport } = useContext(ConfigContext)
|
|
11
11
|
|
|
12
12
|
const { innerClasses, containerClasses } = useLegendClasses(config)
|
|
13
13
|
|
|
@@ -106,11 +106,18 @@ const Legend = () => {
|
|
|
106
106
|
|
|
107
107
|
return uniqeLabels
|
|
108
108
|
}
|
|
109
|
+
// in small screens update config legend position.
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
if (currentViewport === 'sm' || currentViewport === 'xs' || config.legend.position === 'left') {
|
|
112
|
+
setConfig({ ...config, legend: { ...config.legend, position: 'bottom' } })
|
|
113
|
+
}
|
|
114
|
+
setConfig({ ...config, legend: { ...config.legend, position: 'right' } })
|
|
115
|
+
}, [currentViewport])
|
|
109
116
|
|
|
110
117
|
if (!legend) return
|
|
111
118
|
|
|
112
119
|
if (!legend.dynamicLegend)
|
|
113
|
-
return (
|
|
120
|
+
return config.visualizationType !== 'Box Plot' ? (
|
|
114
121
|
<aside
|
|
115
122
|
style={{ marginTop: config.legend.position === 'bottom' && config.orientation === 'horizontal' ? `${config.runtime.xAxis.size}px` : '0px', marginBottom: config.legend.position === 'bottom' ? '15px' : '0px' }}
|
|
116
123
|
id='legend'
|
|
@@ -172,119 +179,124 @@ const Legend = () => {
|
|
|
172
179
|
)}
|
|
173
180
|
</LegendOrdinal>
|
|
174
181
|
</aside>
|
|
182
|
+
) : (
|
|
183
|
+
<aside id='legend' className={containerClasses.join(' ')} role='region' aria-label='legend' tabIndex={0}>
|
|
184
|
+
{config.boxplot.legend.displayHowToReadText && <h3>{config.boxplot.legend.howToReadText}</h3>}
|
|
185
|
+
</aside>
|
|
175
186
|
)
|
|
176
|
-
|
|
177
187
|
return (
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
{
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
<
|
|
192
|
-
{config.legend.dynamicLegendDefaultText}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (seriesHighlight.length > 0 && false === seriesHighlight.includes(itemName)) {
|
|
210
|
-
className += ' inactive'
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
dynamicLegendItems.map(listItem => {
|
|
214
|
-
if (listItem.text === label.text) {
|
|
215
|
-
inDynamicList = true
|
|
188
|
+
config.visualizationType !== 'Box Plot' && (
|
|
189
|
+
<aside id='legend' className={containerClasses.join(' ')} role='region' aria-label='legend' tabIndex={0}>
|
|
190
|
+
{legend.label && <h2>{parse(legend.label)}</h2>}
|
|
191
|
+
{legend.description && <p>{parse(legend.description)}</p>}
|
|
192
|
+
|
|
193
|
+
<LegendOrdinal scale={colorScale} itemDirection='row' labelMargin='0 20px 0 0' shapeMargin='0 10px 0'>
|
|
194
|
+
{labels => {
|
|
195
|
+
if (
|
|
196
|
+
Number(config.legend.dynamicLegendItemLimit) > dynamicLegendItems.length && // legend items are less than limit
|
|
197
|
+
dynamicLegendItems.length !== config.runtime.seriesLabelsAll.length
|
|
198
|
+
) {
|
|
199
|
+
// legend items are equal to series length
|
|
200
|
+
return (
|
|
201
|
+
<select className='dynamic-legend-dropdown' onChange={e => handleDynamicLegendChange(e)}>
|
|
202
|
+
<option className={'all'} tabIndex={0} value={JSON.stringify({ text: config.legend.dynamicLegendDefaultText })}>
|
|
203
|
+
{config.legend.dynamicLegendDefaultText}
|
|
204
|
+
</option>
|
|
205
|
+
{labels.map((label, i) => {
|
|
206
|
+
let className = 'legend-item'
|
|
207
|
+
let itemName = label.datum
|
|
208
|
+
let inDynamicList = false
|
|
209
|
+
|
|
210
|
+
// Filter excluded data keys from legend
|
|
211
|
+
if (config.exclusions.active && config.exclusions.keys?.includes(itemName)) {
|
|
212
|
+
return
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (config.runtime.seriesLabels) {
|
|
216
|
+
let index = config.runtime.seriesLabelsAll.indexOf(itemName)
|
|
217
|
+
itemName = config.runtime.seriesKeys[index]
|
|
216
218
|
}
|
|
217
|
-
})
|
|
218
219
|
|
|
219
|
-
|
|
220
|
-
|
|
220
|
+
if (seriesHighlight.length > 0 && false === seriesHighlight.includes(itemName)) {
|
|
221
|
+
className += ' inactive'
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
dynamicLegendItems.map(listItem => {
|
|
225
|
+
if (listItem.text === label.text) {
|
|
226
|
+
inDynamicList = true
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
if (inDynamicList) return true
|
|
231
|
+
let palette = colorPalettes[config.palette]
|
|
232
|
+
|
|
233
|
+
label.value = palette[dynamicLegendItems.length]
|
|
234
|
+
|
|
235
|
+
return (
|
|
236
|
+
<option className={className} tabIndex={0} value={JSON.stringify(label)}>
|
|
237
|
+
{label.text}
|
|
238
|
+
</option>
|
|
239
|
+
)
|
|
240
|
+
})}
|
|
241
|
+
</select>
|
|
242
|
+
)
|
|
243
|
+
} else {
|
|
244
|
+
return config.legend.dynamicLegendItemLimitMessage
|
|
245
|
+
}
|
|
246
|
+
}}
|
|
247
|
+
</LegendOrdinal>
|
|
248
|
+
|
|
249
|
+
<div className='dynamic-legend-list'>
|
|
250
|
+
{dynamicLegendItems.map((label, i) => {
|
|
251
|
+
let className = ['legend-item']
|
|
252
|
+
let itemName = label.text
|
|
253
|
+
let palette = colorPalettes[config.palette]
|
|
254
|
+
|
|
255
|
+
// Filter excluded data keys from legend
|
|
256
|
+
if (config.exclusions.active && config.exclusions.keys?.includes(itemName)) {
|
|
257
|
+
return
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (config.runtime.seriesLabels && !config.legend.dynamicLegend) {
|
|
261
|
+
let index = config.runtime.seriesLabelsAll.indexOf(itemName)
|
|
262
|
+
itemName = config.runtime.seriesKeys[index]
|
|
263
|
+
}
|
|
221
264
|
|
|
222
|
-
|
|
265
|
+
if (seriesHighlight.length > 0 && !seriesHighlight.includes(itemName)) {
|
|
266
|
+
className.push('inactive')
|
|
267
|
+
}
|
|
223
268
|
|
|
224
|
-
|
|
225
|
-
|
|
269
|
+
if (seriesHighlight.length === 0 && config.legend.dynamicLegend) {
|
|
270
|
+
className.push('inactive')
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<>
|
|
275
|
+
<LegendItem className={className.join(' ')} tabIndex={0} key={`dynamic-legend-item-${i}`} alignItems='center'>
|
|
276
|
+
<button
|
|
277
|
+
className='btn-wrapper'
|
|
278
|
+
onClick={() => {
|
|
279
|
+
highlight(label)
|
|
280
|
+
}}
|
|
281
|
+
>
|
|
282
|
+
<LegendCircle fill={palette[i]} config={config} />
|
|
283
|
+
<LegendLabel align='space-between' margin='4px 0 0 4px'>
|
|
226
284
|
{label.text}
|
|
227
|
-
</
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
285
|
+
</LegendLabel>
|
|
286
|
+
</button>
|
|
287
|
+
<button onClick={() => removeDynamicLegendItem(label)}>x</button>
|
|
288
|
+
</LegendItem>
|
|
289
|
+
</>
|
|
231
290
|
)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
let itemName = label.text
|
|
242
|
-
let palette = colorPalettes[config.palette]
|
|
243
|
-
|
|
244
|
-
// Filter excluded data keys from legend
|
|
245
|
-
if (config.exclusions.active && config.exclusions.keys?.includes(itemName)) {
|
|
246
|
-
return
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
if (config.runtime.seriesLabels && !config.legend.dynamicLegend) {
|
|
250
|
-
let index = config.runtime.seriesLabelsAll.indexOf(itemName)
|
|
251
|
-
itemName = config.runtime.seriesKeys[index]
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
if (seriesHighlight.length > 0 && !seriesHighlight.includes(itemName)) {
|
|
255
|
-
className.push('inactive')
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
if (seriesHighlight.length === 0 && config.legend.dynamicLegend) {
|
|
259
|
-
className.push('inactive')
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return (
|
|
263
|
-
<>
|
|
264
|
-
<LegendItem className={className.join(' ')} tabIndex={0} key={`dynamic-legend-item-${i}`} alignItems='center'>
|
|
265
|
-
<button
|
|
266
|
-
className='btn-wrapper'
|
|
267
|
-
onClick={() => {
|
|
268
|
-
highlight(label)
|
|
269
|
-
}}
|
|
270
|
-
>
|
|
271
|
-
<LegendCircle fill={palette[i]} config={config} />
|
|
272
|
-
<LegendLabel align='space-between' margin='4px 0 0 4px'>
|
|
273
|
-
{label.text}
|
|
274
|
-
</LegendLabel>
|
|
275
|
-
</button>
|
|
276
|
-
<button onClick={() => removeDynamicLegendItem(label)}>x</button>
|
|
277
|
-
</LegendItem>
|
|
278
|
-
</>
|
|
279
|
-
)
|
|
280
|
-
})}
|
|
281
|
-
</div>
|
|
282
|
-
{seriesHighlight.length < dynamicLegendItems.length && (
|
|
283
|
-
<button className={`legend-reset legend-reset--dynamic ${config.theme}`} onClick={highlightReset} tabIndex={0}>
|
|
284
|
-
Reset
|
|
285
|
-
</button>
|
|
286
|
-
)}
|
|
287
|
-
</aside>
|
|
291
|
+
})}
|
|
292
|
+
</div>
|
|
293
|
+
{seriesHighlight.length < dynamicLegendItems.length && (
|
|
294
|
+
<button className={`legend-reset legend-reset--dynamic ${config.theme}`} onClick={highlightReset} tabIndex={0}>
|
|
295
|
+
Reset
|
|
296
|
+
</button>
|
|
297
|
+
)}
|
|
298
|
+
</aside>
|
|
299
|
+
)
|
|
288
300
|
)
|
|
289
301
|
}
|
|
290
302
|
|
|
@@ -7,12 +7,15 @@ import { Text } from '@visx/text'
|
|
|
7
7
|
|
|
8
8
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
9
9
|
|
|
10
|
-
import
|
|
10
|
+
import ConfigContext from '../ConfigContext'
|
|
11
11
|
|
|
12
12
|
import useRightAxis from '../hooks/useRightAxis'
|
|
13
13
|
|
|
14
14
|
export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData, xMax, yMax, seriesStyle = 'Line' }) {
|
|
15
|
-
const { colorPalettes, transformedData: data, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, updateConfig } = useContext
|
|
15
|
+
const { colorPalettes, transformedData: data, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, isNumber, cleanData, updateConfig } = useContext(ConfigContext)
|
|
16
|
+
// Just do this once up front otherwise we end up
|
|
17
|
+
// calling clean several times on same set of data (TT)
|
|
18
|
+
const cleanedData = cleanData(data, config.xAxis.dataKey)
|
|
16
19
|
const { yScaleRight } = useRightAxis({ config, yMax, data, updateConfig })
|
|
17
20
|
|
|
18
21
|
const handleLineType = lineType => {
|
|
@@ -29,6 +32,9 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
const handleAxisFormating = (axis = 'left', label, value) => {
|
|
35
|
+
// if this is an x axis category/date value return without doing any formatting.
|
|
36
|
+
if (label === config.runtime.xAxis.label) return value
|
|
37
|
+
|
|
32
38
|
axis = String(axis).toLocaleLowerCase()
|
|
33
39
|
if (label) {
|
|
34
40
|
return `${label}: ${formatNumber(value, axis)}`
|
|
@@ -38,7 +44,9 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
38
44
|
|
|
39
45
|
return (
|
|
40
46
|
<ErrorBoundary component='LineChart'>
|
|
41
|
-
<Group left={config.runtime.yAxis.size}>
|
|
47
|
+
<Group left={config.runtime.yAxis.size ? parseInt(config.runtime.yAxis.size) : 66}>
|
|
48
|
+
{' '}
|
|
49
|
+
{/* left - expects a number not a string */}
|
|
42
50
|
{(config.runtime.lineSeriesKeys || config.runtime.seriesKeys).map((seriesKey, index) => {
|
|
43
51
|
let lineType = config.series.filter(item => item.dataKey === seriesKey)[0].type
|
|
44
52
|
const seriesData = config.series.filter(item => item.dataKey === seriesKey)
|
|
@@ -50,7 +58,7 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
50
58
|
opacity={config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(seriesKey) === -1 ? 0.5 : 1}
|
|
51
59
|
display={config.legend.behavior === 'highlight' || (seriesHighlight.length === 0 && !config.legend.dynamicLegend) || seriesHighlight.indexOf(seriesKey) !== -1 ? 'block' : 'none'}
|
|
52
60
|
>
|
|
53
|
-
{
|
|
61
|
+
{cleanedData.map((d, dataIndex) => {
|
|
54
62
|
// Find the series object from the config.series array that has a dataKey matching the seriesKey variable.
|
|
55
63
|
const series = config.series.find(({ dataKey }) => dataKey === seriesKey)
|
|
56
64
|
const { axis } = series
|
|
@@ -73,11 +81,18 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
73
81
|
${xAxisTooltip}
|
|
74
82
|
</div>`
|
|
75
83
|
let circleRadii = 4.5
|
|
84
|
+
|
|
76
85
|
return (
|
|
77
86
|
d[seriesKey] !== undefined &&
|
|
78
87
|
d[seriesKey] !== '' &&
|
|
79
88
|
d[seriesKey] !== null && (
|
|
89
|
+
// isNumber(d[seriesKey]) &&
|
|
90
|
+
// isNumber(getYAxisData(d, seriesKey)) &&
|
|
91
|
+
// isNumber(getXAxisData(d)) &&
|
|
92
|
+
// isNumber(yScaleRight(getXAxisData(d))) &&
|
|
93
|
+
// isNumber(yScale(getXAxisData(d))) &&
|
|
80
94
|
<Group key={`series-${seriesKey}-point-${dataIndex}`}>
|
|
95
|
+
{/* Render legend */}
|
|
81
96
|
<Text
|
|
82
97
|
display={config.labels ? 'block' : 'none'}
|
|
83
98
|
x={xScale(getXAxisData(d))}
|
|
@@ -91,12 +106,12 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
91
106
|
<circle
|
|
92
107
|
key={`${seriesKey}-${dataIndex}`}
|
|
93
108
|
r={circleRadii}
|
|
94
|
-
cx={xScale(getXAxisData(d))}
|
|
109
|
+
cx={Number(xScale(getXAxisData(d)))}
|
|
95
110
|
cy={seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey))}
|
|
96
111
|
fill={colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[seriesKey] : seriesKey) : '#000'}
|
|
97
112
|
style={{ fill: colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[seriesKey] : seriesKey) : '#000' }}
|
|
98
|
-
data-
|
|
99
|
-
data-
|
|
113
|
+
data-tooltip-html={tooltip}
|
|
114
|
+
data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
100
115
|
/>
|
|
101
116
|
</Group>
|
|
102
117
|
)
|
|
@@ -105,7 +120,7 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
105
120
|
|
|
106
121
|
<LinePath
|
|
107
122
|
curve={allCurves.curveLinear}
|
|
108
|
-
data={
|
|
123
|
+
data={cleanedData}
|
|
109
124
|
x={d => xScale(getXAxisData(d))}
|
|
110
125
|
y={d => (seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey)))}
|
|
111
126
|
stroke={
|
|
@@ -122,14 +137,14 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
122
137
|
shapeRendering='geometricPrecision'
|
|
123
138
|
strokeDasharray={lineType ? handleLineType(lineType) : 0}
|
|
124
139
|
defined={(item, i) => {
|
|
125
|
-
return item[config.runtime.seriesLabels[seriesKey]] !== '' && item[config.runtime.seriesLabels[seriesKey]] !== null
|
|
140
|
+
return item[config.runtime.seriesLabels[seriesKey]] !== '' && item[config.runtime.seriesLabels[seriesKey]] !== null && item[config.runtime.seriesLabels[seriesKey]] !== undefined
|
|
126
141
|
}}
|
|
127
142
|
/>
|
|
128
143
|
{config.animate && (
|
|
129
144
|
<LinePath
|
|
130
145
|
className='animation'
|
|
131
146
|
curve={allCurves.curveLinear}
|
|
132
|
-
data={
|
|
147
|
+
data={cleanedData}
|
|
133
148
|
x={d => xScale(getXAxisData(d))}
|
|
134
149
|
y={d => (seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey)))}
|
|
135
150
|
stroke='#fff'
|
|
@@ -138,7 +153,7 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
138
153
|
shapeRendering='geometricPrecision'
|
|
139
154
|
strokeDasharray={lineType ? handleLineType(lineType) : 0}
|
|
140
155
|
defined={(item, i) => {
|
|
141
|
-
return item[config.runtime.seriesLabels[seriesKey]]
|
|
156
|
+
return isNumber(item[config.runtime.seriesLabels[seriesKey]])
|
|
142
157
|
}}
|
|
143
158
|
/>
|
|
144
159
|
)}
|
|
@@ -165,7 +180,6 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
165
180
|
</Group>
|
|
166
181
|
)
|
|
167
182
|
})}
|
|
168
|
-
|
|
169
183
|
{/* Message when dynamic legend and nothing has been picked */}
|
|
170
184
|
{config.legend.dynamicLegend && seriesHighlight.length === 0 && (
|
|
171
185
|
<Text x={xMax / 2} y={yMax / 2} fill='black' textAnchor='middle' color='black'>
|