@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,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