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