@cdc/chart 4.23.3 → 4.23.5
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 +52543 -50830
- package/examples/feature/__data__/area-chart.json +56 -0
- package/examples/{planet-example-data.json → feature/__data__/planet-example-data.json} +3 -8
- package/examples/feature/__data__/planet-logaritmic-data.json +56 -0
- package/examples/feature/area/area-chart-category.json +240 -0
- package/examples/{area-chart.json → feature/area/area-chart-date.json} +70 -13
- package/examples/feature/bar/example-bar-chart.json +558 -0
- package/examples/{horizontal-chart-max-increase.json → feature/bar/horizontal-chart-max-increase.json} +10 -4
- package/examples/{horizontal-chart.json → feature/bar/horizontal-chart.json} +10 -4
- package/examples/{horizontal-stacked-bar-chart.json → feature/bar/horizontal-stacked-bar-chart.json} +7 -3
- package/examples/{planet-chart-horizontal-example-config.json → feature/bar/planet-chart-horizontal-example-config.json} +8 -3
- package/examples/feature/bar/planet-chart-logaritmic-config.json +170 -0
- package/examples/{planet-example-config.json → feature/bar/planet-example-config.json} +2 -2
- package/examples/{box-plot.json → feature/boxplot/boxplot.json} +7 -7
- package/examples/feature/boxplot/testing.csv +38 -0
- package/examples/feature/boxplot/valid-boxplot.csv +17 -0
- package/examples/feature/combo/combochart-categories_are_numbers .json +18 -0
- package/examples/{planet-combo-example-config.json → feature/combo/planet-combo-example-config.json} +1 -1
- package/examples/{planet-deviation-config.json → feature/deviation/planet-deviation-config.json} +2 -2
- package/examples/{planet-deviation-data.json → feature/deviation/planet-deviation-data.json} +9 -9
- package/examples/feature/filters/filter-testing.json +212 -0
- package/examples/feature/forecasting/case_date_example.csv +130 -0
- package/examples/feature/forecasting/effective_reproduction.json +202 -0
- package/examples/feature/forecasting/r_data.csv +130 -0
- package/examples/feature/forecasting/random_data.csv +366 -0
- package/examples/feature/line/line-chart.json +124 -0
- package/examples/{paired-bar-example.json → feature/paired-bar/paired-bar-example.json} +10 -4
- package/examples/{planet-pie-example-config.json → feature/pie/planet-pie-example-config.json} +2 -2
- package/examples/{scatterplot.json → feature/scatterplot/scatterplot.json} +1 -1
- package/examples/feature/test-highlight/test-highlight-2.json +789 -0
- package/examples/feature/test-highlight/test-highlight-vertical.json +561 -0
- package/examples/feature/test-highlight/test-highlight.json +100 -0
- package/examples/{case-rate-example-config.json → feature/tests-case-rate/case-rate-example-config.json} +2 -2
- package/examples/{covid-confidence-example-config.json → feature/tests-covid/covid-confidence-example-config.json} +8 -3
- package/examples/{covid-example-config.json → feature/tests-covid/covid-example-config.json} +7 -3
- package/examples/{cutoff-example-config.json → feature/tests-cutoff/cutoff-example-config.json} +7 -3
- package/examples/{date-exclusions-config.json → feature/tests-date-exclusions/date-exclusions-config.json} +2 -2
- package/examples/{example-bar-chart-nonnumeric.json → feature/tests-non-numerics/example-bar-chart-nonnumeric.json} +1 -1
- package/examples/{planet-pie-example-config-nonnumeric.json → feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json} +2 -2
- package/examples/{sparkline-chart-nonnumeric.json → feature/tests-non-numerics/sparkline-chart-nonnumeric.json} +1 -1
- package/examples/{stacked-vertical-bar-example-nonnumerics.json → feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json} +1 -2
- package/examples/gallery/bar-chart-horizontal/horizontal-highlight.json +345 -0
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +145 -7
- package/examples/gallery/paired-bar/paired-bar-chart.json +1 -0
- package/index.html +73 -49
- package/package.json +2 -2
- package/src/CdcChart.jsx +405 -40
- package/src/components/AreaChart.jsx +122 -80
- package/src/components/BarChart.jsx +126 -49
- package/src/components/BoxPlot.jsx +28 -20
- package/src/components/DataTable.jsx +7 -6
- package/src/components/DeviationBar.jsx +34 -34
- package/src/components/EditorPanel.jsx +1332 -352
- package/src/components/Legend.jsx +40 -4
- package/src/components/LineChart.jsx +10 -23
- package/src/components/LinearChart.jsx +133 -286
- package/src/components/PairedBarChart.jsx +6 -6
- package/src/components/PieChart.jsx +2 -4
- package/src/components/SparkLine.jsx +6 -42
- package/src/data/initial-state.js +23 -4
- package/src/hooks/useHighlightedBars.js +154 -0
- package/src/hooks/useMinMax.js +92 -0
- package/src/hooks/useReduceData.js +31 -57
- package/src/hooks/useScales.js +202 -0
- package/src/index.jsx +2 -1
- package/src/scss/editor-panel.scss +15 -0
- package/src/scss/main.scss +8 -6
- package/examples/box-plot.csv +0 -5
- package/examples/dynamic-legends.json +0 -125
- package/examples/example-bar-chart.json +0 -36
- package/examples/line-chart.json +0 -34
- package/examples/temp-example-config.json +0 -64
- package/examples/temp-example-data.json +0 -130
- package/src/components/Filters.jsx +0 -126
- /package/examples/{age-adjusted-rates.json → feature/__data__/age-adjusted-rates.json} +0 -0
- /package/examples/{new-data.csv → feature/__data__/new-data.csv} +0 -0
- /package/examples/{planet-example-data-max-increase.json → feature/__data__/planet-example-data-max-increase.json} +0 -0
- /package/examples/{Barchart_with_negative.json → feature/bar/Barchart_with_negative.json} +0 -0
- /package/examples/{stacked-vertical-bar-example-negative.json → feature/bar/stacked-vertical-bar-example-negative.json} +0 -0
- /package/examples/{stacked-vertical-bar-example.json → feature/bar/stacked-vertical-bar-example.json} +0 -0
- /package/examples/{box-plot-data.json → feature/boxplot/box-plot-data.json} +0 -0
- /package/examples/{newdata.json → feature/boxplot/boxplot-data.json} +0 -0
- /package/examples/{line-chart-max-increase.json → feature/line/line-chart-max-increase.json} +0 -0
- /package/examples/{paired-bar-data.json → feature/paired-bar/paired-bar-data.json} +0 -0
- /package/examples/{paired-bar-formatted.json → feature/paired-bar/paired-bar-formatted.json} +0 -0
- /package/examples/{scatterplot-continuous.csv → feature/scatterplot/scatterplot-continuous.csv} +0 -0
- /package/examples/{example-sparkline.json → feature/sparkline/example-sparkline.json} +0 -0
- /package/examples/{big-small-test-bar.json → feature/tests-big-small/big-small-test-bar.json} +0 -0
- /package/examples/{big-small-test-line.json → feature/tests-big-small/big-small-test-line.json} +0 -0
- /package/examples/{big-small-test-negative.json → feature/tests-big-small/big-small-test-negative.json} +0 -0
- /package/examples/{case-rate-example-data.json → feature/tests-case-rate/case-rate-example-data.json} +0 -0
- /package/examples/{covid-example-data-confidence.json → feature/tests-covid/covid-example-data-confidence.json} +0 -0
- /package/examples/{covid-example-data.json → feature/tests-covid/covid-example-data.json} +0 -0
- /package/examples/{cutoff-example-data.json → feature/tests-cutoff/cutoff-example-data.json} +0 -0
- /package/examples/{date-exclusions-data.json → feature/tests-date-exclusions/date-exclusions-data.json} +0 -0
- /package/examples/{example-combo-bar-nonnumeric.json → feature/tests-non-numerics/example-combo-bar-nonnumeric.json} +0 -0
- /package/examples/{line-chart-nonnumeric.json → feature/tests-non-numerics/line-chart-nonnumeric.json} +0 -0
- /package/examples/{planet-example-data-nonnumeric.json → feature/tests-non-numerics/planet-example-data-nonnumeric.json} +0 -0
|
@@ -4,314 +4,85 @@ import { Tooltip as ReactTooltip } from 'react-tooltip'
|
|
|
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, scaleTime } from '@visx/scale'
|
|
8
7
|
import { AxisLeft, AxisBottom, AxisRight, AxisTop } from '@visx/axis'
|
|
9
8
|
|
|
10
|
-
import CoveScatterPlot from './ScatterPlot'
|
|
11
9
|
import BarChart from './BarChart'
|
|
12
|
-
import LineChart from './LineChart'
|
|
13
10
|
import ConfigContext from '../ConfigContext'
|
|
11
|
+
import CoveAreaChart from './AreaChart'
|
|
12
|
+
import CoveBoxPlot from './BoxPlot'
|
|
13
|
+
import CoveScatterPlot from './ScatterPlot'
|
|
14
|
+
import DeviationBar from './DeviationBar'
|
|
15
|
+
import LineChart from './LineChart'
|
|
14
16
|
import PairedBarChart from './PairedBarChart'
|
|
15
17
|
import useIntersectionObserver from './useIntersectionObserver'
|
|
16
|
-
import CoveBoxPlot from './BoxPlot'
|
|
17
|
-
import CoveAreaChart from './AreaChart'
|
|
18
18
|
|
|
19
19
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
20
20
|
import '../scss/LinearChart.scss'
|
|
21
21
|
import useReduceData from '../hooks/useReduceData'
|
|
22
|
+
import useScales from '../hooks/useScales'
|
|
23
|
+
import useMinMax from '../hooks/useMinMax'
|
|
22
24
|
import useRightAxis from '../hooks/useRightAxis'
|
|
23
25
|
import useTopAxis from '../hooks/useTopAxis'
|
|
24
|
-
import { DeviationBar } from './DeviationBar'
|
|
25
26
|
|
|
26
|
-
// TODO: Move scaling functions into hooks to manage complexity
|
|
27
27
|
export default function LinearChart() {
|
|
28
|
-
const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig,
|
|
28
|
+
const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig, handleLineType } = useContext(ConfigContext)
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
const triggerRef = useRef()
|
|
35
|
-
const dataRef = useIntersectionObserver(triggerRef, {
|
|
36
|
-
freezeOnceVisible: false
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
// Make sure the chart is visible if in the editor
|
|
40
|
-
/* eslint-disable react-hooks/exhaustive-deps */
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
const element = document.querySelector('.isEditor')
|
|
43
|
-
if (element) {
|
|
44
|
-
// parent element is visible
|
|
45
|
-
setAnimatedChart(prevState => true)
|
|
46
|
-
}
|
|
47
|
-
}) /* eslint-disable-line */
|
|
48
|
-
|
|
49
|
-
// If the chart is in view, set to animate if it has not already played
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
if (dataRef?.isIntersecting === true && config.animate) {
|
|
52
|
-
setTimeout(() => {
|
|
53
|
-
setAnimatedChart(prevState => true)
|
|
54
|
-
}, 500)
|
|
55
|
-
}
|
|
56
|
-
}, [dataRef?.isIntersecting, config.animate])
|
|
30
|
+
// getters & functions
|
|
31
|
+
const getXAxisData = d => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
|
|
32
|
+
const getYAxisData = (d, seriesKey) => d[seriesKey]
|
|
33
|
+
const xAxisDataMapped = data.map(d => getXAxisData(d))
|
|
57
34
|
|
|
58
|
-
|
|
35
|
+
// configure width
|
|
36
|
+
let [width] = dimensions
|
|
37
|
+
if (config && config.legend && !config.legend.hide && config.legend.position !== 'bottom' && ['lg', 'md'].includes(currentViewport)) {
|
|
59
38
|
width = width * 0.73
|
|
60
39
|
}
|
|
40
|
+
// configure height , yMax, xMAx
|
|
61
41
|
const { horizontal: heightHorizontal } = config.heights
|
|
42
|
+
const isHorizontal = config.orientation === 'horizontal'
|
|
43
|
+
const shouldAbbreviate = true
|
|
62
44
|
const height = config.aspectRatio ? width * config.aspectRatio : config.heights[config.orientation]
|
|
63
45
|
const xMax = width - config.runtime.yAxis.size - (config.visualizationType === 'Combo' ? config.yAxis.rightAxisSize : 0)
|
|
64
46
|
const yMax = height - (config.orientation === 'horizontal' ? 0 : config.runtime.xAxis.size)
|
|
65
47
|
|
|
48
|
+
// hooks % states
|
|
49
|
+
const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, data)
|
|
66
50
|
const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data, updateConfig })
|
|
67
51
|
const { hasTopAxis } = useTopAxis(config)
|
|
52
|
+
const [animatedChart, setAnimatedChart] = useState(false)
|
|
53
|
+
const properties = { data, config, minValue, maxValue, isAllLine, existPositiveValue, xAxisDataMapped, xMax, yMax }
|
|
54
|
+
const { min, max } = useMinMax(properties)
|
|
55
|
+
const { xScale, yScale, seriesScale, g1xScale, g2xScale } = useScales({ ...properties, min, max })
|
|
68
56
|
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const { max: enteredMaxValue, min: enteredMinValue } = config.runtime.yAxis
|
|
77
|
-
const isMaxValid = existPositiveValue ? enteredMaxValue >= maxValue : enteredMaxValue >= 0
|
|
78
|
-
const isMinValid = (enteredMinValue <= 0 && minValue >= 0) || (enteredMinValue <= minValue && minValue < 0)
|
|
79
|
-
|
|
80
|
-
let max = 0 // need outside the if statement
|
|
81
|
-
let min = 0
|
|
82
|
-
if (data) {
|
|
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
|
-
}
|
|
109
|
-
|
|
110
|
-
if ((config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && min > 0) {
|
|
111
|
-
min = 0
|
|
112
|
-
}
|
|
113
|
-
if (config.visualizationType === 'Combo' && isAllLine) {
|
|
114
|
-
if ((enteredMinValue === undefined || enteredMinValue === null || enteredMinValue === '') && min > 0) {
|
|
115
|
-
min = 0
|
|
116
|
-
}
|
|
117
|
-
if (enteredMinValue) {
|
|
118
|
-
const isMinValid = +enteredMinValue < minValue
|
|
119
|
-
min = +enteredMinValue && isMinValid ? enteredMinValue : minValue
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (config.visualizationType === 'Line') {
|
|
124
|
-
const isMinValid = enteredMinValue < minValue
|
|
125
|
-
min = enteredMinValue && isMinValid ? enteredMinValue : minValue
|
|
126
|
-
}
|
|
127
|
-
//If data value max wasn't provided, calculate it
|
|
128
|
-
if (max === Number.MIN_VALUE) {
|
|
129
|
-
// if all values in data are negative set max = 0
|
|
130
|
-
max = existPositiveValue ? maxValue : 0
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
//Adds Y Axis data padding if applicable
|
|
134
|
-
if (config.runtime.yAxis.paddingPercent) {
|
|
135
|
-
let paddingValue = (max - min) * config.runtime.yAxis.paddingPercent
|
|
136
|
-
min -= paddingValue
|
|
137
|
-
max += paddingValue
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
let xAxisDataMapped = data.map(d => getXAxisData(d))
|
|
141
|
-
|
|
142
|
-
if (config.isLollipopChart && config.yAxis.displayNumbersOnBar) {
|
|
143
|
-
const dataKey = data.map(item => item[config.series[0].dataKey])
|
|
144
|
-
const maxDataVal = Math.max(...dataKey).toString().length
|
|
145
|
-
|
|
146
|
-
switch (true) {
|
|
147
|
-
case maxDataVal > 8 && maxDataVal <= 12:
|
|
148
|
-
max = max * 1.3
|
|
149
|
-
break
|
|
150
|
-
case maxDataVal > 4 && maxDataVal <= 7:
|
|
151
|
-
max = max * 1.1
|
|
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
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (config.runtime.horizontal) {
|
|
170
|
-
xScale = scaleLinear({
|
|
171
|
-
domain: [min, max],
|
|
172
|
-
range: [0, xMax]
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
yScale =
|
|
176
|
-
config.runtime.xAxis.type === 'date'
|
|
177
|
-
? scaleLinear({
|
|
178
|
-
domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)]
|
|
179
|
-
})
|
|
180
|
-
: scalePoint({ domain: xAxisDataMapped, padding: 0.5 })
|
|
181
|
-
|
|
182
|
-
seriesScale = scalePoint({
|
|
183
|
-
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
184
|
-
range: [0, yMax]
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
yScale.rangeRound([0, yMax])
|
|
188
|
-
} else {
|
|
189
|
-
min = min < 0 ? min * 1.11 : min
|
|
190
|
-
|
|
191
|
-
yScale = scaleLinear({
|
|
192
|
-
domain: [min, max],
|
|
193
|
-
range: [yMax, 0]
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
xScale = scalePoint({
|
|
197
|
-
domain: xAxisDataMapped,
|
|
198
|
-
range: [0, xMax],
|
|
199
|
-
padding: 0.5
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
seriesScale = scalePoint({
|
|
203
|
-
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
204
|
-
range: [0, xMax]
|
|
205
|
-
})
|
|
206
|
-
}
|
|
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
|
-
|
|
215
|
-
if (config.visualizationType === 'Paired Bar') {
|
|
216
|
-
const offset = 1.02 // Offset of the ticks/values from the Axis
|
|
217
|
-
let groupOneMax = Math.max.apply(
|
|
218
|
-
Math,
|
|
219
|
-
data.map(d => d[config.series[0].dataKey])
|
|
220
|
-
)
|
|
221
|
-
let groupTwoMax = Math.max.apply(
|
|
222
|
-
Math,
|
|
223
|
-
data.map(d => d[config.series[1].dataKey])
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
// group one
|
|
227
|
-
var g1xScale = scaleLinear({
|
|
228
|
-
domain: [0, Math.max(groupOneMax, groupTwoMax) * offset],
|
|
229
|
-
range: [xMax / 2, 0]
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
// group 2
|
|
233
|
-
var g2xScale = scaleLinear({
|
|
234
|
-
domain: g1xScale.domain(),
|
|
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
|
|
295
|
-
})
|
|
296
|
-
}
|
|
297
|
-
}
|
|
57
|
+
// refs
|
|
58
|
+
const triggerRef = useRef()
|
|
59
|
+
const svgRef = useRef()
|
|
60
|
+
const dataRef = useIntersectionObserver(triggerRef, {
|
|
61
|
+
freezeOnceVisible: false
|
|
62
|
+
})
|
|
298
63
|
|
|
299
64
|
const handleLeftTickFormatting = tick => {
|
|
65
|
+
if (config.useLogScale && tick === 0.1) {
|
|
66
|
+
//when logaritmic scale applyed change value of FIRST tick
|
|
67
|
+
tick = 0
|
|
68
|
+
}
|
|
300
69
|
if (config.runtime.yAxis.type === 'date') return formatDate(parseDate(tick))
|
|
301
|
-
if (config.orientation === 'vertical') return formatNumber(tick, 'left')
|
|
70
|
+
if (config.orientation === 'vertical') return formatNumber(tick, 'left', shouldAbbreviate)
|
|
302
71
|
return tick
|
|
303
72
|
}
|
|
304
73
|
|
|
305
74
|
const handleBottomTickFormatting = tick => {
|
|
75
|
+
if (config.useLogScale && tick === 0.1) {
|
|
76
|
+
// when logaritmic scale applyed change value FIRST of tick
|
|
77
|
+
tick = 0
|
|
78
|
+
}
|
|
306
79
|
if (config.runtime.xAxis.type === 'date') return formatDate(tick)
|
|
307
|
-
if (config.orientation === 'horizontal') return formatNumber(tick, 'left')
|
|
308
|
-
if (config.xAxis.type === 'continuous') return formatNumber(tick, 'bottom')
|
|
80
|
+
if (config.orientation === 'horizontal') return formatNumber(tick, 'left', shouldAbbreviate)
|
|
81
|
+
if (config.xAxis.type === 'continuous') return formatNumber(tick, 'bottom', shouldAbbreviate)
|
|
309
82
|
return tick
|
|
310
83
|
}
|
|
311
84
|
|
|
312
85
|
const countNumOfTicks = axis => {
|
|
313
|
-
// function get number of ticks based on bar type & users value
|
|
314
|
-
const isHorizontal = config.orientation === 'horizontal'
|
|
315
86
|
const { numTicks } = config.runtime[axis]
|
|
316
87
|
let tickCount = undefined
|
|
317
88
|
|
|
@@ -347,11 +118,32 @@ export default function LinearChart() {
|
|
|
347
118
|
return tickCount
|
|
348
119
|
}
|
|
349
120
|
|
|
121
|
+
// Make sure the chart is visible if in the editor
|
|
122
|
+
/* eslint-disable react-hooks/exhaustive-deps */
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
const element = document.querySelector('.isEditor')
|
|
125
|
+
if (element) {
|
|
126
|
+
// parent element is visible
|
|
127
|
+
setAnimatedChart(prevState => true)
|
|
128
|
+
}
|
|
129
|
+
}) /* eslint-disable-line */
|
|
130
|
+
|
|
131
|
+
// If the chart is in view, set to animate if it has not already played
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (dataRef?.isIntersecting === true && config.animate) {
|
|
134
|
+
setTimeout(() => {
|
|
135
|
+
setAnimatedChart(prevState => true)
|
|
136
|
+
}, 500)
|
|
137
|
+
}
|
|
138
|
+
}, [dataRef?.isIntersecting, config.animate])
|
|
139
|
+
|
|
140
|
+
const { orientation, xAxis, yAxis } = config
|
|
141
|
+
|
|
350
142
|
return isNaN(width) ? (
|
|
351
143
|
<></>
|
|
352
144
|
) : (
|
|
353
145
|
<ErrorBoundary component='LinearChart'>
|
|
354
|
-
<svg width={width} height={height} className={`linear ${config.animate ? 'animated' : ''} ${animatedChart && config.animate ? 'animate' : ''}`} role='img' aria-label={handleChartAriaLabels(config)} tabIndex={0}>
|
|
146
|
+
<svg width={width} height={height} className={`linear ${config.animate ? 'animated' : ''} ${animatedChart && config.animate ? 'animate' : ''}`} role='img' aria-label={handleChartAriaLabels(config)} tabIndex={0} ref={svgRef}>
|
|
355
147
|
{/* Higlighted regions */}
|
|
356
148
|
{config.regions
|
|
357
149
|
? config.regions.map(region => {
|
|
@@ -398,7 +190,7 @@ export default function LinearChart() {
|
|
|
398
190
|
|
|
399
191
|
{/* Y axis */}
|
|
400
192
|
{config.visualizationType !== 'Spark Line' && (
|
|
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')}>
|
|
193
|
+
<AxisLeft scale={yScale} tickLength={config.useLogScale ? 6 : 8} left={Number(config.runtime.yAxis.size) - config.yAxis.axisPadding} label={config.runtime.yAxis.label} stroke='#333' tickFormat={tick => handleLeftTickFormatting(tick)} numTicks={countNumOfTicks('yAxis')}>
|
|
402
194
|
{props => {
|
|
403
195
|
const axisCenter = config.runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
|
|
404
196
|
const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
|
|
@@ -407,12 +199,15 @@ export default function LinearChart() {
|
|
|
407
199
|
{props.ticks.map((tick, i) => {
|
|
408
200
|
const minY = props.ticks[0].to.y
|
|
409
201
|
const barMinHeight = 15 // 15 is the min height for bars by default
|
|
202
|
+
const showTicks = String(tick.value).startsWith('1') || tick.value === 0.1 ? 'block' : 'none'
|
|
203
|
+
const tickLength = showTicks === 'block' ? 7 : 0
|
|
204
|
+
const to = { x: tick.to.x - tickLength, y: tick.to.y }
|
|
410
205
|
|
|
411
206
|
return (
|
|
412
207
|
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
413
|
-
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke={config.yAxis.tickColor} display={config.runtime.horizontal ? 'none' : 'block'} />}
|
|
208
|
+
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={config.useLogScale ? to : tick.to} stroke={config.yAxis.tickColor} display={config.runtime.horizontal ? 'none' : 'block'} />}
|
|
414
209
|
|
|
415
|
-
{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)' /> : ''}
|
|
210
|
+
{config.runtime.yAxis.gridLines ? <Line display={config.useLogScale && showTicks} from={{ x: tick.from.x + xMax, y: tick.from.y }} to={tick.from} stroke='rgba(0,0,0,0.3)' /> : ''}
|
|
416
211
|
|
|
417
212
|
{config.orientation === 'horizontal' && config.visualizationSubType !== 'stacked' && config.yAxis.labelPlacement === 'On Date/Category Axis' && !config.yAxis.hideLabel && (
|
|
418
213
|
<Text
|
|
@@ -441,8 +236,10 @@ export default function LinearChart() {
|
|
|
441
236
|
</Text>
|
|
442
237
|
)}
|
|
443
238
|
|
|
444
|
-
{config.orientation
|
|
239
|
+
{config.orientation === 'vertical' && config.visualizationType !== 'Paired Bar' && !config.yAxis.hideLabel && (
|
|
445
240
|
<Text
|
|
241
|
+
display={config.useLogScale ? showTicks : 'block'}
|
|
242
|
+
dx={config.useLogScale ? -6 : 0}
|
|
446
243
|
x={config.runtime.horizontal ? tick.from.x + 2 : tick.to.x}
|
|
447
244
|
y={tick.to.y + (config.runtime.horizontal ? horizontalTickOffset : 0)}
|
|
448
245
|
verticalAnchor={config.runtime.horizontal ? 'start' : 'middle'}
|
|
@@ -457,6 +254,7 @@ export default function LinearChart() {
|
|
|
457
254
|
})}
|
|
458
255
|
{!config.yAxis.hideAxis && <Line from={props.axisFromPoint} to={config.runtime.horizontal ? { x: 0, y: Number(heightHorizontal) } : props.axisToPoint} stroke='#000' />}
|
|
459
256
|
{yScale.domain()[0] < 0 && <Line from={{ x: props.axisFromPoint.x, y: yScale(0) }} to={{ x: xMax, y: yScale(0) }} stroke='#333' />}
|
|
257
|
+
{config.visualizationType === 'Bar' && config.orientation === 'horizontal' && xScale.domain()[0] < 0 && <Line from={{ x: xScale(0), y: 0 }} to={{ x: xScale(0), y: yMax }} stroke='#333' strokeWidth={2} />}
|
|
460
258
|
<Text className='y-label' textAnchor='middle' verticalAnchor='start' transform={`translate(${-1 * config.runtime.yAxis.size}, ${axisCenter}) rotate(-90)`} fontWeight='bold' fill={config.yAxis.labelColor}>
|
|
461
259
|
{props.label}
|
|
462
260
|
</Text>
|
|
@@ -529,12 +327,19 @@ export default function LinearChart() {
|
|
|
529
327
|
return (
|
|
530
328
|
<Group className='bottom-axis'>
|
|
531
329
|
{props.ticks.map((tick, i) => {
|
|
330
|
+
// when using LogScale show major ticks values only
|
|
331
|
+
const showTick = String(tick.value).startsWith('1') || tick.value === 0.1 ? 'block' : 'none'
|
|
532
332
|
const tickWidth = xMax / props.ticks.length
|
|
333
|
+
const tickLength = showTick === 'block' ? 16 : 8
|
|
334
|
+
const to = { x: tick.to.x, y: tickLength }
|
|
335
|
+
|
|
533
336
|
return (
|
|
534
337
|
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
535
|
-
{!config.xAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke={config.xAxis.tickColor} />}
|
|
338
|
+
{!config.xAxis.hideTicks && <Line from={tick.from} to={config.orientation === 'horizontal' && config.useLogScale ? to : tick.to} stroke={config.xAxis.tickColor} strokeWidth={showTick === 'block' ? 1.3 : 1} />}
|
|
536
339
|
{!config.xAxis.hideLabel && (
|
|
537
340
|
<Text
|
|
341
|
+
dy={config.orientation === 'horizontal' && config.useLogScale ? 8 : 0}
|
|
342
|
+
display={config.orientation === 'horizontal' && config.useLogScale ? showTick : 'block'}
|
|
538
343
|
transform={`translate(${tick.to.x}, ${tick.to.y}) rotate(-${!config.runtime.horizontal ? config.runtime.xAxis.tickRotation : 0})`}
|
|
539
344
|
verticalAnchor='start'
|
|
540
345
|
textAnchor={config.runtime.xAxis.tickRotation && config.runtime.xAxis.tickRotation !== '0' ? 'end' : 'middle'}
|
|
@@ -571,7 +376,7 @@ export default function LinearChart() {
|
|
|
571
376
|
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
|
|
572
377
|
{!config.runtime.yAxis.hideLabel && (
|
|
573
378
|
<Text x={tick.to.x} y={tick.to.y} angle={-angle} verticalAnchor='start' textAnchor={textAnchor}>
|
|
574
|
-
{formatNumber(tick.
|
|
379
|
+
{formatNumber(tick.value, 'left')}
|
|
575
380
|
</Text>
|
|
576
381
|
)}
|
|
577
382
|
</Group>
|
|
@@ -604,7 +409,7 @@ export default function LinearChart() {
|
|
|
604
409
|
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
|
|
605
410
|
{!config.runtime.yAxis.hideLabel && (
|
|
606
411
|
<Text x={tick.to.x} y={tick.to.y} angle={-angle} verticalAnchor='start' textAnchor={textAnchor}>
|
|
607
|
-
{tick.
|
|
412
|
+
{formatNumber(tick.value, 'left')}
|
|
608
413
|
</Text>
|
|
609
414
|
)}
|
|
610
415
|
</Group>
|
|
@@ -625,11 +430,13 @@ export default function LinearChart() {
|
|
|
625
430
|
)}
|
|
626
431
|
|
|
627
432
|
{config.visualizationType === 'Deviation Bar' && <DeviationBar xScale={xScale} yScale={yScale} width={xMax} height={yMax} />}
|
|
628
|
-
|
|
629
|
-
{/* Paired Bar chart */}
|
|
630
433
|
{config.visualizationType === 'Paired Bar' && <PairedBarChart originalWidth={width} width={xMax} height={yMax} />}
|
|
434
|
+
{config.visualizationType === 'Scatter Plot' && <CoveScatterPlot xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} />}
|
|
435
|
+
{config.visualizationType === 'Box Plot' && <CoveBoxPlot xScale={xScale} yScale={yScale} />}
|
|
436
|
+
{(config.visualizationType === 'Area Chart' || config.visualizationType === 'Combo') && <CoveAreaChart xScale={xScale} yScale={yScale} yMax={yMax} xMax={xMax} chartRef={svgRef} />}
|
|
631
437
|
|
|
632
438
|
{/* Bar chart */}
|
|
439
|
+
{/* TODO: Make this just bar or combo? */}
|
|
633
440
|
{config.visualizationType !== 'Line' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Area Chart' && config.visualizationType !== 'Scatter Plot' && config.visualizationType !== 'Deviation Bar' && (
|
|
634
441
|
<>
|
|
635
442
|
<BarChart xScale={xScale} yScale={yScale} seriesScale={seriesScale} xMax={xMax} yMax={yMax} getXAxisData={getXAxisData} getYAxisData={getYAxisData} animatedChart={animatedChart} visible={animatedChart} />
|
|
@@ -637,18 +444,58 @@ export default function LinearChart() {
|
|
|
637
444
|
)}
|
|
638
445
|
|
|
639
446
|
{/* Line chart */}
|
|
447
|
+
{/* TODO: Make this just line or combo? */}
|
|
640
448
|
{config.visualizationType !== 'Bar' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Area Chart' && config.visualizationType !== 'Scatter Plot' && config.visualizationType !== 'Deviation Bar' && (
|
|
641
449
|
<>
|
|
642
450
|
<LineChart xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} xMax={xMax} yMax={yMax} seriesStyle={config.series} />
|
|
643
451
|
</>
|
|
644
452
|
)}
|
|
645
453
|
|
|
646
|
-
{/*
|
|
647
|
-
{config.
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
454
|
+
{/* y anchors */}
|
|
455
|
+
{config.yAxis.anchors &&
|
|
456
|
+
config.yAxis.anchors.map(anchor => {
|
|
457
|
+
let anchorPosition = yScale(anchor.value)
|
|
458
|
+
const padding = config.orientation === 'horizontal' ? Number(config.xAxis.size) : Number(config.yAxis.size)
|
|
459
|
+
const middleOffset = config.orientation === 'horizontal' && config.visualizationType === 'Bar' ? config.barHeight / 4 : 0
|
|
460
|
+
|
|
461
|
+
return (
|
|
462
|
+
// prettier-ignore
|
|
463
|
+
<Line
|
|
464
|
+
key={anchor.value}
|
|
465
|
+
strokeDasharray={handleLineType(anchor.lineStyle)}
|
|
466
|
+
stroke={anchor.color ? anchor.color : 'rgba(0,0,0,1)'}
|
|
467
|
+
className='anchor-y'
|
|
468
|
+
from={{ x: 0 + padding, y: anchorPosition - middleOffset}}
|
|
469
|
+
to={{ x: width, y: anchorPosition - middleOffset }}
|
|
470
|
+
/>
|
|
471
|
+
)
|
|
472
|
+
})}
|
|
473
|
+
|
|
474
|
+
{/* x anchors */}
|
|
475
|
+
{config.xAxis.anchors &&
|
|
476
|
+
config.xAxis.anchors.map(anchor => {
|
|
477
|
+
let newX = xAxis
|
|
478
|
+
if (orientation === 'horizontal') {
|
|
479
|
+
newX = yAxis
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
let anchorPosition = newX.type === 'date' ? xScale(parseDate(anchor.value, false)) : xScale(anchor.value)
|
|
483
|
+
|
|
484
|
+
const padding = orientation === 'horizontal' ? Number(config.xAxis.size) : Number(config.yAxis.size)
|
|
485
|
+
|
|
486
|
+
return (
|
|
487
|
+
// prettier-ignore
|
|
488
|
+
<Line
|
|
489
|
+
key={anchor.value}
|
|
490
|
+
strokeDasharray={handleLineType(anchor.lineStyle)}
|
|
491
|
+
stroke={anchor.color ? anchor.color : 'rgba(0,0,0,1)'}
|
|
492
|
+
fill={anchor.color ? anchor.color : 'rgba(0,0,0,1)'}
|
|
493
|
+
className='anchor-x'
|
|
494
|
+
from={{ x: Number(anchorPosition) + Number(padding), y: 0 }}
|
|
495
|
+
to={{ x: Number(anchorPosition) + Number(padding), y: yMax }}
|
|
496
|
+
/>
|
|
497
|
+
)
|
|
498
|
+
})}
|
|
652
499
|
</svg>
|
|
653
500
|
<ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} variant='light' arrowColor='rgba(0,0,0,0)' className='tooltip' />
|
|
654
501
|
<div className='animation-trigger' ref={triggerRef} />
|
|
@@ -61,7 +61,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
|
|
|
61
61
|
return `<p>
|
|
62
62
|
${config.dataDescription.seriesKey}: ${groupOne.dataKey}<br/>
|
|
63
63
|
${config.xAxis.dataKey}: ${d[config.xAxis.dataKey]}<br/>
|
|
64
|
-
${label}${formatNumber(d[groupOne.dataKey])}
|
|
64
|
+
${label}${formatNumber(d[groupOne.dataKey], 'left')}
|
|
65
65
|
</p>`
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -69,7 +69,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
|
|
|
69
69
|
return `<p>
|
|
70
70
|
${config.dataDescription.seriesKey}: ${groupTwo.dataKey}<br/>
|
|
71
71
|
${config.xAxis.dataKey}: ${d[config.xAxis.dataKey]}<br/>
|
|
72
|
-
${label}${formatNumber(d[groupTwo.dataKey])}
|
|
72
|
+
${label}${formatNumber(d[groupTwo.dataKey], 'left')}
|
|
73
73
|
</p>`
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -99,7 +99,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
|
|
|
99
99
|
const totalheight = (Number(config.barSpace) + barHeight + borderWidth) * data.length
|
|
100
100
|
config.heights.horizontal = totalheight
|
|
101
101
|
// check if text fits inside of the bar including suffix/prefix,comma,fontSize ..etc
|
|
102
|
-
const textWidth = getTextWidth(formatNumber(d[groupOne.dataKey]), `normal ${fontSize[config.fontSize]}px sans-serif`)
|
|
102
|
+
const textWidth = getTextWidth(formatNumber(d[groupOne.dataKey], 'left'), `normal ${fontSize[config.fontSize]}px sans-serif`)
|
|
103
103
|
const textFits = textWidth < barWidth - 5 // minus padding dx(5)
|
|
104
104
|
|
|
105
105
|
return (
|
|
@@ -123,7 +123,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
|
|
|
123
123
|
/>
|
|
124
124
|
{config.yAxis.displayNumbersOnBar && displayBar && (
|
|
125
125
|
<Text textAnchor={textFits ? 'start' : 'end'} dx={textFits ? 5 : -5} verticalAnchor='middle' x={halfWidth - barWidth} y={y + config.barHeight / 2} fill={textFits ? groupOne.labelColor : '#000'}>
|
|
126
|
-
{formatNumber(d[groupOne.dataKey])}
|
|
126
|
+
{formatNumber(d[groupOne.dataKey], 'left')}
|
|
127
127
|
</Text>
|
|
128
128
|
)}
|
|
129
129
|
</Group>
|
|
@@ -143,7 +143,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
|
|
|
143
143
|
const totalheight = (Number(config.barSpace) + barHeight + borderWidth) * data.length
|
|
144
144
|
config.heights.horizontal = totalheight
|
|
145
145
|
// check if text fits inside of the bar including suffix/prefix,comma,fontSize ..etc
|
|
146
|
-
const textWidth = getTextWidth(formatNumber(d[groupTwo.dataKey]), `normal ${fontSize[config.fontSize]}px sans-serif`)
|
|
146
|
+
const textWidth = getTextWidth(formatNumber(d[groupTwo.dataKey], 'left'), `normal ${fontSize[config.fontSize]}px sans-serif`)
|
|
147
147
|
const isTextFits = textWidth < barWidth - 5 // minus padding dx(5)
|
|
148
148
|
|
|
149
149
|
return (
|
|
@@ -174,7 +174,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
|
|
|
174
174
|
/>
|
|
175
175
|
{config.yAxis.displayNumbersOnBar && displayBar && (
|
|
176
176
|
<Text textAnchor={isTextFits ? 'end' : 'start'} dx={isTextFits ? -5 : 5} verticalAnchor='middle' x={halfWidth + barWidth} y={y + config.barHeight / 2} fill={isTextFits ? groupTwo.labelColor : '#000'}>
|
|
177
|
-
{formatNumber(d[groupTwo.dataKey])}
|
|
177
|
+
{formatNumber(d[groupTwo.dataKey], 'left')}
|
|
178
178
|
</Text>
|
|
179
179
|
)}
|
|
180
180
|
</Group>
|
|
@@ -18,9 +18,7 @@ const enterUpdateTransition = ({ startAngle, endAngle }) => ({
|
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
export default function PieChart() {
|
|
21
|
-
const { transformedData: data, config, dimensions, seriesHighlight, colorScale, formatNumber, currentViewport, handleChartAriaLabels
|
|
22
|
-
|
|
23
|
-
const cleanedData = cleanData(data, config.xAxis.dataKey)
|
|
21
|
+
const { transformedData: data, config, dimensions, seriesHighlight, colorScale, formatNumber, currentViewport, handleChartAriaLabels } = useContext(ConfigContext)
|
|
24
22
|
|
|
25
23
|
const [filteredData, setFilteredData] = useState(undefined)
|
|
26
24
|
const [animatedPie, setAnimatePie] = useState(false)
|
|
@@ -140,7 +138,7 @@ export default function PieChart() {
|
|
|
140
138
|
<ErrorBoundary component='PieChart'>
|
|
141
139
|
<svg width={width} height={height} className={`animated-pie group ${config.animate === false || animatedPie ? 'animated' : ''}`} role='img' aria-label={handleChartAriaLabels(config)}>
|
|
142
140
|
<Group top={centerY} left={centerX}>
|
|
143
|
-
<Pie data={filteredData ||
|
|
141
|
+
<Pie data={filteredData || data} pieValue={d => d[config.runtime.yAxis.dataKey]} pieSortValues={() => -1} innerRadius={radius - donutThickness} outerRadius={radius}>
|
|
144
142
|
{pie => <AnimatedPie {...pie} getKey={d => d.data[config.runtime.xAxis.dataKey]} />}
|
|
145
143
|
</Pie>
|
|
146
144
|
</Group>
|