@cdc/chart 4.22.11 → 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 +54569 -16
- package/examples/Barchart_with_negative.json +34 -0
- package/examples/box-plot-data.json +71 -0
- package/examples/box-plot.csv +5 -0
- package/examples/box-plot.json +124 -0
- 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/combo-line-chart.json +3 -1
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +1 -1
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +86 -17
- 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/new-data.csv +17 -0
- package/examples/newdata.json +90 -0
- 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/{private/yaxis-test.json → scatterplot.json} +53 -50
- 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/{src/index.html → index.html} +18 -11
- package/package.json +29 -22
- package/src/{CdcChart.tsx → CdcChart.jsx} +193 -119
- package/src/components/BarChart.jsx +517 -0
- package/src/components/BoxPlot.jsx +88 -0
- package/src/components/{DataTable.tsx → DataTable.jsx} +125 -32
- package/src/components/{EditorPanel.js → EditorPanel.jsx} +376 -115
- package/src/components/Filters.jsx +125 -0
- package/src/components/Legend.jsx +303 -0
- package/src/components/{LineChart.tsx → LineChart.jsx} +87 -22
- package/src/components/{LinearChart.tsx → LinearChart.jsx} +172 -113
- package/src/components/{PairedBarChart.tsx → PairedBarChart.jsx} +46 -79
- package/src/components/{PieChart.tsx → PieChart.jsx} +29 -34
- package/src/components/ScatterPlot.jsx +48 -0
- package/src/components/{SparkLine.js → SparkLine.jsx} +49 -18
- package/src/components/useIntersectionObserver.jsx +29 -0
- package/src/data/initial-state.js +44 -8
- package/src/hooks/{useColorPalette.ts → useColorPalette.js} +10 -28
- package/src/hooks/{useReduceData.ts → useReduceData.js} +27 -13
- package/src/hooks/useRightAxis.js +3 -1
- package/src/index.jsx +16 -0
- package/src/scss/DataTable.scss +23 -1
- package/src/scss/main.scss +83 -32
- package/vite.config.js +4 -0
- package/examples/private/filters.json +0 -170
- package/examples/private/line-test-data.json +0 -22
- package/examples/private/line-test-two.json +0 -210
- package/examples/private/line-test.json +0 -102
- package/examples/private/new.json +0 -48800
- package/examples/private/newtest.csv +0 -101
- package/examples/private/shawn.json +0 -1106
- package/examples/private/test.json +0 -10124
- package/examples/private/yaxis-testing.csv +0 -27
- package/examples/private/yaxis.json +0 -28
- package/src/components/BarChart.tsx +0 -579
- package/src/components/Legend.js +0 -284
- package/src/components/useIntersectionObserver.tsx +0 -27
- package/src/index.tsx +0 -18
- /package/src/{context.tsx → ConfigContext.jsx} +0 -0
|
@@ -1,43 +1,47 @@
|
|
|
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 } from '@visx/scale'
|
|
7
|
+
import { scaleLinear, scalePoint, scaleBand } 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
|
-
import
|
|
16
|
+
import CoveBoxPlot from './BoxPlot'
|
|
16
17
|
|
|
17
18
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
18
|
-
import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
19
19
|
import '../scss/LinearChart.scss'
|
|
20
20
|
import useReduceData from '../hooks/useReduceData'
|
|
21
21
|
import useRightAxis from '../hooks/useRightAxis'
|
|
22
22
|
import useTopAxis from '../hooks/useTopAxis'
|
|
23
23
|
|
|
24
24
|
// TODO: Move scaling functions into hooks to manage complexity
|
|
25
|
-
|
|
26
|
-
// TODO: remove unused imports/variables
|
|
27
|
-
// TODO: consider moving logic into hooks
|
|
28
|
-
// TODO: formatting
|
|
29
25
|
export default function LinearChart() {
|
|
30
|
-
const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig } = useContext
|
|
26
|
+
const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig } = useContext(ConfigContext)
|
|
31
27
|
let [width] = dimensions
|
|
32
|
-
const { minValue, maxValue, existPositiveValue } = useReduceData(config, data)
|
|
33
|
-
const [animatedChart, setAnimatedChart] = useState
|
|
34
|
-
const [animatedChartPlayed, setAnimatedChartPlayed] = useState<boolean>(false)
|
|
28
|
+
const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, data)
|
|
29
|
+
const [animatedChart, setAnimatedChart] = useState(false)
|
|
35
30
|
|
|
36
31
|
const triggerRef = useRef()
|
|
37
32
|
const dataRef = useIntersectionObserver(triggerRef, {
|
|
38
33
|
freezeOnceVisible: false
|
|
39
34
|
})
|
|
40
|
-
//
|
|
35
|
+
// Make sure the chart is visible if in the editor
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const element = document.querySelector('.isEditor')
|
|
38
|
+
if (element) {
|
|
39
|
+
// parent element is visible
|
|
40
|
+
setAnimatedChart(prevState => true)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// If the chart is in view, set to animate if it has not already played
|
|
41
45
|
useEffect(() => {
|
|
42
46
|
if (dataRef?.isIntersecting === true && config.animate) {
|
|
43
47
|
setTimeout(() => {
|
|
@@ -49,35 +53,45 @@ export default function LinearChart() {
|
|
|
49
53
|
if (config && config.legend && !config.legend.hide && config.legend.position !== 'bottom' && (currentViewport === 'lg' || currentViewport === 'md')) {
|
|
50
54
|
width = width * 0.73
|
|
51
55
|
}
|
|
52
|
-
|
|
53
|
-
const height = config.aspectRatio ? width * config.aspectRatio : config.
|
|
54
|
-
const xMax = width - config.runtime.yAxis.size - config.yAxis.rightAxisSize
|
|
55
|
-
const yMax = height - config.runtime.xAxis.size
|
|
56
|
+
const { horizontal: heightHorizontal } = config.heights
|
|
57
|
+
const height = config.aspectRatio ? width * config.aspectRatio : config.heights[config.orientation]
|
|
58
|
+
const xMax = width - config.runtime.yAxis.size - (config.visualizationType === 'Combo' ? config.yAxis.rightAxisSize : 0)
|
|
59
|
+
const yMax = height - (config.orientation === 'horizontal' ? 0 : config.runtime.xAxis.size)
|
|
56
60
|
|
|
57
61
|
const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data, updateConfig })
|
|
58
62
|
const { hasTopAxis } = useTopAxis(config)
|
|
59
63
|
|
|
60
|
-
const getXAxisData =
|
|
61
|
-
const getYAxisData = (d
|
|
64
|
+
const getXAxisData = d => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
|
|
65
|
+
const getYAxisData = (d, seriesKey) => d[seriesKey]
|
|
62
66
|
|
|
63
67
|
let xScale
|
|
64
68
|
let yScale
|
|
65
69
|
let seriesScale
|
|
66
70
|
|
|
67
71
|
const { max: enteredMaxValue, min: enteredMinValue } = config.runtime.yAxis
|
|
68
|
-
const isMaxValid = existPositiveValue ?
|
|
69
|
-
const isMinValid = (
|
|
72
|
+
const isMaxValid = existPositiveValue ? enteredMaxValue >= maxValue : enteredMaxValue >= 0
|
|
73
|
+
const isMinValid = (enteredMinValue <= 0 && minValue >= 0) || (enteredMinValue <= minValue && minValue < 0)
|
|
70
74
|
|
|
71
75
|
if (data) {
|
|
72
76
|
let min = enteredMinValue && isMinValid ? enteredMinValue : minValue
|
|
73
77
|
let max = enteredMaxValue && isMaxValid ? enteredMaxValue : Number.MIN_VALUE
|
|
74
78
|
|
|
75
|
-
if ((config.visualizationType === 'Bar' || config.visualizationType === 'Combo') && min > 0) {
|
|
79
|
+
if ((config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && min > 0) {
|
|
76
80
|
min = 0
|
|
77
81
|
}
|
|
82
|
+
if (config.visualizationType === 'Combo' && isAllLine) {
|
|
83
|
+
if ((enteredMinValue === undefined || enteredMinValue === null || enteredMinValue === '') && min > 0) {
|
|
84
|
+
min = 0
|
|
85
|
+
}
|
|
86
|
+
if (enteredMinValue) {
|
|
87
|
+
const isMinValid = +enteredMinValue < minValue
|
|
88
|
+
min = +enteredMinValue && isMinValid ? enteredMinValue : minValue
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
78
92
|
if (config.visualizationType === 'Line') {
|
|
79
|
-
const isMinValid =
|
|
80
|
-
min = enteredMinValue && isMinValid ?
|
|
93
|
+
const isMinValid = enteredMinValue < minValue
|
|
94
|
+
min = enteredMinValue && isMinValid ? enteredMinValue : minValue
|
|
81
95
|
}
|
|
82
96
|
//If data value max wasn't provided, calculate it
|
|
83
97
|
if (max === Number.MIN_VALUE) {
|
|
@@ -109,19 +123,19 @@ export default function LinearChart() {
|
|
|
109
123
|
}
|
|
110
124
|
|
|
111
125
|
if (config.runtime.horizontal) {
|
|
112
|
-
xScale = scaleLinear
|
|
126
|
+
xScale = scaleLinear({
|
|
113
127
|
domain: [min, max],
|
|
114
128
|
range: [0, xMax]
|
|
115
129
|
})
|
|
116
130
|
|
|
117
131
|
yScale =
|
|
118
132
|
config.runtime.xAxis.type === 'date'
|
|
119
|
-
? scaleLinear
|
|
133
|
+
? scaleLinear({
|
|
120
134
|
domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)]
|
|
121
135
|
})
|
|
122
|
-
: scalePoint
|
|
136
|
+
: scalePoint({ domain: xAxisDataMapped, padding: 0.5 })
|
|
123
137
|
|
|
124
|
-
seriesScale = scalePoint
|
|
138
|
+
seriesScale = scalePoint({
|
|
125
139
|
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
126
140
|
range: [0, yMax]
|
|
127
141
|
})
|
|
@@ -130,24 +144,25 @@ export default function LinearChart() {
|
|
|
130
144
|
} else {
|
|
131
145
|
min = min < 0 ? min * 1.11 : min
|
|
132
146
|
|
|
133
|
-
yScale = scaleLinear
|
|
147
|
+
yScale = scaleLinear({
|
|
134
148
|
domain: [min, max],
|
|
135
149
|
range: [yMax, 0]
|
|
136
150
|
})
|
|
137
151
|
|
|
138
|
-
xScale = scalePoint
|
|
152
|
+
xScale = scalePoint({
|
|
139
153
|
domain: xAxisDataMapped,
|
|
140
154
|
range: [0, xMax],
|
|
141
155
|
padding: 0.5
|
|
142
156
|
})
|
|
143
157
|
|
|
144
|
-
seriesScale = scalePoint
|
|
158
|
+
seriesScale = scalePoint({
|
|
145
159
|
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
146
160
|
range: [0, xMax]
|
|
147
161
|
})
|
|
148
162
|
}
|
|
149
163
|
|
|
150
164
|
if (config.visualizationType === 'Paired Bar') {
|
|
165
|
+
const offset = 1.02 // Offset of the ticks/values from the Axis
|
|
151
166
|
let groupOneMax = Math.max.apply(
|
|
152
167
|
Math,
|
|
153
168
|
data.map(d => d[config.series[0].dataKey])
|
|
@@ -158,49 +173,99 @@ export default function LinearChart() {
|
|
|
158
173
|
)
|
|
159
174
|
|
|
160
175
|
// group one
|
|
161
|
-
var g1xScale = scaleLinear
|
|
162
|
-
domain: [0, Math.max(groupOneMax, groupTwoMax)],
|
|
176
|
+
var g1xScale = scaleLinear({
|
|
177
|
+
domain: [0, Math.max(groupOneMax, groupTwoMax) * offset],
|
|
163
178
|
range: [xMax / 2, 0]
|
|
164
179
|
})
|
|
165
180
|
|
|
166
181
|
// group 2
|
|
167
|
-
var g2xScale = scaleLinear
|
|
182
|
+
var g2xScale = scaleLinear({
|
|
168
183
|
domain: g1xScale.domain(),
|
|
169
|
-
range: [xMax / 2, xMax]
|
|
184
|
+
range: [xMax / 2, xMax],
|
|
185
|
+
nice: true
|
|
170
186
|
})
|
|
171
187
|
}
|
|
188
|
+
|
|
189
|
+
if (config.visualizationType === 'Scatter Plot') {
|
|
190
|
+
if (config.xAxis.type === 'continuous') {
|
|
191
|
+
xScale = scaleLinear({
|
|
192
|
+
domain: [0, Math.max.apply(null, xScale.domain())],
|
|
193
|
+
range: [0, xMax]
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const handleLeftTickFormatting = tick => {
|
|
200
|
+
if (config.runtime.yAxis.type === 'date') return formatDate(parseDate(tick))
|
|
201
|
+
if (config.orientation === 'vertical') return formatNumber(tick, 'left')
|
|
202
|
+
return tick
|
|
172
203
|
}
|
|
173
204
|
|
|
174
|
-
|
|
175
|
-
|
|
205
|
+
const handleBottomTickFormatting = tick => {
|
|
206
|
+
if (config.runtime.xAxis.type === 'date') return formatDate(tick)
|
|
207
|
+
if (config.orientation === 'horizontal') return formatNumber(tick, 'bottom')
|
|
208
|
+
return tick
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const countNumOfTicks = axis => {
|
|
176
212
|
// function get number of ticks based on bar type & users value
|
|
177
|
-
const isHorizontal = config.orientation ==='horizontal'
|
|
178
|
-
const {numTicks} = config.runtime[axis]
|
|
179
|
-
let tickCount = undefined
|
|
180
|
-
|
|
181
|
-
if(axis === 'yAxis'){
|
|
182
|
-
tickCount = (
|
|
183
|
-
(isHorizontal && !numTicks) ? data.length
|
|
184
|
-
: (isHorizontal && numTicks) ? numTicks
|
|
185
|
-
:(!isHorizontal && !numTicks) ? undefined
|
|
186
|
-
:(!isHorizontal && numTicks) && numTicks
|
|
187
|
-
);
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
if(axis === 'xAxis'){
|
|
191
|
-
tickCount = (
|
|
192
|
-
(isHorizontal && !numTicks) ? undefined
|
|
193
|
-
: (isHorizontal && numTicks) ? numTicks
|
|
194
|
-
:(!isHorizontal && !numTicks) ? undefined
|
|
195
|
-
:(!isHorizontal && numTicks) && numTicks
|
|
196
|
-
);
|
|
197
|
-
};
|
|
198
|
-
return tickCount;
|
|
199
|
-
};
|
|
213
|
+
const isHorizontal = config.orientation === 'horizontal'
|
|
214
|
+
const { numTicks } = config.runtime[axis]
|
|
215
|
+
let tickCount = undefined
|
|
200
216
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
217
|
+
if (axis === 'yAxis') {
|
|
218
|
+
tickCount = isHorizontal && !numTicks ? data.length : isHorizontal && numTicks ? numTicks : !isHorizontal && !numTicks ? undefined : !isHorizontal && numTicks && numTicks
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (axis === 'xAxis') {
|
|
222
|
+
tickCount = isHorizontal && !numTicks ? undefined : isHorizontal && numTicks ? numTicks : !isHorizontal && !numTicks ? undefined : !isHorizontal && numTicks && numTicks
|
|
223
|
+
}
|
|
224
|
+
return tickCount
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Handle Box Plots
|
|
228
|
+
if (config.visualizationType === 'Box Plot') {
|
|
229
|
+
let minYValue
|
|
230
|
+
let maxYValue
|
|
231
|
+
let allOutliers = []
|
|
232
|
+
let allLowerBounds = config.boxplot.plots.map(plot => plot.columnMin)
|
|
233
|
+
let allUpperBounds = config.boxplot.plots.map(plot => plot.columnMax)
|
|
234
|
+
|
|
235
|
+
minYValue = Math.min(...allLowerBounds)
|
|
236
|
+
maxYValue = Math.max(...allUpperBounds)
|
|
237
|
+
|
|
238
|
+
const hasOutliers = config.boxplot.plots.map(b => b.columnOutliers.map(outlier => allOutliers.push(outlier))) && !config.boxplot.hideOutliers
|
|
239
|
+
|
|
240
|
+
if (hasOutliers) {
|
|
241
|
+
let outlierMin = Math.min(...allOutliers)
|
|
242
|
+
let outlierMax = Math.max(...allOutliers)
|
|
243
|
+
|
|
244
|
+
// check if outliers exceed standard bounds
|
|
245
|
+
if (outlierMin < minYValue) minYValue = outlierMin
|
|
246
|
+
if (outlierMax > maxYValue) maxYValue = outlierMax
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const seriesNames = data.map(d => d[config.xAxis.dataKey])
|
|
250
|
+
|
|
251
|
+
// Set Scales
|
|
252
|
+
yScale = scaleLinear({
|
|
253
|
+
range: [yMax, 0],
|
|
254
|
+
round: true,
|
|
255
|
+
domain: [minYValue, maxYValue]
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
xScale = scaleBand({
|
|
259
|
+
range: [0, xMax],
|
|
260
|
+
round: true,
|
|
261
|
+
domain: config.boxplot.categories,
|
|
262
|
+
padding: 0.4
|
|
263
|
+
})
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const handleTick = tick => {
|
|
267
|
+
return config.runtime.xAxis.type === 'date' ? formatDate(tick) : config.orientation === 'horizontal' ? formatNumber(tick) : tick
|
|
268
|
+
}
|
|
204
269
|
|
|
205
270
|
return isNaN(width) ? (
|
|
206
271
|
<></>
|
|
@@ -217,7 +282,7 @@ export default function LinearChart() {
|
|
|
217
282
|
const width = to - from
|
|
218
283
|
|
|
219
284
|
return (
|
|
220
|
-
<Group className='regions' left={config.runtime.yAxis.size} key={region.label}>
|
|
285
|
+
<Group className='regions' left={Number(config.runtime.yAxis.size)} key={region.label}>
|
|
221
286
|
<path
|
|
222
287
|
stroke='#333'
|
|
223
288
|
d={`M${from} -5
|
|
@@ -238,22 +303,16 @@ export default function LinearChart() {
|
|
|
238
303
|
|
|
239
304
|
{/* Y axis */}
|
|
240
305
|
{config.visualizationType !== 'Spark Line' && (
|
|
241
|
-
<AxisLeft
|
|
242
|
-
scale={yScale}
|
|
243
|
-
left={config.runtime.yAxis.size}
|
|
244
|
-
label={config.runtime.yAxis.label}
|
|
245
|
-
stroke='#333'
|
|
246
|
-
tickFormat={tick => (config.runtime.yAxis.type === 'date' ? formatDate(parseDate(tick)) : config.orientation === 'vertical' ? formatNumber(tick) : tick)}
|
|
247
|
-
numTicks={countNumOfTicks('yAxis')}
|
|
248
|
-
>
|
|
306
|
+
<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')}>
|
|
249
307
|
{props => {
|
|
250
|
-
const lollipopShapeSize = config.lollipopSize === 'large' ? 14 : config.lollipopSize === 'medium' ? 12 : 10
|
|
251
308
|
const axisCenter = config.runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
|
|
252
309
|
const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
|
|
253
|
-
const belowBarPaddingFromTop = 9
|
|
254
310
|
return (
|
|
255
311
|
<Group className='left-axis'>
|
|
256
312
|
{props.ticks.map((tick, i) => {
|
|
313
|
+
const minY = props.ticks[0].to.y
|
|
314
|
+
const barMinHeight = 15 // 15 is the min height for bars by default
|
|
315
|
+
|
|
257
316
|
return (
|
|
258
317
|
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
259
318
|
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke={config.yAxis.tickColor} display={config.runtime.horizontal ? 'none' : 'block'} />}
|
|
@@ -261,32 +320,24 @@ export default function LinearChart() {
|
|
|
261
320
|
{config.runtime.yAxis.gridLines ? <Line from={{ x: tick.from.x + xMax, y: tick.from.y }} to={tick.from} stroke='rgba(0,0,0,0.3)' /> : ''}
|
|
262
321
|
|
|
263
322
|
{config.orientation === 'horizontal' && config.visualizationSubType !== 'stacked' && config.yAxis.labelPlacement === 'On Date/Category Axis' && !config.yAxis.hideLabel && (
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
</Fragment>
|
|
270
|
-
)}
|
|
271
|
-
|
|
272
|
-
{config.orientation === 'horizontal' && config.visualizationSubType === 'stacked' && config.yAxis.labelPlacement === 'On Date/Category Axis' && !config.yAxis.hideLabel && (
|
|
273
|
-
// 17 is a magic number from the offset in barchart.
|
|
274
|
-
<Text transform={`translate(${tick.to.x - 5}, ${tick.from.y - config.barHeight / 2 - 3}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} verticalAnchor={config.isLollipopChart ? 'middle' : 'middle'} textAnchor={'end'}>
|
|
323
|
+
<Text
|
|
324
|
+
transform={`translate(${tick.to.x - 5}, ${config.isLollipopChart ? tick.to.y - minY : tick.to.y - minY + (Number(config.barHeight * config.series.length) - barMinHeight) / 2}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`}
|
|
325
|
+
verticalAnchor={'start'}
|
|
326
|
+
textAnchor={'end'}
|
|
327
|
+
>
|
|
275
328
|
{tick.formattedValue}
|
|
276
329
|
</Text>
|
|
277
330
|
)}
|
|
278
331
|
|
|
279
|
-
{config.orientation === 'horizontal' && config.
|
|
280
|
-
|
|
281
|
-
<Text transform={`translate(${-15}, ${tick.from.y}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} verticalAnchor={config.isLollipopChart ? 'middle' : 'middle'} textAnchor={'end'}>
|
|
332
|
+
{config.orientation === 'horizontal' && config.visualizationSubType === 'stacked' && config.yAxis.labelPlacement === 'On Date/Category Axis' && !config.yAxis.hideLabel && (
|
|
333
|
+
<Text transform={`translate(${tick.to.x - 5}, ${tick.to.y - minY + (Number(config.barHeight) - barMinHeight) / 2}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} verticalAnchor={'start'} textAnchor={'end'}>
|
|
282
334
|
{tick.formattedValue}
|
|
283
335
|
</Text>
|
|
284
336
|
)}
|
|
285
337
|
|
|
286
338
|
{config.orientation === 'horizontal' && config.visualizationType === 'Paired Bar' && !config.yAxis.hideLabel && (
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
{formatNumber(tick.formattedValue)}
|
|
339
|
+
<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'>
|
|
340
|
+
{tick.formattedValue}
|
|
290
341
|
</Text>
|
|
291
342
|
)}
|
|
292
343
|
|
|
@@ -304,7 +355,7 @@ export default function LinearChart() {
|
|
|
304
355
|
</Group>
|
|
305
356
|
)
|
|
306
357
|
})}
|
|
307
|
-
{!config.yAxis.hideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#
|
|
358
|
+
{!config.yAxis.hideAxis && <Line from={props.axisFromPoint} to={config.runtime.horizontal ? { x: 0, y: Number(heightHorizontal) } : props.axisToPoint} stroke='#000' />}
|
|
308
359
|
{yScale.domain()[0] < 0 && <Line from={{ x: props.axisFromPoint.x, y: yScale(0) }} to={{ x: xMax, y: yScale(0) }} stroke='#333' />}
|
|
309
360
|
<Text className='y-label' textAnchor='middle' verticalAnchor='start' transform={`translate(${-1 * config.runtime.yAxis.size}, ${axisCenter}) rotate(-90)`} fontWeight='bold' fill={config.yAxis.labelColor}>
|
|
310
361
|
{props.label}
|
|
@@ -317,7 +368,7 @@ export default function LinearChart() {
|
|
|
317
368
|
|
|
318
369
|
{/* Right Axis */}
|
|
319
370
|
{hasRightAxis && (
|
|
320
|
-
<AxisRight scale={yScaleRight} left={width - config.yAxis.rightAxisSize} label={config.yAxis.rightLabel} tickFormat={tick => formatNumber(tick, 'right')} numTicks={config.runtime.yAxis.rightNumTicks || undefined} labelOffset={45}>
|
|
371
|
+
<AxisRight scale={yScaleRight} left={Number(width - config.yAxis.rightAxisSize)} label={config.yAxis.rightLabel} tickFormat={tick => formatNumber(tick, 'right')} numTicks={config.runtime.yAxis.rightNumTicks || undefined} labelOffset={45}>
|
|
321
372
|
{props => {
|
|
322
373
|
const axisCenter = config.runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
|
|
323
374
|
const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
|
|
@@ -351,7 +402,7 @@ export default function LinearChart() {
|
|
|
351
402
|
{hasTopAxis && config.topAxis.hasLine && (
|
|
352
403
|
<AxisTop
|
|
353
404
|
stroke='#333'
|
|
354
|
-
left={config.runtime.yAxis.size}
|
|
405
|
+
left={Number(config.runtime.yAxis.size)}
|
|
355
406
|
scale={xScale}
|
|
356
407
|
hideTicks
|
|
357
408
|
hideZero
|
|
@@ -364,10 +415,10 @@ export default function LinearChart() {
|
|
|
364
415
|
{/* X axis */}
|
|
365
416
|
{config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Spark Line' && (
|
|
366
417
|
<AxisBottom
|
|
367
|
-
top={yMax}
|
|
368
|
-
left={config.runtime.yAxis.size}
|
|
418
|
+
top={config.runtime.horizontal ? Number(heightHorizontal) + Number(config.xAxis.axisPadding) : yMax + Number(config.xAxis.axisPadding)}
|
|
419
|
+
left={Number(config.runtime.yAxis.size)}
|
|
369
420
|
label={config.runtime.xAxis.label}
|
|
370
|
-
tickFormat={
|
|
421
|
+
tickFormat={handleBottomTickFormatting}
|
|
371
422
|
scale={xScale}
|
|
372
423
|
stroke='#333'
|
|
373
424
|
tickStroke='#333'
|
|
@@ -397,7 +448,7 @@ export default function LinearChart() {
|
|
|
397
448
|
)
|
|
398
449
|
})}
|
|
399
450
|
{!config.xAxis.hideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
|
|
400
|
-
<Text x={axisCenter} y={config.
|
|
451
|
+
<Text x={axisCenter} y={config.orientation === 'horizontal' ? config.xAxis.labelOffset : config.xAxis.size} textAnchor='middle' fontWeight='bold' fill={config.xAxis.labelColor}>
|
|
401
452
|
{props.label}
|
|
402
453
|
</Text>
|
|
403
454
|
</Group>
|
|
@@ -408,18 +459,18 @@ export default function LinearChart() {
|
|
|
408
459
|
|
|
409
460
|
{config.visualizationType === 'Paired Bar' && (
|
|
410
461
|
<>
|
|
411
|
-
<AxisBottom top={yMax} left={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}>
|
|
462
|
+
<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}>
|
|
412
463
|
{props => {
|
|
413
|
-
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
|
|
414
464
|
return (
|
|
415
465
|
<Group className='bottom-axis'>
|
|
416
466
|
{props.ticks.map((tick, i) => {
|
|
417
|
-
const
|
|
467
|
+
const angle = tick.index !== 0 ? config.yAxis.tickRotation : 0
|
|
468
|
+
const textAnchor = tick.index !== 0 && config.yAxis.tickRotation && config.yAxis.tickRotation > 0 ? 'end' : 'middle'
|
|
418
469
|
return (
|
|
419
470
|
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
420
471
|
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
|
|
421
472
|
{!config.runtime.yAxis.hideLabel && (
|
|
422
|
-
<Text
|
|
473
|
+
<Text x={tick.to.x} y={tick.to.y} angle={-angle} verticalAnchor='start' textAnchor={textAnchor}>
|
|
423
474
|
{formatNumber(tick.formattedValue)}
|
|
424
475
|
</Text>
|
|
425
476
|
)}
|
|
@@ -433,7 +484,7 @@ export default function LinearChart() {
|
|
|
433
484
|
</AxisBottom>
|
|
434
485
|
<AxisBottom
|
|
435
486
|
top={yMax}
|
|
436
|
-
left={config.runtime.yAxis.size}
|
|
487
|
+
left={Number(config.runtime.yAxis.size)}
|
|
437
488
|
label={config.runtime.xAxis.label}
|
|
438
489
|
tickFormat={config.runtime.xAxis.type === 'date' ? formatDate : config.runtime.xAxis.dataKey !== 'Year' ? formatNumber : tick => tick}
|
|
439
490
|
scale={g2xScale}
|
|
@@ -442,17 +493,17 @@ export default function LinearChart() {
|
|
|
442
493
|
numTicks={config.runtime.xAxis.numTicks || undefined}
|
|
443
494
|
>
|
|
444
495
|
{props => {
|
|
445
|
-
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
|
|
446
496
|
return (
|
|
447
497
|
<>
|
|
448
498
|
<Group className='bottom-axis'>
|
|
449
499
|
{props.ticks.map((tick, i) => {
|
|
450
|
-
const
|
|
500
|
+
const angle = tick.index !== 0 ? config.yAxis.tickRotation : 0
|
|
501
|
+
const textAnchor = tick.index !== 0 && config.yAxis.tickRotation && config.yAxis.tickRotation > 0 ? 'end' : 'middle'
|
|
451
502
|
return (
|
|
452
503
|
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
453
504
|
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
|
|
454
505
|
{!config.runtime.yAxis.hideLabel && (
|
|
455
|
-
<Text
|
|
506
|
+
<Text x={tick.to.x} y={tick.to.y} angle={-angle} verticalAnchor='start' textAnchor={textAnchor}>
|
|
456
507
|
{tick.formattedValue}
|
|
457
508
|
</Text>
|
|
458
509
|
)}
|
|
@@ -462,7 +513,7 @@ export default function LinearChart() {
|
|
|
462
513
|
{!config.runtime.yAxis.hideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
|
|
463
514
|
</Group>
|
|
464
515
|
<Group>
|
|
465
|
-
<Text
|
|
516
|
+
<Text x={xMax / 2} y={config.xAxis.labelOffset} stroke='#333' textAnchor={'middle'} verticalAnchor='start'>
|
|
466
517
|
{config.runtime.xAxis.label}
|
|
467
518
|
</Text>
|
|
468
519
|
</Group>
|
|
@@ -472,23 +523,31 @@ export default function LinearChart() {
|
|
|
472
523
|
</AxisBottom>
|
|
473
524
|
</>
|
|
474
525
|
)}
|
|
475
|
-
|
|
526
|
+
|
|
527
|
+
{/* Paired Bar chart */}
|
|
528
|
+
{config.visualizationType === 'Paired Bar' && <PairedBarChart originalWidth={width} width={xMax} height={yMax} />}
|
|
476
529
|
|
|
477
530
|
{/* Bar chart */}
|
|
478
|
-
{config.visualizationType !== 'Line' && config.visualizationType !== 'Paired Bar' && (
|
|
531
|
+
{config.visualizationType !== 'Line' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Scatter Plot' && (
|
|
479
532
|
<>
|
|
480
533
|
<BarChart xScale={xScale} yScale={yScale} seriesScale={seriesScale} xMax={xMax} yMax={yMax} getXAxisData={getXAxisData} getYAxisData={getYAxisData} animatedChart={animatedChart} visible={animatedChart} />
|
|
481
534
|
</>
|
|
482
535
|
)}
|
|
483
536
|
|
|
484
537
|
{/* Line chart */}
|
|
485
|
-
{config.visualizationType !== 'Bar' && config.visualizationType !== 'Paired Bar' && (
|
|
538
|
+
{config.visualizationType !== 'Bar' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Scatter Plot' && (
|
|
486
539
|
<>
|
|
487
540
|
<LineChart xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} xMax={xMax} yMax={yMax} seriesStyle={config.series} />
|
|
488
541
|
</>
|
|
489
542
|
)}
|
|
543
|
+
|
|
544
|
+
{/* Scatter Plot chart */}
|
|
545
|
+
{config.visualizationType === 'Scatter Plot' && <CoveScatterPlot xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} />}
|
|
546
|
+
|
|
547
|
+
{/* Box Plot chart */}
|
|
548
|
+
{config.visualizationType === 'Box Plot' && <CoveBoxPlot xScale={xScale} yScale={yScale} />}
|
|
490
549
|
</svg>
|
|
491
|
-
<ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
550
|
+
<ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} variant='light' arrowColor='rgba(0,0,0,0)' className='tooltip' />
|
|
492
551
|
<div className='animation-trigger' ref={triggerRef} />
|
|
493
552
|
</ErrorBoundary>
|
|
494
553
|
)
|