@cdc/chart 4.22.10 → 4.22.11
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/README.md +5 -5
- package/dist/cdcchart.js +4 -4
- package/examples/age-adjusted-rates.json +1486 -1218
- package/examples/case-rate-example-config.json +1 -1
- package/examples/covid-confidence-example-config.json +33 -33
- package/examples/covid-example-config.json +34 -34
- package/examples/covid-example-data-confidence.json +30 -30
- package/examples/covid-example-data.json +20 -20
- package/examples/cutoff-example-config.json +36 -36
- package/examples/cutoff-example-data.json +36 -36
- package/examples/date-exclusions-config.json +1 -1
- package/examples/dynamic-legends.json +124 -124
- package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json +191 -197
- package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +230 -240
- package/examples/gallery/bar-chart-horizontal/horizontal-stacked.json +239 -247
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +136 -136
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +79 -79
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +80 -80
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +67 -67
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +110 -110
- package/examples/gallery/lollipop/lollipop-style-horizontal.json +215 -219
- package/examples/gallery/paired-bar/paired-bar-chart.json +195 -195
- package/examples/horizontal-chart.json +35 -35
- package/examples/horizontal-stacked-bar-chart.json +34 -34
- package/examples/line-chart.json +75 -75
- package/examples/paired-bar-data.json +16 -14
- package/examples/paired-bar-example.json +48 -48
- package/examples/paired-bar-formatted.json +36 -36
- package/examples/planet-chart-horizontal-example-config.json +33 -33
- package/examples/planet-combo-example-config.json +34 -31
- package/examples/planet-example-config.json +35 -33
- package/examples/planet-example-data.json +56 -56
- package/examples/planet-pie-example-config.json +28 -28
- package/examples/private/filters.json +170 -0
- package/examples/private/line-test-data.json +21 -21
- package/examples/private/line-test-two.json +209 -215
- package/examples/private/line-test.json +101 -101
- package/examples/private/new.json +48800 -0
- package/examples/private/shawn.json +1105 -1295
- package/examples/private/test.json +10123 -10123
- package/examples/private/yaxis-test.json +4 -3
- package/examples/private/yaxis.json +26 -26
- package/examples/stacked-vertical-bar-example.json +1 -1
- package/examples/temp-example-config.json +61 -54
- package/examples/temp-example-data.json +1 -1
- package/package.json +2 -2
- package/src/CdcChart.tsx +339 -380
- package/src/components/BarChart.tsx +425 -469
- package/src/components/DataTable.tsx +164 -195
- package/src/components/EditorPanel.js +1009 -710
- package/src/components/Legend.js +279 -329
- package/src/components/LineChart.tsx +90 -79
- package/src/components/LinearChart.tsx +376 -434
- package/src/components/PairedBarChart.tsx +197 -213
- package/src/components/PieChart.tsx +95 -151
- package/src/components/SparkLine.js +179 -201
- package/src/components/useIntersectionObserver.tsx +17 -20
- package/src/context.tsx +3 -3
- package/src/data/initial-state.js +37 -16
- package/src/hooks/useActiveElement.js +13 -13
- package/src/hooks/useChartClasses.js +34 -28
- package/src/hooks/useColorPalette.ts +56 -63
- package/src/hooks/useLegendClasses.js +18 -10
- package/src/hooks/useReduceData.ts +62 -78
- package/src/hooks/useRightAxis.js +25 -0
- package/src/hooks/useTopAxis.js +6 -0
- package/src/index.html +45 -45
- package/src/index.tsx +13 -16
- package/src/scss/DataTable.scss +5 -4
- package/src/scss/editor-panel.scss +71 -69
- package/src/scss/main.scss +157 -114
- package/src/scss/variables.scss +1 -1
|
@@ -1,160 +1,166 @@
|
|
|
1
|
-
import React, { Fragment, useContext, useEffect, useRef, useState } from 'react'
|
|
2
|
-
import ReactTooltip from 'react-tooltip'
|
|
3
|
-
|
|
4
|
-
import { Group } from '@visx/group'
|
|
5
|
-
import { Line } from '@visx/shape'
|
|
6
|
-
import { Text } from '@visx/text'
|
|
7
|
-
import { scaleLinear, scalePoint } from '@visx/scale'
|
|
8
|
-
import { AxisLeft, AxisBottom } from '@visx/axis'
|
|
9
|
-
|
|
10
|
-
import BarChart from './BarChart'
|
|
11
|
-
import LineChart from './LineChart'
|
|
12
|
-
import Context from '../context'
|
|
13
|
-
import PairedBarChart from './PairedBarChart'
|
|
14
|
-
import useIntersectionObserver from
|
|
15
|
-
import SparkLine from './SparkLine'
|
|
16
|
-
|
|
17
|
-
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
1
|
+
import React, { Fragment, useContext, useEffect, useRef, useState } from 'react'
|
|
2
|
+
import ReactTooltip from 'react-tooltip'
|
|
3
|
+
|
|
4
|
+
import { Group } from '@visx/group'
|
|
5
|
+
import { Line } from '@visx/shape'
|
|
6
|
+
import { Text } from '@visx/text'
|
|
7
|
+
import { scaleLinear, scalePoint } from '@visx/scale'
|
|
8
|
+
import { AxisLeft, AxisBottom, AxisRight, AxisTop } from '@visx/axis'
|
|
9
|
+
|
|
10
|
+
import BarChart from './BarChart'
|
|
11
|
+
import LineChart from './LineChart'
|
|
12
|
+
import Context from '../context'
|
|
13
|
+
import PairedBarChart from './PairedBarChart'
|
|
14
|
+
import useIntersectionObserver from './useIntersectionObserver'
|
|
15
|
+
import SparkLine from './SparkLine'
|
|
16
|
+
|
|
17
|
+
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
18
18
|
import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
19
|
-
import '../scss/LinearChart.scss'
|
|
20
|
-
import useReduceData from '../hooks/useReduceData'
|
|
19
|
+
import '../scss/LinearChart.scss'
|
|
20
|
+
import useReduceData from '../hooks/useReduceData'
|
|
21
|
+
import useRightAxis from '../hooks/useRightAxis'
|
|
22
|
+
import useTopAxis from '../hooks/useTopAxis'
|
|
23
|
+
|
|
24
|
+
// TODO: Move scaling functions into hooks to manage complexity
|
|
21
25
|
|
|
22
26
|
// TODO: remove unused imports/variables
|
|
23
27
|
// TODO: consider moving logic into hooks
|
|
24
28
|
// TODO: formatting
|
|
25
29
|
export default function LinearChart() {
|
|
26
|
-
const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels } = useContext<any>(Context)
|
|
27
|
-
let [
|
|
28
|
-
const {minValue,maxValue,existPositiveValue} = useReduceData(config,data)
|
|
29
|
-
const [animatedChart, setAnimatedChart] = useState<boolean>(false)
|
|
30
|
-
const [animatedChartPlayed, setAnimatedChartPlayed] = useState<boolean>(false)
|
|
30
|
+
const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig } = useContext<any>(Context)
|
|
31
|
+
let [width] = dimensions
|
|
32
|
+
const { minValue, maxValue, existPositiveValue } = useReduceData(config, data)
|
|
33
|
+
const [animatedChart, setAnimatedChart] = useState<boolean>(false)
|
|
34
|
+
const [animatedChartPlayed, setAnimatedChartPlayed] = useState<boolean>(false)
|
|
31
35
|
|
|
32
|
-
const triggerRef = useRef()
|
|
36
|
+
const triggerRef = useRef()
|
|
33
37
|
const dataRef = useIntersectionObserver(triggerRef, {
|
|
34
38
|
freezeOnceVisible: false
|
|
35
|
-
})
|
|
39
|
+
})
|
|
36
40
|
// If the chart is in view and set to animate and it has not already played
|
|
37
|
-
useEffect(
|
|
38
|
-
if(
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (dataRef?.isIntersecting === true && config.animate) {
|
|
39
43
|
setTimeout(() => {
|
|
40
|
-
setAnimatedChart(prevState => true)
|
|
41
|
-
}, 500)
|
|
44
|
+
setAnimatedChart(prevState => true)
|
|
45
|
+
}, 500)
|
|
42
46
|
}
|
|
43
|
-
}, [dataRef?.isIntersecting, config.animate])
|
|
47
|
+
}, [dataRef?.isIntersecting, config.animate])
|
|
44
48
|
|
|
45
|
-
if(config && config.legend && !config.legend.hide && (currentViewport === 'lg' || currentViewport === 'md')) {
|
|
46
|
-
width = width * 0.73
|
|
49
|
+
if (config && config.legend && !config.legend.hide && config.legend.position !== 'bottom' && (currentViewport === 'lg' || currentViewport === 'md')) {
|
|
50
|
+
width = width * 0.73
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
const height = config.aspectRatio ?
|
|
53
|
+
const height = config.aspectRatio ? width * config.aspectRatio : config.height
|
|
54
|
+
const xMax = width - config.runtime.yAxis.size - config.yAxis.rightAxisSize
|
|
55
|
+
const yMax = height - config.runtime.xAxis.size
|
|
50
56
|
|
|
51
|
-
const
|
|
52
|
-
const
|
|
57
|
+
const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data, updateConfig })
|
|
58
|
+
const { hasTopAxis } = useTopAxis(config)
|
|
53
59
|
|
|
54
|
-
const getXAxisData = (d: any) => config.runtime.xAxis.type === 'date' ?
|
|
55
|
-
const getYAxisData = (d: any, seriesKey: string) => d[seriesKey]
|
|
60
|
+
const getXAxisData = (d: any) => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
|
|
61
|
+
const getYAxisData = (d: any, seriesKey: string) => d[seriesKey]
|
|
56
62
|
|
|
57
|
-
let xScale
|
|
58
|
-
let yScale
|
|
59
|
-
let seriesScale
|
|
63
|
+
let xScale
|
|
64
|
+
let yScale
|
|
65
|
+
let seriesScale
|
|
60
66
|
|
|
61
|
-
const {max:enteredMaxValue,min:enteredMinValue} = config.runtime.yAxis
|
|
62
|
-
const isMaxValid = existPositiveValue ? numberFromString(enteredMaxValue)
|
|
63
|
-
const isMinValid = (
|
|
67
|
+
const { max: enteredMaxValue, min: enteredMinValue } = config.runtime.yAxis
|
|
68
|
+
const isMaxValid = existPositiveValue ? numberFromString(enteredMaxValue) >= numberFromString(maxValue) : numberFromString(enteredMaxValue) >= 0
|
|
69
|
+
const isMinValid = (numberFromString(enteredMinValue) <= 0 && numberFromString(minValue) >= 0) || (numberFromString(enteredMinValue) <= minValue && minValue < 0)
|
|
64
70
|
|
|
65
71
|
if (data) {
|
|
66
|
-
let min = enteredMinValue && isMinValid ? enteredMinValue : minValue
|
|
67
|
-
let max = enteredMaxValue && isMaxValid ? enteredMaxValue : Number.MIN_VALUE
|
|
72
|
+
let min = enteredMinValue && isMinValid ? enteredMinValue : minValue
|
|
73
|
+
let max = enteredMaxValue && isMaxValid ? enteredMaxValue : Number.MIN_VALUE
|
|
68
74
|
|
|
69
|
-
if((config.visualizationType === 'Bar' || config.visualizationType === 'Combo') && min > 0) {
|
|
70
|
-
min = 0
|
|
75
|
+
if ((config.visualizationType === 'Bar' || config.visualizationType === 'Combo') && min > 0) {
|
|
76
|
+
min = 0
|
|
71
77
|
}
|
|
72
|
-
if(config.visualizationType === 'Line'
|
|
78
|
+
if (config.visualizationType === 'Line') {
|
|
73
79
|
const isMinValid = Number(enteredMinValue) < Number(minValue)
|
|
74
|
-
min =
|
|
80
|
+
min = enteredMinValue && isMinValid ? Number(enteredMinValue) : minValue
|
|
75
81
|
}
|
|
76
82
|
//If data value max wasn't provided, calculate it
|
|
77
|
-
if(max === Number.MIN_VALUE){
|
|
83
|
+
if (max === Number.MIN_VALUE) {
|
|
78
84
|
// if all values in data are negative set max = 0
|
|
79
|
-
max = existPositiveValue ? maxValue : 0
|
|
85
|
+
max = existPositiveValue ? maxValue : 0
|
|
80
86
|
}
|
|
81
|
-
|
|
87
|
+
|
|
82
88
|
//Adds Y Axis data padding if applicable
|
|
83
|
-
if(config.runtime.yAxis.paddingPercent) {
|
|
84
|
-
let paddingValue = (max - min) * config.runtime.yAxis.paddingPercent
|
|
85
|
-
min -= paddingValue
|
|
86
|
-
max += paddingValue
|
|
89
|
+
if (config.runtime.yAxis.paddingPercent) {
|
|
90
|
+
let paddingValue = (max - min) * config.runtime.yAxis.paddingPercent
|
|
91
|
+
min -= paddingValue
|
|
92
|
+
max += paddingValue
|
|
87
93
|
}
|
|
88
94
|
|
|
89
|
-
let xAxisDataMapped = data.map(d => getXAxisData(d))
|
|
95
|
+
let xAxisDataMapped = data.map(d => getXAxisData(d))
|
|
90
96
|
|
|
91
97
|
if (config.isLollipopChart && config.yAxis.displayNumbersOnBar) {
|
|
92
|
-
const dataKey = data.map(
|
|
93
|
-
const maxDataVal = Math.max(...dataKey).toString().length
|
|
98
|
+
const dataKey = data.map(item => item[config.series[0].dataKey])
|
|
99
|
+
const maxDataVal = Math.max(...dataKey).toString().length
|
|
94
100
|
|
|
95
101
|
switch (true) {
|
|
96
102
|
case maxDataVal > 8 && maxDataVal <= 12:
|
|
97
|
-
max = max * 1.3
|
|
98
|
-
break
|
|
103
|
+
max = max * 1.3
|
|
104
|
+
break
|
|
99
105
|
case maxDataVal > 4 && maxDataVal <= 7:
|
|
100
|
-
max = max * 1.1
|
|
101
|
-
break
|
|
106
|
+
max = max * 1.1
|
|
107
|
+
break
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
110
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
range: [0, xMax],
|
|
138
|
-
padding: 0.5,
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
seriesScale = scalePoint<string>({
|
|
142
|
-
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
143
|
-
range: [0, xMax],
|
|
144
|
-
});
|
|
145
|
-
}
|
|
111
|
+
if (config.runtime.horizontal) {
|
|
112
|
+
xScale = scaleLinear<number>({
|
|
113
|
+
domain: [min, max],
|
|
114
|
+
range: [0, xMax]
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
yScale =
|
|
118
|
+
config.runtime.xAxis.type === 'date'
|
|
119
|
+
? scaleLinear<number>({
|
|
120
|
+
domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)]
|
|
121
|
+
})
|
|
122
|
+
: scalePoint<string>({ domain: xAxisDataMapped, padding: 0.5 })
|
|
123
|
+
|
|
124
|
+
seriesScale = scalePoint<string>({
|
|
125
|
+
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
126
|
+
range: [0, yMax]
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
yScale.rangeRound([0, yMax])
|
|
130
|
+
} else {
|
|
131
|
+
min = min < 0 ? min * 1.11 : min
|
|
132
|
+
|
|
133
|
+
yScale = scaleLinear<number>({
|
|
134
|
+
domain: [min, max],
|
|
135
|
+
range: [yMax, 0]
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
xScale = scalePoint<string>({
|
|
139
|
+
domain: xAxisDataMapped,
|
|
140
|
+
range: [0, xMax],
|
|
141
|
+
padding: 0.5
|
|
142
|
+
})
|
|
146
143
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
144
|
+
seriesScale = scalePoint<string>({
|
|
145
|
+
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
146
|
+
range: [0, xMax]
|
|
147
|
+
})
|
|
148
|
+
}
|
|
150
149
|
|
|
151
|
-
|
|
152
|
-
let
|
|
150
|
+
if (config.visualizationType === 'Paired Bar') {
|
|
151
|
+
let groupOneMax = Math.max.apply(
|
|
152
|
+
Math,
|
|
153
|
+
data.map(d => d[config.series[0].dataKey])
|
|
154
|
+
)
|
|
155
|
+
let groupTwoMax = Math.max.apply(
|
|
156
|
+
Math,
|
|
157
|
+
data.map(d => d[config.series[1].dataKey])
|
|
158
|
+
)
|
|
153
159
|
|
|
154
160
|
// group one
|
|
155
161
|
var g1xScale = scaleLinear<number>({
|
|
156
|
-
domain: [0, Math.max(groupOneMax,groupTwoMax)
|
|
157
|
-
range: [xMax/2, 0]
|
|
162
|
+
domain: [0, Math.max(groupOneMax, groupTwoMax)],
|
|
163
|
+
range: [xMax / 2, 0]
|
|
158
164
|
})
|
|
159
165
|
|
|
160
166
|
// group 2
|
|
@@ -162,391 +168,327 @@ export default function LinearChart() {
|
|
|
162
168
|
domain: g1xScale.domain(),
|
|
163
169
|
range: [xMax / 2, xMax]
|
|
164
170
|
})
|
|
165
|
-
|
|
166
171
|
}
|
|
167
172
|
}
|
|
168
173
|
|
|
169
|
-
|
|
174
|
+
|
|
175
|
+
const countNumOfTicks = (axis)=>{
|
|
176
|
+
// 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
|
+
};
|
|
170
200
|
|
|
171
201
|
useEffect(() => {
|
|
172
|
-
ReactTooltip.rebuild()
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
return isNaN(width) ?
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
<Group className="regions" left={config.runtime.yAxis.size} key={region.label}>
|
|
195
|
-
<path stroke="#333" d={`M${from} -5
|
|
202
|
+
ReactTooltip.rebuild()
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
return isNaN(width) ? (
|
|
206
|
+
<></>
|
|
207
|
+
) : (
|
|
208
|
+
<ErrorBoundary component='LinearChart'>
|
|
209
|
+
<svg width={width} height={height} className={`linear ${config.animate ? 'animated' : ''} ${animatedChart && config.animate ? 'animate' : ''}`} role='img' aria-label={handleChartAriaLabels(config)} tabIndex={0}>
|
|
210
|
+
{/* Higlighted regions */}
|
|
211
|
+
{config.regions
|
|
212
|
+
? config.regions.map(region => {
|
|
213
|
+
if (!Object.keys(region).includes('from') || !Object.keys(region).includes('to')) return null
|
|
214
|
+
|
|
215
|
+
const from = xScale(parseDate(region.from).getTime())
|
|
216
|
+
const to = xScale(parseDate(region.to).getTime())
|
|
217
|
+
const width = to - from
|
|
218
|
+
|
|
219
|
+
return (
|
|
220
|
+
<Group className='regions' left={config.runtime.yAxis.size} key={region.label}>
|
|
221
|
+
<path
|
|
222
|
+
stroke='#333'
|
|
223
|
+
d={`M${from} -5
|
|
196
224
|
L${from} 5
|
|
197
225
|
M${from} 0
|
|
198
226
|
L${to} 0
|
|
199
227
|
M${to} -5
|
|
200
|
-
L${to} 5`}
|
|
201
|
-
|
|
202
|
-
x={from}
|
|
203
|
-
y={
|
|
204
|
-
width={width}
|
|
205
|
-
height={yMax}
|
|
206
|
-
fill={region.background}
|
|
207
|
-
opacity={0.3} />
|
|
208
|
-
<Text
|
|
209
|
-
x={from + (width / 2)}
|
|
210
|
-
y={5}
|
|
211
|
-
fill={region.color}
|
|
212
|
-
verticalAnchor="start"
|
|
213
|
-
textAnchor="middle">
|
|
228
|
+
L${to} 5`}
|
|
229
|
+
/>
|
|
230
|
+
<rect x={from} y={0} width={width} height={yMax} fill={region.background} opacity={0.3} />
|
|
231
|
+
<Text x={from + width / 2} y={5} fill={region.color} verticalAnchor='start' textAnchor='middle'>
|
|
214
232
|
{region.label}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
233
|
+
</Text>
|
|
234
|
+
</Group>
|
|
235
|
+
)
|
|
236
|
+
})
|
|
237
|
+
: ''}
|
|
238
|
+
|
|
239
|
+
{/* Y axis */}
|
|
240
|
+
{config.visualizationType !== 'Spark Line' && (
|
|
241
|
+
<AxisLeft
|
|
223
242
|
scale={yScale}
|
|
224
243
|
left={config.runtime.yAxis.size}
|
|
225
244
|
label={config.runtime.yAxis.label}
|
|
226
|
-
stroke=
|
|
227
|
-
tickFormat={
|
|
228
|
-
numTicks={
|
|
245
|
+
stroke='#333'
|
|
246
|
+
tickFormat={tick => (config.runtime.yAxis.type === 'date' ? formatDate(parseDate(tick)) : config.orientation === 'vertical' ? formatNumber(tick) : tick)}
|
|
247
|
+
numTicks={countNumOfTicks('yAxis')}
|
|
229
248
|
>
|
|
230
249
|
{props => {
|
|
231
|
-
const lollipopShapeSize = config.lollipopSize === 'large' ? 14 : config.lollipopSize === 'medium' ? 12 : 10
|
|
232
|
-
const axisCenter = config.runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
|
|
233
|
-
const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length * (1 - config.barThickness)
|
|
234
|
-
const belowBarPaddingFromTop = 9
|
|
250
|
+
const lollipopShapeSize = config.lollipopSize === 'large' ? 14 : config.lollipopSize === 'medium' ? 12 : 10
|
|
251
|
+
const axisCenter = config.runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
|
|
252
|
+
const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
|
|
253
|
+
const belowBarPaddingFromTop = 9
|
|
235
254
|
return (
|
|
236
|
-
<Group className=
|
|
255
|
+
<Group className='left-axis'>
|
|
237
256
|
{props.ticks.map((tick, i) => {
|
|
238
257
|
return (
|
|
239
|
-
<Group
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
{!config.runtime.yAxis.hideTicks && (
|
|
244
|
-
<Line
|
|
245
|
-
from={tick.from}
|
|
246
|
-
to={tick.to}
|
|
247
|
-
stroke="#333"
|
|
248
|
-
display={config.runtime.horizontal ? 'none' : 'block'}
|
|
249
|
-
/>
|
|
250
|
-
)}
|
|
258
|
+
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
259
|
+
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke={config.yAxis.tickColor} display={config.runtime.horizontal ? 'none' : 'block'} />}
|
|
260
|
+
|
|
261
|
+
{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)' /> : ''}
|
|
251
262
|
|
|
252
|
-
{ config.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
stroke="rgba(0,0,0,0.3)"
|
|
257
|
-
/>
|
|
258
|
-
) : ''
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
{( config.orientation === "horizontal" && config.visualizationSubType !== 'stacked') && (config.yAxis.labelPlacement === 'On Date/Category Axis' ) && !config.yAxis.hideLabel &&
|
|
262
|
-
// 17 is a magic number from the offset in barchart.
|
|
263
|
-
<Fragment>
|
|
264
|
-
<Text
|
|
265
|
-
transform={`translate(${tick.to.x - 5}, ${ config.isLollipopChart ? tick.from.y : tick.from.y - 17 }) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`}
|
|
266
|
-
verticalAnchor={ config.isLollipopChart ? "middle" : "middle"}
|
|
267
|
-
textAnchor={"end"}
|
|
268
|
-
>{tick.formattedValue}</Text>
|
|
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
|
|
275
|
-
transform={`translate(${tick.to.x - 5}, ${ tick.from.y - config.barHeight / 2 - 3 }) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`}
|
|
276
|
-
verticalAnchor={ config.isLollipopChart ? "middle" : "middle"}
|
|
277
|
-
textAnchor={"end"}
|
|
278
|
-
>{tick.formattedValue}</Text>
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
{ (config.orientation === "horizontal" && config.visualizationType === 'Paired Bar') && !config.yAxis.hideLabel &&
|
|
282
|
-
// 17 is a magic number from the offset in barchart.
|
|
283
|
-
<Text
|
|
284
|
-
transform={`translate(${-15}, ${ tick.from.y }) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`}
|
|
285
|
-
verticalAnchor={ config.isLollipopChart ? "middle" : "middle"}
|
|
286
|
-
textAnchor={"end"}
|
|
287
|
-
>{tick.formattedValue}</Text>
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
{ (config.orientation === "horizontal" && config.visualizationType === 'Paired Bar') && !config.yAxis.hideLabel &&
|
|
291
|
-
// 17 is a magic number from the offset in barchart.
|
|
292
|
-
<Text
|
|
293
|
-
transform={`translate(${-15}, ${ tick.from.y }) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`}
|
|
294
|
-
verticalAnchor={ config.isLollipopChart ? "middle" : "middle"}
|
|
295
|
-
textAnchor={"end"}
|
|
296
|
-
>{formatNumber(tick.formattedValue)}</Text>
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
{ config.orientation !== "horizontal" && config.visualizationType !== 'Paired Bar' && !config.yAxis.hideLabel &&
|
|
301
|
-
<Text
|
|
302
|
-
x={config.runtime.horizontal ? tick.from.x + 2 : tick.to.x}
|
|
303
|
-
y={tick.to.y + (config.runtime.horizontal ? horizontalTickOffset : 0)}
|
|
304
|
-
verticalAnchor={config.runtime.horizontal ? "start" : "middle"}
|
|
305
|
-
textAnchor={config.runtime.horizontal ? 'start' : 'end'}
|
|
306
|
-
>
|
|
263
|
+
{config.orientation === 'horizontal' && config.visualizationSubType !== 'stacked' && config.yAxis.labelPlacement === 'On Date/Category Axis' && !config.yAxis.hideLabel && (
|
|
264
|
+
// 17 is a magic number from the offset in barchart.
|
|
265
|
+
<Fragment>
|
|
266
|
+
<Text transform={`translate(${tick.to.x - 5}, ${config.isLollipopChart ? tick.from.y : tick.from.y - 17}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} verticalAnchor={config.isLollipopChart ? 'middle' : 'middle'} textAnchor={'end'}>
|
|
307
267
|
{tick.formattedValue}
|
|
308
268
|
</Text>
|
|
309
|
-
|
|
269
|
+
</Fragment>
|
|
270
|
+
)}
|
|
310
271
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
to={props.axisToPoint}
|
|
318
|
-
stroke="#333"
|
|
319
|
-
/>
|
|
320
|
-
)}
|
|
321
|
-
{ yScale.domain()[0] < 0 && (
|
|
322
|
-
<Line
|
|
323
|
-
from={{x: props.axisFromPoint.x, y: yScale(0)}}
|
|
324
|
-
to={{x: xMax, y: yScale(0)}}
|
|
325
|
-
stroke="#333"
|
|
326
|
-
/>
|
|
327
|
-
)}
|
|
328
|
-
<Text
|
|
329
|
-
className="y-label"
|
|
330
|
-
textAnchor="middle"
|
|
331
|
-
verticalAnchor="start"
|
|
332
|
-
transform={`translate(${-1 * config.runtime.yAxis.size}, ${axisCenter}) rotate(-90)`}
|
|
333
|
-
fontWeight="bold"
|
|
334
|
-
>
|
|
335
|
-
{props.label}
|
|
336
|
-
</Text>
|
|
337
|
-
</Group>
|
|
338
|
-
);
|
|
339
|
-
}}
|
|
340
|
-
</AxisLeft>
|
|
341
|
-
}
|
|
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'}>
|
|
275
|
+
{tick.formattedValue}
|
|
276
|
+
</Text>
|
|
277
|
+
)}
|
|
342
278
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
label={config.runtime.xAxis.label}
|
|
349
|
-
tickFormat={tick=> config.runtime.xAxis.type === 'date' ? formatDate(tick) : config.orientation ==='horizontal' ? formatNumber(tick) : tick}
|
|
350
|
-
scale={xScale}
|
|
351
|
-
stroke="#333"
|
|
352
|
-
tickStroke="#333"
|
|
353
|
-
numTicks={config.runtime.xAxis.numTicks || undefined}
|
|
354
|
-
>
|
|
355
|
-
{props => {
|
|
356
|
-
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2;
|
|
357
|
-
return (
|
|
358
|
-
<Group className="bottom-axis">
|
|
359
|
-
{props.ticks.map((tick, i) => {
|
|
360
|
-
const tickWidth = xMax / props.ticks.length;
|
|
361
|
-
return (
|
|
362
|
-
<Group
|
|
363
|
-
key={`vx-tick-${tick.value}-${i}`}
|
|
364
|
-
className={'vx-axis-tick'}
|
|
365
|
-
>
|
|
366
|
-
{!config.xAxis.hideTicks && (
|
|
367
|
-
<Line
|
|
368
|
-
from={tick.from}
|
|
369
|
-
to={tick.to}
|
|
370
|
-
stroke="#333"
|
|
371
|
-
/>
|
|
279
|
+
{config.orientation === 'horizontal' && config.visualizationType === 'Paired Bar' && !config.yAxis.hideLabel && (
|
|
280
|
+
// 17 is a magic number from the offset in barchart.
|
|
281
|
+
<Text transform={`translate(${-15}, ${tick.from.y}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} verticalAnchor={config.isLollipopChart ? 'middle' : 'middle'} textAnchor={'end'}>
|
|
282
|
+
{tick.formattedValue}
|
|
283
|
+
</Text>
|
|
372
284
|
)}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
verticalAnchor=
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
>
|
|
380
|
-
{tick.formattedValue}
|
|
381
|
-
</Text>
|
|
285
|
+
|
|
286
|
+
{config.orientation === 'horizontal' && config.visualizationType === 'Paired Bar' && !config.yAxis.hideLabel && (
|
|
287
|
+
// 17 is a magic number from the offset in barchart.
|
|
288
|
+
<Text transform={`translate(${-15}, ${tick.from.y}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} verticalAnchor={config.isLollipopChart ? 'middle' : 'middle'} textAnchor={'end'}>
|
|
289
|
+
{formatNumber(tick.formattedValue)}
|
|
290
|
+
</Text>
|
|
382
291
|
)}
|
|
383
292
|
|
|
293
|
+
{config.orientation !== 'horizontal' && config.visualizationType !== 'Paired Bar' && !config.yAxis.hideLabel && (
|
|
294
|
+
<Text
|
|
295
|
+
x={config.runtime.horizontal ? tick.from.x + 2 : tick.to.x}
|
|
296
|
+
y={tick.to.y + (config.runtime.horizontal ? horizontalTickOffset : 0)}
|
|
297
|
+
verticalAnchor={config.runtime.horizontal ? 'start' : 'middle'}
|
|
298
|
+
textAnchor={config.runtime.horizontal ? 'start' : 'end'}
|
|
299
|
+
fill={config.yAxis.tickLabelColor}
|
|
300
|
+
>
|
|
301
|
+
{tick.formattedValue}
|
|
302
|
+
</Text>
|
|
303
|
+
)}
|
|
384
304
|
</Group>
|
|
385
|
-
)
|
|
305
|
+
)
|
|
386
306
|
})}
|
|
387
|
-
{!config.
|
|
388
|
-
<Line
|
|
389
|
-
|
|
390
|
-
to={props.axisToPoint}
|
|
391
|
-
stroke="#333"
|
|
392
|
-
/>
|
|
393
|
-
)}
|
|
394
|
-
<Text
|
|
395
|
-
x={axisCenter}
|
|
396
|
-
y={config.runtime.xAxis.size}
|
|
397
|
-
textAnchor="middle"
|
|
398
|
-
verticalAnchor="end"
|
|
399
|
-
fontWeight="bold"
|
|
400
|
-
>
|
|
307
|
+
{!config.yAxis.hideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
|
|
308
|
+
{yScale.domain()[0] < 0 && <Line from={{ x: props.axisFromPoint.x, y: yScale(0) }} to={{ x: xMax, y: yScale(0) }} stroke='#333' />}
|
|
309
|
+
<Text className='y-label' textAnchor='middle' verticalAnchor='start' transform={`translate(${-1 * config.runtime.yAxis.size}, ${axisCenter}) rotate(-90)`} fontWeight='bold' fill={config.yAxis.labelColor}>
|
|
401
310
|
{props.label}
|
|
402
311
|
</Text>
|
|
403
312
|
</Group>
|
|
404
|
-
)
|
|
313
|
+
)
|
|
405
314
|
}}
|
|
406
|
-
</
|
|
407
|
-
|
|
315
|
+
</AxisLeft>
|
|
316
|
+
)}
|
|
408
317
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
<
|
|
412
|
-
top={yMax}
|
|
413
|
-
left={config.runtime.yAxis.size}
|
|
414
|
-
label={config.runtime.xAxis.label}
|
|
415
|
-
tickFormat={config.runtime.xAxis.type === 'date' ? formatDate :formatNumber}
|
|
416
|
-
scale={g1xScale}
|
|
417
|
-
stroke="#333"
|
|
418
|
-
tickStroke="#333"
|
|
419
|
-
numTicks={config.runtime.xAxis.numTicks || undefined}
|
|
420
|
-
>
|
|
318
|
+
{/* Right Axis */}
|
|
319
|
+
{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}>
|
|
421
321
|
{props => {
|
|
422
|
-
const axisCenter = (props.axisToPoint.
|
|
322
|
+
const axisCenter = config.runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
|
|
323
|
+
const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
|
|
423
324
|
return (
|
|
424
|
-
<Group className=
|
|
325
|
+
<Group className='right-axis'>
|
|
425
326
|
{props.ticks.map((tick, i) => {
|
|
426
|
-
const tickWidth = xMax / props.ticks.length;
|
|
427
327
|
return (
|
|
428
|
-
<Group
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
stroke="#333"
|
|
437
|
-
/>
|
|
438
|
-
}
|
|
439
|
-
{!config.runtime.yAxis.hideLabel &&
|
|
440
|
-
<Text
|
|
441
|
-
transform={`translate(${tick.to.x}, ${tick.to.y}) rotate(-${60})`}
|
|
442
|
-
verticalAnchor="start"
|
|
443
|
-
textAnchor={'end'}
|
|
444
|
-
width={config.runtime.xAxis.tickRotation && config.runtime.xAxis.tickRotation !== '0' ? undefined : tickWidth}
|
|
445
|
-
>
|
|
446
|
-
{formatNumber(tick.formattedValue)}
|
|
328
|
+
<Group key={`vx-tick-${tick.value}-${i}`} className='vx-axis-tick'>
|
|
329
|
+
{!config.runtime.yAxis.rightHideTicks && <Line from={tick.from} to={tick.to} display={config.runtime.horizontal ? 'none' : 'block'} stroke={config.yAxis.rightAxisTickColor} />}
|
|
330
|
+
|
|
331
|
+
{config.runtime.yAxis.rightGridLines ? <Line from={{ x: tick.from.x + xMax, y: tick.from.y }} to={tick.from} stroke='rgba(0,0,0,0.3)' /> : ''}
|
|
332
|
+
|
|
333
|
+
{!config.yAxis.rightHideLabel && (
|
|
334
|
+
<Text x={tick.to.x} y={tick.to.y + (config.runtime.horizontal ? horizontalTickOffset : 0)} verticalAnchor={config.runtime.horizontal ? 'start' : 'middle'} textAnchor={'start'} fill={config.yAxis.rightAxisTickLabelColor}>
|
|
335
|
+
{tick.formattedValue}
|
|
447
336
|
</Text>
|
|
448
|
-
|
|
337
|
+
)}
|
|
449
338
|
</Group>
|
|
450
|
-
)
|
|
339
|
+
)
|
|
451
340
|
})}
|
|
452
|
-
{!config.
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
stroke="#333"
|
|
457
|
-
/>
|
|
458
|
-
}
|
|
341
|
+
{!config.yAxis.rightHideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
|
|
342
|
+
<Text className='y-label' textAnchor='middle' verticalAnchor='start' transform={`translate(${config.yAxis.rightLabelOffsetSize ? config.yAxis.rightLabelOffsetSize : 0}, ${axisCenter}) rotate(90)`} fontWeight='bold' fill={config.yAxis.rightAxisLabelColor}>
|
|
343
|
+
{props.label}
|
|
344
|
+
</Text>
|
|
459
345
|
</Group>
|
|
460
|
-
)
|
|
346
|
+
)
|
|
461
347
|
}}
|
|
462
|
-
</
|
|
348
|
+
</AxisRight>
|
|
349
|
+
)}
|
|
350
|
+
|
|
351
|
+
{hasTopAxis && config.topAxis.hasLine && (
|
|
352
|
+
<AxisTop
|
|
353
|
+
stroke='#333'
|
|
354
|
+
left={config.runtime.yAxis.size}
|
|
355
|
+
scale={xScale}
|
|
356
|
+
hideTicks
|
|
357
|
+
hideZero
|
|
358
|
+
tickLabelProps={() => ({
|
|
359
|
+
fill: 'transparent'
|
|
360
|
+
})}
|
|
361
|
+
/>
|
|
362
|
+
)}
|
|
363
|
+
|
|
364
|
+
{/* X axis */}
|
|
365
|
+
{config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Spark Line' && (
|
|
463
366
|
<AxisBottom
|
|
464
367
|
top={yMax}
|
|
465
368
|
left={config.runtime.yAxis.size}
|
|
466
369
|
label={config.runtime.xAxis.label}
|
|
467
|
-
tickFormat={config.runtime.xAxis.type === 'date' ? formatDate : config.
|
|
468
|
-
scale={
|
|
469
|
-
stroke=
|
|
470
|
-
tickStroke=
|
|
471
|
-
numTicks={
|
|
370
|
+
tickFormat={tick => (config.runtime.xAxis.type === 'date' ? formatDate(tick) : config.orientation === 'horizontal' ? formatNumber(tick) : tick)}
|
|
371
|
+
scale={xScale}
|
|
372
|
+
stroke='#333'
|
|
373
|
+
tickStroke='#333'
|
|
374
|
+
numTicks={countNumOfTicks('xAxis')}
|
|
472
375
|
>
|
|
473
376
|
{props => {
|
|
474
|
-
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
|
|
377
|
+
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
|
|
475
378
|
return (
|
|
476
|
-
|
|
477
|
-
<Group className="bottom-axis">
|
|
379
|
+
<Group className='bottom-axis'>
|
|
478
380
|
{props.ticks.map((tick, i) => {
|
|
479
|
-
const tickWidth = xMax / props.ticks.length
|
|
381
|
+
const tickWidth = xMax / props.ticks.length
|
|
480
382
|
return (
|
|
481
|
-
<Group
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
>
|
|
485
|
-
{!config.runtime.yAxis.hideTicks &&
|
|
486
|
-
<Line
|
|
487
|
-
from={tick.from}
|
|
488
|
-
to={tick.to}
|
|
489
|
-
stroke="#333"
|
|
490
|
-
/>
|
|
491
|
-
}
|
|
492
|
-
{!config.runtime.yAxis.hideLabel &&
|
|
383
|
+
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
384
|
+
{!config.xAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke={config.xAxis.tickColor} />}
|
|
385
|
+
{!config.xAxis.hideLabel && (
|
|
493
386
|
<Text
|
|
494
|
-
transform={`translate(${tick.to.x}, ${tick.to.y}) rotate(-${
|
|
495
|
-
verticalAnchor=
|
|
496
|
-
textAnchor={'end'}
|
|
387
|
+
transform={`translate(${tick.to.x}, ${tick.to.y}) rotate(-${!config.runtime.horizontal ? config.runtime.xAxis.tickRotation : 0})`}
|
|
388
|
+
verticalAnchor='start'
|
|
389
|
+
textAnchor={config.runtime.xAxis.tickRotation && config.runtime.xAxis.tickRotation !== '0' ? 'end' : 'middle'}
|
|
497
390
|
width={config.runtime.xAxis.tickRotation && config.runtime.xAxis.tickRotation !== '0' ? undefined : tickWidth}
|
|
391
|
+
fill={config.xAxis.tickLabelColor}
|
|
498
392
|
>
|
|
499
393
|
{tick.formattedValue}
|
|
500
394
|
</Text>
|
|
501
|
-
}
|
|
395
|
+
)}
|
|
502
396
|
</Group>
|
|
503
|
-
)
|
|
397
|
+
)
|
|
504
398
|
})}
|
|
505
|
-
{!config.
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
stroke="#333"
|
|
510
|
-
/>
|
|
511
|
-
}
|
|
399
|
+
{!config.xAxis.hideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
|
|
400
|
+
<Text x={axisCenter} y={config.runtime.xAxis.size} textAnchor='middle' verticalAnchor='end' fontWeight='bold' fill={config.xAxis.labelColor}>
|
|
401
|
+
{props.label}
|
|
402
|
+
</Text>
|
|
512
403
|
</Group>
|
|
513
|
-
|
|
514
|
-
<Text
|
|
515
|
-
transform={`translate(${xMax/2}, ${config.height - yMax + 20}) rotate(-${0})`}
|
|
516
|
-
verticalAnchor="start"
|
|
517
|
-
textAnchor={'middle'}
|
|
518
|
-
stroke="#333"
|
|
519
|
-
>
|
|
520
|
-
{config.runtime.xAxis.label}
|
|
521
|
-
</Text>
|
|
522
|
-
</Group>
|
|
523
|
-
</>
|
|
524
|
-
);
|
|
404
|
+
)
|
|
525
405
|
}}
|
|
526
406
|
</AxisBottom>
|
|
407
|
+
)}
|
|
408
|
+
|
|
409
|
+
{config.visualizationType === 'Paired Bar' && (
|
|
410
|
+
<>
|
|
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}>
|
|
412
|
+
{props => {
|
|
413
|
+
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
|
|
414
|
+
return (
|
|
415
|
+
<Group className='bottom-axis'>
|
|
416
|
+
{props.ticks.map((tick, i) => {
|
|
417
|
+
const tickWidth = xMax / props.ticks.length
|
|
418
|
+
return (
|
|
419
|
+
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
420
|
+
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
|
|
421
|
+
{!config.runtime.yAxis.hideLabel && (
|
|
422
|
+
<Text transform={`translate(${tick.to.x}, ${tick.to.y}) rotate(-${60})`} verticalAnchor='start' textAnchor={'end'} width={config.runtime.xAxis.tickRotation && config.runtime.xAxis.tickRotation !== '0' ? undefined : tickWidth}>
|
|
423
|
+
{formatNumber(tick.formattedValue)}
|
|
424
|
+
</Text>
|
|
425
|
+
)}
|
|
426
|
+
</Group>
|
|
427
|
+
)
|
|
428
|
+
})}
|
|
429
|
+
{!config.runtime.yAxis.hideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
|
|
430
|
+
</Group>
|
|
431
|
+
)
|
|
432
|
+
}}
|
|
433
|
+
</AxisBottom>
|
|
434
|
+
<AxisBottom
|
|
435
|
+
top={yMax}
|
|
436
|
+
left={config.runtime.yAxis.size}
|
|
437
|
+
label={config.runtime.xAxis.label}
|
|
438
|
+
tickFormat={config.runtime.xAxis.type === 'date' ? formatDate : config.runtime.xAxis.dataKey !== 'Year' ? formatNumber : tick => tick}
|
|
439
|
+
scale={g2xScale}
|
|
440
|
+
stroke='#333'
|
|
441
|
+
tickStroke='#333'
|
|
442
|
+
numTicks={config.runtime.xAxis.numTicks || undefined}
|
|
443
|
+
>
|
|
444
|
+
{props => {
|
|
445
|
+
const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
|
|
446
|
+
return (
|
|
447
|
+
<>
|
|
448
|
+
<Group className='bottom-axis'>
|
|
449
|
+
{props.ticks.map((tick, i) => {
|
|
450
|
+
const tickWidth = xMax / props.ticks.length
|
|
451
|
+
return (
|
|
452
|
+
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
453
|
+
{!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
|
|
454
|
+
{!config.runtime.yAxis.hideLabel && (
|
|
455
|
+
<Text transform={`translate(${tick.to.x}, ${tick.to.y}) rotate(-${60})`} verticalAnchor='start' textAnchor={'end'} width={config.runtime.xAxis.tickRotation && config.runtime.xAxis.tickRotation !== '0' ? undefined : tickWidth}>
|
|
456
|
+
{tick.formattedValue}
|
|
457
|
+
</Text>
|
|
458
|
+
)}
|
|
459
|
+
</Group>
|
|
460
|
+
)
|
|
461
|
+
})}
|
|
462
|
+
{!config.runtime.yAxis.hideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
|
|
463
|
+
</Group>
|
|
464
|
+
<Group>
|
|
465
|
+
<Text transform={`translate(${xMax / 2}, ${config.height - yMax + 20}) rotate(-${0})`} verticalAnchor='start' textAnchor={'middle'} stroke='#333'>
|
|
466
|
+
{config.runtime.xAxis.label}
|
|
467
|
+
</Text>
|
|
468
|
+
</Group>
|
|
469
|
+
</>
|
|
470
|
+
)
|
|
471
|
+
}}
|
|
472
|
+
</AxisBottom>
|
|
473
|
+
</>
|
|
474
|
+
)}
|
|
475
|
+
{config.visualizationType === 'Paired Bar' && <PairedBarChart width={xMax} height={yMax} />}
|
|
476
|
+
|
|
477
|
+
{/* Bar chart */}
|
|
478
|
+
{config.visualizationType !== 'Line' && config.visualizationType !== 'Paired Bar' && (
|
|
479
|
+
<>
|
|
480
|
+
<BarChart xScale={xScale} yScale={yScale} seriesScale={seriesScale} xMax={xMax} yMax={yMax} getXAxisData={getXAxisData} getYAxisData={getYAxisData} animatedChart={animatedChart} visible={animatedChart} />
|
|
481
|
+
</>
|
|
482
|
+
)}
|
|
483
|
+
|
|
484
|
+
{/* Line chart */}
|
|
485
|
+
{config.visualizationType !== 'Bar' && config.visualizationType !== 'Paired Bar' && (
|
|
486
|
+
<>
|
|
487
|
+
<LineChart xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} xMax={xMax} yMax={yMax} seriesStyle={config.series} />
|
|
527
488
|
</>
|
|
528
|
-
|
|
529
|
-
{ config.visualizationType === 'Paired Bar' && (
|
|
530
|
-
<PairedBarChart width={xMax} height={yMax} />
|
|
531
|
-
) }
|
|
532
|
-
|
|
533
|
-
{/* Bar chart */}
|
|
534
|
-
{ (config.visualizationType !== 'Line' && config.visualizationType !== 'Paired Bar') && (
|
|
535
|
-
<>
|
|
536
|
-
<BarChart xScale={xScale} yScale={yScale} seriesScale={seriesScale} xMax={xMax} yMax={yMax} getXAxisData={getXAxisData} getYAxisData={getYAxisData} animatedChart={animatedChart} visible={animatedChart} />
|
|
537
|
-
</>
|
|
538
|
-
|
|
539
|
-
)}
|
|
540
|
-
|
|
541
|
-
{/* Line chart */}
|
|
542
|
-
{ (config.visualizationType !== 'Bar' && config.visualizationType !== 'Paired Bar') && (
|
|
543
|
-
<>
|
|
544
|
-
<LineChart xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} xMax={xMax} yMax={yMax} seriesStyle={config.series} />
|
|
545
|
-
</>
|
|
546
|
-
|
|
547
|
-
)}
|
|
489
|
+
)}
|
|
548
490
|
</svg>
|
|
549
|
-
<ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} html={true} type=
|
|
491
|
+
<ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} html={true} type='light' arrowColor='rgba(0,0,0,0)' className='tooltip' />
|
|
550
492
|
<div className='animation-trigger' ref={triggerRef} />
|
|
551
493
|
</ErrorBoundary>
|
|
552
494
|
)
|