@cdc/chart 4.24.4 → 4.24.5

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 (33) hide show
  1. package/dist/cdcchart.js +32130 -31726
  2. package/index.html +7 -7
  3. package/package.json +2 -2
  4. package/src/CdcChart.tsx +17 -13
  5. package/src/_stories/Chart.stories.tsx +8 -0
  6. package/src/_stories/_mock/bar-chart-suppressed.json +474 -0
  7. package/src/components/AreaChart/components/AreaChart.jsx +2 -2
  8. package/src/components/BarChart/components/BarChart.Horizontal.tsx +52 -47
  9. package/src/components/BarChart/components/BarChart.Vertical.tsx +77 -92
  10. package/src/components/DeviationBar.jsx +4 -2
  11. package/src/components/EditorPanel/EditorPanel.tsx +289 -601
  12. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +19 -2
  13. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +4 -5
  14. package/src/components/EditorPanel/useEditorPermissions.js +4 -1
  15. package/src/components/Legend/Legend.Component.tsx +62 -10
  16. package/src/components/LineChart/LineChartProps.ts +13 -6
  17. package/src/components/LineChart/components/LineChart.Circle.tsx +22 -11
  18. package/src/components/LineChart/helpers.ts +134 -10
  19. package/src/components/LineChart/index.tsx +69 -42
  20. package/src/components/LinearChart.jsx +155 -139
  21. package/src/components/ZoomBrush.tsx +40 -21
  22. package/src/data/initial-state.js +4 -4
  23. package/src/hooks/useBarChart.js +47 -22
  24. package/src/hooks/useMinMax.ts +21 -2
  25. package/src/hooks/useScales.ts +23 -23
  26. package/src/hooks/useTooltip.tsx +11 -11
  27. package/src/scss/main.scss +56 -6
  28. package/src/types/ChartConfig.ts +3 -13
  29. package/src/types/ChartContext.ts +4 -0
  30. package/src/_stories/ChartLine.preliminary.tsx +0 -19
  31. package/src/_stories/ChartSuppress.stories.tsx +0 -19
  32. package/src/_stories/_mock/suppress_mock.json +0 -911
  33. package/src/helpers/computeMarginBottom.ts +0 -56
@@ -1,23 +1,29 @@
1
1
  import React, { useContext } from 'react'
2
+
3
+ // Local context and hooks
2
4
  import ConfigContext from '../../../ConfigContext'
3
5
  import { useBarChart } from '../../../hooks/useBarChart'
6
+ import { useHighlightedBars } from '../../../hooks/useHighlightedBars'
7
+
8
+ // VisX library imports
4
9
  import { Group } from '@visx/group'
5
10
  import { Text } from '@visx/text'
6
11
  import { BarGroup } from '@visx/shape'
7
- import { useHighlightedBars } from '../../../hooks/useHighlightedBars'
8
- import { FaStar } from 'react-icons/fa'
12
+
13
+ // CDC core components and helpers
9
14
  import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
15
+ import createBarElement from '@cdc/core/components/createBarElement'
10
16
 
11
- // third party
17
+ // Third party libraries
12
18
  import chroma from 'chroma-js'
19
+
20
+ // Local context and types
13
21
  import BarChartContext, { BarChartContextValues } from './context'
14
22
  import { ChartContext } from '../../../types/ChartContext'
15
23
 
16
- import createBarElement from '@cdc/core/components/createBarElement'
17
-
18
24
  export const BarChartHorizontal = () => {
19
25
  const { xScale, yScale, yMax, seriesScale } = useContext<BarChartContextValues>(BarChartContext)
20
- const { transformedData: data, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter, isNumber, getTextWidth, getYAxisData, getXAxisData } = useContext<ChartContext>(ConfigContext)
26
+ const { transformedData: data, tableData, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter, isNumber, getTextWidth, getYAxisData, getXAxisData } = useContext<ChartContext>(ConfigContext)
21
27
  const {
22
28
  isHorizontal,
23
29
  barBorderWidth,
@@ -31,32 +37,22 @@ export const BarChartHorizontal = () => {
31
37
  lollipopShapeSize,
32
38
  getHighlightedBarColorByValue,
33
39
  getHighlightedBarByValue,
34
- generateIconSize,
35
40
  getAdditionalColumn,
36
41
  hoveredBar,
37
42
  onMouseLeaveBar,
38
- onMouseOverBar
43
+ onMouseOverBar,
44
+ composeSuppressionBars
39
45
  } = useBarChart()
40
46
 
41
47
  const { HighLightedBarUtils } = useHighlightedBars(config)
42
- const getIcon = (bar, barWidth) => {
43
- let icon = null
44
- const iconSize = generateIconSize(barWidth)
45
- config.suppressedData?.forEach(d => {
46
- if (bar.key === d.column && String(bar.value) === String(d.value) && d.icon) {
47
- icon = <FaStar color='#000' size={iconSize} />
48
- // icon = <BarIcon color='#000' size={fontSize[config.fontSize] / 1.7} />
49
- }
50
- })
51
- return icon
52
- }
48
+
53
49
  return (
54
50
  config.visualizationSubType !== 'stacked' &&
55
51
  config.visualizationType === 'Bar' &&
56
52
  config.orientation === 'horizontal' && (
57
53
  <Group>
58
54
  <BarGroup
59
- data={data}
55
+ data={config.preliminaryData?.some(pd => pd.value && pd.type === 'suppression') ? tableData : data}
60
56
  keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys}
61
57
  height={yMax}
62
58
  x0={d => d[config.runtime.originalXAxis.dataKey]}
@@ -72,6 +68,7 @@ export const BarChartHorizontal = () => {
72
68
  <Group className={`bar-group-${barGroup.index}-${barGroup.x0}--${index} ${config.orientation}`} key={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`} id={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`} top={barGroup.y}>
73
69
  {barGroup.bars.map((bar, index) => {
74
70
  const scaleVal = config.useLogScale ? 0.1 : 0
71
+ const { suppresedBarHeight: suppresedBarWidth, getIconSize, getIconPadding, getVerticalAnchor, isSuppressed } = composeSuppressionBars({ bar })
75
72
 
76
73
  let highlightedBarValues = config.highlightedBarValues.map(item => item.value).filter(item => item !== ('' || undefined))
77
74
  highlightedBarValues = config.xAxis.type === 'date' ? HighLightedBarUtils.formatDates(highlightedBarValues) : highlightedBarValues
@@ -83,23 +80,20 @@ export const BarChartHorizontal = () => {
83
80
  numbericBarHeight = 25
84
81
  }
85
82
  let barY = bar.value >= 0 && isNumber(bar.value) ? bar.y : yScale(scaleVal)
86
- const barXBase = bar.value < 0 ? Math.abs(xScale(bar.value)) : xScale(scaleVal)
87
83
  const barWidthHorizontal = Math.abs(xScale(bar.value) - xScale(scaleVal))
88
- const suppresedBarWidth = 25
84
+ // const suppresedBarWidth = config.xAxis.showSuppressedLine ? 4 : 0
89
85
  const isPositiveBar = bar.value >= 0 && isNumber(bar.value)
90
- let barWidth = bar.value && config.suppressedData.some(({ column, value }) => bar.key === column && bar.value === value) ? suppresedBarWidth : barWidthHorizontal
91
-
92
- const supprssedBarX = isPositiveBar ? xScale(0) : xScale(scaleVal) - suppresedBarWidth
93
- const barX = config.suppressedData.some(d => bar.key === d.column && String(bar.value) === String(d.value)) ? supprssedBarX : barXBase
86
+ let barWidth = isSuppressed ? suppresedBarWidth : barWidthHorizontal
87
+ const barX = bar.value < 0 ? Math.abs(xScale(bar.value)) : xScale(scaleVal)
94
88
  const yAxisValue = formatNumber(bar.value, 'left')
95
89
  const xAxisValue = config.runtime[section].type === 'date' ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey])) : data[barGroup.index][config.runtime.originalXAxis.dataKey]
96
90
 
97
91
  const barPosition = !isPositiveBar ? 'below' : 'above'
98
- const barValueLabel = config.suppressedData.some(d => bar.key === d.column && bar.value === d.value) ? '' : yAxisValue
92
+ const barValueLabel = isSuppressed ? '' : yAxisValue
99
93
 
100
94
  // check if bar text/value string fits into each bars.
101
95
  let textWidth = getTextWidth(xAxisValue, `normal ${fontSize[config.fontSize]}px sans-serif`)
102
- let textFits = textWidth < barWidthHorizontal - 5 // minus padding 5
96
+ let textFits = Number(textWidth) < barWidthHorizontal - 5 // minus padding 5
103
97
 
104
98
  // control text position
105
99
  let textAnchor = textFits ? 'end' : 'start'
@@ -140,7 +134,7 @@ export const BarChartHorizontal = () => {
140
134
  const highlightedBar = getHighlightedBarByValue(xAxisValue)
141
135
  const borderColor = isHighlightedBar ? highlightedBarColor : config.barHasBorder === 'true' ? '#000' : 'transparent'
142
136
  const borderWidth = isHighlightedBar ? highlightedBar.borderWidth : config.isLollipopChart ? 0 : config.barHasBorder === 'true' ? barBorderWidth : 0
143
- const displaylollipopShape = config.suppressedData.some(d => bar.key === d.column && bar.value === d.value) ? 'none' : 'block'
137
+ const displaylollipopShape = isSuppressed ? 'none' : 'block'
144
138
  // update label color
145
139
  if (barColor && labelColor && textFits) {
146
140
  labelColor = getContrastColor('#000', barColor)
@@ -153,6 +147,8 @@ export const BarChartHorizontal = () => {
153
147
  return barColor
154
148
  }
155
149
 
150
+ const iconPadding = symbol => (symbol === 'Asterisk' ? '3px' : symbol === 'Double Asterisks' ? '4px' : '12px')
151
+
156
152
  return (
157
153
  <Group key={`${barGroup.index}--${index}`}>
158
154
  <Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}-${barY}--${index}`}>
@@ -185,24 +181,33 @@ export const BarChartHorizontal = () => {
185
181
  display: displayBar ? 'block' : 'none'
186
182
  }
187
183
  })}
188
- <g
189
- transform={`translate(${barX},${barHeight * bar.index})`}
190
- onMouseOver={() => onMouseOverBar(xAxisValue, bar.key)}
191
- onMouseLeave={onMouseLeaveBar}
192
- opacity={transparentBar ? 0.2 : 1}
193
- display={displayBar ? 'block' : 'none'}
194
- data-tooltip-html={tooltip}
195
- data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
196
- onClick={e => {
197
- e.preventDefault()
198
- if (setSharedFilter) {
199
- bar[config.xAxis.dataKey] = yAxisValue
200
- setSharedFilter(config.uid, bar)
201
- }
202
- }}
203
- >
204
- {getIcon(bar, barWidth)}
205
- </g>
184
+ {config.preliminaryData?.map((pd, index) => {
185
+ // check if user selected column
186
+ const selectedSuppressionColumn = !pd.column || pd.column === bar.key
187
+ // compare entered suppressed value with data value
188
+ const isValueMatch = String(pd.value) === String(tableData[barGroup.index][bar.key]) && pd.value !== ''
189
+ const isSuppressed = isValueMatch && selectedSuppressionColumn
190
+ if (!isSuppressed || barHeight < 10 || !config.xAxis.showSuppressedSymbol) {
191
+ return
192
+ }
193
+ return (
194
+ <Text // prettier-ignore
195
+ key={index}
196
+ fontSize={getIconSize(pd.symbol, barHeight)}
197
+ angle={90}
198
+ display={displayBar ? 'block' : 'none'}
199
+ opacity={transparentBar ? 0.5 : 1}
200
+ x={barX}
201
+ y={config.barHeight / 2 + config.barHeight * bar.index}
202
+ fill={'#000'}
203
+ dx={iconPadding(pd.symbol)}
204
+ verticalAnchor={getVerticalAnchor(pd.symbol)}
205
+ textAnchor={'middle'}
206
+ >
207
+ {pd.iconCode}
208
+ </Text>
209
+ )
210
+ })}
206
211
 
207
212
  {!config.isLollipopChart && displayNumbersOnBar && (
208
213
  <Text // prettier-ignore
@@ -1,72 +1,47 @@
1
1
  import React, { useContext, useState } from 'react'
2
+ // Local contexts
2
3
  import ConfigContext from '../../../ConfigContext'
3
- import { type ChartContext } from '../../../types/ChartContext'
4
+ import BarChartContext, { type BarChartContextValues } from './context'
5
+ // Local hooks
4
6
  import { useBarChart } from '../../../hooks/useBarChart'
7
+ import { useHighlightedBars } from '../../../hooks/useHighlightedBars'
8
+ // VisX library imports
5
9
  import { Group } from '@visx/group'
6
10
  import { Text } from '@visx/text'
7
11
  import { BarGroup } from '@visx/shape'
8
- import { useHighlightedBars } from '../../../hooks/useHighlightedBars'
9
- import { FaStar } from 'react-icons/fa'
10
- import Regions from './../../Regions'
12
+ // Local components
13
+ import Regions from '../../Regions'
14
+ // CDC core components and helpers
11
15
  import { isDateScale } from '@cdc/core/helpers/cove/date'
12
-
13
16
  import createBarElement from '@cdc/core/components/createBarElement'
14
-
15
- // third party
17
+ // Third party libraries
16
18
  import chroma from 'chroma-js'
17
- import BarChartContext, { type BarChartContextValues } from './context'
19
+ // Types
20
+ import { type ChartContext } from '../../../types/ChartContext'
18
21
 
19
22
  export const BarChartVertical = () => {
20
23
  const { xScale, yScale, xMax, yMax, seriesScale } = useContext<BarChartContextValues>(BarChartContext)
21
24
 
22
25
  const [barWidth, setBarWidth] = useState(0)
23
26
  const [totalBarsInGroup, setTotalBarsInGroup] = useState(0)
24
-
25
27
  // prettier-ignore
26
- const {
27
- applyRadius,
28
- assignColorsToValues,
29
- barBorderWidth,
30
- generateIconSize,
31
- getAdditionalColumn,
32
- getHighlightedBarByValue,
33
- getHighlightedBarColorByValue,
34
- lollipopBarWidth,
35
- lollipopShapeSize,
36
- onMouseLeaveBar,
37
- onMouseOverBar,
38
- section
39
- } = useBarChart()
28
+ const { assignColorsToValues, barBorderWidth, getAdditionalColumn, getHighlightedBarByValue, getHighlightedBarColorByValue, lollipopBarWidth, lollipopShapeSize, onMouseLeaveBar, onMouseOverBar, section, composeSuppressionBars, shouldSuppress } = useBarChart()
40
29
 
41
30
  // prettier-ignore
42
- const {
43
- colorScale,
44
- config,
45
- dashboardConfig,
46
- formatDate,
47
- formatNumber,
48
- getXAxisData,
49
- getYAxisData,
50
- isNumber,
51
- parseDate,
52
- seriesHighlight,
53
- setSharedFilter,
54
- transformedData,
55
- } = useContext<ChartContext>(ConfigContext)
56
-
31
+ const { colorScale, config, dashboardConfig, tableData, formatDate, formatNumber, getXAxisData, getYAxisData, isNumber, parseDate, seriesHighlight, setSharedFilter, transformedData, brushConfig, } = useContext<ChartContext>(ConfigContext)
57
32
  const { HighLightedBarUtils } = useHighlightedBars(config)
58
- const data = config.brush.active && config.brush.data?.length ? config.brush.data : transformedData
59
-
60
- const getIcon = (bar, barWidth) => {
61
- let icon = null
62
- const iconSize = generateIconSize(barWidth)
63
- config.suppressedData?.forEach(d => {
64
- if (bar.key === d.column && String(bar.value) === String(d.value) && d.icon) {
65
- icon = <FaStar color='#000' size={iconSize} />
66
- }
67
- })
68
- return icon
33
+ let data = transformedData
34
+ // check if user add suppression
35
+ const isSuppressionActive = config.preliminaryData.some(pd => pd.value && pd.type === 'suppression')
36
+ // if suppression active use table data (filtere | excluded) but non cleaned
37
+ if (isSuppressionActive) {
38
+ data = tableData
39
+ }
40
+ // if brush active use brush data (filtered|excluded) not cleaned
41
+ if (brushConfig.data.length) {
42
+ data = brushConfig.data
69
43
  }
44
+
70
45
  return (
71
46
  config.visualizationSubType !== 'stacked' &&
72
47
  (config.visualizationType === 'Bar' || config.visualizationType === 'Combo') &&
@@ -91,16 +66,15 @@ export const BarChartVertical = () => {
91
66
  return barGroups.map((barGroup, index) => (
92
67
  <Group className={`bar-group-${barGroup.index}-${barGroup.x0}--${index} ${config.orientation}`} key={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`} id={`bar-group-${barGroup.index}-${barGroup.x0}--${index}`} left={barGroup.x0}>
93
68
  {barGroup.bars.map((bar, index) => {
69
+ const { suppresedBarHeight, getIconSize, getIconPadding, getVerticalAnchor, isSuppressed } = composeSuppressionBars({ bar })
94
70
  const scaleVal = config.useLogScale ? 0.1 : 0
95
- const suppresedBarHeight = 20
96
71
  let highlightedBarValues = config.highlightedBarValues.map(item => item.value).filter(item => item !== ('' || undefined))
97
72
  highlightedBarValues = config.xAxis.type === 'date' ? HighLightedBarUtils.formatDates(highlightedBarValues) : highlightedBarValues
98
- let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
99
- let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
100
- let barHeightBase = Math.abs(yScale(bar.value) - yScale(scaleVal))
101
- let barYBase = bar.value >= 0 && isNumber(bar.value) ? bar.y : yScale(0)
102
- const supprssedBarY = bar.value >= 0 && isNumber(bar.value) ? yScale(scaleVal) - suppresedBarHeight : yScale(0)
103
- const barY = config.suppressedData.some(d => bar.key === d.column && String(bar.value) === String(d.value)) ? supprssedBarY : barYBase
73
+ const transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
74
+ const displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
75
+ const barHeightBase = Math.abs(yScale(bar.value) - yScale(scaleVal))
76
+ const barYBase = bar.value >= 0 && isNumber(bar.value) ? bar.y : yScale(0)
77
+ const barY = isSuppressed ? yScale(scaleVal) - suppresedBarHeight : barYBase
104
78
 
105
79
  let barGroupWidth = seriesScale.range()[1]
106
80
 
@@ -108,9 +82,8 @@ export const BarChartVertical = () => {
108
82
  let barX = bar.x + (config.isLollipopChart ? (barGroupWidth / barGroup.bars.length - lollipopBarWidth) / 2 : 0) - (config.xAxis.type === 'date-time' ? barGroupWidth / 2 : 0)
109
83
  setBarWidth(barWidth)
110
84
  setTotalBarsInGroup(barGroup.bars.length)
111
-
112
- let yAxisValue = formatNumber(bar.value, 'left')
113
- let xAxisValue = config.runtime[section].type === 'date' ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey])) : data[barGroup.index][config.runtime.originalXAxis.dataKey]
85
+ const yAxisValue = formatNumber(/[a-zA-Z]/.test(String(bar.value)) ? '' : bar.value, 'left')
86
+ const xAxisValue = config.runtime[section].type === 'date' ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey])) : data[barGroup.index][config.runtime.originalXAxis.dataKey]
114
87
 
115
88
  // create new Index for bars with negative values
116
89
  const newIndex = bar.value < 0 ? -1 : index
@@ -138,10 +111,10 @@ export const BarChartVertical = () => {
138
111
  const highlightedBar = getHighlightedBarByValue(xAxisValue)
139
112
  const borderColor = isHighlightedBar ? highlightedBarColor : config.barHasBorder === 'true' ? '#000' : 'transparent'
140
113
  const borderWidth = isHighlightedBar ? highlightedBar.borderWidth : config.isLollipopChart ? 0 : config.barHasBorder === 'true' ? barBorderWidth : 0
141
- const barValueLabel = config.suppressedData.some(d => bar.key === d.column && bar.value === d.value) ? '' : yAxisValue
142
- let barHeight = config.suppressedData.some(d => bar.key === d.column && String(bar.value) === String(d.value)) ? suppresedBarHeight : barHeightBase
143
- const displaylollipopShape = config.suppressedData.some(d => bar.key === d.column && bar.value === d.value) ? 'none' : 'block'
114
+ const barValueLabel = isSuppressed ? '' : yAxisValue
115
+ const barHeight = isSuppressed ? suppresedBarHeight : barHeightBase
144
116
 
117
+ const displaylollipopShape = isSuppressed ? 'none' : 'block'
145
118
  const getBarBackgroundColor = (barColor: string, filteredOutColor?: string): string => {
146
119
  let _barColor = barColor
147
120
  let _filteredOutColor = filteredOutColor || '#f2f2f2'
@@ -154,18 +127,20 @@ export const BarChartVertical = () => {
154
127
  if (dashboardConfig && dashboardConfig.dashboard.sharedFilters?.length !== 0) {
155
128
  const { sharedFilters } = dashboardConfig.dashboard
156
129
 
157
- _barColor = sharedFilters.map(_sharedFilter => {
158
- if (_sharedFilter.setBy === config.uid) {
159
- // If the current filter is the reset filter item.
160
- if (_sharedFilter.resetLabel === _sharedFilter.active) return colorScale(config.runtime.seriesLabels[bar.key])
161
- // If the current filter is the bars
162
- if (_sharedFilter.active === transformedData[barGroup.index][config.xAxis.dataKey]) return colorScale(config.runtime.seriesLabels[bar.key])
163
- return _filteredOutColor
164
- } else {
165
- // If the setBy isn't the config.uid return the original barColor
166
- return colorScale(config.runtime.seriesLabels[bar.key])
167
- }
168
- })[0]
130
+ _barColor = sharedFilters
131
+ ? sharedFilters.map(_sharedFilter => {
132
+ if (_sharedFilter.setBy === config.uid) {
133
+ // If the current filter is the reset filter item.
134
+ if (_sharedFilter.resetLabel === _sharedFilter.active) return colorScale(config.runtime.seriesLabels[bar.key])
135
+ // If the current filter is the bars
136
+ if (_sharedFilter.active === transformedData[barGroup.index][config.xAxis.dataKey]) return colorScale(config.runtime.seriesLabels[bar.key])
137
+ return _filteredOutColor
138
+ } else {
139
+ // If the setBy isn't the config.uid return the original barColor
140
+ return colorScale(config.runtime.seriesLabels[bar.key])
141
+ }
142
+ })[0]
143
+ : colorScale(config.runtime.seriesLabels[bar.key])
169
144
 
170
145
  if (isRegularLollipopColor) _barColor = barColor
171
146
  if (isTwoToneLollipopColor) _barColor = chroma(barColor).brighten(1)
@@ -214,24 +189,34 @@ export const BarChartVertical = () => {
214
189
  cursor: dashboardConfig ? 'pointer' : 'default'
215
190
  }
216
191
  })}
217
- <g
218
- transform={`translate(${barX},${yMax - suppresedBarHeight})`}
219
- onMouseOver={() => onMouseOverBar(xAxisValue, bar.key)}
220
- onMouseLeave={onMouseLeaveBar}
221
- opacity={transparentBar ? 0.2 : 1}
222
- display={displayBar ? 'block' : 'none'}
223
- data-tooltip-html={tooltip}
224
- data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
225
- onClick={e => {
226
- e.preventDefault()
227
- if (setSharedFilter) {
228
- bar[config.xAxis.dataKey] = xAxisValue
229
- setSharedFilter(config.uid, bar)
230
- }
231
- }}
232
- >
233
- {getIcon(bar, barWidth)}
234
- </g>
192
+ {config.preliminaryData.map((pd, index) => {
193
+ // check if user selected column
194
+ const selectedSuppressionColumn = !pd.column || pd.column === bar.key
195
+ // compare entered suppressed value with data value
196
+ const isValueMatch = String(pd.value) === String(bar.value) && pd.value !== ''
197
+ let isSuppressed = isValueMatch && selectedSuppressionColumn
198
+
199
+ if (!isSuppressed || barWidth < 10 || !config.xAxis.showSuppressedSymbol) {
200
+ return
201
+ }
202
+
203
+ return (
204
+ <Text // prettier-ignore
205
+ key={index}
206
+ dy={getIconPadding(pd.symbol)}
207
+ display={displayBar ? 'block' : 'none'}
208
+ opacity={transparentBar ? 0.5 : 1}
209
+ x={barX + barWidth / 2}
210
+ y={barY}
211
+ verticalAnchor={getVerticalAnchor(pd.symbol)}
212
+ fill={labelColor}
213
+ textAnchor='middle'
214
+ fontSize={`${getIconSize(pd.symbol, barWidth)}px`}
215
+ >
216
+ {pd.iconCode}
217
+ </Text>
218
+ )
219
+ })}
235
220
 
236
221
  <Text // prettier-ignore
237
222
  display={config.labels && displayBar ? 'block' : 'none'}
@@ -82,7 +82,8 @@ export default function DeviationBar({ height, xScale }) {
82
82
  useEffect(() => {
83
83
  const handleResize = () => {
84
84
  setWindowWidth(window.innerWidth)
85
- barRefs.current.forEach(bar => {
85
+ barRefs.current?.forEach(bar => {
86
+ if (!bar || !bar.style) return
86
87
  bar.style.transition = 'none'
87
88
  bar.style.transform = 'translate(0) scale(1)'
88
89
  })
@@ -104,7 +105,8 @@ export default function DeviationBar({ height, xScale }) {
104
105
  }, [entry?.isIntersecting, config.animate]) // eslint-disable-line
105
106
 
106
107
  useEffect(() => {
107
- barRefs.current.forEach((bar, i) => {
108
+ barRefs.current?.forEach((bar, i) => {
109
+ if (!bar || !bar.style) return
108
110
  if (config.animate) {
109
111
  const normalizedTarget = (target / maxVal) * 100
110
112
  bar.style.opacity = '0'