@cdc/chart 4.22.11 → 4.23.2

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 (65) hide show
  1. package/dist/cdcchart.js +54569 -16
  2. package/examples/Barchart_with_negative.json +34 -0
  3. package/examples/box-plot-data.json +71 -0
  4. package/examples/box-plot.csv +5 -0
  5. package/examples/box-plot.json +124 -0
  6. package/examples/dynamic-legends.json +1 -1
  7. package/examples/example-bar-chart-nonnumeric.json +36 -0
  8. package/examples/example-bar-chart.json +33 -0
  9. package/examples/example-combo-bar-nonnumeric.json +105 -0
  10. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +3 -1
  11. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +1 -1
  12. package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +86 -17
  13. package/examples/gallery/paired-bar/paired-bar-chart.json +65 -13
  14. package/examples/line-chart-nonnumeric.json +32 -0
  15. package/examples/line-chart.json +21 -63
  16. package/examples/new-data.csv +17 -0
  17. package/examples/newdata.json +90 -0
  18. package/examples/planet-combo-example-config.json +143 -20
  19. package/examples/planet-example-data-nonnumeric.json +56 -0
  20. package/examples/planet-example-data.json +2 -2
  21. package/examples/planet-pie-example-config-nonnumeric.json +30 -0
  22. package/examples/scatterplot-continuous.csv +17 -0
  23. package/examples/{private/yaxis-test.json → scatterplot.json} +53 -50
  24. package/examples/sparkline-chart-nonnumeric.json +76 -0
  25. package/examples/stacked-vertical-bar-example-negative.json +154 -0
  26. package/examples/stacked-vertical-bar-example-nonnumerics.json +154 -0
  27. package/{src/index.html → index.html} +18 -11
  28. package/package.json +29 -22
  29. package/src/{CdcChart.tsx → CdcChart.jsx} +193 -119
  30. package/src/components/BarChart.jsx +517 -0
  31. package/src/components/BoxPlot.jsx +88 -0
  32. package/src/components/{DataTable.tsx → DataTable.jsx} +125 -32
  33. package/src/components/{EditorPanel.js → EditorPanel.jsx} +376 -115
  34. package/src/components/Filters.jsx +125 -0
  35. package/src/components/Legend.jsx +303 -0
  36. package/src/components/{LineChart.tsx → LineChart.jsx} +87 -22
  37. package/src/components/{LinearChart.tsx → LinearChart.jsx} +172 -113
  38. package/src/components/{PairedBarChart.tsx → PairedBarChart.jsx} +46 -79
  39. package/src/components/{PieChart.tsx → PieChart.jsx} +29 -34
  40. package/src/components/ScatterPlot.jsx +48 -0
  41. package/src/components/{SparkLine.js → SparkLine.jsx} +49 -18
  42. package/src/components/useIntersectionObserver.jsx +29 -0
  43. package/src/data/initial-state.js +44 -8
  44. package/src/hooks/{useColorPalette.ts → useColorPalette.js} +10 -28
  45. package/src/hooks/{useReduceData.ts → useReduceData.js} +27 -13
  46. package/src/hooks/useRightAxis.js +3 -1
  47. package/src/index.jsx +16 -0
  48. package/src/scss/DataTable.scss +23 -1
  49. package/src/scss/main.scss +83 -32
  50. package/vite.config.js +4 -0
  51. package/examples/private/filters.json +0 -170
  52. package/examples/private/line-test-data.json +0 -22
  53. package/examples/private/line-test-two.json +0 -210
  54. package/examples/private/line-test.json +0 -102
  55. package/examples/private/new.json +0 -48800
  56. package/examples/private/newtest.csv +0 -101
  57. package/examples/private/shawn.json +0 -1106
  58. package/examples/private/test.json +0 -10124
  59. package/examples/private/yaxis-testing.csv +0 -27
  60. package/examples/private/yaxis.json +0 -28
  61. package/src/components/BarChart.tsx +0 -579
  62. package/src/components/Legend.js +0 -284
  63. package/src/components/useIntersectionObserver.tsx +0 -27
  64. package/src/index.tsx +0 -18
  65. /package/src/{context.tsx → ConfigContext.jsx} +0 -0
@@ -1,27 +0,0 @@
1
- week,tot_tests_0_12,tot_tests_13_17,tot_tests_18_older,0_12_positivity_rate,13_17_positivity_rate,18_older_positivity_rate
2
- 5/21/2022,0,0,3,,,100
3
- 5/28/2022,0,0,31,,,33.3
4
- 6/4/2022,7,0,53,0,,34
5
- 6/11/2022,3,0,128,0,,23.5
6
- 6/18/2022,3,0,153,0,,38.8
7
- 6/25/2022,10,0,232,0,,43.4
8
- 7/2/2022,16,5,530,8.3,20,53
9
- 7/9/2022,14,3,734,7.1,0,53.6
10
- 7/16/2022,38,20,2442,2.9,0,58.3
11
- 7/23/2022,74,21,2962,4.2,5,54
12
- 7/30/2022,215,72,4032,0.5,0,47.2
13
- 8/6/2022,339,131,5236,0.6,0,36.6
14
- 8/13/2022,590,153,6540,0.8,0,30.3
15
- 8/20/2022,717,240,7696,1.8,5.5,28.5
16
- 8/27/2022,548,202,5488,0.6,3.3,27.4
17
- 9/3/2022,566,152,4612,0.2,2.1,26
18
- 9/10/2022,432,139,3399,0.3,2.4,24.2
19
- 9/17/2022,350,119,3065,1.3,2.9,25.8
20
- 9/24/2022,307,102,2648,0,5.6,26.9
21
- 10/1/2022,222,84,2002,0,6.8,24.9
22
- 10/8/2022,143,59,1645,0,3.9,24.3
23
- 10/15/2022,151,71,1528,0.8,0,27.1
24
- 10/22/2022,106,48,1156,3.5,0,25.6
25
- 10/29/2022,80,38,969,1.3,5.4,21
26
- 11/5/2022,80,33,912,5.9,0,19
27
- 11/12/2022,25,7,266,17.4,0,18.9
@@ -1,28 +0,0 @@
1
- [
2
- { "week": "5/21/2022", "tot_tests_0_12": "0", "tot_tests_13_17": "0", "tot_tests_18_older": "3", "0_12_positivity_rate": "", "13_17_positivity_rate": "", "18_older_positivity_rate": "100" },
3
- { "week": "5/28/2022", "tot_tests_0_12": "0", "tot_tests_13_17": "0", "tot_tests_18_older": "31", "0_12_positivity_rate": "", "13_17_positivity_rate": "", "18_older_positivity_rate": "33.3" },
4
- { "week": "6/4/2022", "tot_tests_0_12": "7", "tot_tests_13_17": "0", "tot_tests_18_older": "53", "0_12_positivity_rate": "0", "13_17_positivity_rate": "", "18_older_positivity_rate": "34" },
5
- { "week": "6/11/2022", "tot_tests_0_12": "3", "tot_tests_13_17": "0", "tot_tests_18_older": "128", "0_12_positivity_rate": "0", "13_17_positivity_rate": "", "18_older_positivity_rate": "23.5" },
6
- { "week": "6/18/2022", "tot_tests_0_12": "3", "tot_tests_13_17": "0", "tot_tests_18_older": "153", "0_12_positivity_rate": "0", "13_17_positivity_rate": "", "18_older_positivity_rate": "38.8" },
7
- { "week": "6/25/2022", "tot_tests_0_12": "10", "tot_tests_13_17": "0", "tot_tests_18_older": "232", "0_12_positivity_rate": "0", "13_17_positivity_rate": "", "18_older_positivity_rate": "43.4" },
8
- { "week": "7/2/2022", "tot_tests_0_12": "16", "tot_tests_13_17": "5", "tot_tests_18_older": "530", "0_12_positivity_rate": "8.3", "13_17_positivity_rate": "20", "18_older_positivity_rate": "53" },
9
- { "week": "7/9/2022", "tot_tests_0_12": "14", "tot_tests_13_17": "3", "tot_tests_18_older": "734", "0_12_positivity_rate": "7.1", "13_17_positivity_rate": "0", "18_older_positivity_rate": "53.6" },
10
- { "week": "7/16/2022", "tot_tests_0_12": "38", "tot_tests_13_17": "20", "tot_tests_18_older": "2442", "0_12_positivity_rate": "2.9", "13_17_positivity_rate": "0", "18_older_positivity_rate": "58.3" },
11
- { "week": "7/23/2022", "tot_tests_0_12": "74", "tot_tests_13_17": "21", "tot_tests_18_older": "2962", "0_12_positivity_rate": "4.2", "13_17_positivity_rate": "5", "18_older_positivity_rate": "54" },
12
- { "week": "7/30/2022", "tot_tests_0_12": "215", "tot_tests_13_17": "72", "tot_tests_18_older": "4032", "0_12_positivity_rate": "0.5", "13_17_positivity_rate": "0", "18_older_positivity_rate": "47.2" },
13
- { "week": "8/6/2022", "tot_tests_0_12": "339", "tot_tests_13_17": "131", "tot_tests_18_older": "5236", "0_12_positivity_rate": "0.6", "13_17_positivity_rate": "0", "18_older_positivity_rate": "36.6" },
14
- { "week": "8/13/2022", "tot_tests_0_12": "590", "tot_tests_13_17": "153", "tot_tests_18_older": "6540", "0_12_positivity_rate": "0.8", "13_17_positivity_rate": "0", "18_older_positivity_rate": "30.3" },
15
- { "week": "8/20/2022", "tot_tests_0_12": "717", "tot_tests_13_17": "240", "tot_tests_18_older": "7696", "0_12_positivity_rate": "1.8", "13_17_positivity_rate": "5.5", "18_older_positivity_rate": "28.5" },
16
- { "week": "8/27/2022", "tot_tests_0_12": "548", "tot_tests_13_17": "202", "tot_tests_18_older": "5488", "0_12_positivity_rate": "0.6", "13_17_positivity_rate": "3.3", "18_older_positivity_rate": "27.4" },
17
- { "week": "9/3/2022", "tot_tests_0_12": "566", "tot_tests_13_17": "152", "tot_tests_18_older": "4612", "0_12_positivity_rate": "0.2", "13_17_positivity_rate": "2.1", "18_older_positivity_rate": "26" },
18
- { "week": "9/10/2022", "tot_tests_0_12": "432", "tot_tests_13_17": "139", "tot_tests_18_older": "3399", "0_12_positivity_rate": "0.3", "13_17_positivity_rate": "2.4", "18_older_positivity_rate": "24.2" },
19
- { "week": "9/17/2022", "tot_tests_0_12": "350", "tot_tests_13_17": "119", "tot_tests_18_older": "3065", "0_12_positivity_rate": "1.3", "13_17_positivity_rate": "2.9", "18_older_positivity_rate": "25.8" },
20
- { "week": "9/24/2022", "tot_tests_0_12": "307", "tot_tests_13_17": "102", "tot_tests_18_older": "2648", "0_12_positivity_rate": "0", "13_17_positivity_rate": "5.6", "18_older_positivity_rate": "26.9" },
21
- { "week": "10/1/2022", "tot_tests_0_12": "222", "tot_tests_13_17": "84", "tot_tests_18_older": "2002", "0_12_positivity_rate": "0", "13_17_positivity_rate": "6.8", "18_older_positivity_rate": "24.9" },
22
- { "week": "10/8/2022", "tot_tests_0_12": "143", "tot_tests_13_17": "59", "tot_tests_18_older": "1645", "0_12_positivity_rate": "0", "13_17_positivity_rate": "3.9", "18_older_positivity_rate": "24.3" },
23
- { "week": "10/15/2022", "tot_tests_0_12": "151", "tot_tests_13_17": "71", "tot_tests_18_older": "1528", "0_12_positivity_rate": "0.8", "13_17_positivity_rate": "0", "18_older_positivity_rate": "27.1" },
24
- { "week": "10/22/2022", "tot_tests_0_12": "106", "tot_tests_13_17": "48", "tot_tests_18_older": "1156", "0_12_positivity_rate": "3.5", "13_17_positivity_rate": "0", "18_older_positivity_rate": "25.6" },
25
- { "week": "10/29/2022", "tot_tests_0_12": "80", "tot_tests_13_17": "38", "tot_tests_18_older": "969", "0_12_positivity_rate": "1.3", "13_17_positivity_rate": "5.4", "18_older_positivity_rate": "21" },
26
- { "week": "11/5/2022", "tot_tests_0_12": "80", "tot_tests_13_17": "33", "tot_tests_18_older": "912", "0_12_positivity_rate": "5.9", "13_17_positivity_rate": "0", "18_older_positivity_rate": "19" },
27
- { "week": "11/12/2022", "tot_tests_0_12": "25", "tot_tests_13_17": "7", "tot_tests_18_older": "266", "0_12_positivity_rate": "17.4", "13_17_positivity_rate": "0", "18_older_positivity_rate": "18.9" }
28
- ]
@@ -1,579 +0,0 @@
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
32
-
33
- const applyRadius = (index: number) => {
34
- if (index === undefined || index === null || !isRounded) return
35
- let style = {}
36
-
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
- }
46
-
47
- return style
48
- }
49
-
50
- // Using State
51
- const [horizBarHeight, setHorizBarHeight] = useState(null)
52
- const [textWidth, setTextWidth] = useState(null)
53
-
54
- useEffect(() => {
55
- if (orientation === 'horizontal' && !config.yAxis.labelPlacement) {
56
- updateConfig({
57
- ...config,
58
- yAxis: {
59
- ...config,
60
- labelPlacement: 'Below Bar'
61
- }
62
- })
63
- }
64
- }, [config, updateConfig])
65
-
66
- useEffect(() => {
67
- if (config.isLollipopChart === false && config.barHeight < 25) {
68
- updateConfig({ ...config, barHeight: 25 })
69
- }
70
- }, [config.isLollipopChart])
71
-
72
- useEffect(() => {
73
- if (config.visualizationSubType === 'horizontal') {
74
- updateConfig({
75
- ...config,
76
- orientation: 'horizontal'
77
- })
78
- }
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])
89
-
90
- // config.runtime.seriesKeys.sort().reverse();
91
-
92
- return (
93
- <ErrorBoundary component='BarChart'>
94
- <Group left={config.runtime.yAxis.size}>
95
- {/* Stacked Vertical */}
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
- }
153
- </BarStack>
154
- )}
155
-
156
- {/* Stacked Horizontal */}
157
- {config.visualizationSubType === 'stacked' && isHorizontal && (
158
- <>
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
- barStack.bars.map((bar, index) => {
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}`
166
- let xAxisTooltip = config.xAxis.label ? `${config.xAxis.label}: ${xAxisValue}` : xAxisValue
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
-
170
- const tooltip = `<div>
171
- ${yAxisTooltip}<br />
172
- ${xAxisTooltip}<br />
173
- ${config.seriesLabel ? `${config.seriesLabel}: ${bar.key}` : ''}`
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
179
-
180
- config.barHeight = Number(config.barHeight)
181
- const style = applyRadius(barStack.index)
182
-
183
- if (orientation === 'horizontal') {
184
- if (isLabelBelowBar || isLabelMissing || isLabelOnYAxis) {
185
- if (barHeight < 40) {
186
- config.barPadding = 40
187
- } else {
188
- config.barPadding = Number(barPadding)
189
- }
190
- } else {
191
- config.barPadding = Number(barPadding) / 2
192
- }
193
- }
194
-
195
- config.height = Number(barHeight) * data.length + Number(config.barPadding) * data.length
196
-
197
- let labelColor = '#000000'
198
-
199
- let textPosition = bar.y - config.barPadding / 2 - Number(config.barHeight / 2) + Number(config.barHeight) + 5
200
-
201
- if (chroma.contrast(labelColor, bar.color) < 4.9) {
202
- labelColor = '#FFFFFF'
203
- }
204
-
205
- return (
206
- <Group key={index}>
207
- <foreignObject
208
- key={`barstack-horizontal-${barStack.index}-${bar.index}-${index}`}
209
- className={`animated-chart group ${animatedChart ? 'animated' : ''}`}
210
- x={bar.x}
211
- y={bar.y - config.barPadding / 2 - config.barHeight / 2}
212
- width={bar.width}
213
- height={config.barHeight}
214
- style={{ background: bar.color, border: `${config.barHasBorder === 'true' ? barBorderWidth : 0}px solid #333`, ...style }}
215
- opacity={transparentBar ? 0.5 : 1}
216
- display={displayBar ? 'block' : 'none'}
217
- data-tip={tooltip}
218
- data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
219
- ></foreignObject>
220
-
221
- {orientation === 'horizontal' && visualizationSubType === 'stacked' && isLabelBelowBar && barStack.index === 0 && !config.yAxis.hideLabel && (
222
- <Text
223
- x={`${bar.x + (config.isLollipopChart ? 15 : 5)}`} // padding
224
- y={textPosition}
225
- fill={'#000000'}
226
- textAnchor='start'
227
- verticalAnchor='start'
228
- >
229
- {isHorizontal ? xAxisValue : formatNumber(xAxisValue)}
230
- </Text>
231
- )}
232
-
233
- {displayNumbersOnBar && textWidth + 50 < bar.width && (
234
- <Text
235
- display={displayBar ? 'block' : 'none'}
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
- }
247
- }}
248
- >
249
- {formatNumber(data[bar.index][bar.key])}
250
- </Text>
251
- )}
252
- </Group>
253
- )
254
- })
255
- )
256
- }
257
- </BarStackHorizontal>
258
- </>
259
- )}
260
-
261
- {/* Bar Groups: Not Stacked */}
262
- {config.visualizationSubType !== 'stacked' && (
263
- <Group>
264
- <BarGroup
265
- data={data}
266
- keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys}
267
- height={yMax}
268
- x0={(d: any) => d[config.runtime.originalXAxis.dataKey]}
269
- x0Scale={config.runtime.horizontal ? yScale : xScale}
270
- x1Scale={seriesScale}
271
- yScale={config.runtime.horizontal ? xScale : yScale}
272
- color={() => {
273
- return ''
274
- }}
275
- >
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
287
- } else {
288
- config.barPadding = barPadding
289
- }
290
- } else {
291
- config.barPadding = barPadding / 2
292
- }
293
-
294
- if (config.isLollipopChart && config.yAxis.labelPlacement === 'Below Bar') {
295
- config.barPadding = config.barPadding + 7
296
- }
297
- config.barHeight = config.isLollipopChart ? lollipopBarWidth : barHeight
298
- config.height = barsPerGroup * barHeight * barGroups.length + config.barPadding * barGroups.length
299
- }
300
-
301
- return barGroups.map((barGroup, index) => (
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
- }
320
-
321
- const set = new Set()
322
- data.forEach(d => set.add(d[config.legend.colorCode]))
323
- const uniqValues = Array.from(set)
324
-
325
- let palette = colorPalettes[config.palette].slice(0, uniqValues.length)
326
-
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]
333
-
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]
336
-
337
- if (config.runtime.horizontal) {
338
- let tempValue = yAxisValue
339
- yAxisValue = xAxisValue
340
- xAxisValue = tempValue
341
- barWidth = config.barHeight
342
- }
343
-
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>
364
- ${yAxisTooltip}<br />
365
- ${xAxisTooltip}<br />
366
- ${config.seriesLabel ? `${config.seriesLabel}: ${bar.key}` : ''}`
367
- const style = applyRadius(index)
368
-
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
- <>
467
- <Text
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'}
472
- >
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])}
478
- </Text>
479
-
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
- }}
549
- </BarGroup>
550
-
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={`
564
- M${xPos - tickWidth} ${upperPos}
565
- L${xPos + tickWidth} ${upperPos}
566
- M${xPos} ${upperPos}
567
- L${xPos} ${lowerPos}
568
- M${xPos - tickWidth} ${lowerPos}
569
- L${xPos + tickWidth} ${lowerPos}`}
570
- />
571
- )
572
- })
573
- : ''}
574
- </Group>
575
- )}
576
- </Group>
577
- </ErrorBoundary>
578
- )
579
- }