@cdc/chart 4.23.1 → 4.23.3
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 +56289 -702
- package/examples/Barchart_with_negative.json +34 -0
- package/examples/area-chart.json +187 -0
- package/examples/big-small-test-bar.json +328 -0
- package/examples/big-small-test-line.json +328 -0
- package/examples/big-small-test-negative.json +328 -0
- package/examples/box-plot.json +1 -2
- package/examples/dynamic-legends.json +1 -1
- package/examples/example-bar-chart-nonnumeric.json +36 -0
- package/examples/example-bar-chart.json +36 -0
- package/examples/example-combo-bar-nonnumeric.json +105 -0
- package/examples/example-sparkline.json +76 -0
- package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +31 -172
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +1 -1
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json +1 -0
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +96 -14
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +2 -2
- package/examples/gallery/line/line.json +1 -0
- package/examples/gallery/paired-bar/paired-bar-chart.json +65 -13
- package/examples/horizontal-chart-max-increase.json +38 -0
- package/examples/line-chart-max-increase.json +32 -0
- 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-deviation-config.json +168 -0
- package/examples/planet-deviation-data.json +38 -0
- package/examples/planet-example-config.json +139 -20
- package/examples/planet-example-data-max-increase.json +56 -0
- package/examples/planet-example-data-nonnumeric.json +56 -0
- package/examples/planet-example-data.json +9 -9
- 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 +91 -0
- package/package.json +33 -24
- package/src/{CdcChart.tsx → CdcChart.jsx} +196 -124
- package/src/components/AreaChart.jsx +198 -0
- package/src/components/{BarChart.tsx → BarChart.jsx} +154 -122
- package/src/components/BoxPlot.jsx +101 -0
- package/src/components/{DataTable.tsx → DataTable.jsx} +109 -28
- package/src/components/DeviationBar.jsx +191 -0
- package/src/components/{EditorPanel.js → EditorPanel.jsx} +676 -157
- package/src/components/{Filters.js → Filters.jsx} +6 -11
- package/src/components/Legend.jsx +316 -0
- package/src/components/{LineChart.tsx → LineChart.jsx} +22 -26
- package/src/components/{LinearChart.tsx → LinearChart.jsx} +214 -91
- package/src/components/{PairedBarChart.tsx → PairedBarChart.jsx} +44 -78
- package/src/components/{PieChart.tsx → PieChart.jsx} +26 -44
- package/src/components/ScatterPlot.jsx +51 -0
- package/src/components/SparkLine.jsx +218 -0
- package/src/components/{useIntersectionObserver.tsx → useIntersectionObserver.jsx} +2 -2
- package/src/data/initial-state.js +51 -5
- package/src/hooks/useColorPalette.js +68 -0
- package/src/hooks/{useReduceData.ts → useReduceData.js} +26 -16
- package/src/hooks/useRightAxis.js +3 -1
- package/src/index.jsx +16 -0
- package/src/scss/DataTable.scss +22 -0
- package/src/scss/editor-panel.scss +5 -0
- package/src/scss/main.scss +30 -10
- package/src/test/CdcChart.test.jsx +6 -0
- 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/components/Legend.js +0 -291
- package/src/components/SparkLine.js +0 -185
- package/src/hooks/useColorPalette.ts +0 -76
- package/src/index.html +0 -67
- package/src/index.tsx +0 -18
- /package/src/{context.tsx → ConfigContext.jsx} +0 -0
|
@@ -1,46 +1,52 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import ReactTooltip from 'react-tooltip'
|
|
1
|
+
import React, { useContext, useEffect, useRef, useState } from 'react'
|
|
2
|
+
import { Tooltip as ReactTooltip } from 'react-tooltip'
|
|
3
3
|
|
|
4
4
|
import { Group } from '@visx/group'
|
|
5
5
|
import { Line } from '@visx/shape'
|
|
6
6
|
import { Text } from '@visx/text'
|
|
7
|
-
import { scaleLinear, scalePoint, scaleBand } from '@visx/scale'
|
|
7
|
+
import { scaleLinear, scalePoint, scaleBand, scaleTime } from '@visx/scale'
|
|
8
8
|
import { AxisLeft, AxisBottom, AxisRight, AxisTop } from '@visx/axis'
|
|
9
9
|
|
|
10
|
+
import CoveScatterPlot from './ScatterPlot'
|
|
10
11
|
import BarChart from './BarChart'
|
|
11
12
|
import LineChart from './LineChart'
|
|
12
|
-
import
|
|
13
|
+
import ConfigContext from '../ConfigContext'
|
|
13
14
|
import PairedBarChart from './PairedBarChart'
|
|
14
15
|
import useIntersectionObserver from './useIntersectionObserver'
|
|
15
16
|
import CoveBoxPlot from './BoxPlot'
|
|
17
|
+
import CoveAreaChart from './AreaChart'
|
|
16
18
|
|
|
17
19
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
18
20
|
import '../scss/LinearChart.scss'
|
|
19
21
|
import useReduceData from '../hooks/useReduceData'
|
|
20
22
|
import useRightAxis from '../hooks/useRightAxis'
|
|
21
23
|
import useTopAxis from '../hooks/useTopAxis'
|
|
24
|
+
import { DeviationBar } from './DeviationBar'
|
|
22
25
|
|
|
23
26
|
// TODO: Move scaling functions into hooks to manage complexity
|
|
24
27
|
export default function LinearChart() {
|
|
25
|
-
const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig } = useContext
|
|
28
|
+
const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig, stringFormattingOptions } = useContext(ConfigContext)
|
|
29
|
+
|
|
26
30
|
let [width] = dimensions
|
|
27
31
|
const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, data)
|
|
28
|
-
const [animatedChart, setAnimatedChart] = useState
|
|
32
|
+
const [animatedChart, setAnimatedChart] = useState(false)
|
|
29
33
|
|
|
30
34
|
const triggerRef = useRef()
|
|
31
35
|
const dataRef = useIntersectionObserver(triggerRef, {
|
|
32
36
|
freezeOnceVisible: false
|
|
33
37
|
})
|
|
38
|
+
|
|
34
39
|
// Make sure the chart is visible if in the editor
|
|
40
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
35
41
|
useEffect(() => {
|
|
36
42
|
const element = document.querySelector('.isEditor')
|
|
37
43
|
if (element) {
|
|
38
44
|
// parent element is visible
|
|
39
45
|
setAnimatedChart(prevState => true)
|
|
40
46
|
}
|
|
41
|
-
})
|
|
47
|
+
}) /* eslint-disable-line */
|
|
42
48
|
|
|
43
|
-
// If the chart is in view
|
|
49
|
+
// If the chart is in view, set to animate if it has not already played
|
|
44
50
|
useEffect(() => {
|
|
45
51
|
if (dataRef?.isIntersecting === true && config.animate) {
|
|
46
52
|
setTimeout(() => {
|
|
@@ -54,14 +60,14 @@ export default function LinearChart() {
|
|
|
54
60
|
}
|
|
55
61
|
const { horizontal: heightHorizontal } = config.heights
|
|
56
62
|
const height = config.aspectRatio ? width * config.aspectRatio : config.heights[config.orientation]
|
|
57
|
-
const xMax = width - config.runtime.yAxis.size - config.yAxis.rightAxisSize
|
|
63
|
+
const xMax = width - config.runtime.yAxis.size - (config.visualizationType === 'Combo' ? config.yAxis.rightAxisSize : 0)
|
|
58
64
|
const yMax = height - (config.orientation === 'horizontal' ? 0 : config.runtime.xAxis.size)
|
|
59
65
|
|
|
60
66
|
const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data, updateConfig })
|
|
61
67
|
const { hasTopAxis } = useTopAxis(config)
|
|
62
68
|
|
|
63
|
-
const getXAxisData =
|
|
64
|
-
const getYAxisData = (d
|
|
69
|
+
const getXAxisData = d => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
|
|
70
|
+
const getYAxisData = (d, seriesKey) => d[seriesKey]
|
|
65
71
|
|
|
66
72
|
let xScale
|
|
67
73
|
let yScale
|
|
@@ -71,11 +77,37 @@ export default function LinearChart() {
|
|
|
71
77
|
const isMaxValid = existPositiveValue ? enteredMaxValue >= maxValue : enteredMaxValue >= 0
|
|
72
78
|
const isMinValid = (enteredMinValue <= 0 && minValue >= 0) || (enteredMinValue <= minValue && minValue < 0)
|
|
73
79
|
|
|
80
|
+
let max = 0 // need outside the if statement
|
|
81
|
+
let min = 0
|
|
74
82
|
if (data) {
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
min = enteredMinValue && isMinValid ? enteredMinValue : minValue
|
|
84
|
+
max = enteredMaxValue && isMaxValid ? enteredMaxValue : Number.MIN_VALUE
|
|
85
|
+
|
|
86
|
+
// DEV-3263 - If Confidence Intervals in data, then need to account for increased height in max for YScale
|
|
87
|
+
if (config.visualizationType === 'Bar' || config.visualizationType === 'Combo' || config.visualizationType === 'Deviation Bar') {
|
|
88
|
+
let ciYMax = 0
|
|
89
|
+
if (config.hasOwnProperty('confidenceKeys')) {
|
|
90
|
+
let upperCIValues = data.map(function (d) {
|
|
91
|
+
return d[config.confidenceKeys.upper]
|
|
92
|
+
})
|
|
93
|
+
ciYMax = Math.max.apply(Math, upperCIValues)
|
|
94
|
+
if (ciYMax > max) max = ciYMax // bump up the max
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// DEV-3263 - If Confidence Intervals in data, then need to account for increased height in max for YScale
|
|
99
|
+
if (config.visualizationType === 'Bar' || config.visualizationType === 'Combo') {
|
|
100
|
+
let ciYMax = 0
|
|
101
|
+
if (config.hasOwnProperty('confidenceKeys')) {
|
|
102
|
+
let upperCIValues = data.map(function (d) {
|
|
103
|
+
return d[config.confidenceKeys.upper]
|
|
104
|
+
})
|
|
105
|
+
ciYMax = Math.max.apply(Math, upperCIValues)
|
|
106
|
+
if (ciYMax > max) max = ciYMax // bump up the max
|
|
107
|
+
}
|
|
108
|
+
}
|
|
77
109
|
|
|
78
|
-
if ((config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && min > 0) {
|
|
110
|
+
if ((config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && min > 0) {
|
|
79
111
|
min = 0
|
|
80
112
|
}
|
|
81
113
|
if (config.visualizationType === 'Combo' && isAllLine) {
|
|
@@ -118,23 +150,36 @@ export default function LinearChart() {
|
|
|
118
150
|
case maxDataVal > 4 && maxDataVal <= 7:
|
|
119
151
|
max = max * 1.1
|
|
120
152
|
break
|
|
153
|
+
default:
|
|
154
|
+
break
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// DEV-3219 - bc some values are going above YScale - adding 10% or 20% factor onto Max
|
|
159
|
+
// - put the statement up here and it works for both vert and horiz charts of all types
|
|
160
|
+
if (config.yAxis.enablePadding) {
|
|
161
|
+
if (min < 0) {
|
|
162
|
+
// sets with negative data need more padding on the max
|
|
163
|
+
max *= 1.2
|
|
164
|
+
} else {
|
|
165
|
+
max *= 1.1
|
|
121
166
|
}
|
|
122
167
|
}
|
|
123
168
|
|
|
124
169
|
if (config.runtime.horizontal) {
|
|
125
|
-
xScale = scaleLinear
|
|
170
|
+
xScale = scaleLinear({
|
|
126
171
|
domain: [min, max],
|
|
127
172
|
range: [0, xMax]
|
|
128
173
|
})
|
|
129
174
|
|
|
130
175
|
yScale =
|
|
131
176
|
config.runtime.xAxis.type === 'date'
|
|
132
|
-
? scaleLinear
|
|
177
|
+
? scaleLinear({
|
|
133
178
|
domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)]
|
|
134
179
|
})
|
|
135
|
-
: scalePoint
|
|
180
|
+
: scalePoint({ domain: xAxisDataMapped, padding: 0.5 })
|
|
136
181
|
|
|
137
|
-
seriesScale = scalePoint
|
|
182
|
+
seriesScale = scalePoint({
|
|
138
183
|
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
139
184
|
range: [0, yMax]
|
|
140
185
|
})
|
|
@@ -143,24 +188,32 @@ export default function LinearChart() {
|
|
|
143
188
|
} else {
|
|
144
189
|
min = min < 0 ? min * 1.11 : min
|
|
145
190
|
|
|
146
|
-
yScale = scaleLinear
|
|
191
|
+
yScale = scaleLinear({
|
|
147
192
|
domain: [min, max],
|
|
148
193
|
range: [yMax, 0]
|
|
149
194
|
})
|
|
150
195
|
|
|
151
|
-
xScale = scalePoint
|
|
196
|
+
xScale = scalePoint({
|
|
152
197
|
domain: xAxisDataMapped,
|
|
153
198
|
range: [0, xMax],
|
|
154
199
|
padding: 0.5
|
|
155
200
|
})
|
|
156
201
|
|
|
157
|
-
seriesScale = scalePoint
|
|
202
|
+
seriesScale = scalePoint({
|
|
158
203
|
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
159
204
|
range: [0, xMax]
|
|
160
205
|
})
|
|
161
206
|
}
|
|
162
207
|
|
|
208
|
+
if (config.visualizationType === 'Area Chart' && config.xAxis.type === 'date') {
|
|
209
|
+
xScale = scaleTime({
|
|
210
|
+
domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)],
|
|
211
|
+
range: [0, xMax]
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
|
|
163
215
|
if (config.visualizationType === 'Paired Bar') {
|
|
216
|
+
const offset = 1.02 // Offset of the ticks/values from the Axis
|
|
164
217
|
let groupOneMax = Math.max.apply(
|
|
165
218
|
Math,
|
|
166
219
|
data.map(d => d[config.series[0].dataKey])
|
|
@@ -171,15 +224,74 @@ export default function LinearChart() {
|
|
|
171
224
|
)
|
|
172
225
|
|
|
173
226
|
// group one
|
|
174
|
-
var g1xScale = scaleLinear
|
|
175
|
-
domain: [0, Math.max(groupOneMax, groupTwoMax)],
|
|
227
|
+
var g1xScale = scaleLinear({
|
|
228
|
+
domain: [0, Math.max(groupOneMax, groupTwoMax) * offset],
|
|
176
229
|
range: [xMax / 2, 0]
|
|
177
230
|
})
|
|
178
231
|
|
|
179
232
|
// group 2
|
|
180
|
-
var g2xScale = scaleLinear
|
|
233
|
+
var g2xScale = scaleLinear({
|
|
181
234
|
domain: g1xScale.domain(),
|
|
182
|
-
range: [xMax / 2, xMax]
|
|
235
|
+
range: [xMax / 2, xMax],
|
|
236
|
+
nice: true
|
|
237
|
+
})
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (config.visualizationType === 'Scatter Plot') {
|
|
241
|
+
if (config.xAxis.type === 'continuous') {
|
|
242
|
+
xScale = scaleLinear({
|
|
243
|
+
domain: [0, Math.max.apply(null, xScale.domain())],
|
|
244
|
+
range: [0, xMax]
|
|
245
|
+
})
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (config.visualizationType === 'Deviation Bar') {
|
|
250
|
+
const leftOffset = config.isLollipopChart ? 1.05 : 1.03
|
|
251
|
+
yScale = scaleBand({
|
|
252
|
+
domain: xAxisDataMapped,
|
|
253
|
+
range: [0, yMax]
|
|
254
|
+
})
|
|
255
|
+
xScale = scaleLinear({
|
|
256
|
+
domain: [min * leftOffset, Math.max(Number(config.xAxis.target), max)],
|
|
257
|
+
range: [0, xMax],
|
|
258
|
+
round: true
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
// Handle Box Plots
|
|
262
|
+
if (config.visualizationType === 'Box Plot') {
|
|
263
|
+
const allOutliers = []
|
|
264
|
+
const hasOutliers = config.boxplot.plots.map(b => b.columnOutliers.map(outlier => allOutliers.push(outlier))) && !config.boxplot.hideOutliers
|
|
265
|
+
|
|
266
|
+
// check if outliers are lower
|
|
267
|
+
if (hasOutliers) {
|
|
268
|
+
let outlierMin = Math.min(...allOutliers)
|
|
269
|
+
let outlierMax = Math.max(...allOutliers)
|
|
270
|
+
|
|
271
|
+
// check if outliers exceed standard bounds
|
|
272
|
+
if (outlierMin < min) min = outlierMin
|
|
273
|
+
if (outlierMax > max) max = outlierMax
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// check fences for max/min
|
|
277
|
+
let lowestFence = Math.min(...config.boxplot.plots.map(item => item.columnMin))
|
|
278
|
+
let highestFence = Math.max(...config.boxplot.plots.map(item => item.columnMax))
|
|
279
|
+
|
|
280
|
+
if (lowestFence < min) min = lowestFence
|
|
281
|
+
if (highestFence > max) max = highestFence
|
|
282
|
+
|
|
283
|
+
// Set Scales
|
|
284
|
+
yScale = scaleLinear({
|
|
285
|
+
range: [yMax, 0],
|
|
286
|
+
round: true,
|
|
287
|
+
domain: [min, max]
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
xScale = scaleBand({
|
|
291
|
+
range: [0, xMax],
|
|
292
|
+
round: true,
|
|
293
|
+
domain: config.boxplot.categories,
|
|
294
|
+
padding: 0.4
|
|
183
295
|
})
|
|
184
296
|
}
|
|
185
297
|
}
|
|
@@ -192,7 +304,8 @@ export default function LinearChart() {
|
|
|
192
304
|
|
|
193
305
|
const handleBottomTickFormatting = tick => {
|
|
194
306
|
if (config.runtime.xAxis.type === 'date') return formatDate(tick)
|
|
195
|
-
if (config.orientation === 'horizontal') return formatNumber(tick, '
|
|
307
|
+
if (config.orientation === 'horizontal') return formatNumber(tick, 'left')
|
|
308
|
+
if (config.xAxis.type === 'continuous') return formatNumber(tick, 'bottom')
|
|
196
309
|
return tick
|
|
197
310
|
}
|
|
198
311
|
|
|
@@ -204,57 +317,36 @@ export default function LinearChart() {
|
|
|
204
317
|
|
|
205
318
|
if (axis === 'yAxis') {
|
|
206
319
|
tickCount = isHorizontal && !numTicks ? data.length : isHorizontal && numTicks ? numTicks : !isHorizontal && !numTicks ? undefined : !isHorizontal && numTicks && numTicks
|
|
320
|
+
// to fix edge case of small numbers with decimals
|
|
321
|
+
if (tickCount === undefined && !config.dataFormat.roundTo) {
|
|
322
|
+
// then it is set to Auto
|
|
323
|
+
if (Number(max) <= 3) {
|
|
324
|
+
tickCount = 2
|
|
325
|
+
} else {
|
|
326
|
+
tickCount = 4 // same default as standalone components
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (Number(tickCount) > Number(max)) {
|
|
330
|
+
// cap it and round it so its an integer
|
|
331
|
+
tickCount = Number(min) < 0 ? Math.round(max) * 2 : Math.round(max)
|
|
332
|
+
}
|
|
207
333
|
}
|
|
208
334
|
|
|
209
335
|
if (axis === 'xAxis') {
|
|
210
336
|
tickCount = isHorizontal && !numTicks ? undefined : isHorizontal && numTicks ? numTicks : !isHorizontal && !numTicks ? undefined : !isHorizontal && numTicks && numTicks
|
|
337
|
+
if (isHorizontal && tickCount === undefined && !config.dataFormat.roundTo) {
|
|
338
|
+
// then it is set to Auto
|
|
339
|
+
// - check for small numbers situation
|
|
340
|
+
if (max <= 3) {
|
|
341
|
+
tickCount = 2
|
|
342
|
+
} else {
|
|
343
|
+
tickCount = 4 // same default as standalone components
|
|
344
|
+
}
|
|
345
|
+
}
|
|
211
346
|
}
|
|
212
347
|
return tickCount
|
|
213
348
|
}
|
|
214
349
|
|
|
215
|
-
// Handle Box Plots
|
|
216
|
-
if (config.visualizationType === 'Box Plot') {
|
|
217
|
-
let minYValue
|
|
218
|
-
let maxYValue
|
|
219
|
-
let allOutliers = []
|
|
220
|
-
let allLowerBounds = config.boxplot.map(plot => plot.columnMin)
|
|
221
|
-
let allUpperBounds = config.boxplot.map(plot => plot.columnMax)
|
|
222
|
-
|
|
223
|
-
minYValue = Math.min(...allLowerBounds)
|
|
224
|
-
maxYValue = Math.max(...allUpperBounds)
|
|
225
|
-
|
|
226
|
-
const hasOutliers = config.boxplot.map(b => b.columnOutliers.map(outlier => allOutliers.push(outlier)))
|
|
227
|
-
|
|
228
|
-
if (hasOutliers) {
|
|
229
|
-
let outlierMin = Math.min(...allOutliers)
|
|
230
|
-
let outlierMax = Math.max(...allOutliers)
|
|
231
|
-
|
|
232
|
-
// check if outliers exceed standard bounds
|
|
233
|
-
if (outlierMin < minYValue) minYValue = outlierMin
|
|
234
|
-
if (outlierMax > maxYValue) maxYValue = outlierMax
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const seriesNames = data.map(d => d[config.xAxis.dataKey])
|
|
238
|
-
|
|
239
|
-
// Set Scales
|
|
240
|
-
yScale = scaleLinear({
|
|
241
|
-
range: [yMax, 0],
|
|
242
|
-
round: true,
|
|
243
|
-
domain: [minYValue, maxYValue]
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
xScale = scaleBand({
|
|
247
|
-
range: [0, xMax],
|
|
248
|
-
round: true,
|
|
249
|
-
domain: config.boxplot.categories,
|
|
250
|
-
padding: 0.4
|
|
251
|
-
})
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
useEffect(() => {
|
|
255
|
-
ReactTooltip.rebuild()
|
|
256
|
-
})
|
|
257
|
-
|
|
258
350
|
return isNaN(width) ? (
|
|
259
351
|
<></>
|
|
260
352
|
) : (
|
|
@@ -265,9 +357,24 @@ export default function LinearChart() {
|
|
|
265
357
|
? config.regions.map(region => {
|
|
266
358
|
if (!Object.keys(region).includes('from') || !Object.keys(region).includes('to')) return null
|
|
267
359
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
360
|
+
let from
|
|
361
|
+
let to
|
|
362
|
+
let width
|
|
363
|
+
|
|
364
|
+
if (config.xAxis.type === 'date') {
|
|
365
|
+
from = xScale(parseDate(region.from).getTime())
|
|
366
|
+
to = xScale(parseDate(region.to).getTime())
|
|
367
|
+
width = to - from
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (config.xAxis.type === 'categorical') {
|
|
371
|
+
from = xScale(region.from)
|
|
372
|
+
to = xScale(region.to)
|
|
373
|
+
width = to - from
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (!from) return null
|
|
377
|
+
if (!to) return null
|
|
271
378
|
|
|
272
379
|
return (
|
|
273
380
|
<Group className='regions' left={Number(config.runtime.yAxis.size)} key={region.label}>
|
|
@@ -291,7 +398,7 @@ export default function LinearChart() {
|
|
|
291
398
|
|
|
292
399
|
{/* Y axis */}
|
|
293
400
|
{config.visualizationType !== 'Spark Line' && (
|
|
294
|
-
<AxisLeft scale={yScale} left={Number(config.runtime.yAxis.size)} label={config.runtime.yAxis.label} stroke='#333' tickFormat={tick => handleLeftTickFormatting(tick)} numTicks={countNumOfTicks('yAxis')}>
|
|
401
|
+
<AxisLeft scale={yScale} left={Number(config.runtime.yAxis.size) - config.yAxis.axisPadding} label={config.runtime.yAxis.label} stroke='#333' tickFormat={tick => handleLeftTickFormatting(tick)} numTicks={countNumOfTicks('yAxis')}>
|
|
295
402
|
{props => {
|
|
296
403
|
const axisCenter = config.runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
|
|
297
404
|
const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
|
|
@@ -324,15 +431,13 @@ export default function LinearChart() {
|
|
|
324
431
|
)}
|
|
325
432
|
|
|
326
433
|
{config.orientation === 'horizontal' && config.visualizationType === 'Paired Bar' && !config.yAxis.hideLabel && (
|
|
327
|
-
<Text transform={`translate(${-
|
|
434
|
+
<Text transform={`translate(${tick.to.x - 5}, ${tick.to.y - minY + Number(config.barHeight) / 2}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} textAnchor={'end'} verticalAnchor='middle'>
|
|
328
435
|
{tick.formattedValue}
|
|
329
436
|
</Text>
|
|
330
437
|
)}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
<Text transform={`translate(${-15}, ${tick.from.y}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} verticalAnchor={config.isLollipopChart ? 'middle' : 'middle'} textAnchor={'end'}>
|
|
335
|
-
{formatNumber(tick.formattedValue)}
|
|
438
|
+
{config.orientation === 'horizontal' && config.visualizationType === 'Deviation Bar' && !config.yAxis.hideLabel && (
|
|
439
|
+
<Text transform={`translate(${tick.to.x - 5}, ${config.isLollipopChart ? tick.to.y - minY + 2 : tick.to.y - minY + Number(config.barHeight) / 2}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} textAnchor={'end'} verticalAnchor='middle'>
|
|
440
|
+
{tick.formattedValue}
|
|
336
441
|
</Text>
|
|
337
442
|
)}
|
|
338
443
|
|
|
@@ -409,7 +514,16 @@ export default function LinearChart() {
|
|
|
409
514
|
|
|
410
515
|
{/* X axis */}
|
|
411
516
|
{config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Spark Line' && (
|
|
412
|
-
<AxisBottom
|
|
517
|
+
<AxisBottom
|
|
518
|
+
top={config.runtime.horizontal ? Number(heightHorizontal) + Number(config.xAxis.axisPadding) : yMax + Number(config.xAxis.axisPadding)}
|
|
519
|
+
left={Number(config.runtime.yAxis.size)}
|
|
520
|
+
label={config.runtime.xAxis.label}
|
|
521
|
+
tickFormat={handleBottomTickFormatting}
|
|
522
|
+
scale={xScale}
|
|
523
|
+
stroke='#333'
|
|
524
|
+
tickStroke='#333'
|
|
525
|
+
numTicks={countNumOfTicks('xAxis')}
|
|
526
|
+
>
|
|
413
527
|
{props => {
|
|
414
528
|
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
|
|
415
529
|
return (
|
|
@@ -447,16 +561,16 @@ export default function LinearChart() {
|
|
|
447
561
|
<>
|
|
448
562
|
<AxisBottom top={yMax} left={Number(config.runtime.yAxis.size)} label={config.runtime.xAxis.label} tickFormat={config.runtime.xAxis.type === 'date' ? formatDate : formatNumber} scale={g1xScale} stroke='#333' tickStroke='#333' numTicks={config.runtime.xAxis.numTicks || undefined}>
|
|
449
563
|
{props => {
|
|
450
|
-
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
|
|
451
564
|
return (
|
|
452
565
|
<Group className='bottom-axis'>
|
|
453
566
|
{props.ticks.map((tick, i) => {
|
|
454
|
-
const
|
|
567
|
+
const angle = tick.index !== 0 ? config.yAxis.tickRotation : 0
|
|
568
|
+
const textAnchor = tick.index !== 0 && config.yAxis.tickRotation && config.yAxis.tickRotation > 0 ? 'end' : 'middle'
|
|
455
569
|
return (
|
|
456
570
|
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
457
571
|
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
|
|
458
572
|
{!config.runtime.yAxis.hideLabel && (
|
|
459
|
-
<Text
|
|
573
|
+
<Text x={tick.to.x} y={tick.to.y} angle={-angle} verticalAnchor='start' textAnchor={textAnchor}>
|
|
460
574
|
{formatNumber(tick.formattedValue)}
|
|
461
575
|
</Text>
|
|
462
576
|
)}
|
|
@@ -479,17 +593,17 @@ export default function LinearChart() {
|
|
|
479
593
|
numTicks={config.runtime.xAxis.numTicks || undefined}
|
|
480
594
|
>
|
|
481
595
|
{props => {
|
|
482
|
-
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
|
|
483
596
|
return (
|
|
484
597
|
<>
|
|
485
598
|
<Group className='bottom-axis'>
|
|
486
599
|
{props.ticks.map((tick, i) => {
|
|
487
|
-
const
|
|
600
|
+
const angle = tick.index !== 0 ? config.yAxis.tickRotation : 0
|
|
601
|
+
const textAnchor = tick.index !== 0 && config.yAxis.tickRotation && config.yAxis.tickRotation > 0 ? 'end' : 'middle'
|
|
488
602
|
return (
|
|
489
603
|
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
490
604
|
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
|
|
491
605
|
{!config.runtime.yAxis.hideLabel && (
|
|
492
|
-
<Text
|
|
606
|
+
<Text x={tick.to.x} y={tick.to.y} angle={-angle} verticalAnchor='start' textAnchor={textAnchor}>
|
|
493
607
|
{tick.formattedValue}
|
|
494
608
|
</Text>
|
|
495
609
|
)}
|
|
@@ -499,7 +613,7 @@ export default function LinearChart() {
|
|
|
499
613
|
{!config.runtime.yAxis.hideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
|
|
500
614
|
</Group>
|
|
501
615
|
<Group>
|
|
502
|
-
<Text
|
|
616
|
+
<Text x={xMax / 2} y={config.xAxis.labelOffset} stroke='#333' textAnchor={'middle'} verticalAnchor='start'>
|
|
503
617
|
{config.runtime.xAxis.label}
|
|
504
618
|
</Text>
|
|
505
619
|
</Group>
|
|
@@ -509,25 +623,34 @@ export default function LinearChart() {
|
|
|
509
623
|
</AxisBottom>
|
|
510
624
|
</>
|
|
511
625
|
)}
|
|
512
|
-
|
|
626
|
+
|
|
627
|
+
{config.visualizationType === 'Deviation Bar' && <DeviationBar xScale={xScale} yScale={yScale} width={xMax} height={yMax} />}
|
|
628
|
+
|
|
629
|
+
{/* Paired Bar chart */}
|
|
630
|
+
{config.visualizationType === 'Paired Bar' && <PairedBarChart originalWidth={width} width={xMax} height={yMax} />}
|
|
513
631
|
|
|
514
632
|
{/* Bar chart */}
|
|
515
|
-
{config.visualizationType !== 'Line' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && (
|
|
633
|
+
{config.visualizationType !== 'Line' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Area Chart' && config.visualizationType !== 'Scatter Plot' && config.visualizationType !== 'Deviation Bar' && (
|
|
516
634
|
<>
|
|
517
635
|
<BarChart xScale={xScale} yScale={yScale} seriesScale={seriesScale} xMax={xMax} yMax={yMax} getXAxisData={getXAxisData} getYAxisData={getYAxisData} animatedChart={animatedChart} visible={animatedChart} />
|
|
518
636
|
</>
|
|
519
637
|
)}
|
|
520
638
|
|
|
521
639
|
{/* Line chart */}
|
|
522
|
-
{config.visualizationType !== 'Bar' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && (
|
|
640
|
+
{config.visualizationType !== 'Bar' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Area Chart' && config.visualizationType !== 'Scatter Plot' && config.visualizationType !== 'Deviation Bar' && (
|
|
523
641
|
<>
|
|
524
642
|
<LineChart xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} xMax={xMax} yMax={yMax} seriesStyle={config.series} />
|
|
525
643
|
</>
|
|
526
644
|
)}
|
|
527
645
|
|
|
646
|
+
{/* Scatter Plot chart */}
|
|
647
|
+
{config.visualizationType === 'Scatter Plot' && <CoveScatterPlot xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} />}
|
|
648
|
+
|
|
649
|
+
{/* Box Plot chart */}
|
|
528
650
|
{config.visualizationType === 'Box Plot' && <CoveBoxPlot xScale={xScale} yScale={yScale} />}
|
|
651
|
+
{config.visualizationType === 'Area Chart' && <CoveAreaChart xScale={xScale} yScale={yScale} yMax={yMax} xMax={xMax} />}
|
|
529
652
|
</svg>
|
|
530
|
-
<ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
653
|
+
<ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} variant='light' arrowColor='rgba(0,0,0,0)' className='tooltip' />
|
|
531
654
|
<div className='animation-trigger' ref={triggerRef} />
|
|
532
655
|
</ErrorBoundary>
|
|
533
656
|
)
|