@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.
- package/dist/cdcchart.js +28341 -27278
- package/examples/feature/__data__/area-chart-date-apple.json +5122 -0
- package/examples/feature/__data__/city-temperature.json +2198 -0
- package/examples/feature/area/area-chart-category.json +45 -45
- package/examples/feature/area/area-chart-date-apple.json +10376 -0
- package/examples/feature/area/area-chart-date-city-temperature.json +4528 -0
- package/examples/feature/area/area-chart-date.json +111 -3
- package/examples/feature/forest-plot/broken.json +700 -0
- package/examples/feature/forest-plot/data.csv +24 -0
- package/examples/feature/forest-plot/forest-plot.json +717 -0
- package/examples/feature/pie/planet-pie-example-config.json +1 -1
- package/index.html +28 -8
- package/package.json +4 -3
- package/src/CdcChart.jsx +24 -14
- package/src/components/AreaChart.jsx +84 -59
- package/src/components/BarChart.Horizontal.jsx +251 -0
- package/src/components/BarChart.StackedHorizontal.jsx +118 -0
- package/src/components/BarChart.StackedVertical.jsx +95 -0
- package/src/components/BarChart.Vertical.jsx +204 -0
- package/src/components/BarChart.jsx +14 -674
- package/src/components/BarChartType.jsx +15 -0
- package/src/components/BrushHandle.jsx +17 -0
- package/src/components/DataTable.jsx +185 -23
- package/src/components/EditorPanel.jsx +361 -305
- package/src/components/ForestPlot.jsx +191 -0
- package/src/components/ForestPlotSettings.jsx +508 -0
- package/src/components/Legend.jsx +11 -3
- package/src/components/LineChart.jsx +2 -2
- package/src/components/LinearChart.jsx +115 -310
- package/src/data/initial-state.js +47 -1
- package/src/hooks/useBarChart.js +186 -0
- package/src/hooks/useEditorPermissions.js +218 -0
- package/src/hooks/useLegendClasses.js +14 -11
- package/src/hooks/useMinMax.js +15 -3
- package/src/hooks/useReduceData.js +2 -2
- package/src/hooks/useScales.js +46 -3
- package/src/hooks/useTooltip.jsx +407 -0
- package/src/scss/legend.scss +206 -0
- package/src/scss/main.scss +26 -12
|
@@ -0,0 +1,204 @@
|
|
|
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 BarChartVertical = props => {
|
|
13
|
+
const { xScale, yScale, xMax, yMax, seriesScale } = props
|
|
14
|
+
const { transformedData: data, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter, isNumber, getXAxisData, getYAxisData } = useContext(ConfigContext)
|
|
15
|
+
const { barBorderWidth, hasMultipleSeries, applyRadius, updateBars, assignColorsToValues, section, lollipopBarWidth, lollipopShapeSize, getHighlightedBarColorByValue, getHighlightedBarByValue } = useBarChart()
|
|
16
|
+
const { HighLightedBarUtils } = useHighlightedBars(config)
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
config.visualizationSubType !== 'stacked' &&
|
|
20
|
+
(config.visualizationType === 'Bar' || config.visualizationType === 'Combo') &&
|
|
21
|
+
config.orientation === 'vertical' && (
|
|
22
|
+
<Group>
|
|
23
|
+
<BarGroup
|
|
24
|
+
data={data}
|
|
25
|
+
keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys}
|
|
26
|
+
height={yMax}
|
|
27
|
+
x0={d => d[config.runtime.originalXAxis.dataKey]}
|
|
28
|
+
x0Scale={xScale}
|
|
29
|
+
x1Scale={seriesScale}
|
|
30
|
+
yScale={yScale}
|
|
31
|
+
color={() => {
|
|
32
|
+
return ''
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
{barGroups => {
|
|
36
|
+
return updateBars(barGroups).map((barGroup, index) => (
|
|
37
|
+
<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={(xMax / barGroups.length) * barGroup.index}>
|
|
38
|
+
{barGroup.bars.map((bar, index) => {
|
|
39
|
+
const scaleVal = config.useLogScale ? 0.1 : 0
|
|
40
|
+
let highlightedBarValues = config.highlightedBarValues.map(item => item.value).filter(item => item !== ('' || undefined))
|
|
41
|
+
highlightedBarValues = config.xAxis.type === 'date' ? HighLightedBarUtils.formatDates(highlightedBarValues) : highlightedBarValues
|
|
42
|
+
let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
|
|
43
|
+
let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
|
|
44
|
+
let barHeight = Math.abs(yScale(bar.value) - yScale(scaleVal))
|
|
45
|
+
let barY = bar.value >= 0 && isNumber(bar.value) ? bar.y : yScale(0)
|
|
46
|
+
let barGroupWidth = (xMax / barGroups.length) * (config.barThickness || 0.8)
|
|
47
|
+
let offset = ((xMax / barGroups.length) * (1 - (config.barThickness || 0.8))) / 2
|
|
48
|
+
// configure left side offset of lollipop bars
|
|
49
|
+
if (config.isLollipopChart) {
|
|
50
|
+
offset = xMax / barGroups.length / 2 - lollipopBarWidth / 2
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let barWidth = config.isLollipopChart ? lollipopBarWidth : barGroupWidth / barGroup.bars.length
|
|
54
|
+
|
|
55
|
+
let yAxisValue = formatNumber(bar.value, 'left')
|
|
56
|
+
let xAxisValue = config.runtime[section].type === 'date' ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey])) : data[barGroup.index][config.runtime.originalXAxis.dataKey]
|
|
57
|
+
|
|
58
|
+
// create new Index for bars with negative values
|
|
59
|
+
const newIndex = bar.value < 0 ? -1 : index
|
|
60
|
+
const borderRadius = applyRadius(newIndex)
|
|
61
|
+
|
|
62
|
+
let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
|
|
63
|
+
let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
|
|
64
|
+
|
|
65
|
+
if (!hasMultipleSeries) {
|
|
66
|
+
yAxisTooltip = config.isLegendValue ? `${bar.key}: ${yAxisValue}` : config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const tooltip = `<ul>
|
|
70
|
+
${config.legend.showLegendValuesTooltip && config.runtime.seriesLabels && hasMultipleSeries ? `${config.runtime.seriesLabels[bar.key] || ''}<br/>` : ''}
|
|
71
|
+
<li class="tooltip-heading">${yAxisTooltip}</li>
|
|
72
|
+
<li class="tooltip-body">${xAxisTooltip}</li>
|
|
73
|
+
</li></ul>`
|
|
74
|
+
|
|
75
|
+
// configure colors
|
|
76
|
+
let labelColor = '#000000'
|
|
77
|
+
labelColor = HighLightedBarUtils.checkFontColor(yAxisValue, highlightedBarValues, labelColor) // Set if background is transparent'
|
|
78
|
+
let barColor = config.runtime.seriesLabels && config.runtime.seriesLabels[bar.key] ? colorScale(config.runtime.seriesLabels[bar.key]) : colorScale(bar.key)
|
|
79
|
+
barColor = assignColorsToValues(barGroups.length, barGroup.index, barColor) // Color code by category
|
|
80
|
+
const isRegularLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'regular'
|
|
81
|
+
const isTwoToneLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'two-tone'
|
|
82
|
+
const isHighlightedBar = highlightedBarValues?.includes(xAxisValue)
|
|
83
|
+
const highlightedBarColor = getHighlightedBarColorByValue(xAxisValue)
|
|
84
|
+
const highlightedBar = getHighlightedBarByValue(xAxisValue)
|
|
85
|
+
const borderColor = isHighlightedBar ? highlightedBarColor : config.barHasBorder === 'true' ? '#000' : 'transparent'
|
|
86
|
+
const borderWidth = isHighlightedBar ? highlightedBar.borderWidth : config.isLollipopChart ? 0 : config.barHasBorder === 'true' ? barBorderWidth : 0
|
|
87
|
+
|
|
88
|
+
const background = () => {
|
|
89
|
+
if (isRegularLollipopColor) return barColor
|
|
90
|
+
if (isTwoToneLollipopColor) return chroma(barColor).brighten(1)
|
|
91
|
+
if (isHighlightedBar) return 'transparent'
|
|
92
|
+
return barColor
|
|
93
|
+
}
|
|
94
|
+
const finalStyle = {
|
|
95
|
+
background: background(),
|
|
96
|
+
borderColor,
|
|
97
|
+
borderStyle: 'solid',
|
|
98
|
+
borderWidth,
|
|
99
|
+
...borderRadius
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<Group key={`${barGroup.index}--${index}`}>
|
|
104
|
+
{/* This feels gross but inline transition was not working well*/}
|
|
105
|
+
<style>
|
|
106
|
+
{`
|
|
107
|
+
.linear #barGroup${barGroup.index},
|
|
108
|
+
.Combo #barGroup${barGroup.index} {
|
|
109
|
+
transform-origin: 0 ${barY + barHeight}px;
|
|
110
|
+
}
|
|
111
|
+
`}
|
|
112
|
+
</style>
|
|
113
|
+
<Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}-${barY}--${index}`}>
|
|
114
|
+
<foreignObject
|
|
115
|
+
id={`barGroup${barGroup.index}`}
|
|
116
|
+
key={`bar-group-bar-${barGroup.index}-${bar.index}-${bar.value}-${bar.key}`}
|
|
117
|
+
x={barWidth * bar.index + offset}
|
|
118
|
+
y={barY}
|
|
119
|
+
width={barWidth}
|
|
120
|
+
height={barHeight}
|
|
121
|
+
style={finalStyle}
|
|
122
|
+
opacity={transparentBar ? 0.5 : 1}
|
|
123
|
+
display={displayBar ? 'block' : 'none'}
|
|
124
|
+
data-tooltip-html={tooltip}
|
|
125
|
+
data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
126
|
+
onClick={e => {
|
|
127
|
+
e.preventDefault()
|
|
128
|
+
if (setSharedFilter) {
|
|
129
|
+
bar[config.xAxis.dataKey] = xAxisValue
|
|
130
|
+
setSharedFilter(config.uid, bar)
|
|
131
|
+
}
|
|
132
|
+
}}
|
|
133
|
+
></foreignObject>
|
|
134
|
+
|
|
135
|
+
<Text display={config.labels && displayBar ? 'block' : 'none'} opacity={transparentBar ? 0.5 : 1} x={barWidth * (bar.index + 0.5) + offset} y={barY - 5} fill={labelColor} textAnchor='middle'>
|
|
136
|
+
{yAxisValue}
|
|
137
|
+
</Text>
|
|
138
|
+
|
|
139
|
+
{config.isLollipopChart && config.lollipopShape === 'circle' && (
|
|
140
|
+
<circle
|
|
141
|
+
cx={barWidth * (barGroup.bars.length - bar.index - 1) + offset + lollipopShapeSize / 3.5}
|
|
142
|
+
cy={bar.y}
|
|
143
|
+
r={lollipopShapeSize / 2}
|
|
144
|
+
fill={barColor}
|
|
145
|
+
key={`circle--${bar.index}`}
|
|
146
|
+
data-tooltip-html={tooltip}
|
|
147
|
+
data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
148
|
+
style={{ filter: 'unset', opacity: 1 }}
|
|
149
|
+
/>
|
|
150
|
+
)}
|
|
151
|
+
{config.isLollipopChart && config.lollipopShape === 'square' && (
|
|
152
|
+
<rect
|
|
153
|
+
x={offset - lollipopBarWidth / 2}
|
|
154
|
+
y={barY}
|
|
155
|
+
width={lollipopShapeSize}
|
|
156
|
+
height={lollipopShapeSize}
|
|
157
|
+
fill={barColor}
|
|
158
|
+
key={`circle--${bar.index}`}
|
|
159
|
+
data-tooltip-html={tooltip}
|
|
160
|
+
data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
161
|
+
style={{ opacity: 1, filter: 'unset' }}
|
|
162
|
+
>
|
|
163
|
+
<animate attributeName='height' values={`0, ${lollipopShapeSize}`} dur='2.5s' />
|
|
164
|
+
</rect>
|
|
165
|
+
)}
|
|
166
|
+
</Group>
|
|
167
|
+
</Group>
|
|
168
|
+
)
|
|
169
|
+
})}
|
|
170
|
+
</Group>
|
|
171
|
+
))
|
|
172
|
+
}}
|
|
173
|
+
</BarGroup>
|
|
174
|
+
|
|
175
|
+
{Object.keys(config.confidenceKeys).length > 0
|
|
176
|
+
? data.map(d => {
|
|
177
|
+
let xPos, yPos
|
|
178
|
+
let upperPos
|
|
179
|
+
let lowerPos
|
|
180
|
+
let tickWidth = 5
|
|
181
|
+
xPos = xScale(getXAxisData(d))
|
|
182
|
+
upperPos = yScale(getYAxisData(d, config.confidenceKeys.lower))
|
|
183
|
+
lowerPos = yScale(getYAxisData(d, config.confidenceKeys.upper))
|
|
184
|
+
return (
|
|
185
|
+
<path
|
|
186
|
+
key={`confidence-interval-v-${yPos}-${d[config.runtime.originalXAxis.dataKey]}`}
|
|
187
|
+
stroke='#333'
|
|
188
|
+
strokeWidth='px'
|
|
189
|
+
d={`
|
|
190
|
+
M${xPos - tickWidth} ${upperPos}
|
|
191
|
+
L${xPos + tickWidth} ${upperPos}
|
|
192
|
+
M${xPos} ${upperPos}
|
|
193
|
+
L${xPos} ${lowerPos}
|
|
194
|
+
M${xPos - tickWidth} ${lowerPos}
|
|
195
|
+
L${xPos + tickWidth} ${lowerPos}`}
|
|
196
|
+
/>
|
|
197
|
+
)
|
|
198
|
+
})
|
|
199
|
+
: ''}
|
|
200
|
+
</Group>
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
export default BarChartVertical
|