@cdc/chart 4.23.3 → 4.23.4

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 (84) hide show
  1. package/dist/cdcchart.js +24397 -24193
  2. package/examples/feature/__data__/area-chart.json +56 -0
  3. package/examples/{planet-example-data.json → feature/__data__/planet-example-data.json} +16 -4
  4. package/examples/{area-chart.json → feature/area/area-chart.json} +70 -13
  5. package/examples/{horizontal-chart-max-increase.json → feature/bar/horizontal-chart-max-increase.json} +10 -4
  6. package/examples/{horizontal-chart.json → feature/bar/horizontal-chart.json} +10 -4
  7. package/examples/{horizontal-stacked-bar-chart.json → feature/bar/horizontal-stacked-bar-chart.json} +7 -3
  8. package/examples/{planet-chart-horizontal-example-config.json → feature/bar/planet-chart-horizontal-example-config.json} +8 -3
  9. package/examples/{planet-example-config.json → feature/bar/planet-example-config.json} +2 -2
  10. package/examples/{box-plot.json → feature/boxplot/boxplot.json} +7 -7
  11. package/examples/feature/boxplot/testing.csv +38 -0
  12. package/examples/feature/combo/combochart-categories_are_numbers .json +18 -0
  13. package/examples/{planet-combo-example-config.json → feature/combo/planet-combo-example-config.json} +1 -1
  14. package/examples/{planet-deviation-config.json → feature/deviation/planet-deviation-config.json} +2 -2
  15. package/examples/{planet-deviation-data.json → feature/deviation/planet-deviation-data.json} +9 -9
  16. package/examples/feature/filters/filter-testing.json +178 -0
  17. package/examples/feature/forecasting/case_date_example.csv +130 -0
  18. package/examples/feature/forecasting/effective_reproduction.json +202 -0
  19. package/examples/feature/forecasting/r_data.csv +130 -0
  20. package/examples/feature/line/line-chart.json +124 -0
  21. package/examples/{paired-bar-example.json → feature/paired-bar/paired-bar-example.json} +10 -4
  22. package/examples/{planet-pie-example-config.json → feature/pie/planet-pie-example-config.json} +2 -2
  23. package/examples/{scatterplot.json → feature/scatterplot/scatterplot.json} +1 -1
  24. package/examples/{case-rate-example-config.json → feature/tests-case-rate/case-rate-example-config.json} +2 -2
  25. package/examples/{covid-confidence-example-config.json → feature/tests-covid/covid-confidence-example-config.json} +8 -3
  26. package/examples/{covid-example-config.json → feature/tests-covid/covid-example-config.json} +7 -3
  27. package/examples/{cutoff-example-config.json → feature/tests-cutoff/cutoff-example-config.json} +7 -3
  28. package/examples/{date-exclusions-config.json → feature/tests-date-exclusions/date-exclusions-config.json} +2 -2
  29. package/examples/{example-bar-chart-nonnumeric.json → feature/tests-non-numerics/example-bar-chart-nonnumeric.json} +1 -1
  30. package/examples/{planet-pie-example-config-nonnumeric.json → feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json} +2 -2
  31. package/examples/{sparkline-chart-nonnumeric.json → feature/tests-non-numerics/sparkline-chart-nonnumeric.json} +1 -1
  32. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +145 -7
  33. package/examples/gallery/paired-bar/paired-bar-chart.json +1 -0
  34. package/index.html +73 -49
  35. package/package.json +2 -2
  36. package/src/CdcChart.jsx +111 -26
  37. package/src/components/AreaChart.jsx +105 -70
  38. package/src/components/BarChart.jsx +45 -28
  39. package/src/components/BoxPlot.jsx +28 -20
  40. package/src/components/DataTable.jsx +7 -6
  41. package/src/components/DeviationBar.jsx +2 -2
  42. package/src/components/EditorPanel.jsx +252 -193
  43. package/src/components/Legend.jsx +1 -1
  44. package/src/components/LineChart.jsx +10 -16
  45. package/src/components/LinearChart.jsx +30 -34
  46. package/src/components/PairedBarChart.jsx +6 -6
  47. package/src/components/PieChart.jsx +2 -4
  48. package/src/components/SparkLine.jsx +6 -42
  49. package/src/data/initial-state.js +7 -3
  50. package/src/index.jsx +2 -1
  51. package/src/scss/editor-panel.scss +15 -0
  52. package/src/scss/main.scss +8 -6
  53. package/examples/box-plot.csv +0 -5
  54. package/examples/dynamic-legends.json +0 -125
  55. package/examples/line-chart.json +0 -34
  56. package/examples/temp-example-config.json +0 -64
  57. package/examples/temp-example-data.json +0 -130
  58. package/src/components/Filters.jsx +0 -126
  59. /package/examples/{age-adjusted-rates.json → feature/__data__/age-adjusted-rates.json} +0 -0
  60. /package/examples/{new-data.csv → feature/__data__/new-data.csv} +0 -0
  61. /package/examples/{planet-example-data-max-increase.json → feature/__data__/planet-example-data-max-increase.json} +0 -0
  62. /package/examples/{Barchart_with_negative.json → feature/bar/Barchart_with_negative.json} +0 -0
  63. /package/examples/{example-bar-chart.json → feature/bar/example-bar-chart.json} +0 -0
  64. /package/examples/{stacked-vertical-bar-example-negative.json → feature/bar/stacked-vertical-bar-example-negative.json} +0 -0
  65. /package/examples/{stacked-vertical-bar-example.json → feature/bar/stacked-vertical-bar-example.json} +0 -0
  66. /package/examples/{box-plot-data.json → feature/boxplot/box-plot-data.json} +0 -0
  67. /package/examples/{newdata.json → feature/boxplot/boxplot-data.json} +0 -0
  68. /package/examples/{line-chart-max-increase.json → feature/line/line-chart-max-increase.json} +0 -0
  69. /package/examples/{paired-bar-data.json → feature/paired-bar/paired-bar-data.json} +0 -0
  70. /package/examples/{paired-bar-formatted.json → feature/paired-bar/paired-bar-formatted.json} +0 -0
  71. /package/examples/{scatterplot-continuous.csv → feature/scatterplot/scatterplot-continuous.csv} +0 -0
  72. /package/examples/{example-sparkline.json → feature/sparkline/example-sparkline.json} +0 -0
  73. /package/examples/{big-small-test-bar.json → feature/tests-big-small/big-small-test-bar.json} +0 -0
  74. /package/examples/{big-small-test-line.json → feature/tests-big-small/big-small-test-line.json} +0 -0
  75. /package/examples/{big-small-test-negative.json → feature/tests-big-small/big-small-test-negative.json} +0 -0
  76. /package/examples/{case-rate-example-data.json → feature/tests-case-rate/case-rate-example-data.json} +0 -0
  77. /package/examples/{covid-example-data-confidence.json → feature/tests-covid/covid-example-data-confidence.json} +0 -0
  78. /package/examples/{covid-example-data.json → feature/tests-covid/covid-example-data.json} +0 -0
  79. /package/examples/{cutoff-example-data.json → feature/tests-cutoff/cutoff-example-data.json} +0 -0
  80. /package/examples/{date-exclusions-data.json → feature/tests-date-exclusions/date-exclusions-data.json} +0 -0
  81. /package/examples/{example-combo-bar-nonnumeric.json → feature/tests-non-numerics/example-combo-bar-nonnumeric.json} +0 -0
  82. /package/examples/{line-chart-nonnumeric.json → feature/tests-non-numerics/line-chart-nonnumeric.json} +0 -0
  83. /package/examples/{planet-example-data-nonnumeric.json → feature/tests-non-numerics/planet-example-data-nonnumeric.json} +0 -0
  84. /package/examples/{stacked-vertical-bar-example-nonnumerics.json → feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json} +0 -0
@@ -8,10 +8,7 @@ import ConfigContext from '../ConfigContext'
8
8
  import { BarStackHorizontal } from '@visx/shape'
9
9
 
10
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, isNumber, cleanData, getTextWidth, parseDate } = useContext(ConfigContext)
12
- // Just do this once up front otherwise we end up
13
- // calling clean several times on same set of data (TT)
14
- const cleanedData = cleanData(data, config.xAxis.dataKey)
11
+ const { transformedData: data, colorScale, seriesHighlight, config, formatNumber, updateConfig, colorPalettes, formatDate, isNumber, getTextWidth, parseDate } = useContext(ConfigContext)
15
12
 
16
13
  const { orientation, visualizationSubType } = config
17
14
  const isHorizontal = orientation === 'horizontal'
@@ -32,17 +29,15 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
32
29
  const fontSize = { small: 16, medium: 18, large: 20 }
33
30
  const hasMultipleSeries = Object.keys(config.runtime.seriesLabels).length > 1
34
31
 
35
- const applyRadius = (index, isNegative) => {
32
+ const applyRadius = index => {
36
33
  if (index === undefined || index === null || !isRounded) return
37
34
  let style = {}
38
35
 
39
36
  if ((isStacked && index + 1 === stackCount) || !isStacked) {
40
- if (isNegative) {
41
- // reverse borderRadius to bottom
42
- style = isHorizontal ? { borderRadius: `0 ${radius} ${radius} 0` } : { borderRadius: `0 0 ${radius} ${radius}` }
43
- } else {
44
- style = isHorizontal ? { borderRadius: `0 ${radius} ${radius} 0` } : { borderRadius: `${radius} ${radius} 0 0` }
45
- }
37
+ style = isHorizontal ? { borderRadius: `0 ${radius} ${radius} 0` } : { borderRadius: `${radius} ${radius} 0 0` }
38
+ }
39
+ if (!isStacked && index === -1) {
40
+ style = isHorizontal ? { borderRadius: `${radius} 0 0 ${radius} ` } : { borderRadius: ` 0 0 ${radius} ${radius}` }
46
41
  }
47
42
  if (tipRounding === 'full' && isStacked && index === 0 && stackCount > 1) {
48
43
  style = isHorizontal ? { borderRadius: `${radius} 0 0 ${radius}` } : { borderRadius: `0 0 ${radius} ${radius}` }
@@ -52,7 +47,6 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
52
47
  }
53
48
  return style
54
49
  }
55
- // }
56
50
 
57
51
  const updateBars = defaultBars => {
58
52
  // function updates stacked && regular && lollipop horizontal bars
@@ -136,7 +130,7 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
136
130
  <Group left={parseFloat(config.runtime.yAxis.size)}>
137
131
  {/* Stacked Vertical */}
138
132
  {config.visualizationSubType === 'stacked' && !isHorizontal && (
139
- <BarStack data={cleanedData} keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys} x={d => d[config.runtime.xAxis.dataKey]} xScale={xScale} yScale={yScale} color={colorScale}>
133
+ <BarStack data={data} keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys} x={d => d[config.runtime.xAxis.dataKey]} xScale={xScale} yScale={yScale} color={colorScale}>
140
134
  {barStacks =>
141
135
  barStacks.reverse().map(barStack =>
142
136
  barStack.bars.map(bar => {
@@ -148,7 +142,8 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
148
142
  // tooltips
149
143
  const xAxisValue = config.runtime.xAxis.type === 'date' ? formatDate(parseDate(data[bar.index][config.runtime.xAxis.dataKey])) : data[bar.index][config.runtime.xAxis.dataKey]
150
144
  const yAxisValue = formatNumber(bar.bar ? bar.bar.data[bar.key] : 0, 'left')
151
- const style = applyRadius(barStack.index, yAxisValue < 0)
145
+
146
+ const style = applyRadius(barStack.index)
152
147
  let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
153
148
  const xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
154
149
  if (!hasMultipleSeries) {
@@ -199,7 +194,7 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
199
194
  {/* Stacked Horizontal */}
200
195
  {config.visualizationSubType === 'stacked' && isHorizontal && (
201
196
  <>
202
- <BarStackHorizontal data={cleanedData} keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys} height={yMax} y={d => d[config.runtime.yAxis.dataKey]} xScale={xScale} yScale={yScale} color={colorScale} offset='none'>
197
+ <BarStackHorizontal data={data} keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys} height={yMax} y={d => d[config.runtime.yAxis.dataKey]} xScale={xScale} yScale={yScale} color={colorScale} offset='none'>
203
198
  {barStacks =>
204
199
  barStacks.map(barStack =>
205
200
  updateBars(barStack.bars).map((bar, index) => {
@@ -210,7 +205,7 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
210
205
  // tooltips
211
206
  const xAxisValue = formatNumber(data[bar.index][bar.key], 'left')
212
207
  const yAxisValue = config.runtime.yAxis.type === 'date' ? formatDate(parseDate(data[bar.index][config.runtime.originalXAxis.dataKey])) : data[bar.index][config.runtime.originalXAxis.dataKey]
213
- const style = applyRadius(barStack.index, yAxisValue < 0)
208
+ const style = applyRadius(barStack.index)
214
209
  let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
215
210
  let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
216
211
  if (!hasMultipleSeries) {
@@ -297,7 +292,7 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
297
292
  {config.visualizationSubType !== 'stacked' && (
298
293
  <Group>
299
294
  <BarGroup
300
- data={cleanedData}
295
+ data={data}
301
296
  keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys}
302
297
  height={yMax}
303
298
  x0={d => d[config.runtime.originalXAxis.dataKey]}
@@ -324,7 +319,8 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
324
319
  let barY = bar.value >= 0 && isNumber(bar.value) ? bar.y : yScale(0)
325
320
  let barGroupWidth = ((config.runtime.horizontal ? yMax : xMax) / barGroups.length) * (config.barThickness || 0.8)
326
321
  let offset = (((config.runtime.horizontal ? yMax : xMax) / barGroups.length) * (1 - (config.barThickness || 0.8))) / 2
327
-
322
+ const barX = bar.value < 0 ? Math.abs(xScale(bar.value)) : xScale(0)
323
+ const barWidthHorizontal = Math.abs(xScale(bar.value) - xScale(0))
328
324
  // ! Unsure if this should go back.
329
325
  if (config.isLollipopChart) {
330
326
  offset = (config.runtime.horizontal ? yMax : xMax) / barGroups.length / 2 - lollipopBarWidth / 2
@@ -351,18 +347,38 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
351
347
  xAxisValue = tempValue
352
348
  barWidth = config.barHeight
353
349
  }
350
+
351
+ const barPosition = bar.value < 0 ? 'below' : 'above'
352
+ const textX = barPosition === 'below' ? 0 : 0
353
+
354
354
  // check if bar text/value string fits into each bars.
355
355
  let textWidth = getTextWidth(xAxisValue, `normal ${fontSize[config.fontSize]}px sans-serif`)
356
- let textFits = textWidth < bar.y - 5 // minus padding 5
357
-
356
+ let textFits = textWidth < barWidthHorizontal - 5 // minus padding 5
358
357
  let labelColor = '#000000'
359
358
 
360
359
  // Set label color
361
360
  if (chroma.contrast(labelColor, barColor) < 4.9) {
362
- if (textFits) labelColor = '#FFFFFF'
361
+ textFits ? (labelColor = '#FFFFFF') : '#000000'
362
+ }
363
+
364
+ // control text position
365
+ let textAnchor = textFits ? 'end' : 'start'
366
+ let textAnchorLollipop = 'start'
367
+ let textPadding = textFits ? -5 : 5
368
+ let textPaddingLollipop = 10
369
+ // if bars are negative we change positions of text
370
+ if (barPosition === 'below') {
371
+ textAnchor = textFits ? 'start' : 'end'
372
+ textPadding = textFits ? 5 : -5
373
+ if (config.isLollipopChart) {
374
+ textAnchorLollipop = 'end'
375
+ textPaddingLollipop = -10
376
+ }
363
377
  }
364
378
 
365
- const style = applyRadius(index, yAxisValue < 0)
379
+ // create new Index based on bar value for border Radius
380
+ const newIndex = bar.value < 0 ? -1 : index
381
+ const style = applyRadius(newIndex)
366
382
 
367
383
  let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
368
384
  let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
@@ -394,9 +410,9 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
394
410
  <foreignObject
395
411
  id={`barGroup${barGroup.index}`}
396
412
  key={`bar-group-bar-${barGroup.index}-${bar.index}-${bar.value}-${bar.key}`}
397
- x={config.runtime.horizontal ? 0 : barWidth * bar.index + offset}
413
+ x={config.runtime.horizontal ? barX : barWidth * bar.index + offset}
398
414
  y={config.runtime.horizontal ? barWidth * bar.index : barY}
399
- width={config.runtime.horizontal ? bar.y : barWidth}
415
+ width={config.runtime.horizontal ? barWidthHorizontal : barWidth}
400
416
  height={isHorizontal && !config.isLollipopChart ? barWidth : isHorizontal && config.isLollipopChart ? lollipopBarWidth : barHeight}
401
417
  style={{
402
418
  background: config.isLollipopChart && config.lollipopColorStyle === 'regular' ? barColor : config.isLollipopChart && config.lollipopColorStyle === 'two-tone' ? chroma(barColor).brighten(1) : barColor,
@@ -414,9 +430,9 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
414
430
  x={bar.y}
415
431
  y={config.barHeight / 2 + config.barHeight * bar.index}
416
432
  fill={labelColor}
417
- dx={textFits ? -5 : 5}
433
+ dx={textPadding}
418
434
  verticalAnchor='middle'
419
- textAnchor={textFits ? 'end' : 'start'}
435
+ textAnchor={textAnchor}
420
436
  >
421
437
  {xAxisValue}
422
438
  </Text>
@@ -425,10 +441,11 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
425
441
  {orientation === 'horizontal' && config.isLollipopChart && displayNumbersOnBar && (
426
442
  <Text
427
443
  display={displayBar ? 'block' : 'none'}
428
- x={`${bar.y + (config.isLollipopChart ? 15 : 5) + (config.isLollipopChart && barGroup.bars.length === bar.index ? offset : 0)}`} // padding
444
+ x={bar.y} // padding
429
445
  y={0}
430
446
  fill={'#000000'}
431
- textAnchor='start'
447
+ dx={textPaddingLollipop}
448
+ textAnchor={textAnchorLollipop}
432
449
  verticalAnchor='middle'
433
450
  fontWeight={'normal'}
434
451
  >
@@ -7,9 +7,18 @@ import { colorPalettesChart } from '@cdc/core/data/colorPalettes'
7
7
 
8
8
  const CoveBoxPlot = ({ xScale, yScale }) => {
9
9
  const { config, setConfig } = useContext(ConfigContext)
10
- const boxWidth = xScale.bandwidth()
11
- const constrainedWidth = Math.min(40, boxWidth)
12
- const color_0 = colorPalettesChart[config?.palette][0] ? colorPalettesChart[config?.palette][0] : '#000'
10
+
11
+ useEffect(() => {
12
+ if (config.legend.hide === false) {
13
+ setConfig({
14
+ ...config,
15
+ legend: {
16
+ ...config.legend,
17
+ hide: true
18
+ }
19
+ })
20
+ }
21
+ }, []) // eslint-disable-line
13
22
 
14
23
  // tooltips
15
24
  const tooltip_id = `cdc-open-viz-tooltip-${config.runtime.uniqueId}`
@@ -23,17 +32,16 @@ const CoveBoxPlot = ({ xScale, yScale }) => {
23
32
  `
24
33
  }
25
34
 
26
- useEffect(() => {
27
- if (config.legend.hide === false) {
28
- setConfig({
29
- ...config,
30
- legend: {
31
- ...config.legend,
32
- hide: true
33
- }
34
- })
35
- }
36
- }, []) // eslint-disable-line
35
+ // accessors & constants
36
+ const max = d => Number(d.columnMax)
37
+ const min = d => Number(d.columnMin)
38
+ const median = d => Number(d.columnMedian)
39
+ const thirdQuartile = d => Number(d.columnThirdQuartile)
40
+ const firstQuartile = d => Number(d.columnFirstQuartile)
41
+ const fillOpacity = 0.5
42
+ const boxWidth = xScale.bandwidth()
43
+ const constrainedWidth = Math.min(40, boxWidth)
44
+ const color_0 = colorPalettesChart[config?.palette][0] ? colorPalettesChart[config?.palette][0] : '#000'
37
45
 
38
46
  return (
39
47
  <ErrorBoundary component='BoxPlot'>
@@ -50,15 +58,15 @@ const CoveBoxPlot = ({ xScale, yScale }) => {
50
58
  <BoxPlot
51
59
  data-left={xScale(d.columnCategory) + config.yAxis.size + offset / 2 + 0.5}
52
60
  key={`box-plot-${i}`}
53
- min={Number(d.columnMin)}
54
- max={Number(d.columnMax)}
61
+ min={min(d)}
62
+ max={max(d)}
55
63
  left={Number(xScale(d.columnCategory)) + Number(config.yAxis.size) + offset / 2 + 0.5}
56
- firstQuartile={Number(d.columnFirstQuartile)}
57
- thirdQuartile={Number(d.columnThirdQuartile)}
58
- median={Number(d.columnMedian)}
64
+ firstQuartile={firstQuartile(d)}
65
+ thirdQuartile={thirdQuartile(d)}
66
+ median={median(d)}
59
67
  boxWidth={constrainedWidth}
60
68
  fill={color_0}
61
- fillOpacity={0.5}
69
+ fillOpacity={fillOpacity}
62
70
  stroke='black'
63
71
  valueScale={yScale}
64
72
  outliers={config.boxplot.plotOutlierValues ? d.columnOutliers : []}
@@ -12,7 +12,7 @@ import ConfigContext from '../ConfigContext'
12
12
  import CoveMediaControls from '@cdc/core/components/CoveMediaControls'
13
13
 
14
14
  export default function DataTable() {
15
- const { rawData, transformedData: data, config, colorScale, parseDate, formatDate, formatNumber: numberFormatter, colorPalettes } = useContext(ConfigContext)
15
+ const { rawData, tableData: data, config, colorScale, parseDate, formatDate, formatNumber: numberFormatter, colorPalettes } = useContext(ConfigContext)
16
16
 
17
17
  const section = config.orientation === 'horizontal' ? 'yAxis' : 'xAxis'
18
18
  const [tableExpanded, setTableExpanded] = useState(config.table.expanded)
@@ -35,7 +35,7 @@ export default function DataTable() {
35
35
  switch (type) {
36
36
  case 'download':
37
37
  return (
38
- <a download={fileName} onClick={saveBlob} href={`data:text/csv;base64,${Base64.encode(csvData)}`} aria-label='Download this data in a CSV file format.' className={`btn btn-download no-border`}>
38
+ <a download={fileName} onClick={saveBlob} href={`data:text/csv;base64,${Base64.encode(csvData)}`} aria-label='Download this data in a CSV file format.' className={`btn btn-download no-border margin-sm`}>
39
39
  Download Data (CSV)
40
40
  </a>
41
41
  )
@@ -75,7 +75,9 @@ export default function DataTable() {
75
75
  values: labels.values,
76
76
  columnTotal: labels.total,
77
77
  columnSd: 'Standard Deviation',
78
- nonOutlierValues: 'Non Outliers'
78
+ nonOutlierValues: 'Non Outliers',
79
+ columnLowerBounds: labels.lowerBounds,
80
+ columnUpperBounds: labels.upperBounds
79
81
  }
80
82
 
81
83
  let resolvedName = columnLookup[props.row.original[0]]
@@ -232,8 +234,7 @@ export default function DataTable() {
232
234
  </div>
233
235
  <div className='table-container' hidden={!tableExpanded} style={{ maxHeight: config.table.limitHeight && `${config.table.height}px`, overflowY: 'scroll' }}>
234
236
  <table className={tableExpanded ? 'data-table' : 'data-table cdcdataviz-sr-only'} {...getTableProps()} aria-rowcount={config?.series?.length ? config?.series?.length : '-1'}>
235
- <caption className='cdcdataviz-sr-only'>{config.table.caption ? config.table.caption : ''}</caption>
236
- <caption className='visually-hidden'>{config.table.label}</caption>
237
+ <caption className='cdcdataviz-sr-only visually-hidden'>{config.table.caption ? config.table.caption : config.table.label ? config.table.label : 'Data Table'}</caption>
237
238
  <thead>
238
239
  {headerGroups.map((headerGroup, index) => (
239
240
  <tr {...headerGroup.getHeaderGroupProps()} key={`headerGroups--${index}`}>
@@ -275,7 +276,7 @@ export default function DataTable() {
275
276
  })}
276
277
  </tbody>
277
278
  </table>
278
- {config.regions && config.regions.length > 0 && !config.visualizationType === 'Box Plot' ? (
279
+ {config.regions && config.regions.length > 0 && config.visualizationType !== 'Box Plot' ? (
279
280
  <table className='region-table data-table'>
280
281
  <caption className='visually-hidden'>Table of the highlighted regions in the visualization</caption>
281
282
  <thead>
@@ -56,7 +56,7 @@ export function DeviationBar({ height, xScale }) {
56
56
  const lollipopBarHeight = config.lollipopSize === 'large' ? 7 : config.lollipopSize === 'medium' ? 6 : 5
57
57
  const lollipopShapeSize = config.lollipopSize === 'large' ? 14 : config.lollipopSize === 'medium' ? 12 : 10
58
58
 
59
- const targetX = Math.max(xScale(0), Math.min(xScale(target), xScale(maxVal * 1.05)))
59
+ const targetX = Math.max(xScale(0), Math.min(xScale(target), xScale(maxVal)))
60
60
 
61
61
  const applyRadius = barPosition => {
62
62
  if (barPosition === undefined || barPosition === null || barStyle !== 'rounded') return
@@ -122,7 +122,7 @@ export function DeviationBar({ height, xScale }) {
122
122
  {data.map((d, index) => {
123
123
  const barValue = Number(d[seriesKey])
124
124
  const barHeight = config.isLollipopChart ? lollipopBarHeight : Number(config.barHeight)
125
- const barSpace = Number(config.barSpace) || 15
125
+ const barSpace = Number(config.barSpace)
126
126
  const barWidth = Math.abs(xScale(barValue) - targetX)
127
127
  const barBaseX = xScale(barValue)
128
128
  const barX = barValue > target ? targetX : barBaseX