@cdc/chart 4.23.7 → 4.23.9

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 (39) hide show
  1. package/dist/cdcchart.js +28341 -27278
  2. package/examples/feature/__data__/area-chart-date-apple.json +5122 -0
  3. package/examples/feature/__data__/city-temperature.json +2198 -0
  4. package/examples/feature/area/area-chart-category.json +45 -45
  5. package/examples/feature/area/area-chart-date-apple.json +10376 -0
  6. package/examples/feature/area/area-chart-date-city-temperature.json +4528 -0
  7. package/examples/feature/area/area-chart-date.json +111 -3
  8. package/examples/feature/forest-plot/broken.json +700 -0
  9. package/examples/feature/forest-plot/data.csv +24 -0
  10. package/examples/feature/forest-plot/forest-plot.json +717 -0
  11. package/examples/feature/pie/planet-pie-example-config.json +1 -1
  12. package/index.html +28 -8
  13. package/package.json +4 -3
  14. package/src/CdcChart.jsx +24 -14
  15. package/src/components/AreaChart.jsx +84 -59
  16. package/src/components/BarChart.Horizontal.jsx +251 -0
  17. package/src/components/BarChart.StackedHorizontal.jsx +118 -0
  18. package/src/components/BarChart.StackedVertical.jsx +95 -0
  19. package/src/components/BarChart.Vertical.jsx +204 -0
  20. package/src/components/BarChart.jsx +14 -674
  21. package/src/components/BarChartType.jsx +15 -0
  22. package/src/components/BrushHandle.jsx +17 -0
  23. package/src/components/DataTable.jsx +185 -23
  24. package/src/components/EditorPanel.jsx +361 -305
  25. package/src/components/ForestPlot.jsx +191 -0
  26. package/src/components/ForestPlotSettings.jsx +508 -0
  27. package/src/components/Legend.jsx +11 -3
  28. package/src/components/LineChart.jsx +2 -2
  29. package/src/components/LinearChart.jsx +115 -310
  30. package/src/data/initial-state.js +47 -1
  31. package/src/hooks/useBarChart.js +186 -0
  32. package/src/hooks/useEditorPermissions.js +218 -0
  33. package/src/hooks/useLegendClasses.js +14 -11
  34. package/src/hooks/useMinMax.js +15 -3
  35. package/src/hooks/useReduceData.js +2 -2
  36. package/src/hooks/useScales.js +46 -3
  37. package/src/hooks/useTooltip.jsx +407 -0
  38. package/src/scss/legend.scss +206 -0
  39. package/src/scss/main.scss +26 -12
@@ -0,0 +1,251 @@
1
+ import React, { useContext } from 'react'
2
+ import ConfigContext from '../ConfigContext'
3
+ import { useBarChart } from '../hooks/useBarChart'
4
+ import { Group } from '@visx/group'
5
+ import { Text } from '@visx/text'
6
+ import { BarGroup } from '@visx/shape'
7
+ import { useHighlightedBars } from '../hooks/useHighlightedBars'
8
+
9
+ // third party
10
+ import chroma from 'chroma-js'
11
+
12
+ export const BarChartHorizontal = props => {
13
+ const { xScale, yScale, yMax, seriesScale } = props
14
+ const { transformedData: data, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter, isNumber, getTextWidth, getYAxisData, getXAxisData } = useContext(ConfigContext)
15
+ const { isHorizontal, barBorderWidth, hasMultipleSeries, applyRadius, updateBars, assignColorsToValues, section, fontSize, isLabelBelowBar, displayNumbersOnBar, lollipopBarWidth, lollipopShapeSize, getHighlightedBarColorByValue, getHighlightedBarByValue } = useBarChart()
16
+
17
+ const { HighLightedBarUtils } = useHighlightedBars(config)
18
+
19
+ return (
20
+ config.visualizationSubType !== 'stacked' &&
21
+ config.visualizationType === 'Bar' &&
22
+ config.orientation === 'horizontal' && (
23
+ <Group>
24
+ <BarGroup
25
+ data={data}
26
+ keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys}
27
+ height={yMax}
28
+ x0={d => d[config.runtime.originalXAxis.dataKey]}
29
+ x0Scale={yScale}
30
+ x1Scale={seriesScale}
31
+ yScale={xScale}
32
+ color={() => {
33
+ return ''
34
+ }}
35
+ >
36
+ {barGroups => {
37
+ return updateBars(barGroups).map((barGroup, index) => (
38
+ <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}>
39
+ {barGroup.bars.map((bar, index) => {
40
+ const scaleVal = config.useLogScale ? 0.1 : 0
41
+
42
+ let highlightedBarValues = config.highlightedBarValues.map(item => item.value).filter(item => item !== ('' || undefined))
43
+
44
+ highlightedBarValues = config.xAxis.type === 'date' ? HighLightedBarUtils.formatDates(highlightedBarValues) : highlightedBarValues
45
+
46
+ let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
47
+ let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
48
+ let barHeight = config.barHeight
49
+ let barY = bar.value >= 0 && isNumber(bar.value) ? bar.y : yScale(0)
50
+ const barX = bar.value < 0 ? Math.abs(xScale(bar.value)) : xScale(0)
51
+ const barWidthHorizontal = Math.abs(xScale(bar.value) - xScale(scaleVal))
52
+ const barWidth = config.barHeight
53
+
54
+ const yAxisValue = formatNumber(bar.value, 'left')
55
+ const xAxisValue = config.runtime[section].type === 'date' ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey])) : data[barGroup.index][config.runtime.originalXAxis.dataKey]
56
+
57
+ const barPosition = bar.value < 0 ? 'below' : 'above'
58
+
59
+ // check if bar text/value string fits into each bars.
60
+ let textWidth = getTextWidth(xAxisValue, `normal ${fontSize[config.fontSize]}px sans-serif`)
61
+ let textFits = textWidth < barWidthHorizontal - 5 // minus padding 5
62
+
63
+ // control text position
64
+ let textAnchor = textFits ? 'end' : 'start'
65
+ let textAnchorLollipop = 'start'
66
+ let textPadding = textFits ? -5 : 5
67
+ let textPaddingLollipop = 10
68
+ // if bars are negative we change positions of text
69
+ if (barPosition === 'below') {
70
+ textAnchor = textFits ? 'start' : 'end'
71
+ textPadding = textFits ? 5 : -5
72
+ if (config.isLollipopChart) {
73
+ textAnchorLollipop = 'end'
74
+ textPaddingLollipop = -10
75
+ }
76
+ }
77
+
78
+ // create new Index for bars with negative values
79
+ const newIndex = bar.value < 0 ? -1 : index
80
+ const borderRadius = applyRadius(newIndex)
81
+
82
+ let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
83
+ let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
84
+ if (!hasMultipleSeries) {
85
+ xAxisTooltip = config.isLegendValue ? `<p className="tooltip-heading">${bar.key}: ${xAxisValue}</p>` : config.runtime.xAxis.label ? `<p className="tooltip-heading">${config.runtime.xAxis.label}: ${xAxisValue}</p>` : xAxisValue
86
+ }
87
+
88
+ const tooltip = `<ul>
89
+ ${config.legend.showLegendValuesTooltip && config.runtime.seriesLabels && hasMultipleSeries ? `${config.runtime.seriesLabels[bar.key] || ''}<br/>` : ''}
90
+ <li class="tooltip-heading">${yAxisTooltip}</li>
91
+ <li class="tooltip-body">${xAxisTooltip}</li>
92
+ </li></ul>`
93
+
94
+ // configure colors
95
+ let labelColor = '#000000'
96
+ labelColor = HighLightedBarUtils.checkFontColor(yAxisValue, highlightedBarValues, labelColor) // Set if background is transparent'
97
+ let barColor = config.runtime.seriesLabels && config.runtime.seriesLabels[bar.key] ? colorScale(config.runtime.seriesLabels[bar.key]) : colorScale(bar.key)
98
+ barColor = assignColorsToValues(barGroups.length, barGroup.index, barColor) // Color code by category
99
+ const isRegularLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'regular'
100
+ const isTwoToneLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'two-tone'
101
+ const isHighlightedBar = highlightedBarValues?.includes(yAxisValue)
102
+ const highlightedBarColor = getHighlightedBarColorByValue(yAxisValue)
103
+ const highlightedBar = getHighlightedBarByValue(yAxisValue)
104
+ const borderColor = isHighlightedBar ? highlightedBarColor : config.barHasBorder === 'true' ? '#000' : 'transparent'
105
+ const borderWidth = isHighlightedBar ? highlightedBar.borderWidth : config.isLollipopChart ? 0 : config.barHasBorder === 'true' ? barBorderWidth : 0
106
+ // update label color
107
+ if (barColor && labelColor) {
108
+ if (chroma.contrast(labelColor, barColor) < 4.9) {
109
+ labelColor = textFits ? '#FFFFFF' : '#000000'
110
+ }
111
+ }
112
+ const background = () => {
113
+ if (isRegularLollipopColor) return barColor
114
+ if (isTwoToneLollipopColor) return chroma(barColor).brighten(1)
115
+ if (isHighlightedBar) return 'transparent'
116
+ return barColor
117
+ }
118
+ const finalStyle = {
119
+ background: background(),
120
+ borderColor,
121
+ borderStyle: 'solid',
122
+ borderWidth,
123
+ ...borderRadius
124
+ }
125
+
126
+ return (
127
+ <Group key={`${barGroup.index}--${index}`}>
128
+ {/* This feels gross but inline transition was not working well*/}
129
+ <style>
130
+ {`
131
+ .linear #barGroup${barGroup.index},
132
+ .Combo #barGroup${barGroup.index} {
133
+ transform-origin: 0 ${barY + barHeight}px;
134
+ }
135
+ `}
136
+ </style>
137
+ <Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}-${barY}--${index}`}>
138
+ <foreignObject
139
+ id={`barGroup${barGroup.index}`}
140
+ key={`bar-group-bar-${barGroup.index}-${bar.index}-${bar.value}-${bar.key}`}
141
+ x={barX}
142
+ y={barWidth * bar.index}
143
+ width={barWidthHorizontal}
144
+ height={!config.isLollipopChart ? barWidth : lollipopBarWidth}
145
+ style={finalStyle}
146
+ opacity={transparentBar ? 0.5 : 1}
147
+ display={displayBar ? 'block' : 'none'}
148
+ data-tooltip-html={tooltip}
149
+ data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
150
+ onClick={e => {
151
+ e.preventDefault()
152
+ if (setSharedFilter) {
153
+ bar[config.xAxis.dataKey] = yAxisValue
154
+ setSharedFilter(config.uid, bar)
155
+ }
156
+ }}
157
+ ></foreignObject>
158
+ {!config.isLollipopChart && displayNumbersOnBar && (
159
+ <Text // prettier-ignore
160
+ display={displayBar ? 'block' : 'none'}
161
+ x={bar.y}
162
+ y={config.barHeight / 2 + config.barHeight * bar.index}
163
+ fill={labelColor}
164
+ dx={textPadding}
165
+ verticalAnchor='middle'
166
+ textAnchor={textAnchor}
167
+ >
168
+ {yAxisValue}
169
+ </Text>
170
+ )}
171
+ {config.isLollipopChart && displayNumbersOnBar && (
172
+ <Text // prettier-ignore
173
+ display={displayBar ? 'block' : 'none'}
174
+ x={bar.y}
175
+ y={0}
176
+ fill={'#000000'}
177
+ dx={textPaddingLollipop}
178
+ textAnchor={textAnchorLollipop}
179
+ verticalAnchor='middle'
180
+ fontWeight={'normal'}
181
+ >
182
+ {yAxisValue}
183
+ </Text>
184
+ )}
185
+ {isLabelBelowBar && !config.yAxis.hideLabel && (
186
+ <Text x={config.yAxis.hideAxis ? 0 : 5} y={barGroup.height} dy={4} verticalAnchor={'start'} textAnchor={'start'}>
187
+ {config.runtime.yAxis.type === 'date'
188
+ ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey]))
189
+ : isHorizontal
190
+ ? data[barGroup.index][config.runtime.originalXAxis.dataKey]
191
+ : formatNumber(data[barGroup.index][config.runtime.originalXAxis.dataKey])}
192
+ </Text>
193
+ )}
194
+
195
+ {config.isLollipopChart && config.lollipopShape === 'circle' && (
196
+ <circle cx={bar.y} cy={0 + lollipopBarWidth / 2} r={lollipopShapeSize / 2} fill={barColor} key={`circle--${bar.index}`} data-tooltip-html={tooltip} data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} style={{ filter: 'unset', opacity: 1 }} />
197
+ )}
198
+ {config.isLollipopChart && config.lollipopShape === 'square' && (
199
+ <rect
200
+ x={bar.y > 10 ? bar.y - lollipopShapeSize / 2 : 0}
201
+ y={0 - lollipopBarWidth / 2}
202
+ width={lollipopShapeSize}
203
+ height={lollipopShapeSize}
204
+ fill={barColor}
205
+ key={`circle--${bar.index}`}
206
+ data-tooltip-html={tooltip}
207
+ data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
208
+ style={{ opacity: 1, filter: 'unset' }}
209
+ >
210
+ <animate attributeName='height' values={`0, ${lollipopShapeSize}`} dur='2.5s' />
211
+ </rect>
212
+ )}
213
+ </Group>
214
+ </Group>
215
+ )
216
+ })}
217
+ </Group>
218
+ ))
219
+ }}
220
+ </BarGroup>
221
+
222
+ {Object.keys(config.confidenceKeys).length > 0
223
+ ? data.map(d => {
224
+ let xPos, yPos
225
+ let upperPos
226
+ let lowerPos
227
+ let tickWidth = 5
228
+ yPos = yScale(getXAxisData(d)) - 0.75 * config.barHeight
229
+ upperPos = xScale(getYAxisData(d, config.confidenceKeys.upper))
230
+ lowerPos = xScale(getYAxisData(d, config.confidenceKeys.lower))
231
+ return (
232
+ <path
233
+ key={`confidence-interval-h-${yPos}-${d[config.runtime.originalXAxis.dataKey]}`}
234
+ stroke='#333'
235
+ strokeWidth='px'
236
+ d={`
237
+ M${lowerPos} ${yPos - tickWidth}
238
+ L${lowerPos} ${yPos + tickWidth}
239
+ M${lowerPos} ${yPos}
240
+ L${upperPos} ${yPos}
241
+ M${upperPos} ${yPos - tickWidth}
242
+ L${upperPos} ${yPos + tickWidth} `}
243
+ />
244
+ )
245
+ })
246
+ : ''}
247
+ </Group>
248
+ )
249
+ )
250
+ }
251
+ export default BarChartHorizontal
@@ -0,0 +1,118 @@
1
+ import React, { useContext } from 'react'
2
+ import ConfigContext from '../ConfigContext'
3
+ import { useBarChart } from '../hooks/useBarChart'
4
+ import { BarStackHorizontal } from '@visx/shape'
5
+ import { Group } from '@visx/group'
6
+ import { Text } from '@visx/text'
7
+
8
+ // third party
9
+ import chroma from 'chroma-js'
10
+
11
+ const BarChartStackedHorizontal = props => {
12
+ const { xScale, yScale, xMax, yMax } = props
13
+ const { transformedData: data, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter, animatedChart, getTextWidth } = useContext(ConfigContext)
14
+ const { isHorizontal, barBorderWidth, hasMultipleSeries, applyRadius, updateBars, isLabelBelowBar, displayNumbersOnBar, fontSize } = useBarChart()
15
+ const { orientation, visualizationSubType } = config
16
+
17
+ return (
18
+ config.visualizationSubType === 'stacked' &&
19
+ isHorizontal && (
20
+ <>
21
+ <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'>
22
+ {barStacks =>
23
+ barStacks.map(barStack =>
24
+ updateBars(barStack.bars).map((bar, index) => {
25
+ let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
26
+ let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
27
+ config.barHeight = Number(config.barHeight)
28
+ let labelColor = '#000000'
29
+ // tooltips
30
+ const xAxisValue = formatNumber(data[bar.index][bar.key], 'left')
31
+ const yAxisValue = config.runtime.yAxis.type === 'date' ? formatDate(parseDate(data[bar.index][config.runtime.originalXAxis.dataKey])) : data[bar.index][config.runtime.originalXAxis.dataKey]
32
+ const style = applyRadius(barStack.index)
33
+ let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
34
+ let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
35
+ let textWidth = getTextWidth(xAxisValue, `normal ${fontSize[config.fontSize]}px sans-serif`)
36
+ if (!hasMultipleSeries) {
37
+ xAxisTooltip = config.isLegendValue ? `${bar.key}: ${xAxisValue}` : config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisTooltip
38
+ }
39
+ const tooltip = `<div>
40
+ ${config.legend.showLegendValuesTooltip && config.runtime.seriesLabels && hasMultipleSeries ? `${config.runtime.seriesLabels[bar.key] || ''}<br/>` : ''}
41
+ ${yAxisTooltip}<br />
42
+ ${xAxisTooltip}
43
+ </div>`
44
+
45
+ if (chroma.contrast(labelColor, bar.color) < 4.9) {
46
+ labelColor = '#FFFFFF'
47
+ }
48
+
49
+ return (
50
+ <>
51
+ <style>
52
+ {`
53
+ #barStack${barStack.index}-${bar.index} rect,
54
+ #barStack${barStack.index}-${bar.index} foreignObject{
55
+ animation-delay: ${barStack.index * 0.5}s;
56
+ transform-origin: ${bar.x}px
57
+ }
58
+ `}
59
+ </style>
60
+ <Group key={index} id={`barStack${barStack.index}-${bar.index}`} className='stack horizontal'>
61
+ <foreignObject
62
+ key={`barstack-horizontal-${barStack.index}-${bar.index}-${index}`}
63
+ className={`animated-chart group ${animatedChart ? 'animated' : ''}`}
64
+ x={bar.x}
65
+ y={bar.y}
66
+ width={bar.width}
67
+ height={bar.height}
68
+ style={{ background: bar.color, border: `${config.barHasBorder === 'true' ? barBorderWidth : 0}px solid #333`, ...style }}
69
+ opacity={transparentBar ? 0.5 : 1}
70
+ display={displayBar ? 'block' : 'none'}
71
+ data-tooltip-html={tooltip}
72
+ data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
73
+ onClick={e => {
74
+ e.preventDefault()
75
+ if (setSharedFilter) {
76
+ bar[config.xAxis.dataKey] = xAxisValue
77
+ setSharedFilter(config.uid, bar)
78
+ }
79
+ }}
80
+ ></foreignObject>
81
+
82
+ {orientation === 'horizontal' && visualizationSubType === 'stacked' && isLabelBelowBar && barStack.index === 0 && !config.yAxis.hideLabel && (
83
+ <Text
84
+ x={`${bar.x + (config.isLollipopChart ? 15 : 5)}`} // padding
85
+ y={bar.y + bar.height * 1.2}
86
+ fill={'#000000'}
87
+ textAnchor='start'
88
+ verticalAnchor='start'
89
+ >
90
+ {yAxisValue}
91
+ </Text>
92
+ )}
93
+
94
+ {displayNumbersOnBar && textWidth < bar.width && (
95
+ <Text
96
+ display={displayBar ? 'block' : 'none'}
97
+ x={bar.x + barStack.bars[bar.index].width / 2} // padding
98
+ y={bar.y + bar.height / 2}
99
+ fill={labelColor}
100
+ textAnchor='middle'
101
+ verticalAnchor='middle'
102
+ >
103
+ {xAxisValue}
104
+ </Text>
105
+ )}
106
+ </Group>
107
+ </>
108
+ )
109
+ })
110
+ )
111
+ }
112
+ </BarStackHorizontal>
113
+ </>
114
+ )
115
+ )
116
+ }
117
+
118
+ export default BarChartStackedHorizontal
@@ -0,0 +1,95 @@
1
+ import React, { useContext } from 'react'
2
+ import ConfigContext from '../ConfigContext'
3
+ import { useBarChart } from '../hooks/useBarChart'
4
+ import { BarStack } from '@visx/shape'
5
+ import { Group } from '@visx/group'
6
+ import { Text } from '@visx/text'
7
+
8
+ const BarChartStackedVertical = props => {
9
+ const { xScale, yScale, xMax, yMax } = props
10
+ const { transformedData: data, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter } = useContext(ConfigContext)
11
+ const { isHorizontal, barBorderWidth, hasMultipleSeries, applyRadius } = useBarChart()
12
+ const { orientation } = config
13
+
14
+ return (
15
+ config.visualizationSubType === 'stacked' &&
16
+ !isHorizontal && (
17
+ <BarStack data={data} keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys} x={d => d[config.runtime.xAxis.dataKey]} xScale={xScale} yScale={yScale} color={colorScale}>
18
+ {barStacks =>
19
+ barStacks.reverse().map(barStack =>
20
+ barStack.bars.map(bar => {
21
+ let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
22
+ let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
23
+ let barThickness = xMax / barStack.bars.length
24
+ let barThicknessAdjusted = barThickness * (config.barThickness || 0.8)
25
+ let offset = (barThickness * (1 - (config.barThickness || 0.8))) / 2
26
+ // tooltips
27
+ const xAxisValue = config.runtime.xAxis.type === 'date' ? formatDate(parseDate(data[bar.index][config.runtime.xAxis.dataKey])) : data[bar.index][config.runtime.xAxis.dataKey]
28
+ const yAxisValue = formatNumber(bar.bar ? bar.bar.data[bar.key] : 0, 'left')
29
+
30
+ if(!yAxisValue) return <></>
31
+
32
+ const style = applyRadius(barStack.index)
33
+ let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
34
+ const xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
35
+ if (!hasMultipleSeries) {
36
+ yAxisTooltip = config.isLegendValue ? `${bar.key}: ${yAxisValue}` : config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
37
+ }
38
+
39
+ const {
40
+ legend: { showLegendValuesTooltip },
41
+ runtime: { seriesLabels }
42
+ } = config
43
+
44
+ const barStackTooltip = `<div>
45
+ <p class="tooltip-heading"><strong>${xAxisTooltip}</strong></p>
46
+ ${showLegendValuesTooltip && seriesLabels && hasMultipleSeries ? `${seriesLabels[bar.key] || ''}<br/>` : ''}
47
+ ${yAxisTooltip}<br />
48
+ </div>`
49
+
50
+ return (
51
+ <Group key={`${barStack.index}--${bar.index}--${orientation}`}>
52
+ <style>
53
+ {`
54
+ #barStack${barStack.index}-${bar.index} rect,
55
+ #barStack${barStack.index}-${bar.index} foreignObject{
56
+ animation-delay: ${barStack.index * 0.5}s;
57
+ transform-origin: ${barThicknessAdjusted / 2}px ${bar.y + bar.height}px
58
+ }
59
+ `}
60
+ </style>
61
+ <Group key={`bar-stack-${barStack.index}-${bar.index}`} id={`barStack${barStack.index}-${bar.index}`} className='stack vertical'>
62
+ <Text display={config.labels && displayBar ? 'block' : 'none'} opacity={transparentBar ? 0.5 : 1} x={barThickness * bar.index + offset} y={bar.y - 5} fill={'#000'} textAnchor='middle'>
63
+ {yAxisValue}
64
+ </Text>
65
+ <foreignObject
66
+ key={`bar-stack-${barStack.index}-${bar.index}`}
67
+ x={barThickness * bar.index + offset}
68
+ y={bar.y}
69
+ width={barThicknessAdjusted}
70
+ height={bar.height}
71
+ style={{ background: bar.color, border: `${config.barHasBorder === 'true' ? barBorderWidth : 0}px solid #333`, ...style }}
72
+ opacity={transparentBar ? 0.5 : 1}
73
+ display={displayBar ? 'block' : 'none'}
74
+ data-tooltip-html={barStackTooltip}
75
+ data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
76
+ onClick={e => {
77
+ e.preventDefault()
78
+ if (setSharedFilter) {
79
+ bar[config.xAxis.dataKey] = xAxisValue
80
+ setSharedFilter(config.uid, bar)
81
+ }
82
+ }}
83
+ ></foreignObject>
84
+ </Group>
85
+ </Group>
86
+ )
87
+ })
88
+ )
89
+ }
90
+ </BarStack>
91
+ )
92
+ )
93
+ }
94
+
95
+ export default BarChartStackedVertical