@cdc/chart 4.22.10 → 4.23.1

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.
Files changed (80) hide show
  1. package/README.md +5 -5
  2. package/dist/495.js +3 -0
  3. package/dist/703.js +1 -0
  4. package/dist/cdcchart.js +723 -6
  5. package/examples/age-adjusted-rates.json +1486 -1218
  6. package/examples/box-plot-data.json +71 -0
  7. package/examples/box-plot.csv +5 -0
  8. package/examples/{private/yaxis-test.json → box-plot.json} +46 -54
  9. package/examples/case-rate-example-config.json +1 -1
  10. package/examples/covid-confidence-example-config.json +33 -33
  11. package/examples/covid-example-config.json +34 -34
  12. package/examples/covid-example-data-confidence.json +30 -30
  13. package/examples/covid-example-data.json +20 -20
  14. package/examples/cutoff-example-config.json +36 -36
  15. package/examples/cutoff-example-data.json +36 -36
  16. package/examples/date-exclusions-config.json +1 -1
  17. package/examples/dynamic-legends.json +124 -124
  18. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json +191 -197
  19. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +230 -240
  20. package/examples/gallery/bar-chart-horizontal/horizontal-stacked.json +239 -247
  21. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +138 -136
  22. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +79 -79
  23. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +80 -80
  24. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +67 -67
  25. package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +179 -110
  26. package/examples/gallery/lollipop/lollipop-style-horizontal.json +215 -219
  27. package/examples/gallery/paired-bar/paired-bar-chart.json +195 -195
  28. package/examples/horizontal-chart.json +35 -35
  29. package/examples/horizontal-stacked-bar-chart.json +34 -34
  30. package/examples/line-chart.json +75 -75
  31. package/examples/new-data.csv +17 -0
  32. package/examples/newdata.json +90 -0
  33. package/examples/paired-bar-data.json +16 -14
  34. package/examples/paired-bar-example.json +48 -48
  35. package/examples/paired-bar-formatted.json +36 -36
  36. package/examples/planet-chart-horizontal-example-config.json +33 -33
  37. package/examples/planet-combo-example-config.json +34 -31
  38. package/examples/planet-example-config.json +35 -33
  39. package/examples/planet-example-data.json +56 -56
  40. package/examples/planet-pie-example-config.json +28 -28
  41. package/examples/stacked-vertical-bar-example.json +1 -1
  42. package/examples/temp-example-config.json +61 -54
  43. package/examples/temp-example-data.json +1 -1
  44. package/package.json +3 -2
  45. package/src/CdcChart.tsx +449 -434
  46. package/src/components/BarChart.tsx +383 -497
  47. package/src/components/BoxPlot.js +92 -0
  48. package/src/components/DataTable.tsx +182 -197
  49. package/src/components/EditorPanel.js +1068 -722
  50. package/src/components/Filters.js +131 -0
  51. package/src/components/Legend.js +286 -329
  52. package/src/components/LineChart.tsx +143 -81
  53. package/src/components/LinearChart.tsx +432 -451
  54. package/src/components/PairedBarChart.tsx +197 -213
  55. package/src/components/PieChart.tsx +105 -151
  56. package/src/components/SparkLine.js +179 -201
  57. package/src/components/useIntersectionObserver.tsx +19 -20
  58. package/src/context.tsx +3 -3
  59. package/src/data/initial-state.js +44 -17
  60. package/src/hooks/useActiveElement.js +13 -13
  61. package/src/hooks/useChartClasses.js +34 -28
  62. package/src/hooks/useColorPalette.ts +56 -63
  63. package/src/hooks/useLegendClasses.js +18 -10
  64. package/src/hooks/useReduceData.ts +64 -77
  65. package/src/hooks/useRightAxis.js +25 -0
  66. package/src/hooks/useTopAxis.js +6 -0
  67. package/src/index.html +19 -19
  68. package/src/index.tsx +13 -16
  69. package/src/scss/DataTable.scss +6 -5
  70. package/src/scss/editor-panel.scss +71 -69
  71. package/src/scss/main.scss +188 -114
  72. package/src/scss/variables.scss +1 -1
  73. package/examples/private/line-test-data.json +0 -22
  74. package/examples/private/line-test-two.json +0 -216
  75. package/examples/private/line-test.json +0 -102
  76. package/examples/private/newtest.csv +0 -101
  77. package/examples/private/shawn.json +0 -1296
  78. package/examples/private/test.json +0 -10124
  79. package/examples/private/yaxis-testing.csv +0 -27
  80. package/examples/private/yaxis.json +0 -28
@@ -1,623 +1,509 @@
1
- import React, { useContext, useState, useEffect } from 'react';
1
+ import React, { useContext, useState, useEffect } from 'react'
2
+ import { Group } from '@visx/group'
3
+ import { BarGroup, BarStack } from '@visx/shape'
4
+ import { Text } from '@visx/text'
5
+ import chroma from 'chroma-js'
6
+ import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
7
+ import Context from '../context'
8
+ import { BarStackHorizontal } from '@visx/shape'
2
9
 
3
- import { Group } from '@visx/group';
4
- import { BarGroup, BarStack } from '@visx/shape';
5
- import { Text } from '@visx/text';
6
- import chroma from 'chroma-js';
10
+ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getXAxisData, getYAxisData, animatedChart, visible }) {
11
+ const { transformedData: data, colorScale, seriesHighlight, config, formatNumber, updateConfig, colorPalettes, formatDate, parseDate } = useContext<any>(Context)
12
+ const { orientation, visualizationSubType } = config
13
+ const isHorizontal = orientation === 'horizontal'
7
14
 
8
- import ErrorBoundary from '@cdc/core/components/ErrorBoundary';
15
+ const lollipopBarWidth = config.lollipopSize === 'large' ? 7 : config.lollipopSize === 'medium' ? 6 : 5
16
+ const lollipopShapeSize = config.lollipopSize === 'large' ? 14 : config.lollipopSize === 'medium' ? 12 : 10
9
17
 
10
- import Context from '../context';
11
- import ReactTooltip from 'react-tooltip';
12
- import { BarStackHorizontal } from '@visx/shape';
18
+ const isLabelBelowBar = config.yAxis.labelPlacement === 'Below Bar'
19
+ const displayNumbersOnBar = config.yAxis.displayNumbersOnBar
20
+ const section = config.orientation === 'horizontal' ? 'yAxis' : 'xAxis'
13
21
 
22
+ const isRounded = config.barStyle === 'rounded'
23
+ const isStacked = config.visualizationSubType === 'stacked'
24
+ const tipRounding = config.tipRounding
25
+ const radius = config.roundingStyle === 'standard' ? '8px' : config.roundingStyle === 'shallow' ? '5px' : config.roundingStyle === 'finger' ? '15px' : '0px'
26
+ const stackCount = config.runtime.seriesKeys.length
27
+ const barBorderWidth = 1
28
+ const fontSize = { small: 14, medium: 16, large: 18 }
29
+ const hasMultipleSeries = Object.keys(config.runtime.seriesLabels).length > 1
30
+
31
+ const applyRadius = (index: number) => {
32
+ if (index === undefined || index === null || !isRounded) return
33
+ let style = {}
34
+
35
+ if ((isStacked && index + 1 === stackCount) || !isStacked) {
36
+ style = isHorizontal ? { borderRadius: `0 ${radius} ${radius} 0` } : { borderRadius: `${radius} ${radius} 0 0` }
37
+ }
38
+ if (tipRounding === 'full' && isStacked && index === 0 && stackCount > 1) {
39
+ style = isHorizontal ? { borderRadius: `${radius} 0 0 ${radius}` } : { borderRadius: `0 0 ${radius} ${radius}` }
40
+ }
41
+ if (tipRounding === 'full' && ((isStacked && index === 0 && stackCount === 1) || !isStacked)) {
42
+ style = { borderRadius: radius }
43
+ }
14
44
 
45
+ return style
46
+ }
47
+ // }
15
48
 
16
- export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getXAxisData, getYAxisData, animatedChart, visible }) {
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';
49
+ const updateBars = defaultBars => {
50
+ // function updates stacked && regular && lollipop horizontal bars
51
+ if (config.visualizationType !== 'Bar' && !isHorizontal) return defaultBars
20
52
 
21
- const lollipopBarWidth = config.lollipopSize === 'large' ? 7 : config.lollipopSize === 'medium' ? 6 : 5;
22
- const lollipopShapeSize = config.lollipopSize === 'large' ? 14 : config.lollipopSize === 'medium' ? 12 : 10;
53
+ const barsArr = [...defaultBars]
54
+ let barHeight
23
55
 
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';
56
+ const heights = {
57
+ stacked: config.barHeight,
58
+ lollipop: lollipopBarWidth
59
+ }
30
60
 
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
- const barBorderWidth = 1;
37
-
38
- const applyRadius = (index:number)=>{
39
- if(index === undefined || index === null || !isRounded) return;
40
- let style = {};
41
-
42
- if((isStacked && index+1 === stackCount) || !isStacked){
43
- style = isHorizontal ? {borderRadius:`0 ${radius} ${radius} 0`} : {borderRadius:`${radius} ${radius} 0 0`};
44
- };
45
- if(tipRounding === 'full' && isStacked && index === 0 && stackCount > 1){
46
- style = isHorizontal ? {borderRadius:`${radius} 0 0 ${radius}`} : {borderRadius:`0 0 ${radius} ${radius}`};
47
- };
48
- if(tipRounding === 'full' && ((isStacked && index === 0 && stackCount === 1) || !isStacked)){
49
- style = {borderRadius:radius};
50
- };
51
-
52
- return style;
53
- }
61
+ if (!isStacked) {
62
+ barHeight = heights[config.isLollipopChart ? 'lollipop' : 'stacked'] * stackCount
63
+ } else {
64
+ barHeight = heights.stacked
65
+ }
66
+
67
+ const labelHeight = isLabelBelowBar ? fontSize[config.fontSize] * 1.2 : 0
68
+ let barSpace = Number(config.barSpace)
69
+
70
+ // calculate height of container based height, space and fontSize of labels
71
+ let totalHeight = barsArr.length * (barHeight + labelHeight + barSpace)
72
+
73
+ if (isHorizontal) {
74
+ config.heights.horizontal = totalHeight
75
+ }
76
+
77
+ // return new updated bars/groupes
78
+ return barsArr.map((bar, i) => {
79
+ // set bars Y dynamycly to handle space between bars
80
+ let y = 0
81
+ bar.index !== 0 && (y = (barHeight + barSpace + labelHeight) * i)
82
+
83
+ return { ...bar, y: y, height: barHeight }
84
+ })
85
+ }
86
+
87
+ function getTextWidth(text, font) {
88
+ // function calculates the width of given text and its font-size
89
+ const canvas = document.createElement('canvas')
90
+ const context = canvas.getContext('2d')
91
+
92
+ context.font = font || getComputedStyle(document.body).font
93
+
94
+ return Math.ceil(context.measureText(text).width)
95
+ }
54
96
 
55
97
  // Using State
56
- const [horizBarHeight, setHorizBarHeight] = useState(null);
57
- const [textWidth, setTextWidth] = useState(null);
98
+ const [textWidth, setTextWidth] = useState(null)
58
99
 
59
100
  useEffect(() => {
60
- if(orientation === "horizontal" && !config.yAxis.labelPlacement) {
101
+ if (orientation === 'horizontal' && !config.yAxis.labelPlacement) {
61
102
  updateConfig({
62
103
  ...config,
63
104
  yAxis: {
64
105
  ...config,
65
- labelPlacement: "Below Bar"
106
+ labelPlacement: 'Below Bar'
66
107
  }
67
108
  })
68
109
  }
69
- }, [config, updateConfig]);
110
+ }, [config, updateConfig])
70
111
 
71
112
  useEffect(() => {
72
- if(config.isLollipopChart === false && config.barHeight < 25) {
113
+ if (config.isLollipopChart === false && config.barHeight < 25) {
73
114
  updateConfig({ ...config, barHeight: 25 })
74
115
  }
75
- }, [config.isLollipopChart]);
116
+ }, [config.isLollipopChart])
76
117
 
77
118
  useEffect(() => {
78
- if(config.visualizationSubType === 'horizontal') {
119
+ if (config.visualizationSubType === 'horizontal') {
79
120
  updateConfig({
80
121
  ...config,
81
122
  orientation: 'horizontal'
82
123
  })
83
124
  }
84
- }, []);
85
-
86
- useEffect(()=>{
87
- if(config.barStyle==='lollipop' && !config.isLollipopChart ){
88
- updateConfig({ ...config, isLollipopChart:true })
125
+ }, [])
126
+
127
+ useEffect(() => {
128
+ if (config.barStyle === 'lollipop' && !config.isLollipopChart) {
129
+ updateConfig({ ...config, isLollipopChart: true })
89
130
  }
90
- if( isRounded || config.barStyle==='flat' ){
91
- updateConfig({ ...config, isLollipopChart:false })
131
+ if (isRounded || config.barStyle === 'flat') {
132
+ updateConfig({ ...config, isLollipopChart: false })
92
133
  }
93
- },[config.barStyle])
94
-
95
- // config.runtime.seriesKeys.sort().reverse();
134
+ }, [config.barStyle])
96
135
 
97
136
  return (
98
- <ErrorBoundary component="BarChart">
137
+ <ErrorBoundary component='BarChart'>
99
138
  <Group left={config.runtime.yAxis.size}>
100
-
101
139
  {/* Stacked Vertical */}
102
- { config.visualizationSubType === 'stacked' && !isHorizontal && (
103
- <BarStack
104
- data={data}
105
- keys={(config.runtime.barSeriesKeys || config.runtime.seriesKeys)}
106
- x={(d: any) => d[config.runtime.xAxis.dataKey]}
107
- xScale={xScale}
108
- yScale={yScale}
109
- color={colorScale}
110
- >
111
- {barStacks => barStacks.reverse().map(barStack => barStack.bars.map(bar => {
112
- const xAxisValue = config.runtime.xAxis.type==='date' ? formatDate(parseDate( data[bar.index][config.runtime.xAxis.dataKey])) : data[bar.index][config.runtime.xAxis.dataKey]
113
- 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)
114
- let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue;
115
-
116
- const tooltip = `<div>
117
- ${yAxisTooltip}<br />
118
- ${xAxisTooltip}<br />
119
- ${config.seriesLabel ? `${config.seriesLabel}: ${bar.key}` : ''}`
120
-
121
- let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1;
122
- let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1;
123
- let barThickness = xMax / barStack.bars.length;
124
- let barThicknessAdjusted = barThickness * (config.barThickness || 0.8);
125
- let offset = barThickness * (1 - (config.barThickness || 0.8)) / 2;
126
- const style = applyRadius(barStack.index)
127
-
128
- return (
129
- <>
130
- <style>
131
- {`
140
+ {config.visualizationSubType === 'stacked' && !isHorizontal && (
141
+ <BarStack data={data} keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys} x={(d: any) => d[config.runtime.xAxis.dataKey]} xScale={xScale} yScale={yScale} color={colorScale}>
142
+ {barStacks =>
143
+ barStacks.reverse().map(barStack =>
144
+ barStack.bars.map(bar => {
145
+ let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
146
+ let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
147
+ let barThickness = xMax / barStack.bars.length
148
+ let barThicknessAdjusted = barThickness * (config.barThickness || 0.8)
149
+ let offset = (barThickness * (1 - (config.barThickness || 0.8))) / 2
150
+ const style = applyRadius(barStack.index)
151
+ // tooltips
152
+ const xAxisValue = config.runtime.xAxis.type === 'date' ? formatDate(parseDate(data[bar.index][config.runtime.xAxis.dataKey])) : data[bar.index][config.runtime.xAxis.dataKey]
153
+ const yAxisValue = formatNumber(bar.bar ? bar.bar.data[bar.key] : 0)
154
+ let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
155
+ const xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
156
+ if (!hasMultipleSeries) {
157
+ yAxisTooltip = config.isLegendValue ? `${bar.key}: ${yAxisValue}` : config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
158
+ }
159
+
160
+ const tooltip = `<div>
161
+ ${config.legend.showLegendValuesTooltip && config.runtime.seriesLabels && hasMultipleSeries ? `${config.runtime.seriesLabels[bar.key] || ''}<br/>` : ''}
162
+ ${yAxisTooltip}<br />
163
+ ${xAxisTooltip}
164
+ </div>`
165
+
166
+ return (
167
+ <>
168
+ <style>
169
+ {`
132
170
  #barStack${barStack.index}-${bar.index} rect,
133
171
  #barStack${barStack.index}-${bar.index} foreignObject{
134
172
  animation-delay: ${barStack.index}.2s;
135
- transform-origin: ${barThicknessAdjusted/2}px ${bar.y + bar.height}px
173
+ transform-origin: ${barThicknessAdjusted / 2}px ${bar.y + bar.height}px
136
174
  }
137
175
  `}
138
- </style>
139
- <Group key={`bar-stack-${barStack.index}-${bar.index}`} id={`barStack${barStack.index}-${bar.index}`} className='stack vertical'>
140
- <Text
141
- display={config.labels && displayBar ? 'block' : 'none'}
142
- opacity={transparentBar ? 0.5 : 1}
143
- x={barThickness * (bar.index + 0.5) + offset}
144
- y={bar.y - 5}
145
- fill={bar.color}
146
- textAnchor="middle">
147
- {formatNumber(bar.bar ? bar.bar.data[bar.key] : 0)}
148
- </Text>
149
- <foreignObject
150
- key={`bar-stack-${barStack.index}-${bar.index}`}
151
- x={barThickness * bar.index + offset}
152
- y={bar.y}
153
- width={barThicknessAdjusted}
154
- height={bar.height}
155
- style={{background:bar.color,border:`${config.barHasBorder==='true' ? barBorderWidth: 0 }px solid #333`,...style}}
156
- opacity={transparentBar ? 0.5 : 1}
157
- display={displayBar ? 'block' : 'none'}
158
- data-tip={tooltip}
159
- data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
160
- > </foreignObject>
161
- </Group>
162
- </>
163
- )}
164
- ))}
176
+ </style>
177
+ <Group key={`bar-stack-${barStack.index}-${bar.index}`} id={`barStack${barStack.index}-${bar.index}`} className='stack vertical'>
178
+ <Text display={config.labels && displayBar ? 'block' : 'none'} opacity={transparentBar ? 0.5 : 1} x={barThickness * bar.index + offset} y={bar.y - 5} fill={bar.color} textAnchor='middle'>
179
+ {formatNumber(bar.bar ? bar.bar.data[bar.key] : 0)}
180
+ </Text>
181
+ <foreignObject
182
+ key={`bar-stack-${barStack.index}-${bar.index}`}
183
+ x={barThickness * bar.index + offset}
184
+ y={bar.y}
185
+ width={barThicknessAdjusted}
186
+ height={bar.height}
187
+ style={{ background: bar.color, border: `${config.barHasBorder === 'true' ? barBorderWidth : 0}px solid #333`, ...style }}
188
+ opacity={transparentBar ? 0.5 : 1}
189
+ display={displayBar ? 'block' : 'none'}
190
+ data-tip={tooltip}
191
+ data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
192
+ ></foreignObject>
193
+ </Group>
194
+ </>
195
+ )
196
+ })
197
+ )
198
+ }
165
199
  </BarStack>
166
200
  )}
167
201
 
168
202
  {/* Stacked Horizontal */}
169
- { config.visualizationSubType === 'stacked' && isHorizontal && (
203
+ {config.visualizationSubType === 'stacked' && isHorizontal && (
170
204
  <>
171
- <BarStackHorizontal
172
- data={data}
173
- keys={(config.runtime.barSeriesKeys || config.runtime.seriesKeys)}
174
- height={yMax }
175
- y={(d: any) => d[config.runtime.yAxis.dataKey]}
176
- xScale={xScale}
177
- yScale={yScale}
178
- color={colorScale}
179
- offset="none"
180
- >
181
- {(barStacks) =>
182
- barStacks.map((barStack) =>
183
- barStack.bars.map((bar, index) => {
184
- const xAxisValue = config.runtime.yAxis.type==='date' ? formatDate(parseDate(data[bar.index][config.runtime.originalXAxis.dataKey])) : data[bar.index][config.runtime.originalXAxis.dataKey]
185
- let yAxisTooltip = config.yAxis.label ? `${config.yAxis.label}: ${formatNumber(data[bar.index][bar.key])}` : `${bar.key}: ${formatNumber(data[bar.index][bar.key])}`
186
- let xAxisTooltip = config.xAxis.label ? `${config.xAxis.label}: ${xAxisValue}` : xAxisValue
187
- // let yAxisTooltip = config.yAxis.label ? `${config.yAxis.label}: ${data[bar.index][bar.key]}` : `${bar.key}: ${data[bar.index][bar.key]}`
188
- // let xAxisTooltip = config.xAxis.label ? `${config.xAxis.label}: ${data[bar.index][config.runtime.originalXAxis.dataKey]}` :`${data[bar.index].name}`
189
-
190
- const tooltip = `<div>
191
- ${yAxisTooltip}<br />
192
- ${xAxisTooltip}<br />
193
- ${config.seriesLabel ? `${config.seriesLabel}: ${bar.key}` : ''}`
194
- let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1;
195
- let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1;
196
- const barsPerGroup = config.series.length;
197
- let barHeight = config.barHeight ? config.barHeight : 25;
198
- let barPadding = barHeight;
199
-
205
+ <BarStackHorizontal data={data} keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys} height={yMax} y={(d: any) => d[config.runtime.yAxis.dataKey]} xScale={xScale} yScale={yScale} color={colorScale} offset='none'>
206
+ {barStacks =>
207
+ barStacks.map(barStack =>
208
+ updateBars(barStack.bars).map((bar, index) => {
209
+ let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
210
+ let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
200
211
  config.barHeight = Number(config.barHeight)
201
- const style = applyRadius(barStack.index);
202
-
203
- if (orientation=== "horizontal") {
204
-
205
- if(isLabelBelowBar || isLabelMissing || isLabelOnYAxis) {
206
- if(barHeight < 40) {
207
- config.barPadding = 40;
208
- } else {
209
- config.barPadding = Number(barPadding);
210
- }
211
- } else {
212
- config.barPadding = Number(barPadding) / 2;
213
- }
212
+ const style = applyRadius(barStack.index)
213
+ let labelColor = '#000000'
214
+ // tooltips
215
+ const xAxisValue = formatNumber(data[bar.index][bar.key])
216
+ const yAxisValue = config.runtime.yAxis.type === 'date' ? formatDate(parseDate(data[bar.index][config.runtime.originalXAxis.dataKey])) : data[bar.index][config.runtime.originalXAxis.dataKey]
217
+ let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
218
+ let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
219
+ if (!hasMultipleSeries) {
220
+ xAxisTooltip = config.isLegendValue ? `${bar.key}: ${xAxisValue}` : config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisTooltip
214
221
  }
215
-
216
- config.height = (Number(barHeight) ) * data.length + (Number(config.barPadding) * data.length);
217
-
218
- let labelColor = "#000000";
219
-
220
- let textPosition = (bar.y - config.barPadding/2 - Number(config.barHeight/2) + Number(config.barHeight) ) + 5;
222
+ const tooltip = `<div>
223
+ ${config.legend.showLegendValuesTooltip && config.runtime.seriesLabels && hasMultipleSeries ? `${config.runtime.seriesLabels[bar.key] || ''}<br/>` : ''}
224
+ ${yAxisTooltip}<br />
225
+ ${xAxisTooltip}
226
+ </div>`
221
227
 
222
228
  if (chroma.contrast(labelColor, bar.color) < 4.9) {
223
- labelColor = '#FFFFFF';
229
+ labelColor = '#FFFFFF'
224
230
  }
225
231
 
226
232
  return (
227
233
  <Group key={index}>
228
- <foreignObject
234
+ <foreignObject
229
235
  key={`barstack-horizontal-${barStack.index}-${bar.index}-${index}`}
230
236
  className={`animated-chart group ${animatedChart ? 'animated' : ''}`}
231
237
  x={bar.x}
232
- y={ bar.y - config.barPadding/2 - config.barHeight/2 }
238
+ y={bar.y}
233
239
  width={bar.width}
234
- height={config.barHeight}
235
- style={{background:bar.color,border:`${config.barHasBorder==='true' ? barBorderWidth: 0 }px solid #333`,...style}}
240
+ height={bar.height}
241
+ style={{ background: bar.color, border: `${config.barHasBorder === 'true' ? barBorderWidth : 0}px solid #333`, ...style }}
236
242
  opacity={transparentBar ? 0.5 : 1}
237
243
  display={displayBar ? 'block' : 'none'}
238
244
  data-tip={tooltip}
239
245
  data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
240
246
  ></foreignObject>
241
247
 
242
- {(orientation === 'horizontal' && visualizationSubType === 'stacked') && isLabelBelowBar && barStack.index === 0 && !config.yAxis.hideLabel &&
248
+ {orientation === 'horizontal' && visualizationSubType === 'stacked' && isLabelBelowBar && barStack.index === 0 && !config.yAxis.hideLabel && (
243
249
  <Text
244
- x={ `${bar.x + (config.isLollipopChart ? 15 : 5)}` } // padding
245
- y={textPosition}
246
- fill={ '#000000' }
247
- textAnchor="start"
248
- verticalAnchor="start"
250
+ x={`${bar.x + (config.isLollipopChart ? 15 : 5)}`} // padding
251
+ y={bar.y + bar.height * 1.2}
252
+ fill={'#000000'}
253
+ textAnchor='start'
254
+ verticalAnchor='start'
249
255
  >
250
- {isHorizontal ? xAxisValue : formatNumber(xAxisValue)}
256
+ {yAxisValue}
251
257
  </Text>
252
- }
258
+ )}
253
259
 
254
- { displayNumbersOnBar && textWidth + 50 < bar.width &&
260
+ {displayNumbersOnBar && textWidth + 50 < bar.width && (
255
261
  <Text
256
262
  display={displayBar ? 'block' : 'none'}
257
- x={ bar.x + barStack.bars[bar.index].width / 2 } // padding
258
- y={ textPosition - 5 - config.barHeight/2 }
259
- fill={ labelColor }
260
- textAnchor="middle"
261
- verticalAnchor="middle"
262
- innerRef={
263
- (e) => {
264
- if(e) {
265
- // use font sizes and padding to set the bar height
266
- let elem = e.getBBox()
267
- setTextWidth(elem.width)
268
- }
263
+ x={bar.x + barStack.bars[bar.index].width / 2} // padding
264
+ y={bar.y + bar.height / 2}
265
+ fill={labelColor}
266
+ textAnchor='middle'
267
+ verticalAnchor='middle'
268
+ innerRef={e => {
269
+ if (e) {
270
+ // use font sizes and padding to set the bar height
271
+ let elem = e.getBBox()
272
+ setTextWidth(elem.width)
269
273
  }
270
- }
274
+ }}
271
275
  >
272
276
  {formatNumber(data[bar.index][bar.key])}
273
277
  </Text>
274
- }
278
+ )}
275
279
  </Group>
276
280
  )
277
- }
278
- ))
281
+ })
282
+ )
279
283
  }
280
284
  </BarStackHorizontal>
281
285
  </>
282
286
  )}
283
287
 
284
288
  {/* Bar Groups: Not Stacked */}
285
- { config.visualizationSubType !== 'stacked' && (
289
+ {config.visualizationSubType !== 'stacked' && (
286
290
  <Group>
287
291
  <BarGroup
288
292
  data={data}
289
- keys={(config.runtime.barSeriesKeys || config.runtime.seriesKeys)}
293
+ keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys}
290
294
  height={yMax}
291
295
  x0={(d: any) => d[config.runtime.originalXAxis.dataKey]}
292
296
  x0Scale={config.runtime.horizontal ? yScale : xScale}
293
297
  x1Scale={seriesScale}
294
298
  yScale={config.runtime.horizontal ? xScale : yScale}
295
- color={() => {return '';}}
299
+ color={() => {
300
+ return ''
301
+ }}
296
302
  >
297
- {(barGroups) => {
298
- let barType = 'vertical';
299
- if (orientation=== "horizontal") {
300
- const barsPerGroup = config.series.length;
301
- let barHeight = config.barHeight ? config.barHeight : 25;
302
- let barPadding = barHeight;
303
- barType = 'horizontal';
304
-
305
- if(isLabelBelowBar || isLabelMissing || isLabelOnYAxis) {
306
- if(barHeight < 40) {
307
- config.barPadding = 40;
308
- } else {
309
- config.barPadding = barPadding;
310
- }
311
- } else {
312
- config.barPadding = barPadding / 2;
313
- }
303
+ {barGroups => {
304
+ return updateBars(barGroups).map((barGroup, index) => (
305
+ <Group
306
+ className={`bar-group-${barGroup.index}-${barGroup.x0}--${index} ${config.orientation}`}
307
+ key={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`}
308
+ top={config.runtime.horizontal ? barGroup.y : 0}
309
+ left={config.runtime.horizontal ? 0 : (xMax / barGroups.length) * barGroup.index}
310
+ >
311
+ {barGroup.bars.map((bar, index) => {
312
+ let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
313
+ let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
314
+ let barHeight = orientation === 'horizontal' ? config.barHeight : Math.abs(yScale(bar.value) - yScale(0))
315
+ let barY = bar.value >= 0 ? bar.y : yScale(0)
316
+ let barGroupWidth = ((config.runtime.horizontal ? yMax : xMax) / barGroups.length) * (config.barThickness || 0.8)
317
+ let offset = (((config.runtime.horizontal ? yMax : xMax) / barGroups.length) * (1 - (config.barThickness || 0.8))) / 2
318
+
319
+ // ! Unsure if this should go back.
320
+ if (config.isLollipopChart) {
321
+ offset = (config.runtime.horizontal ? yMax : xMax) / barGroups.length / 2 - lollipopBarWidth / 2
322
+ }
323
+ const set = new Set()
324
+ data.forEach(d => set.add(d[config.legend.colorCode]))
325
+ const uniqValues = Array.from(set)
314
326
 
315
- if(config.isLollipopChart && config.yAxis.labelPlacement === 'Below Bar') {
316
- config.barPadding = config.barPadding + 7;
317
- }
318
- config.barHeight = config.isLollipopChart ? lollipopBarWidth : barHeight;
319
- config.height = (barsPerGroup * barHeight) * barGroups.length + (config.barPadding * barGroups.length);
320
- }
321
-
322
- return barGroups.map((barGroup, index) => (
323
- <Group
324
- className={`bar-group-${barGroup.index}-${barGroup.x0}--${index} ${barType}`}
325
- key={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`}
326
- top={config.runtime.horizontal ? yMax / barGroups.length * barGroup.index : 0}
327
- left={config.runtime.horizontal ? 0 : xMax / barGroups.length * barGroup.index}>
328
- {barGroup.bars.map((bar,index) => {
329
-
330
- let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1;
331
- let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1;
332
- let barHeight = orientation === "horizontal" ? config.barHeight : Math.abs(yScale(bar.value) - yScale(0));
333
- let barY = bar.value >= 0 ? bar.y : yScale(0);
334
- let barGroupWidth = (config.runtime.horizontal ? yMax : xMax) / barGroups.length * (config.barThickness || 0.8);
335
- let offset = (config.runtime.horizontal ? yMax : xMax) / barGroups.length * (1 - (config.barThickness || 0.8)) / 2;
336
-
337
- // ! Unsure if this should go back.
338
- if(config.isLollipopChart) {
339
- offset = ( (config.runtime.horizontal ? yMax : xMax) / barGroups.length / 2) - lollipopBarWidth / 2
340
- }
341
-
342
- const set = new Set()
343
- data.forEach(d=>set.add(d[config.legend.colorCode]));
344
- const uniqValues = Array.from(set);
327
+ let palette = colorPalettes[config.palette].slice(0, uniqValues.length)
345
328
 
346
- let palette = colorPalettes[config.palette].slice(0,uniqValues.length);
329
+ let barWidth = config.isLollipopChart ? lollipopBarWidth : barGroupWidth / barGroup.bars.length
330
+ let barColor = config.runtime.seriesLabels && config.runtime.seriesLabels[bar.key] ? colorScale(config.runtime.seriesLabels[bar.key]) : colorScale(bar.key)
331
+ while (palette.length < barGroups.length) {
332
+ palette = palette.concat(palette)
333
+ }
334
+ if (config.legend.colorCode && config.series.length === 1) barColor = palette[barGroup.index]
347
335
 
348
- let barWidth = config.isLollipopChart ? lollipopBarWidth : barGroupWidth / barGroup.bars.length;
349
- let barColor = config.runtime.seriesLabels && config.runtime.seriesLabels[bar.key] ? colorScale(config.runtime.seriesLabels[bar.key]) : colorScale(bar.key);
350
- while( palette.length < barGroups.length ){
351
- palette =palette.concat(palette)
352
- }
353
- if( config.legend.colorCode && config.series.length===1) barColor = palette[barGroup.index];
354
-
355
- let yAxisValue = formatNumber(bar.value);
356
- let xAxisValue = config.runtime[section].type==='date' ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey])) : data[barGroup.index][config.runtime.originalXAxis.dataKey]
357
-
358
- if(config.runtime.horizontal){
359
- let tempValue = yAxisValue;
360
- yAxisValue = xAxisValue;
361
- xAxisValue = tempValue;
362
- barWidth = config.barHeight
363
- }
336
+ let yAxisValue = formatNumber(bar.value)
337
+ let xAxisValue = config.runtime[section].type === 'date' ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey])) : data[barGroup.index][config.runtime.originalXAxis.dataKey]
364
338
 
365
- let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
366
- let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
367
- let horizBarLabelPadding = null;
368
- let labelColor = "#000000";
339
+ if (config.runtime.horizontal) {
340
+ let tempValue = yAxisValue
341
+ yAxisValue = xAxisValue
342
+ xAxisValue = tempValue
343
+ barWidth = config.barHeight
344
+ }
345
+ let labelColor = '#000000'
369
346
 
370
- // Set label color
371
- if (chroma.contrast(labelColor, barColor) < 4.9) {
372
- labelColor = '#FFFFFF';
373
- }
347
+ // Set label color
348
+ if (chroma.contrast(labelColor, barColor) < 4.9) {
349
+ labelColor = '#FFFFFF'
350
+ }
374
351
 
375
- // font size and text spacing used for centering text on bar
376
- if(config.fontSize === "small") {
377
- horizBarLabelPadding = 16;
378
- } else if(config.fontSize === "medium") {
379
- horizBarLabelPadding = 18;
380
- } else{
381
- horizBarLabelPadding = 20;
382
- }
383
- const onBarTextSpacing = 25;
384
- const tooltip = `<div>
385
- ${yAxisTooltip}<br />
386
- ${xAxisTooltip}<br />
387
- ${config.seriesLabel ? `${config.seriesLabel}: ${bar.key}` : ''}`
388
- const style = applyRadius(index)
352
+ const style = applyRadius(index)
389
353
 
390
- return (
354
+ // check if bar text/value string fits into each bars.
355
+ let textWidth = getTextWidth(xAxisValue, config.fontSize)
356
+ let doesTextFit = (textWidth / bar.y) * 100 < 48
357
+
358
+ let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
359
+ let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
360
+ if (!hasMultipleSeries && config.runtime.horizontal) {
361
+ xAxisTooltip = config.isLegendValue ? `${bar.key}: ${xAxisValue}` : config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
362
+ }
363
+ if (!hasMultipleSeries && !config.runtime.horizontal) {
364
+ yAxisTooltip = config.isLegendValue ? `${bar.key}: ${yAxisValue}` : config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
365
+ }
366
+
367
+ const tooltip = `<div>
368
+ ${config.legend.showLegendValuesTooltip && config.runtime.seriesLabels && hasMultipleSeries ? `${config.runtime.seriesLabels[bar.key] || ''}<br/>` : ''}
369
+ ${yAxisTooltip}<br />
370
+ ${xAxisTooltip}
371
+ </div>`
372
+
373
+ return (
391
374
  <>
392
375
  {/* This feels gross but inline transition was not working well*/}
393
376
  <style>
394
- {`
377
+ {`
395
378
  .linear #barGroup${barGroup.index},
396
379
  .Combo #barGroup${barGroup.index} {
397
380
  transform-origin: 0 ${barY + barHeight}px;
398
381
  }
399
382
  `}
400
- </style>
401
- <Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}-${barY}--${index}`}>
402
- <Text
403
- display={config.labels && displayBar ? 'block' : 'none'}
404
- opacity={transparentBar ? 0.5 : 1}
405
- x={barWidth * (barGroup.bars.length - bar.index - 0.5) + offset}
406
- y={barY - 5}
407
- fill={barColor}
408
- textAnchor="middle">
409
- {formatNumber(bar.value)}
410
- </Text>
411
- <foreignObject
412
- id={`barGroup${barGroup.index}`}
413
- key={`bar-group-bar-${barGroup.index}-${bar.index}-${bar.value}-${bar.key}`}
414
- x={ config.runtime.horizontal ? 0 : barWidth * (barGroup.bars.length - bar.index - 1) + offset }
415
- y={config.runtime.horizontal ? barWidth * (barGroup.bars.length - bar.index - 1) + (config.isLollipopChart && isLabelOnYAxis ? offset : 0) : barY }
416
- width={config.runtime.horizontal ? bar.y : barWidth}
417
- height={config.runtime.horizontal ? barWidth : barHeight}
418
- style={{
419
- background:config.isLollipopChart && config.lollipopColorStyle === 'regular' ? barColor :
420
- config.isLollipopChart && config.lollipopColorStyle === 'two-tone' ? chroma(barColor).brighten(1) : barColor ,
421
- border:`${config.isLollipopChart ? 0 :config.barHasBorder==='true' ? barBorderWidth: 0 }px solid #333`,
422
- ...style
423
- }}
424
- opacity={transparentBar ? 0.5 : 1}
425
- display={displayBar ? 'block' : 'none'}
426
- data-tip={tooltip}
427
- data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
428
- ></foreignObject>
429
- {config.isLollipopChart && config.lollipopShape === 'circle' &&
430
- <circle
431
- cx={orientation === 'horizontal' ? bar.y : barWidth * (barGroup.bars.length - bar.index - 1) + (isLabelBelowBar && orientation === 'horizontal' ? 0 : offset) + lollipopShapeSize/3.5}
432
- cy={orientation === 'horizontal' ? lollipopShapeSize/3.5 + (isLabelBelowBar && orientation === 'horizontal' ? 0: offset) : bar.y}
433
- r={lollipopShapeSize/2}
434
- fill={barColor}
435
- key={`circle--${bar.index}`}
436
- data-tip={tooltip}
437
- data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
438
- style={{ filter: 'unset', opacity: 1 }}
439
- />
440
- }
441
- {config.isLollipopChart && config.lollipopShape === 'square' &&
442
- <rect
443
- x={
444
- (orientation === 'horizontal' && bar.y > 10) ? bar.y - lollipopShapeSize / 2 : (orientation === 'horizontal' && bar.y < 10) ? 0 :
445
- (orientation !== 'horizontal') ? offset - lollipopBarWidth / 2 : barWidth * (barGroup.bars.length - bar.index - 1) + offset - 5.25
446
- }
447
- y={
448
- orientation === 'horizontal' ? 0 - lollipopBarWidth / 2 + (isLabelBelowBar ? 0 : offset) : config.height - bar.y > 10 ? bar.y - lollipopShapeSize / 2 : 0 }
449
- width={lollipopShapeSize}
450
- height={lollipopShapeSize}
451
- fill={barColor}
452
- key={`circle--${bar.index}`}
453
- data-tip={tooltip}
454
- data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
455
- style={{ 'opacity': 1, filter: 'unset' }}
456
- >
457
- <animate attributeName="height" values={`0, ${lollipopShapeSize}`} dur="2.5s"/>
458
- </rect>
459
- }
460
- {orientation === "horizontal" && textWidth + 100 < bar.y ?
461
- config.yAxis.labelPlacement === "On Bar" &&
462
- <Group>
383
+ </style>
384
+ <Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}-${barY}--${index}`}>
385
+ <foreignObject
386
+ id={`barGroup${barGroup.index}`}
387
+ key={`bar-group-bar-${barGroup.index}-${bar.index}-${bar.value}-${bar.key}`}
388
+ x={config.runtime.horizontal ? 0 : barWidth * bar.index + offset}
389
+ y={config.runtime.horizontal ? barWidth * bar.index : barY}
390
+ width={config.runtime.horizontal ? bar.y : barWidth}
391
+ height={isHorizontal && !config.isLollipopChart ? barWidth : isHorizontal && config.isLollipopChart ? lollipopBarWidth : barHeight}
392
+ style={{
393
+ background: config.isLollipopChart && config.lollipopColorStyle === 'regular' ? barColor : config.isLollipopChart && config.lollipopColorStyle === 'two-tone' ? chroma(barColor).brighten(1) : barColor,
394
+ border: `${config.isLollipopChart ? 0 : config.barHasBorder === 'true' ? barBorderWidth : 0}px solid #333`,
395
+ ...style
396
+ }}
397
+ opacity={transparentBar ? 0.5 : 1}
398
+ display={displayBar ? 'block' : 'none'}
399
+ data-tip={tooltip}
400
+ data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
401
+ ></foreignObject>
402
+ {orientation === 'horizontal' && !config.isLollipopChart && displayNumbersOnBar && (
463
403
  <Text
464
- innerRef={
465
- (e) => {
466
- if(e) {
467
- // use font sizes and padding to set the bar height
468
- let elem = e.getBBox()
469
- setTextWidth(elem.width)
470
- config.barHeight = ( (elem.height * 2) + (horizBarLabelPadding * 2) + onBarTextSpacing / 2 )
471
- config.barPadding = ( horizBarHeight / 2 )
472
- }
473
- }
474
- }
475
- x={ bar.y - horizBarLabelPadding }
476
- y={ barHeight * (barGroup.bars.length - bar.index - 1) + ( horizBarLabelPadding * 2 ) }
477
- fill={ labelColor }
478
- textAnchor="end"
404
+ display={displayBar ? 'block' : 'none'}
405
+ x={bar.y}
406
+ y={config.barHeight / 2 + config.barHeight * bar.index}
407
+ fill={labelColor}
408
+ dx={doesTextFit ? -5 : 5} // X padding
409
+ verticalAnchor='middle'
410
+ textAnchor={doesTextFit ? 'end' : 'start'}
479
411
  >
480
- { yAxisValue }
412
+ {xAxisValue}
481
413
  </Text>
414
+ )}
415
+ ;
416
+ {orientation === 'horizontal' && config.isLollipopChart && displayNumbersOnBar && (
482
417
  <Text
483
- x={ bar.y - horizBarLabelPadding }
484
- y={ barWidth * (barGroup.bars.length - bar.index - 1) + ( horizBarLabelPadding * 2 ) + onBarTextSpacing }
485
- fill={ labelColor }
486
- textAnchor="end"
418
+ display={displayBar ? 'block' : 'none'}
419
+ x={`${bar.y + (config.isLollipopChart ? 15 : 5) + (config.isLollipopChart && barGroup.bars.length === bar.index ? offset : 0)}`} // padding
420
+ y={0}
421
+ fill={'#000000'}
422
+ textAnchor='start'
423
+ verticalAnchor='middle'
424
+ fontWeight={'normal'}
487
425
  >
488
- { xAxisValue }
426
+ {xAxisValue}
489
427
  </Text>
428
+ )}
429
+ {orientation === 'horizontal' && isLabelBelowBar && !config.yAxis.hideLabel && (
430
+ <Text x={config.yAxis.hideAxis ? 0 : 5} y={barGroup.height} dy={4} verticalAnchor={'start'} textAnchor={'start'}>
431
+ {config.runtime.yAxis.type === 'date'
432
+ ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey]))
433
+ : isHorizontal
434
+ ? data[barGroup.index][config.runtime.originalXAxis.dataKey]
435
+ : formatNumber(data[barGroup.index][config.runtime.originalXAxis.dataKey])}
436
+ </Text>
437
+ )}
438
+ ;
439
+ {orientation === 'vertical' && (
440
+ <Text display={config.labels && displayBar ? 'block' : 'none'} opacity={transparentBar ? 0.5 : 1} x={barWidth * (bar.index + 0.5) + offset} y={barY - 5} fill={barColor} textAnchor='middle'>
441
+ {bar.value}
442
+ </Text>
443
+ )}
444
+ ;
445
+ {config.isLollipopChart && config.lollipopShape === 'circle' && (
446
+ <circle
447
+ cx={orientation === 'horizontal' ? bar.y : barWidth * (barGroup.bars.length - bar.index - 1) + (isLabelBelowBar && orientation === 'horizontal' ? 0 : offset) + lollipopShapeSize / 3.5}
448
+ cy={orientation === 'horizontal' ? 0 + lollipopBarWidth / 2 : bar.y}
449
+ r={lollipopShapeSize / 2}
450
+ fill={barColor}
451
+ key={`circle--${bar.index}`}
452
+ data-tip={tooltip}
453
+ data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
454
+ style={{ filter: 'unset', opacity: 1 }}
455
+ />
456
+ )}
457
+ {config.isLollipopChart && config.lollipopShape === 'square' && (
458
+ <rect
459
+ x={orientation === 'horizontal' && bar.y > 10 ? bar.y - lollipopShapeSize / 2 : orientation === 'horizontal' && bar.y < 10 ? 0 : orientation !== 'horizontal' ? offset - lollipopBarWidth / 2 : barWidth * (barGroup.bars.length - bar.index - 1) + offset - 5.25}
460
+ y={orientation === 'horizontal' ? 0 - lollipopBarWidth / 2 : barY}
461
+ width={lollipopShapeSize}
462
+ height={lollipopShapeSize}
463
+ fill={barColor}
464
+ key={`circle--${bar.index}`}
465
+ data-tip={tooltip}
466
+ data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
467
+ style={{ opacity: 1, filter: 'unset' }}
468
+ >
469
+ <animate attributeName='height' values={`0, ${lollipopShapeSize}`} dur='2.5s' />
470
+ </rect>
471
+ )}
490
472
  </Group>
491
- :
492
- (isLabelOnBar) &&
493
- <Group>
494
- {/* hide y label if we're only showing data on bar */}
495
- <Text
496
- x={ bar.y + horizBarLabelPadding }
497
- y={ barWidth * (barGroup.bars.length - bar.index - 1) + ( horizBarLabelPadding * 2 ) }
498
- fill={ "#000" }
499
- textAnchor="start"
500
- verticalAnchor="end"
501
- >{yAxisValue}</Text>
502
- <Text
503
- x={ bar.y + horizBarLabelPadding }
504
- y={ barWidth * (barGroup.bars.length - bar.index - 1) + ( horizBarLabelPadding * 2 ) + onBarTextSpacing }
505
- fill={ "#000" }
506
- textAnchor="start"
507
- verticalAnchor="start"
508
- >
509
- { xAxisValue }
510
- </Text>
511
- </Group>
512
- }
513
-
514
- { orientation === "horizontal" && isLabelBelowBar && !config.yAxis.hideLabel &&
515
- <>
516
- <Text
517
- x={ config.yAxis.hideAxis ? 0 : 5 } // padding
518
- y={ config.isLollipopChart ? lollipopShapeSize * config.series.length + 2 : barWidth * config.series.length + 7 }
519
- verticalAnchor={"start"}
520
- textAnchor={"start"}
521
- >{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])}
522
- </Text>
523
-
524
- { (displayNumbersOnBar) ?
525
- (textWidth + 100 < bar.y && !config.isLollipopChart) ?
526
- (
527
- <Text
528
- display={displayBar ? 'block' : 'none'}
529
- x={ bar.y - 5 } // padding
530
- y={ config.isLollipopChart ? offset : (config.barHeight / 2 ) + config.barHeight * (barGroup.bars.length - bar.index - 1) }
531
- fill={ labelColor }
532
- textAnchor="end"
533
- verticalAnchor="middle"
534
- >
535
- { xAxisValue }
536
- </Text>
537
- )
538
- : (
539
- <Text
540
- display={displayBar ? 'block' : 'none'}
541
- x={ `${bar.y + (config.isLollipopChart ? 15 : 5) + (config.isLollipopChart && barGroup.bars.length === bar.index ? offset : 0 ) }`} // padding
542
- y={ config.isLollipopChart ? 0 : (config.barHeight / 2 ) + config.barHeight * (barGroup.bars.length - bar.index - 1)}
543
- fill={ '#000000'}
544
- textAnchor="start"
545
- verticalAnchor="middle"
546
- fontWeight={'normal'}
547
- >
548
- { xAxisValue }
549
- </Text>
550
- )
551
- : ""
552
- }
553
- </>
554
- }
555
-
556
- { (isLabelOnYAxis && orientation === "horizontal") &&
557
- <>
558
- { (displayNumbersOnBar) ?
559
- (textWidth + 100 < bar.y && !config.isLollipopChart) ?
560
- (
561
- <Text
562
- display={displayBar ? 'block' : 'none'}
563
- x={ bar.y - 5 } // padding
564
- y={
565
- config.isLollipopChart ? (config.barHeight * (barGroup.bars.length - bar.index - 1) ) + offset :
566
- (config.barHeight * (barGroup.bars.length - bar.index - 1) ) + (config.barHeight / 2 )
567
- }
568
- fill={ labelColor }
569
- textAnchor="end"
570
- verticalAnchor="middle"
571
- >
572
- { formatNumber(xAxisValue )}
573
- </Text>
574
- )
575
- : (
576
- <Text
577
- display={displayBar ? 'block' : 'none'}
578
- x={ `${bar.y + (config.isLollipopChart ? 15 : 5)}` } // padding
579
- y={
580
- config.isLollipopChart ? (config.barHeight * (barGroup.bars.length - bar.index - 1) ) + offset :
581
- (config.barHeight * (barGroup.bars.length - bar.index - 1) ) + (config.barHeight / 2 )
582
- }
583
- fill={ '#000000' }
584
- textAnchor="start"
585
- verticalAnchor="middle"
586
- >
587
- {formatNumber( xAxisValue) }
588
- </Text>
589
- )
590
- : ""
591
- }
592
- </>
593
- }
594
- </Group>
595
- </>
596
- )}
597
- )}
598
- </Group>
599
- ))}}
473
+ </>
474
+ )
475
+ })}
476
+ </Group>
477
+ ))
478
+ }}
600
479
  </BarGroup>
601
480
 
602
- {Object.keys(config.confidenceKeys).length > 0 ? data.map((d) => {
603
- let xPos = xScale(getXAxisData(d));
604
- let upperPos = yScale(getYAxisData(d, config.confidenceKeys.lower));
605
- let lowerPos = yScale(getYAxisData(d, config.confidenceKeys.upper));
606
- let tickWidth = 5;
607
-
608
- return (
609
- <path key={`confidence-interval-${d[config.runtime.originalXAxis.dataKey]}`} stroke="#333" strokeWidth="2px" d={`
481
+ {Object.keys(config.confidenceKeys).length > 0
482
+ ? data.map(d => {
483
+ let xPos = xScale(getXAxisData(d))
484
+ let upperPos = yScale(getYAxisData(d, config.confidenceKeys.lower))
485
+ let lowerPos = yScale(getYAxisData(d, config.confidenceKeys.upper))
486
+ let tickWidth = 5
487
+
488
+ return (
489
+ <path
490
+ key={`confidence-interval-${d[config.runtime.originalXAxis.dataKey]}`}
491
+ stroke='#333'
492
+ strokeWidth='2px'
493
+ d={`
610
494
  M${xPos - tickWidth} ${upperPos}
611
495
  L${xPos + tickWidth} ${upperPos}
612
496
  M${xPos} ${upperPos}
613
497
  L${xPos} ${lowerPos}
614
498
  M${xPos - tickWidth} ${lowerPos}
615
- L${xPos + tickWidth} ${lowerPos}`}/>
616
- );
617
- }) : ''}
499
+ L${xPos + tickWidth} ${lowerPos}`}
500
+ />
501
+ )
502
+ })
503
+ : ''}
618
504
  </Group>
619
505
  )}
620
506
  </Group>
621
507
  </ErrorBoundary>
622
- );
508
+ )
623
509
  }