@cdc/chart 1.3.2 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdcchart.js +77 -4
- package/examples/age-adjusted-rates.json +1218 -0
- package/examples/case-rate-example-config.json +36 -0
- package/examples/case-rate-example-data.json +33602 -0
- package/examples/date-exclusions-config.json +62 -0
- package/examples/date-exclusions-data.json +162 -0
- package/examples/horizontal-chart.json +35 -0
- package/examples/horizontal-stacked-bar-chart.json +36 -0
- package/examples/line-chart.json +76 -0
- package/examples/paired-bar-data.json +14 -0
- package/examples/paired-bar-example.json +48 -0
- package/examples/paired-bar-formatted.json +37 -0
- package/examples/planet-chart-horizontal-example-config.json +35 -0
- package/examples/planet-example-config.json +1 -0
- package/examples/private/newtest.csv +101 -0
- package/examples/private/test.json +10124 -0
- package/package.json +9 -5
- package/src/CdcChart.tsx +417 -149
- package/src/components/BarChart.tsx +431 -24
- package/src/components/BarStackVertical.js +0 -0
- package/src/components/DataTable.tsx +55 -28
- package/src/components/EditorPanel.js +914 -260
- package/src/components/LineChart.tsx +4 -3
- package/src/components/LinearChart.tsx +258 -88
- package/src/components/PairedBarChart.tsx +144 -0
- package/src/components/PieChart.tsx +30 -16
- package/src/components/SparkLine.js +206 -0
- package/src/data/initial-state.js +59 -32
- package/src/hooks/useActiveElement.js +19 -0
- package/src/hooks/useColorPalette.ts +83 -0
- package/src/hooks/useReduceData.ts +43 -0
- package/src/index.html +49 -13
- package/src/index.tsx +6 -2
- package/src/scss/editor-panel.scss +12 -4
- package/src/scss/main.scss +112 -3
|
@@ -1,20 +1,95 @@
|
|
|
1
|
-
import React, { useContext } from 'react';
|
|
1
|
+
import React, { useContext, useState, useEffect } from 'react';
|
|
2
2
|
|
|
3
3
|
import { Group } from '@visx/group';
|
|
4
4
|
import { BarGroup, BarStack } from '@visx/shape';
|
|
5
5
|
import { Text } from '@visx/text';
|
|
6
|
+
import chroma from 'chroma-js';
|
|
6
7
|
|
|
7
8
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary';
|
|
8
9
|
|
|
9
10
|
import Context from '../context';
|
|
11
|
+
import ReactTooltip from 'react-tooltip';
|
|
12
|
+
import { BarStackHorizontal } from '@visx/shape';
|
|
13
|
+
|
|
14
|
+
|
|
10
15
|
|
|
11
16
|
export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getXAxisData, getYAxisData }) {
|
|
12
|
-
const {
|
|
17
|
+
const { transformedData: data, colorScale, seriesHighlight, config, formatNumber, updateConfig, setParentConfig, colorPalettes,formatDate,parseDate } = useContext<any>(Context);
|
|
18
|
+
const { orientation, visualizationSubType } = config;
|
|
19
|
+
const isHorizontal = orientation === 'horizontal';
|
|
20
|
+
|
|
21
|
+
const lollipopBarWidth = config.lollipopSize === 'large' ? 7 : config.lollipopSize === 'medium' ? 6 : 5;
|
|
22
|
+
const lollipopShapeSize = config.lollipopSize === 'large' ? 14 : config.lollipopSize === 'medium' ? 12 : 10;
|
|
23
|
+
|
|
24
|
+
const isLabelBelowBar = config.yAxis.labelPlacement === "Below Bar";
|
|
25
|
+
const isLabelOnYAxis = config.yAxis.labelPlacement === "On Date/Category Axis";
|
|
26
|
+
const isLabelOnBar = config.yAxis.labelPlacement === "On Bar";
|
|
27
|
+
const isLabelMissing = !config.yAxis.labelPlacement;
|
|
28
|
+
const displayNumbersOnBar = config.yAxis.displayNumbersOnBar;
|
|
29
|
+
const section = config.orientation ==='horizontal' ? 'yAxis' :'xAxis';
|
|
30
|
+
|
|
31
|
+
const isRounded = config.barStyle==='rounded';
|
|
32
|
+
const isStacked = config.visualizationSubType === 'stacked'
|
|
33
|
+
const tipRounding = config.tipRounding ;
|
|
34
|
+
const radius = config.roundingStyle ==='standard' ? '8px' : config.roundingStyle ==='shallow' ? '5px': config.roundingStyle ==='finger' ? '15px':'0px';
|
|
35
|
+
const stackCount = config.runtime.seriesKeys.length;
|
|
36
|
+
|
|
37
|
+
const applyRadius = (index:number)=>{
|
|
38
|
+
if(index === undefined || index === null || !isRounded) return;
|
|
39
|
+
let style = {};
|
|
40
|
+
|
|
41
|
+
if((isStacked && index+1 === stackCount) || !isStacked){
|
|
42
|
+
style = isHorizontal ? {borderRadius:`0 ${radius} ${radius} 0`} : {borderRadius:`${radius} ${radius} 0 0`};
|
|
43
|
+
};
|
|
44
|
+
if(tipRounding === 'full' && isStacked && index === 0 && stackCount > 1){
|
|
45
|
+
style = isHorizontal ? {borderRadius:`${radius} 0 0 ${radius}`} : {borderRadius:`0 0 ${radius} ${radius}`};
|
|
46
|
+
};
|
|
47
|
+
if(tipRounding === 'full' && ((isStacked && index === 0 && stackCount === 1) || !isStacked)){
|
|
48
|
+
style = {borderRadius:radius};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return style;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Using State
|
|
55
|
+
const [horizBarHeight, setHorizBarHeight] = useState(null);
|
|
56
|
+
const [textWidth, setTextWidth] = useState(null);
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if(orientation === "horizontal" && !config.yAxis.labelPlacement) {
|
|
60
|
+
updateConfig({
|
|
61
|
+
...config,
|
|
62
|
+
yAxis: {
|
|
63
|
+
...config,
|
|
64
|
+
labelPlacement: "Below Bar"
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
}, [config, updateConfig]);
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if(config.isLollipopChart === false && config.barHeight < 25) {
|
|
72
|
+
updateConfig({ ...config, barHeight: 25 })
|
|
73
|
+
}
|
|
74
|
+
}, [config.isLollipopChart]);
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if(config.visualizationSubType === 'horizontal') {
|
|
78
|
+
updateConfig({
|
|
79
|
+
...config,
|
|
80
|
+
orientation: 'horizontal'
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
85
|
+
// config.runtime.seriesKeys.sort().reverse();
|
|
13
86
|
|
|
14
87
|
return (
|
|
15
88
|
<ErrorBoundary component="BarChart">
|
|
16
89
|
<Group left={config.runtime.yAxis.size}>
|
|
17
|
-
|
|
90
|
+
|
|
91
|
+
{/* Stacked Vertical */}
|
|
92
|
+
{ config.visualizationSubType === 'stacked' && !isHorizontal && (
|
|
18
93
|
<BarStack
|
|
19
94
|
data={data}
|
|
20
95
|
keys={(config.runtime.barSeriesKeys || config.runtime.seriesKeys)}
|
|
@@ -24,8 +99,9 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
|
|
|
24
99
|
color={colorScale}
|
|
25
100
|
>
|
|
26
101
|
{barStacks => barStacks.reverse().map(barStack => barStack.bars.map(bar => {
|
|
102
|
+
const xAxisValue = config.runtime.xAxis.type==='date' ? formatDate(parseDate( data[bar.index][config.runtime.xAxis.dataKey])) : data[bar.index][config.runtime.xAxis.dataKey]
|
|
27
103
|
let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${formatNumber(bar.bar ? bar.bar.data[bar.key] : 0)}` : formatNumber(bar.bar ? bar.bar.data[bar.key] : 0)
|
|
28
|
-
let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${
|
|
104
|
+
let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue;
|
|
29
105
|
|
|
30
106
|
const tooltip = `<div>
|
|
31
107
|
${yAxisTooltip}<br />
|
|
@@ -39,7 +115,7 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
|
|
|
39
115
|
let offset = barThickness * (1 - (config.barThickness || 0.8)) / 2;
|
|
40
116
|
return (
|
|
41
117
|
<Group key={`bar-stack-${barStack.index}-${bar.index}`}>
|
|
42
|
-
<Text
|
|
118
|
+
<Text
|
|
43
119
|
display={config.labels && displayBar ? 'block' : 'none'}
|
|
44
120
|
opacity={transparentBar ? 0.5 : 1}
|
|
45
121
|
x={barThickness * (bar.index + 0.5) + offset}
|
|
@@ -64,10 +140,126 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
|
|
|
64
140
|
/>
|
|
65
141
|
</Group>
|
|
66
142
|
)}
|
|
67
|
-
))
|
|
68
|
-
}
|
|
143
|
+
))}
|
|
69
144
|
</BarStack>
|
|
70
|
-
)
|
|
145
|
+
)}
|
|
146
|
+
|
|
147
|
+
{/* Stacked Horizontal */}
|
|
148
|
+
{ config.visualizationSubType === 'stacked' && isHorizontal && (
|
|
149
|
+
<>
|
|
150
|
+
<BarStackHorizontal
|
|
151
|
+
data={data}
|
|
152
|
+
keys={(config.runtime.barSeriesKeys || config.runtime.seriesKeys)}
|
|
153
|
+
height={yMax }
|
|
154
|
+
y={(d: any) => d[config.runtime.yAxis.dataKey]}
|
|
155
|
+
xScale={xScale}
|
|
156
|
+
yScale={yScale}
|
|
157
|
+
color={colorScale}
|
|
158
|
+
offset="none"
|
|
159
|
+
>
|
|
160
|
+
{(barStacks) =>
|
|
161
|
+
barStacks.map((barStack) =>
|
|
162
|
+
barStack.bars.map((bar, index) => {
|
|
163
|
+
const xAxisValue = config.runtime.yAxis.type==='date' ? formatDate(parseDate(data[bar.index][config.runtime.originalXAxis.dataKey])) : data[bar.index][config.runtime.originalXAxis.dataKey]
|
|
164
|
+
let yAxisTooltip = config.yAxis.label ? `${config.yAxis.label}: ${formatNumber(data[bar.index][bar.key])}` : `${bar.key}: ${formatNumber(data[bar.index][bar.key])}`
|
|
165
|
+
let xAxisTooltip = config.xAxis.label ? `${config.xAxis.label}: ${xAxisValue}` : xAxisValue
|
|
166
|
+
|
|
167
|
+
const tooltip = `<div>
|
|
168
|
+
${yAxisTooltip}<br />
|
|
169
|
+
${xAxisTooltip}<br />
|
|
170
|
+
${config.seriesLabel ? `${config.seriesLabel}: ${bar.key}` : ''}`
|
|
171
|
+
let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1;
|
|
172
|
+
let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1;
|
|
173
|
+
const barsPerGroup = config.series.length;
|
|
174
|
+
let barHeight = config.barHeight ? config.barHeight : 25;
|
|
175
|
+
let barPadding = barHeight;
|
|
176
|
+
|
|
177
|
+
config.barHeight = Number(config.barHeight)
|
|
178
|
+
|
|
179
|
+
if (orientation=== "horizontal") {
|
|
180
|
+
|
|
181
|
+
if(isLabelBelowBar || isLabelMissing || isLabelOnYAxis) {
|
|
182
|
+
if(barHeight < 40) {
|
|
183
|
+
config.barPadding = 40;
|
|
184
|
+
} else {
|
|
185
|
+
config.barPadding = Number(barPadding);
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
config.barPadding = Number(barPadding) / 2;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
config.height = (Number(barHeight) ) * data.length + (Number(config.barPadding) * data.length);
|
|
193
|
+
|
|
194
|
+
let labelColor = "#000000";
|
|
195
|
+
|
|
196
|
+
let textPosition = (bar.y - config.barPadding/2 - Number(config.barHeight/2) + Number(config.barHeight) ) + 5;
|
|
197
|
+
|
|
198
|
+
if (chroma.contrast(labelColor, bar.color) < 4.9) {
|
|
199
|
+
labelColor = '#FFFFFF';
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<Group key={index}>
|
|
204
|
+
<rect
|
|
205
|
+
key={`barstack-horizontal-${barStack.index}-${bar.index}-${index}`}
|
|
206
|
+
x={bar.x}
|
|
207
|
+
y={ bar.y - config.barPadding/2 - config.barHeight/2 }
|
|
208
|
+
width={bar.width}
|
|
209
|
+
height={config.barHeight}
|
|
210
|
+
fill={bar.color}
|
|
211
|
+
stroke="#333"
|
|
212
|
+
strokeWidth={config.barBorderThickness || 1}
|
|
213
|
+
opacity={transparentBar ? 0.5 : 1}
|
|
214
|
+
display={displayBar ? 'block' : 'none'}
|
|
215
|
+
data-tip={tooltip}
|
|
216
|
+
data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
217
|
+
/>
|
|
218
|
+
|
|
219
|
+
{(orientation === 'horizontal' && visualizationSubType === 'stacked') && isLabelBelowBar && barStack.index === 0 && !config.yAxis.hideLabel &&
|
|
220
|
+
<Text
|
|
221
|
+
x={ `${bar.x + (config.isLollipopChart ? 15 : 5)}` } // padding
|
|
222
|
+
y={textPosition}
|
|
223
|
+
fill={ '#000000' }
|
|
224
|
+
textAnchor="start"
|
|
225
|
+
verticalAnchor="start"
|
|
226
|
+
>
|
|
227
|
+
{isHorizontal ? xAxisValue : formatNumber(xAxisValue)}
|
|
228
|
+
</Text>
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
{ displayNumbersOnBar && textWidth + 50 < bar.width &&
|
|
232
|
+
<Text
|
|
233
|
+
display={displayBar ? 'block' : 'none'}
|
|
234
|
+
x={ bar.x + barStack.bars[bar.index].width / 2 } // padding
|
|
235
|
+
y={ textPosition - 5 - config.barHeight/2 }
|
|
236
|
+
fill={ labelColor }
|
|
237
|
+
textAnchor="middle"
|
|
238
|
+
verticalAnchor="middle"
|
|
239
|
+
innerRef={
|
|
240
|
+
(e) => {
|
|
241
|
+
if(e) {
|
|
242
|
+
// use font sizes and padding to set the bar height
|
|
243
|
+
let elem = e.getBBox()
|
|
244
|
+
setTextWidth(elem.width)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
>
|
|
249
|
+
{formatNumber(data[bar.index][bar.key])}
|
|
250
|
+
</Text>
|
|
251
|
+
}
|
|
252
|
+
</Group>
|
|
253
|
+
)
|
|
254
|
+
}
|
|
255
|
+
))
|
|
256
|
+
}
|
|
257
|
+
</BarStackHorizontal>
|
|
258
|
+
</>
|
|
259
|
+
)}
|
|
260
|
+
|
|
261
|
+
{/* Bar Groups: Not Stacked */}
|
|
262
|
+
{ config.visualizationSubType !== 'stacked' && (
|
|
71
263
|
<Group>
|
|
72
264
|
<BarGroup
|
|
73
265
|
data={data}
|
|
@@ -79,38 +271,89 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
|
|
|
79
271
|
yScale={config.runtime.horizontal ? xScale : yScale}
|
|
80
272
|
color={() => {return '';}}
|
|
81
273
|
>
|
|
82
|
-
{(barGroups) =>
|
|
83
|
-
|
|
84
|
-
|
|
274
|
+
{(barGroups) => {
|
|
275
|
+
|
|
276
|
+
if (orientation=== "horizontal") {
|
|
277
|
+
const barsPerGroup = config.series.length;
|
|
278
|
+
let barHeight = config.barHeight ? config.barHeight : 25;
|
|
279
|
+
let barPadding = barHeight;
|
|
280
|
+
|
|
281
|
+
if(isLabelBelowBar || isLabelMissing || isLabelOnYAxis) {
|
|
282
|
+
if(barHeight < 40) {
|
|
283
|
+
config.barPadding = 40;
|
|
284
|
+
} else {
|
|
285
|
+
config.barPadding = barPadding;
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
config.barPadding = barPadding / 2;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if(config.isLollipopChart && config.yAxis.labelPlacement === 'Below Bar') {
|
|
292
|
+
config.barPadding = config.barPadding + 7;
|
|
293
|
+
}
|
|
294
|
+
config.barHeight = config.isLollipopChart ? lollipopBarWidth : barHeight;
|
|
295
|
+
config.height = (barsPerGroup * barHeight) * barGroups.length + (config.barPadding * barGroups.length);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return barGroups.map((barGroup, index) => (
|
|
299
|
+
<Group
|
|
300
|
+
className={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`}
|
|
301
|
+
key={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`}
|
|
302
|
+
top={config.runtime.horizontal ? yMax / barGroups.length * barGroup.index : 0}
|
|
303
|
+
left={config.runtime.horizontal ? 0 : xMax / barGroups.length * barGroup.index}>
|
|
304
|
+
{barGroup.bars.map((bar,index) => {
|
|
305
|
+
|
|
85
306
|
let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1;
|
|
86
307
|
let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1;
|
|
87
|
-
let barHeight = Math.abs(yScale(bar.value) - yScale(0));
|
|
308
|
+
let barHeight = orientation === "horizontal" ? config.barHeight : Math.abs(yScale(bar.value) - yScale(0));
|
|
88
309
|
let barY = bar.value >= 0 ? bar.y : yScale(0);
|
|
89
310
|
let barGroupWidth = (config.runtime.horizontal ? yMax : xMax) / barGroups.length * (config.barThickness || 0.8);
|
|
90
311
|
let offset = (config.runtime.horizontal ? yMax : xMax) / barGroups.length * (1 - (config.barThickness || 0.8)) / 2;
|
|
91
|
-
|
|
312
|
+
|
|
313
|
+
// ! Unsure if this should go back.
|
|
314
|
+
if(config.isLollipopChart) {
|
|
315
|
+
offset = ( (config.runtime.horizontal ? yMax : xMax) / barGroups.length / 2) - lollipopBarWidth / 2
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
let barWidth = config.isLollipopChart ? lollipopBarWidth : barGroupWidth / barGroup.bars.length;
|
|
92
319
|
let barColor = config.runtime.seriesLabels && config.runtime.seriesLabels[bar.key] ? colorScale(config.runtime.seriesLabels[bar.key]) : colorScale(bar.key);
|
|
93
320
|
|
|
94
321
|
let yAxisValue = formatNumber(bar.value);
|
|
95
|
-
let xAxisValue = data[barGroup.index][config.runtime.originalXAxis.dataKey]
|
|
322
|
+
let xAxisValue = config.runtime[section].type==='date' ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey])) : data[barGroup.index][config.runtime.originalXAxis.dataKey]
|
|
96
323
|
|
|
97
324
|
if(config.runtime.horizontal){
|
|
98
325
|
let tempValue = yAxisValue;
|
|
99
326
|
yAxisValue = xAxisValue;
|
|
100
327
|
xAxisValue = tempValue;
|
|
328
|
+
barWidth = config.barHeight
|
|
101
329
|
}
|
|
102
330
|
|
|
103
331
|
let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
|
|
104
332
|
let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
|
|
105
|
-
|
|
333
|
+
let horizBarLabelPadding = null;
|
|
334
|
+
let labelColor = "#000000";
|
|
335
|
+
|
|
336
|
+
// Set label color
|
|
337
|
+
if (chroma.contrast(labelColor, barColor) < 4.9) {
|
|
338
|
+
labelColor = '#FFFFFF';
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// font size and text spacing used for centering text on bar
|
|
342
|
+
if(config.fontSize === "small") {
|
|
343
|
+
horizBarLabelPadding = 16;
|
|
344
|
+
} else if(config.fontSize === "medium") {
|
|
345
|
+
horizBarLabelPadding = 18;
|
|
346
|
+
} else{
|
|
347
|
+
horizBarLabelPadding = 20;
|
|
348
|
+
}
|
|
349
|
+
const onBarTextSpacing = 25;
|
|
106
350
|
const tooltip = `<div>
|
|
107
351
|
${yAxisTooltip}<br />
|
|
108
352
|
${xAxisTooltip}<br />
|
|
109
353
|
${config.seriesLabel ? `${config.seriesLabel}: ${bar.key}` : ''}`
|
|
110
|
-
|
|
111
354
|
return (
|
|
112
|
-
<Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}`}>
|
|
113
|
-
<Text
|
|
355
|
+
<Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}-${barY}--${index}`}>
|
|
356
|
+
<Text
|
|
114
357
|
display={config.labels && displayBar ? 'block' : 'none'}
|
|
115
358
|
opacity={transparentBar ? 0.5 : 1}
|
|
116
359
|
x={barWidth * (barGroup.bars.length - bar.index - 0.5) + offset}
|
|
@@ -121,25 +364,189 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
|
|
|
121
364
|
</Text>
|
|
122
365
|
<rect
|
|
123
366
|
key={`bar-group-bar-${barGroup.index}-${bar.index}-${bar.value}-${bar.key}`}
|
|
124
|
-
x={config.runtime.horizontal ? 0 : barWidth * (barGroup.bars.length - bar.index - 1) + offset}
|
|
125
|
-
y={config.runtime.horizontal ? barWidth * (barGroup.bars.length - bar.index - 1) : barY}
|
|
367
|
+
x={ config.runtime.horizontal ? 0 : barWidth * (barGroup.bars.length - bar.index - 1) + offset }
|
|
368
|
+
y={config.runtime.horizontal ? barWidth * (barGroup.bars.length - bar.index - 1) + (config.isLollipopChart && isLabelOnYAxis ? offset : 0) : barY }
|
|
126
369
|
width={config.runtime.horizontal ? bar.y : barWidth}
|
|
127
370
|
height={config.runtime.horizontal ? barWidth : barHeight}
|
|
128
|
-
fill={barColor
|
|
371
|
+
fill={config.isLollipopChart && config.lollipopColorStyle === 'regular' ? barColor :
|
|
372
|
+
config.isLollipopChart && config.lollipopColorStyle === 'two-tone' ? chroma(barColor).brighten(1) : barColor }
|
|
129
373
|
stroke="#333"
|
|
130
|
-
strokeWidth={config.barBorderThickness || 1}
|
|
131
|
-
style={{fill: barColor}}
|
|
374
|
+
strokeWidth={config.isLollipopChart ? 0 : config.barBorderThickness || 1}
|
|
132
375
|
opacity={transparentBar ? 0.5 : 1}
|
|
133
376
|
display={displayBar ? 'block' : 'none'}
|
|
134
377
|
data-tip={tooltip}
|
|
135
378
|
data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
136
379
|
/>
|
|
380
|
+
{config.isLollipopChart && config.lollipopShape === 'circle' &&
|
|
381
|
+
<circle
|
|
382
|
+
cx={orientation === 'horizontal' ? bar.y : barWidth * (barGroup.bars.length - bar.index - 1) + (isLabelBelowBar && orientation === 'horizontal' ? 0 : offset) + lollipopShapeSize/3.5}
|
|
383
|
+
cy={orientation === 'horizontal' ? lollipopShapeSize/3.5 + (isLabelBelowBar && orientation === 'horizontal' ? 0: offset) : bar.y}
|
|
384
|
+
r={lollipopShapeSize/2}
|
|
385
|
+
fill={barColor}
|
|
386
|
+
key={`circle--${bar.index}`}
|
|
387
|
+
data-tip={tooltip}
|
|
388
|
+
data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
389
|
+
style={{ 'opacity': 1, filter: 'unset' }}
|
|
390
|
+
/>
|
|
391
|
+
}
|
|
392
|
+
{config.isLollipopChart && config.lollipopShape === 'square' &&
|
|
393
|
+
<rect
|
|
394
|
+
x={
|
|
395
|
+
(orientation === 'horizontal' && bar.y > 10) ? bar.y - lollipopShapeSize / 2 : (orientation === 'horizontal' && bar.y < 10) ? 0 :
|
|
396
|
+
(orientation !== 'horizontal') ? offset - lollipopBarWidth / 2 : barWidth * (barGroup.bars.length - bar.index - 1) + offset - 5.25
|
|
397
|
+
}
|
|
398
|
+
y={
|
|
399
|
+
orientation === 'horizontal' ? 0 - lollipopBarWidth / 2 + (isLabelBelowBar ? 0 : offset) : config.height - bar.y > 10 ? bar.y - lollipopShapeSize / 2 : 0 }
|
|
400
|
+
width={lollipopShapeSize}
|
|
401
|
+
height={lollipopShapeSize}
|
|
402
|
+
fill={barColor}
|
|
403
|
+
key={`circle--${bar.index}`}
|
|
404
|
+
data-tip={tooltip}
|
|
405
|
+
data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
406
|
+
style={{ 'opacity': 1, filter: 'unset' }}
|
|
407
|
+
/>
|
|
408
|
+
}
|
|
409
|
+
{orientation === "horizontal" && textWidth + 100 < bar.y ?
|
|
410
|
+
config.yAxis.labelPlacement === "On Bar" &&
|
|
411
|
+
<Group>
|
|
412
|
+
<Text
|
|
413
|
+
innerRef={
|
|
414
|
+
(e) => {
|
|
415
|
+
if(e) {
|
|
416
|
+
// use font sizes and padding to set the bar height
|
|
417
|
+
let elem = e.getBBox()
|
|
418
|
+
setTextWidth(elem.width)
|
|
419
|
+
config.barHeight = ( (elem.height * 2) + (horizBarLabelPadding * 2) + onBarTextSpacing / 2 )
|
|
420
|
+
config.barPadding = ( horizBarHeight / 2 )
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
x={ bar.y - horizBarLabelPadding }
|
|
425
|
+
y={ barHeight * (barGroup.bars.length - bar.index - 1) + ( horizBarLabelPadding * 2 ) }
|
|
426
|
+
fill={ labelColor }
|
|
427
|
+
textAnchor="end"
|
|
428
|
+
>
|
|
429
|
+
{ yAxisValue }
|
|
430
|
+
</Text>
|
|
431
|
+
<Text
|
|
432
|
+
x={ bar.y - horizBarLabelPadding }
|
|
433
|
+
y={ barWidth * (barGroup.bars.length - bar.index - 1) + ( horizBarLabelPadding * 2 ) + onBarTextSpacing }
|
|
434
|
+
fill={ labelColor }
|
|
435
|
+
textAnchor="end"
|
|
436
|
+
>
|
|
437
|
+
{ xAxisValue }
|
|
438
|
+
</Text>
|
|
439
|
+
</Group>
|
|
440
|
+
:
|
|
441
|
+
(isLabelOnBar) &&
|
|
442
|
+
<Group>
|
|
443
|
+
{/* hide y label if we're only showing data on bar */}
|
|
444
|
+
<Text
|
|
445
|
+
x={ bar.y + horizBarLabelPadding }
|
|
446
|
+
y={ barWidth * (barGroup.bars.length - bar.index - 1) + ( horizBarLabelPadding * 2 ) }
|
|
447
|
+
fill={ "#000" }
|
|
448
|
+
textAnchor="start"
|
|
449
|
+
verticalAnchor="end"
|
|
450
|
+
>{yAxisValue}</Text>
|
|
451
|
+
<Text
|
|
452
|
+
x={ bar.y + horizBarLabelPadding }
|
|
453
|
+
y={ barWidth * (barGroup.bars.length - bar.index - 1) + ( horizBarLabelPadding * 2 ) + onBarTextSpacing }
|
|
454
|
+
fill={ "#000" }
|
|
455
|
+
textAnchor="start"
|
|
456
|
+
verticalAnchor="start"
|
|
457
|
+
>
|
|
458
|
+
{ xAxisValue }
|
|
459
|
+
</Text>
|
|
460
|
+
</Group>
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
{ orientation === "horizontal" && isLabelBelowBar && !config.yAxis.hideLabel &&
|
|
464
|
+
<>
|
|
465
|
+
<Text
|
|
466
|
+
x={ config.yAxis.hideAxis ? 0 : 5 } // padding
|
|
467
|
+
y={ config.isLollipopChart ? lollipopShapeSize * config.series.length + 2 : barWidth * config.series.length + 7 }
|
|
468
|
+
verticalAnchor={"start"}
|
|
469
|
+
textAnchor={"start"}
|
|
470
|
+
>{config.runtime.yAxis.type==='date' ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey])) :isHorizontal?data[barGroup.index][config.runtime.originalXAxis.dataKey]: formatNumber(data[barGroup.index][config.runtime.originalXAxis.dataKey])}
|
|
471
|
+
</Text>
|
|
472
|
+
|
|
473
|
+
{ (displayNumbersOnBar) ?
|
|
474
|
+
(textWidth + 100 < bar.y && !config.isLollipopChart) ?
|
|
475
|
+
(
|
|
476
|
+
<Text
|
|
477
|
+
display={displayBar ? 'block' : 'none'}
|
|
478
|
+
x={ bar.y - 5 } // padding
|
|
479
|
+
y={ config.isLollipopChart ? offset : (config.barHeight / 2 ) + config.barHeight * (barGroup.bars.length - bar.index - 1) }
|
|
480
|
+
fill={ labelColor }
|
|
481
|
+
textAnchor="end"
|
|
482
|
+
verticalAnchor="middle"
|
|
483
|
+
>
|
|
484
|
+
{ xAxisValue }
|
|
485
|
+
</Text>
|
|
486
|
+
)
|
|
487
|
+
: (
|
|
488
|
+
<Text
|
|
489
|
+
display={displayBar ? 'block' : 'none'}
|
|
490
|
+
x={ `${bar.y + (config.isLollipopChart ? 15 : 5) + (config.isLollipopChart && barGroup.bars.length === bar.index ? offset : 0 ) }`} // padding
|
|
491
|
+
y={ config.isLollipopChart ? 0 : (config.barHeight / 2 ) + config.barHeight * (barGroup.bars.length - bar.index - 1)}
|
|
492
|
+
fill={ '#000000'}
|
|
493
|
+
textAnchor="start"
|
|
494
|
+
verticalAnchor="middle"
|
|
495
|
+
fontWeight={'normal'}
|
|
496
|
+
>
|
|
497
|
+
{ xAxisValue }
|
|
498
|
+
</Text>
|
|
499
|
+
)
|
|
500
|
+
: ""
|
|
501
|
+
}
|
|
502
|
+
</>
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
{ (isLabelOnYAxis && orientation === "horizontal") &&
|
|
506
|
+
<>
|
|
507
|
+
{ (displayNumbersOnBar) ?
|
|
508
|
+
(textWidth + 100 < bar.y && !config.isLollipopChart) ?
|
|
509
|
+
(
|
|
510
|
+
<Text
|
|
511
|
+
display={displayBar ? 'block' : 'none'}
|
|
512
|
+
x={ bar.y - 5 } // padding
|
|
513
|
+
y={
|
|
514
|
+
config.isLollipopChart ? (config.barHeight * (barGroup.bars.length - bar.index - 1) ) + offset :
|
|
515
|
+
(config.barHeight * (barGroup.bars.length - bar.index - 1) ) + (config.barHeight / 2 )
|
|
516
|
+
}
|
|
517
|
+
fill={ labelColor }
|
|
518
|
+
textAnchor="end"
|
|
519
|
+
verticalAnchor="middle"
|
|
520
|
+
>
|
|
521
|
+
{ formatNumber(xAxisValue )}
|
|
522
|
+
</Text>
|
|
523
|
+
)
|
|
524
|
+
: (
|
|
525
|
+
<Text
|
|
526
|
+
display={displayBar ? 'block' : 'none'}
|
|
527
|
+
x={ `${bar.y + (config.isLollipopChart ? 15 : 5)}` } // padding
|
|
528
|
+
y={
|
|
529
|
+
config.isLollipopChart ? (config.barHeight * (barGroup.bars.length - bar.index - 1) ) + offset :
|
|
530
|
+
(config.barHeight * (barGroup.bars.length - bar.index - 1) ) + (config.barHeight / 2 )
|
|
531
|
+
}
|
|
532
|
+
fill={ '#000000' }
|
|
533
|
+
textAnchor="start"
|
|
534
|
+
verticalAnchor="middle"
|
|
535
|
+
>
|
|
536
|
+
{formatNumber( xAxisValue) }
|
|
537
|
+
</Text>
|
|
538
|
+
)
|
|
539
|
+
: ""
|
|
540
|
+
}
|
|
541
|
+
</>
|
|
542
|
+
}
|
|
137
543
|
</Group>
|
|
138
544
|
)}
|
|
139
545
|
)}
|
|
140
546
|
</Group>
|
|
141
|
-
|
|
547
|
+
))}}
|
|
142
548
|
</BarGroup>
|
|
549
|
+
|
|
143
550
|
{Object.keys(config.confidenceKeys).length > 0 ? data.map((d) => {
|
|
144
551
|
let xPos = xScale(getXAxisData(d));
|
|
145
552
|
let upperPos = yScale(getYAxisData(d, config.confidenceKeys.lower));
|
|
File without changes
|