@cdc/chart 4.25.3-6 → 4.25.5-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/cdcchart-1a1724a1.es.js +4886 -0
  2. package/dist/cdcchart.js +50347 -75521
  3. package/index.html +1 -0
  4. package/package.json +22 -27
  5. package/src/CdcChart.tsx +1 -22
  6. package/src/CdcChartComponent.tsx +35 -21
  7. package/src/_stories/Chart.CI.stories.tsx +43 -0
  8. package/src/_stories/Chart.DynamicSeries.stories.tsx +68 -49
  9. package/src/_stories/Chart.Legend.Gradient.stories.tsx +6 -0
  10. package/src/_stories/Chart.stories.tsx +7 -16
  11. package/src/_stories/_mock/bar_chart_ci_labels.json +620 -0
  12. package/src/_stories/_mock/barchart_labels.mock.json +612 -0
  13. package/src/_stories/_mock/dynamic_series_bar_config.json +1 -1
  14. package/src/_stories/_mock/dynamic_series_suppression_mock.json +610 -0
  15. package/{examples/private/line-issue.json → src/_stories/_mock/legend_groupBy_mock.json} +46 -69
  16. package/src/components/Annotations/components/AnnotationDropdown.tsx +2 -2
  17. package/src/components/AreaChart/components/AreaChart.jsx +33 -5
  18. package/src/components/Axis/Categorical.Axis.tsx +2 -2
  19. package/src/components/BarChart/components/BarChart.Horizontal.tsx +51 -41
  20. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +19 -9
  21. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +20 -9
  22. package/src/components/BarChart/components/BarChart.Vertical.tsx +48 -31
  23. package/src/components/BarChart/components/{BarChart.jsx → BarChart.tsx} +23 -5
  24. package/src/components/BarChart/components/context.tsx +20 -2
  25. package/src/components/BarChart/helpers/getBarHeights.ts +47 -0
  26. package/src/components/BarChart/helpers/index.ts +5 -2
  27. package/src/components/BarChart/helpers/tests/getBarHeights.test.ts +83 -0
  28. package/src/{hooks → components/BarChart/helpers}/useBarChart.ts +11 -47
  29. package/src/components/BoxPlot/BoxPlot.tsx +2 -1
  30. package/src/components/DeviationBar.jsx +2 -1
  31. package/src/components/EditorPanel/EditorPanel.tsx +60 -24
  32. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +34 -34
  33. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +51 -25
  34. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +10 -3
  35. package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +4 -3
  36. package/src/components/EditorPanel/useEditorPermissions.ts +1 -4
  37. package/src/components/ForestPlot/ForestPlot.tsx +2 -2
  38. package/src/components/Legend/Legend.Component.tsx +69 -58
  39. package/src/components/Legend/Legend.Suppression.tsx +12 -22
  40. package/src/components/Legend/Legend.tsx +3 -1
  41. package/src/components/Legend/LegendGroup/LegendGroup.styles.css +40 -0
  42. package/src/components/Legend/LegendGroup/LegendGroup.tsx +103 -0
  43. package/src/components/Legend/LegendGroup/index.tsx +3 -0
  44. package/src/components/Legend/helpers/createFormatLabels.tsx +28 -0
  45. package/src/components/LineChart/LineChartProps.ts +3 -1
  46. package/src/components/LineChart/components/LineChart.Circle.tsx +77 -119
  47. package/src/components/LineChart/helpers.ts +133 -56
  48. package/src/components/LineChart/index.tsx +125 -60
  49. package/src/components/LinearChart.tsx +74 -115
  50. package/src/components/PairedBarChart.jsx +3 -2
  51. package/src/components/PieChart/PieChart.tsx +71 -91
  52. package/src/components/ScatterPlot/ScatterPlot.jsx +5 -0
  53. package/src/components/Sparkline/components/SparkLine.tsx +80 -18
  54. package/src/components/ZoomBrush.tsx +4 -4
  55. package/src/data/initial-state.js +4 -2
  56. package/src/helpers/countNumOfTicks.ts +1 -1
  57. package/src/helpers/dataHelpers.ts +31 -0
  58. package/src/helpers/sizeHelpers.ts +23 -0
  59. package/src/hooks/useMinMax.ts +21 -28
  60. package/src/hooks/useRightAxis.ts +4 -2
  61. package/src/hooks/useScales.ts +12 -14
  62. package/src/hooks/useTooltip.tsx +204 -203
  63. package/src/index.jsx +2 -2
  64. package/src/scss/main.scss +13 -6
  65. package/src/store/chart.actions.ts +1 -1
  66. package/src/types/ChartConfig.ts +7 -1
  67. package/LICENSE +0 -201
  68. package/examples/private/DEV-8850-2.json +0 -493
  69. package/examples/private/DEV-9822.json +0 -574
  70. package/examples/private/DEV-9840.json +0 -553
  71. package/examples/private/DEV-9850-3.json +0 -461
  72. package/examples/private/chart.json +0 -1084
  73. package/examples/private/ci_formatted.json +0 -202
  74. package/examples/private/ci_issue.json +0 -3016
  75. package/examples/private/completed.json +0 -634
  76. package/examples/private/dem-data-long.csv +0 -20
  77. package/examples/private/dem-data-long.json +0 -36
  78. package/examples/private/demographic_data.csv +0 -157
  79. package/examples/private/demographic_data.json +0 -2654
  80. package/examples/private/demographic_dynamic.json +0 -443
  81. package/examples/private/demographic_standard.json +0 -560
  82. package/examples/private/ehdi.json +0 -29939
  83. package/examples/private/not-loading.json +0 -360
  84. package/examples/private/test.json +0 -493
@@ -1,6 +1,5 @@
1
1
  import React, { useContext, useState } from 'react'
2
2
  import ConfigContext from '../../../ConfigContext'
3
- import { useBarChart } from '../../../hooks/useBarChart'
4
3
  import { BarStack } from '@visx/shape'
5
4
  import { Group } from '@visx/group'
6
5
  import { Text } from '@visx/text'
@@ -12,22 +11,34 @@ import createBarElement from '@cdc/core/components/createBarElement'
12
11
 
13
12
  const BarChartStackedVertical = () => {
14
13
  const [barWidth, setBarWidth] = useState(0)
15
- const { xScale, yScale, seriesScale, xMax, yMax } = useContext(BarChartContext)
16
- const { transformedData, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter } =
17
- useContext(ConfigContext)
14
+ const { xScale, yScale, seriesScale, xMax, yMax, barChart } = useContext(BarChartContext)
18
15
  const {
19
16
  isHorizontal,
20
17
  barBorderWidth,
21
- applyRadius,
22
18
  hoveredBar,
23
19
  getAdditionalColumn,
24
20
  onMouseLeaveBar,
25
21
  onMouseOverBar,
26
22
  barStackedSeriesKeys
27
- } = useBarChart()
23
+ } = barChart
24
+ const {
25
+ transformedData,
26
+ colorScale,
27
+ seriesHighlight,
28
+ config,
29
+ formatNumber,
30
+ formatDate,
31
+ parseDate,
32
+ setSharedFilter,
33
+ brushConfig
34
+ } = useContext(ConfigContext)
35
+
28
36
  const { orientation } = config
29
37
 
30
- const data = config.brush?.active && config.brush.data?.length ? config.brush.data : transformedData
38
+ let data = transformedData
39
+ if (brushConfig.data.length) {
40
+ data = brushConfig.data
41
+ }
31
42
  const isDateAxisType = config.runtime.xAxis.type === 'date-time' || config.runtime.xAxis.type === 'date'
32
43
  const isDateTimeScaleAxisType = config.runtime.xAxis.type === 'date-time'
33
44
 
@@ -69,7 +80,7 @@ const BarChartStackedVertical = () => {
69
80
  const xAxisTooltip = config.runtime.xAxis.label
70
81
  ? `${config.runtime.xAxis.label}: ${xAxisValue}`
71
82
  : xAxisValue
72
- const additionalColTooltip = getAdditionalColumn(hoveredBar)
83
+ const additionalColTooltip = getAdditionalColumn(bar.key, hoveredBar)
73
84
  const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${yAxisValue}`
74
85
  const tooltip = `<ul>
75
86
  <li class="tooltip-heading"">${xAxisTooltip}</li>
@@ -98,7 +109,7 @@ const BarChartStackedVertical = () => {
98
109
  height: bar.height,
99
110
  x: barX,
100
111
  y: bar.y,
101
- onMouseOver: () => onMouseOverBar(xAxisValue, bar.key),
112
+ onMouseOver: e => onMouseOverBar(xAxisValue, bar.key, e, data),
102
113
  onMouseLeave: onMouseLeaveBar,
103
114
  tooltipHtml: tooltip,
104
115
  tooltipId: `cdc-open-viz-tooltip-${config.runtime.uniqueId}`,
@@ -3,7 +3,6 @@ import React, { useContext, useState } from 'react'
3
3
  import ConfigContext from '../../../ConfigContext'
4
4
  import BarChartContext, { type BarChartContextValues } from './context'
5
5
  // Local hooks
6
- import { useBarChart } from '../../../hooks/useBarChart'
7
6
  import { useHighlightedBars } from '../../../hooks/useHighlightedBars'
8
7
  import { getBarConfig, testZeroValue } from '../helpers'
9
8
  // VisX library imports
@@ -16,6 +15,7 @@ import Regions from '../../Regions'
16
15
  import { isDateScale } from '@cdc/core/helpers/cove/date'
17
16
  import isNumber from '@cdc/core/helpers/isNumber'
18
17
  import createBarElement from '@cdc/core/components/createBarElement'
18
+ import { APP_FONT_COLOR } from '@cdc/core/helpers/constants'
19
19
  // Third party libraries
20
20
  import chroma from 'chroma-js'
21
21
  // Types
@@ -24,14 +24,9 @@ import _ from 'lodash'
24
24
  import { getBarData } from '../helpers/getBarData'
25
25
 
26
26
  export const BarChartVertical = () => {
27
- const { xScale, yScale, xMax, yMax, seriesScale, convertLineToBarGraph } =
27
+ const { xScale, yScale, xMax, yMax, seriesScale, convertLineToBarGraph, barChart } =
28
28
  useContext<BarChartContextValues>(BarChartContext)
29
-
30
- const [barWidth, setBarWidth] = useState(0)
31
- const [totalBarsInGroup, setTotalBarsInGroup] = useState(0)
32
- // prettier-ignore
33
29
  const {
34
- // prettier-ignore
35
30
  assignColorsToValues,
36
31
  barBorderWidth,
37
32
  getAdditionalColumn,
@@ -42,17 +37,29 @@ export const BarChartVertical = () => {
42
37
  onMouseLeaveBar,
43
38
  onMouseOverBar,
44
39
  section
45
- } = useBarChart()
40
+ } = barChart
41
+
42
+ const [barWidth, setBarWidth] = useState(0)
43
+ const [totalBarsInGroup, setTotalBarsInGroup] = useState(0)
46
44
 
47
- // prettier-ignore
48
- const { colorScale, config, dashboardConfig, tableData, formatDate, formatNumber, parseDate, seriesHighlight, setSharedFilter, transformedData, brushConfig } = useContext<ChartContext>(ConfigContext)
45
+ const {
46
+ colorScale,
47
+ config,
48
+ dashboardConfig,
49
+ tableData,
50
+ formatDate,
51
+ formatNumber,
52
+ parseDate,
53
+ seriesHighlight,
54
+ setSharedFilter,
55
+ transformedData,
56
+ brushConfig
57
+ } = useContext<ChartContext>(ConfigContext)
49
58
 
50
59
  const { HighLightedBarUtils } = useHighlightedBars(config)
51
60
 
52
61
  const root = document.documentElement
53
62
 
54
- const coolGray90 = getComputedStyle(root).getPropertyValue('--cool-gray-90')
55
-
56
63
  let data = transformedData
57
64
  // check if user add suppression
58
65
  const isSuppressionActive = config.preliminaryData.some(pd => pd.value && pd.type === 'suppression')
@@ -65,7 +72,11 @@ export const BarChartVertical = () => {
65
72
  data = brushConfig.data
66
73
  }
67
74
 
68
- const hasConfidenceInterval = Object.keys(config.confidenceKeys).length > 0
75
+ const hasConfidenceInterval =
76
+ config.confidenceKeys.upper &&
77
+ config.confidenceKeys.lower &&
78
+ config.confidenceKeys.upper !== '' &&
79
+ config.confidenceKeys.lower !== ''
69
80
 
70
81
  const _data = getBarData(config, data, hasConfidenceInterval)
71
82
  return (
@@ -144,7 +155,14 @@ export const BarChartVertical = () => {
144
155
  <li class="tooltip-body ">${tooltipBody}</li>
145
156
  ${additionalColTooltip ? '<li class="tooltip-body ">' + additionalColTooltip + '</li>' : ''}
146
157
  </li></ul>`
147
-
158
+ const { barHeight, isSuppressed, getBarY, absentDataLabel } = getBarConfig({
159
+ bar,
160
+ defaultBarHeight,
161
+ config,
162
+ barWidth,
163
+ isVertical: true,
164
+ yAxisValue
165
+ })
148
166
  // configure colors
149
167
  let labelColor = '#000000'
150
168
  labelColor = HighLightedBarUtils.checkFontColor(yAxisValue, highlightedBarValues, labelColor) // Set if background is transparent'
@@ -153,6 +171,12 @@ export const BarChartVertical = () => {
153
171
  const isHighlightedBar = highlightedBarValues?.includes(xAxisValue)
154
172
  const highlightedBarColor = getHighlightedBarColorByValue(xAxisValue)
155
173
  const highlightedBar = getHighlightedBarByValue(xAxisValue)
174
+ const hideGroup =
175
+ (!isNumber(bar.value) && !config.general.showMissingDataLabel) ||
176
+ (String(bar.value) === '0' && !config.general.showZeroValueData)
177
+ ? 'none'
178
+ : 'block' // hide bar group if no value or zero value
179
+
156
180
  const borderColor = isHighlightedBar
157
181
  ? highlightedBarColor
158
182
  : config.barHasBorder === 'true'
@@ -162,20 +186,11 @@ export const BarChartVertical = () => {
162
186
  ? highlightedBar.borderWidth
163
187
  : config.isLollipopChart
164
188
  ? 0
165
- : config.barHasBorder === 'true'
189
+ : config.barHasBorder === 'true' && !absentDataLabel && !isSuppressed
166
190
  ? barBorderWidth
167
191
  : 0
168
192
 
169
- const { barHeight, isSuppressed, getBarY, getAbsentDataLabel } = getBarConfig({
170
- bar,
171
- defaultBarHeight,
172
- config,
173
- barWidth,
174
- isVertical: true
175
- })
176
-
177
- const absentDataLabel = getAbsentDataLabel(yAxisValue)
178
- const barDefaultLabel = isSuppressed || !config.labels ? '' : yAxisValue
193
+ const barDefaultLabel = isSuppressed || absentDataLabel || !config.labels ? '' : yAxisValue
179
194
  const barY = getBarY(defaultBarY, yScale(scaleVal))
180
195
  const displaylollipopShape = testZeroValue(bar.value) ? 'none' : 'block'
181
196
  const getBarBackgroundColor = (barColor: string, filteredOutColor?: string): string => {
@@ -242,8 +257,10 @@ export const BarChartVertical = () => {
242
257
  )
243
258
  // End Confidence Interval Variables
244
259
 
260
+ const BAR_LABEL_PADDING = 10
261
+
245
262
  return (
246
- <Group key={`${barGroup.index}--${index}`}>
263
+ <Group display={hideGroup} key={`${barGroup.index}--${index}`}>
247
264
  <Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}-${barY}--${index}`}>
248
265
  {createBarElement({
249
266
  config: config,
@@ -257,7 +274,7 @@ export const BarChartVertical = () => {
257
274
  height: barHeight,
258
275
  x: barX,
259
276
  y: barY,
260
- onMouseOver: () => onMouseOverBar(xAxisValue, bar.key),
277
+ onMouseOver: e => onMouseOverBar(xAxisValue, bar.key, e, data),
261
278
  onMouseLeave: onMouseLeaveBar,
262
279
  tooltipHtml: tooltip,
263
280
  tooltipId: `cdc-open-viz-tooltip-${config.runtime.uniqueId}`,
@@ -322,8 +339,8 @@ export const BarChartVertical = () => {
322
339
  <Text // prettier-ignore
323
340
  display={displayBar ? 'block' : 'none'}
324
341
  opacity={transparentBar ? 0.5 : 1}
325
- x={barX + barWidth / 2}
326
- y={barY - 5}
342
+ x={hasConfidenceInterval ? barX + barWidth : barX + barWidth / 2}
343
+ y={barY - BAR_LABEL_PADDING}
327
344
  fill={labelColor}
328
345
  textAnchor='middle'
329
346
  >
@@ -333,7 +350,7 @@ export const BarChartVertical = () => {
333
350
  display={displayBar ? 'block' : 'none'}
334
351
  opacity={transparentBar ? 0.5 : 1}
335
352
  x={barX + barWidth / 2}
336
- y={barY - 5}
353
+ y={barY - BAR_LABEL_PADDING}
337
354
  fill={labelColor}
338
355
  textAnchor='middle'
339
356
  fontSize={config.isLollipopChart ? null : barWidth / 2}
@@ -373,7 +390,7 @@ export const BarChartVertical = () => {
373
390
  {hasConfidenceInterval && bar.value !== undefined && datum && (
374
391
  <path
375
392
  key={`confidence-interval-v-${datum[config.runtime.originalXAxis.dataKey]}`}
376
- stroke={coolGray90}
393
+ stroke={APP_FONT_COLOR}
377
394
  strokeWidth='px'
378
395
  d={`M${xPos - tickWidth} ${upperPos}
379
396
  L${xPos + tickWidth} ${upperPos}
@@ -1,4 +1,4 @@
1
- import React, { useContext } from 'react'
1
+ import React, { MouseEventHandler, useContext, useState } from 'react'
2
2
 
3
3
  // visx
4
4
  import { Group } from '@visx/group'
@@ -9,8 +9,21 @@ import BarChartType from './BarChartType'
9
9
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
10
10
  import ConfigContext from '../../../ConfigContext'
11
11
  import BarChartContext from './context'
12
+ import { useBarChart } from '../helpers/useBarChart'
13
+ import { PositionScale } from '@visx/shape/lib/types'
12
14
 
13
- const BarChart = ({
15
+ type BarChartProps = {
16
+ xScale: PositionScale
17
+ yScale: PositionScale
18
+ seriesScale: PositionScale
19
+ xMax: number
20
+ yMax: number
21
+ handleTooltipMouseOver: MouseEventHandler<SVGRectElement>
22
+ handleTooltipMouseOff: MouseEventHandler<SVGRectElement>
23
+ handleTooltipClick: MouseEventHandler<SVGRectElement>
24
+ }
25
+
26
+ const BarChart: React.FC<BarChartProps> = ({
14
27
  xScale,
15
28
  yScale,
16
29
  seriesScale,
@@ -20,7 +33,9 @@ const BarChart = ({
20
33
  handleTooltipMouseOff,
21
34
  handleTooltipClick
22
35
  }) => {
23
- const { transformedData: data, config, convertLineToBarGraph } = useContext(ConfigContext)
36
+ const configContext = useContext(ConfigContext)
37
+ const { transformedData: data, config, convertLineToBarGraph } = configContext
38
+ const barChart = useBarChart(handleTooltipMouseOver, handleTooltipMouseOff, configContext)
24
39
 
25
40
  const contextValues = {
26
41
  xScale,
@@ -28,7 +43,8 @@ const BarChart = ({
28
43
  xMax,
29
44
  yMax,
30
45
  seriesScale,
31
- convertLineToBarGraph
46
+ convertLineToBarGraph,
47
+ barChart
32
48
  }
33
49
 
34
50
  return (
@@ -46,7 +62,9 @@ const BarChart = ({
46
62
  height={Number(yMax)}
47
63
  fill={'transparent'}
48
64
  fillOpacity={0.05}
49
- onMouseMove={e => handleTooltipMouseOver(e, data)}
65
+ onMouseMove={e => {
66
+ handleTooltipMouseOver(e, data)
67
+ }}
50
68
  onMouseOut={handleTooltipMouseOff}
51
69
  onClick={e => handleTooltipClick(e, data)}
52
70
  />
@@ -1,3 +1,4 @@
1
+ import { PositionScale } from '@visx/shape/lib/types'
1
2
  import { createContext } from 'react'
2
3
 
3
4
  const BarChartContext = createContext(null)
@@ -5,10 +6,27 @@ const BarChartContext = createContext(null)
5
6
  export type BarChartContextValues = {
6
7
  xMax: number
7
8
  yMax: number
8
- xScale: Function
9
- yScale: Function
9
+ xScale: PositionScale
10
+ yScale: PositionScale
10
11
  seriesScale: Function
11
12
  convertLineToBarGraph: boolean
13
+ barChart: {
14
+ assignColorsToValues: Function
15
+ barBorderWidth: number
16
+ getAdditionalColumn: Function
17
+ getHighlightedBarByValue: Function
18
+ getHighlightedBarColorByValue: Function
19
+ lollipopBarWidth: number
20
+ lollipopShapeSize: number
21
+ onMouseLeaveBar: Function
22
+ onMouseOverBar: Function
23
+ section: string
24
+ hoveredBar: string
25
+ isHorizontal: boolean
26
+ isLabelBelowBar: boolean
27
+ displayNumbersOnBar: boolean
28
+ barStackedSeriesKeys: string[]
29
+ }
12
30
  }
13
31
 
14
32
  export default BarChartContext
@@ -0,0 +1,47 @@
1
+ import { APP_FONT_SIZE } from '@cdc/core/helpers/constants'
2
+ import _ from 'lodash'
3
+ import { ChartConfig } from '../../../types/ChartConfig'
4
+
5
+ export const getHorizontalBarHeights = <T>(config: Partial<ChartConfig>, bars: (T & { index })[]) => {
6
+ const isHorizontal = config.orientation === 'horizontal'
7
+
8
+ const isStacked = config.visualizationSubType === 'stacked'
9
+
10
+ let barHeight
11
+ if (!isStacked) {
12
+ const stackCount = config.runtime.seriesKeys.length
13
+ if (config.isLollipopChart) {
14
+ const lollipopSizes = {
15
+ large: 7,
16
+ medium: 6,
17
+ small: 5
18
+ }
19
+
20
+ const lollipopBarWidth = lollipopSizes[config.lollipopSize] || 5
21
+ barHeight = lollipopBarWidth * stackCount
22
+ } else {
23
+ barHeight = config.barHeight * stackCount
24
+ }
25
+ } else {
26
+ barHeight = config.barHeight
27
+ }
28
+
29
+ const labelHeight = APP_FONT_SIZE * 1.2
30
+ const labelSpace = config.yAxis.labelPlacement === 'Below Bar' ? labelHeight : 0
31
+
32
+ const totalBarHeight = barHeight + labelSpace + Number(config.barSpace)
33
+
34
+ if (isHorizontal) {
35
+ // calculate height of container based height, space and fontSize of labels
36
+ const totalHeight = bars.length * totalBarHeight
37
+ if (!config.heights) config.heights = {}
38
+ config.heights.horizontal = totalHeight
39
+ }
40
+
41
+ // return new updated bars/groupes
42
+ return bars.map((bar, i) => {
43
+ // set bars Y dynamically to handle space between bars
44
+ const y = bar.index === 0 ? 0 : _.round(totalBarHeight * i)
45
+ return { ...bar, y, height: barHeight }
46
+ })
47
+ }
@@ -9,6 +9,7 @@ interface BarConfigProps {
9
9
  config: { [key: string]: any }
10
10
  barWidth: number
11
11
  isVertical: boolean
12
+ yAxisValue: number
12
13
  }
13
14
 
14
15
  // Function to create bar width based on suppression status and missing data label
@@ -18,7 +19,8 @@ export const getBarConfig = ({
18
19
  defaultBarWidth,
19
20
  config,
20
21
  barWidth,
21
- isVertical
22
+ isVertical,
23
+ yAxisValue
22
24
  }: BarConfigProps) => {
23
25
  const heightMini = 3 /// height of small bars aka suppressed/NA/Zero valued
24
26
  let barHeight = defaultBarHeight
@@ -97,7 +99,8 @@ export const getBarConfig = ({
97
99
  return labelFits && isVertical ? label : !isVertical ? label : ''
98
100
  }
99
101
  }
100
- return { barWidthHorizontal, barHeight, isSuppressed, showMissingDataLabel, getBarY, getAbsentDataLabel }
102
+ const absentDataLabel = getAbsentDataLabel(yAxisValue)
103
+ return { barWidthHorizontal, barHeight, isSuppressed, showMissingDataLabel, getBarY, absentDataLabel }
101
104
  }
102
105
 
103
106
  export const testZeroValue = value => {
@@ -0,0 +1,83 @@
1
+ import { getHorizontalBarHeights } from '../getBarHeights'
2
+
3
+ describe('getHorizontalBarHeights', () => {
4
+ it('should calculate bar heights for non-stacked horizontal bars', () => {
5
+ const config = {
6
+ orientation: 'horizontal',
7
+ visualizationSubType: 'grouped',
8
+ runtime: { seriesKeys: ['A', 'B'] },
9
+ barHeight: 10,
10
+ barSpace: 5,
11
+ yAxis: { labelPlacement: 'Above Bar' }
12
+ }
13
+
14
+ const bars = [{ index: 0 }, { index: 1 }]
15
+
16
+ const result = getHorizontalBarHeights(config, bars)
17
+
18
+ expect(result).toEqual([
19
+ { index: 0, y: 0, height: 20 },
20
+ { index: 1, y: 25, height: 20 }
21
+ ])
22
+ })
23
+
24
+ it('should calculate bar heights for stacked horizontal bars', () => {
25
+ const config = {
26
+ orientation: 'horizontal',
27
+ visualizationSubType: 'stacked',
28
+ barHeight: 15,
29
+ barSpace: 5,
30
+ yAxis: { labelPlacement: 'Above Bar' }
31
+ }
32
+
33
+ const bars = [{ index: 0 }, { index: 1 }]
34
+
35
+ const result = getHorizontalBarHeights(config, bars)
36
+
37
+ expect(result).toEqual([
38
+ { index: 0, y: 0, height: 15 },
39
+ { index: 1, y: 20, height: 15 }
40
+ ])
41
+ })
42
+
43
+ it('should include label space when labelPlacement is Below Bar', () => {
44
+ const config = {
45
+ orientation: 'horizontal',
46
+ visualizationSubType: 'grouped',
47
+ runtime: { seriesKeys: ['A'] },
48
+ barHeight: 10,
49
+ barSpace: 5,
50
+ yAxis: { labelPlacement: 'Below Bar' }
51
+ }
52
+
53
+ const bars = [{ index: 0 }, { index: 1 }]
54
+
55
+ const result = getHorizontalBarHeights(config, bars)
56
+
57
+ expect(result).toEqual([
58
+ { index: 0, y: 0, height: 10 },
59
+ { index: 1, y: 37, height: 10 }
60
+ ])
61
+ })
62
+
63
+ it('should handle lollipop chart bar heights', () => {
64
+ const config = {
65
+ orientation: 'horizontal',
66
+ visualizationSubType: 'grouped',
67
+ runtime: { seriesKeys: ['A', 'B', 'C'] },
68
+ isLollipopChart: true,
69
+ lollipopSize: 'medium',
70
+ barSpace: 5,
71
+ yAxis: { labelPlacement: 'Above Bar' }
72
+ }
73
+
74
+ const bars = [{ index: 0 }, { index: 1 }]
75
+
76
+ const result = getHorizontalBarHeights(config, bars)
77
+
78
+ expect(result).toEqual([
79
+ { index: 0, y: 0, height: 18 },
80
+ { index: 1, y: 23, height: 18 }
81
+ ])
82
+ })
83
+ })
@@ -1,12 +1,12 @@
1
1
  import React, { useContext, useEffect, useState } from 'react'
2
- import ConfigContext, { ChartDispatchContext } from '../ConfigContext'
2
+ import { ChartDispatchContext } from '../../../ConfigContext'
3
3
  import { formatNumber as formatColNumber } from '@cdc/core/helpers/cove/number'
4
- import { appFontSize } from '@cdc/core/helpers/cove/fontSettings'
5
- export const useBarChart = () => {
6
- const { config, colorPalettes, tableData, updateConfig, parseDate, formatDate, setSeriesHighlight, seriesHighlight } =
7
- useContext(ConfigContext)
8
- const dispatch = useContext(ChartDispatchContext)
4
+ import { APP_FONT_SIZE } from '@cdc/core/helpers/constants'
5
+
6
+ export const useBarChart = (handleTooltipMouseOver, handleTooltipMouseOff, configContext) => {
7
+ const { config, colorPalettes, tableData, updateConfig, parseDate, formatDate, seriesHighlight } = configContext
9
8
  const { orientation } = config
9
+ const dispatch = useContext(ChartDispatchContext)
10
10
  const [hoveredBar, setHoveredBar] = useState(null)
11
11
 
12
12
  const isHorizontal = orientation === 'horizontal'
@@ -123,43 +123,6 @@ export const useBarChart = () => {
123
123
  const barColor = palette[barIndex]
124
124
  return barColor
125
125
  }
126
- const updateBars = defaultBars => {
127
- // function updates stacked && regular && lollipop horizontal bars
128
- if (config.visualizationType !== 'Bar' && !isHorizontal) return defaultBars
129
-
130
- const barsArr = [...defaultBars]
131
- let barHeight
132
-
133
- const heights = {
134
- stacked: config.barHeight,
135
- lollipop: lollipopBarWidth
136
- }
137
-
138
- if (!isStacked) {
139
- barHeight = heights[config.isLollipopChart ? 'lollipop' : 'stacked'] * stackCount
140
- } else {
141
- barHeight = heights.stacked
142
- }
143
-
144
- const labelHeight = isLabelBelowBar ? appFontSize * 1.2 : 0
145
- let barSpace = Number(config.barSpace)
146
-
147
- // calculate height of container based height, space and fontSize of labels
148
- let totalHeight = barsArr.length * (barHeight + labelHeight + barSpace)
149
-
150
- if (isHorizontal) {
151
- config.heights.horizontal = totalHeight
152
- }
153
-
154
- // return new updated bars/groupes
155
- return barsArr.map((bar, i) => {
156
- // set bars Y dynamically to handle space between bars
157
- let y = 0
158
- bar.index !== 0 && (y = (barHeight + barSpace + labelHeight) * i)
159
-
160
- return { ...bar, y: y, height: barHeight }
161
- })
162
- }
163
126
 
164
127
  const getHighlightedBarColorByValue = value => {
165
128
  const match = config?.highlightedBarValues.find(item => {
@@ -200,7 +163,8 @@ export const useBarChart = () => {
200
163
  return d[config.xAxis.dataKey] === xAxisDataValue && dynamicCategoryMatch
201
164
  }) || {}
202
165
  Object.keys(columns).forEach(colKeys => {
203
- if (series && config.columns[colKeys].series && config.columns[colKeys].series !== series) return
166
+ const colConfig = config.columns[colKeys]
167
+ if (series && colConfig.series && colConfig.series !== series && !colConfig.tooltips) return
204
168
  const formattingParams = {
205
169
  addColPrefix: config.columns[colKeys].prefix,
206
170
  addColSuffix: config.columns[colKeys].suffix,
@@ -225,17 +189,18 @@ export const useBarChart = () => {
225
189
  return additionalTooltipItems
226
190
  }
227
191
 
228
- const onMouseOverBar = (categoryValue, barKey) => {
192
+ const onMouseOverBar = (categoryValue, barKey, event, data) => {
229
193
  if (config.legend.highlightOnHover && config.legend.behavior === 'highlight' && barKey) {
230
194
  dispatch({ type: 'SET_SERIES_HIGHLIGHT', payload: [barKey] })
231
195
  }
232
-
196
+ handleTooltipMouseOver(event, data)
233
197
  setHoveredBar(categoryValue)
234
198
  }
235
199
  const onMouseLeaveBar = () => {
236
200
  if (config.legend.highlightOnHover && config.legend.behavior === 'highlight') {
237
201
  dispatch({ type: 'SET_SERIES_HIGHLIGHT', payload: [] })
238
202
  }
203
+ handleTooltipMouseOff()
239
204
  }
240
205
 
241
206
  return {
@@ -255,7 +220,6 @@ export const useBarChart = () => {
255
220
  barStackedSeriesKeys,
256
221
  hasMultipleSeries,
257
222
  applyRadius,
258
- updateBars,
259
223
  assignColorsToValues,
260
224
  getHighlightedBarColorByValue,
261
225
  getHighlightedBarByValue,
@@ -5,6 +5,7 @@ import ConfigContext from '../../ConfigContext'
5
5
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
6
6
  import { colorPalettesChart } from '@cdc/core/data/colorPalettes'
7
7
  import { handleTooltip, createPlots } from './helpers/index'
8
+ import { APP_FONT_COLOR } from '@cdc/core/helpers/constants'
8
9
  import _ from 'lodash'
9
10
 
10
11
  const CoveBoxPlot = ({ xScale, yScale, seriesScale }) => {
@@ -15,7 +16,7 @@ const CoveBoxPlot = ({ xScale, yScale, seriesScale }) => {
15
16
  const boxWidth = xScale.bandwidth()
16
17
 
17
18
  const bodyStyles = getComputedStyle(document.body)
18
- const defaultColor = bodyStyles.getPropertyValue('--cool-gray-90').trim()
19
+ const defaultColor = APP_FONT_COLOR
19
20
  const constrainedWidth = Math.min(40, boxWidth)
20
21
  const color_0 = _.get(colorPalettesChart, [config.palette, 0], '#000')
21
22
  const plots = createPlots(data, config)
@@ -6,6 +6,7 @@ import { Text } from '@visx/text'
6
6
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
7
7
  import useIntersectionObserver from '../hooks/useIntersectionObserver'
8
8
  import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
9
+ import { APP_FONT_COLOR } from '@cdc/core/helpers/constants'
9
10
  import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
10
11
 
11
12
  export default function DeviationBar({ height, xScale }) {
@@ -178,7 +179,7 @@ export default function DeviationBar({ height, xScale }) {
178
179
  // colors
179
180
  const [leftColor, rightColor] = twoColorPalette[twoColor.palette]
180
181
  const barColor = { left: leftColor, right: rightColor }
181
- const fill = getContrastColor('#000', barColor[barPosition])
182
+ const fill = getContrastColor(APP_FONT_COLOR, barColor[barPosition])
182
183
 
183
184
  let textProps = getTextProps(config.isLollipopChart, textFits, lollipopShapeSize, fill)
184
185
  // tooltips