@cdc/chart 4.24.1 → 4.24.3
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 +48948 -37923
- package/examples/{private/combo.json → chart-regression-1.json} +40 -31
- package/examples/chart-regression-2.json +2360 -0
- package/examples/feature/filters/url-filter.json +1076 -0
- package/examples/feature/line/line-chart-preliminary.json +84 -37
- package/examples/feature/line/line-chart.json +2 -1
- package/examples/feature/regions/index.json +55 -5
- package/examples/feature/sankey/sankey-example-data.json +1364 -0
- package/examples/feature/sankey/sankey_chart_data.csv +20 -0
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +306 -19
- package/examples/sparkline.json +868 -0
- package/index.html +128 -121
- package/package.json +4 -2
- package/src/CdcChart.tsx +73 -38
- package/src/_stories/ChartEditor.stories.tsx +15 -4
- package/src/_stories/_mock/pie_config.json +4 -3
- package/src/_stories/_mock/url_filter.json +1076 -0
- package/src/components/AreaChart/components/AreaChart.Stacked.jsx +2 -1
- package/src/components/AreaChart/components/AreaChart.jsx +2 -25
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +39 -49
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +36 -56
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +36 -41
- package/src/components/BarChart/components/BarChart.Vertical.tsx +48 -64
- package/src/components/BoxPlot/BoxPlot.jsx +11 -9
- package/src/components/DeviationBar.jsx +3 -3
- package/src/components/EditorPanel/EditorPanel.tsx +1717 -1961
- package/src/components/EditorPanel/EditorPanelContext.ts +40 -0
- package/src/components/EditorPanel/components/Panels/Panel.BoxPlot.tsx +148 -0
- package/src/components/EditorPanel/components/{Panel.ForestPlotSettings.tsx → Panels/Panel.ForestPlotSettings.tsx} +16 -7
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +160 -0
- package/src/components/EditorPanel/components/{Panel.Regions.tsx → Panels/Panel.Regions.tsx} +6 -6
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +108 -0
- package/src/components/EditorPanel/components/{Panel.Series.tsx → Panels/Panel.Series.tsx} +50 -6
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +338 -0
- package/src/components/EditorPanel/components/Panels/index.tsx +19 -0
- package/src/components/EditorPanel/components/panels.scss +11 -0
- package/src/components/EditorPanel/editor-panel.scss +1 -13
- package/src/components/EditorPanel/useEditorPermissions.js +44 -13
- package/src/components/Legend/Legend.Component.tsx +207 -0
- package/src/components/Legend/Legend.tsx +8 -327
- package/src/components/Legend/helpers/createFormatLabels.tsx +140 -0
- package/src/components/LineChart/LineChartProps.ts +2 -1
- package/src/components/LineChart/components/LineChart.Circle.tsx +85 -52
- package/src/components/LineChart/helpers.ts +3 -3
- package/src/components/LineChart/index.tsx +99 -23
- package/src/components/LinearChart.jsx +12 -33
- package/src/components/PairedBarChart.jsx +10 -12
- package/src/components/PieChart/PieChart.tsx +80 -27
- package/src/components/Regions/components/Regions.tsx +120 -69
- package/src/components/Sankey/index.tsx +434 -0
- package/src/components/Sankey/sankey.scss +153 -0
- package/src/components/Sankey/types/index.ts +16 -0
- package/src/components/ScatterPlot/ScatterPlot.jsx +1 -0
- package/src/components/Sparkline/{SparkLine.jsx → components/SparkLine.tsx} +14 -30
- package/src/components/Sparkline/index.scss +3 -0
- package/src/components/Sparkline/index.tsx +1 -1
- package/src/components/ZoomBrush.tsx +2 -1
- package/src/data/initial-state.js +51 -4
- package/src/helpers/computeMarginBottom.ts +4 -3
- package/src/helpers/tests/computeMarginBottom.test.ts +2 -1
- package/src/hooks/useBarChart.js +5 -2
- package/src/hooks/useHighlightedBars.js +1 -1
- package/src/hooks/useMinMax.ts +3 -3
- package/src/hooks/useScales.ts +28 -18
- package/src/hooks/useTooltip.tsx +19 -14
- package/src/scss/main.scss +8 -96
- package/src/types/ChartConfig.ts +47 -20
- package/src/types/ChartContext.ts +17 -4
- package/src/types/Label.ts +7 -0
- package/examples/private/chart-t.json +0 -3740
- package/examples/private/epi-data.csv +0 -13
- package/examples/private/epi-data.json +0 -62
- package/examples/private/epi.json +0 -403
- package/examples/private/occupancy.json +0 -109283
- package/examples/private/prod-line-config.json +0 -401
- package/examples/private/region-data.json +0 -822
- package/examples/private/region-testing.json +0 -312
- package/examples/private/scaling.json +0 -45325
- package/examples/private/testing-data.json +0 -1739
- package/examples/private/testing.json +0 -816
- package/src/components/EditorPanel/components/Panel.DateHighlighting.tsx +0 -109
- package/src/components/EditorPanel/components/Panels.tsx +0 -13
|
@@ -8,6 +8,9 @@ import { BarGroup } from '@visx/shape'
|
|
|
8
8
|
import { useHighlightedBars } from '../../../hooks/useHighlightedBars'
|
|
9
9
|
import { FaStar } from 'react-icons/fa'
|
|
10
10
|
import Regions from './../../Regions'
|
|
11
|
+
import { isDateScale } from '@cdc/core/helpers/cove/date'
|
|
12
|
+
|
|
13
|
+
import createBarElement from '@cdc/core/components/createBarElement'
|
|
11
14
|
|
|
12
15
|
// third party
|
|
13
16
|
import chroma from 'chroma-js'
|
|
@@ -73,7 +76,10 @@ export const BarChartVertical = () => {
|
|
|
73
76
|
data={data}
|
|
74
77
|
keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys}
|
|
75
78
|
height={yMax}
|
|
76
|
-
x0={d =>
|
|
79
|
+
x0={d => {
|
|
80
|
+
const rawXValue = d[config.runtime.originalXAxis.dataKey]
|
|
81
|
+
return isDateScale(config.runtime.xAxis) ? parseDate(rawXValue) : rawXValue
|
|
82
|
+
}}
|
|
77
83
|
x0Scale={xScale}
|
|
78
84
|
x1Scale={seriesScale}
|
|
79
85
|
yScale={yScale}
|
|
@@ -83,7 +89,7 @@ export const BarChartVertical = () => {
|
|
|
83
89
|
>
|
|
84
90
|
{barGroups => {
|
|
85
91
|
return barGroups.map((barGroup, index) => (
|
|
86
|
-
<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={
|
|
92
|
+
<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}>
|
|
87
93
|
{barGroup.bars.map((bar, index) => {
|
|
88
94
|
const scaleVal = config.useLogScale ? 0.1 : 0
|
|
89
95
|
const suppresedBarHeight = 20
|
|
@@ -96,14 +102,10 @@ export const BarChartVertical = () => {
|
|
|
96
102
|
const supprssedBarY = bar.value >= 0 && isNumber(bar.value) ? yScale(scaleVal) - suppresedBarHeight : yScale(0)
|
|
97
103
|
const barY = config.suppressedData.some(d => bar.key === d.column && String(bar.value) === String(d.value)) ? supprssedBarY : barYBase
|
|
98
104
|
|
|
99
|
-
let barGroupWidth =
|
|
100
|
-
let offset = ((xMax / barGroups.length) * (1 - (config.barThickness || 0.8))) / 2
|
|
101
|
-
// configure left side offset of lollipop bars
|
|
102
|
-
if (config.isLollipopChart) {
|
|
103
|
-
offset = xMax / barGroups.length / 2 - lollipopBarWidth / 2
|
|
104
|
-
}
|
|
105
|
+
let barGroupWidth = seriesScale.range()[1]
|
|
105
106
|
|
|
106
107
|
let barWidth = config.isLollipopChart ? lollipopBarWidth : barGroupWidth / barGroup.bars.length
|
|
108
|
+
let barX = bar.x + (config.isLollipopChart ? (barGroupWidth / barGroup.bars.length - lollipopBarWidth) / 2 : 0) - (config.xAxis.type === 'date-time' ? barGroupWidth / 2 : 0)
|
|
107
109
|
setBarWidth(barWidth)
|
|
108
110
|
setTotalBarsInGroup(barGroup.bars.length)
|
|
109
111
|
|
|
@@ -112,7 +114,6 @@ export const BarChartVertical = () => {
|
|
|
112
114
|
|
|
113
115
|
// create new Index for bars with negative values
|
|
114
116
|
const newIndex = bar.value < 0 ? -1 : index
|
|
115
|
-
const borderRadius = applyRadius(newIndex)
|
|
116
117
|
// tooltips
|
|
117
118
|
|
|
118
119
|
const additionalColTooltip = getAdditionalColumn(bar.key, data[barGroup.index][config.runtime.originalXAxis.dataKey])
|
|
@@ -180,57 +181,43 @@ export const BarChartVertical = () => {
|
|
|
180
181
|
return _barColor
|
|
181
182
|
}
|
|
182
183
|
|
|
183
|
-
const getLeft = () => {
|
|
184
|
-
if (barWidth < 50 && barWidth > 15) return barWidth / 2.5
|
|
185
|
-
if (barWidth < 15 && barWidth > 5) return barWidth / 6
|
|
186
|
-
if (barWidth < 5) return 0
|
|
187
|
-
return barWidth / 2
|
|
188
|
-
}
|
|
189
|
-
const iconStyle: { [key: string]: any } = {
|
|
190
|
-
position: 'absolute',
|
|
191
|
-
top: bar.value >= 0 && isNumber(bar.value) ? -suppresedBarHeight : undefined,
|
|
192
|
-
bottom: bar.value >= 0 && isNumber(bar.value) ? undefined : `-${suppresedBarHeight}px`,
|
|
193
|
-
left: getLeft()
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (config.isLollipopChart) {
|
|
197
|
-
iconStyle.left = 0
|
|
198
|
-
iconStyle.transform = `translateX(0)`
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const finalStyle = {
|
|
202
|
-
background: getBarBackgroundColor(barColor),
|
|
203
|
-
borderColor,
|
|
204
|
-
borderStyle: 'solid',
|
|
205
|
-
borderWidth: `${borderWidth}px`,
|
|
206
|
-
width: barWidth,
|
|
207
|
-
height: barHeight,
|
|
208
|
-
...borderRadius,
|
|
209
|
-
cursor: dashboardConfig ? 'pointer' : 'default'
|
|
210
|
-
}
|
|
211
|
-
|
|
212
184
|
return (
|
|
213
185
|
<Group key={`${barGroup.index}--${index}`}>
|
|
214
|
-
{/* This feels gross but inline transition was not working well*/}
|
|
215
|
-
<style>
|
|
216
|
-
{`
|
|
217
|
-
.linear #barGroup${barGroup.index} div,
|
|
218
|
-
.Combo #barGroup${barGroup.index} div {
|
|
219
|
-
transform-origin: 0 ${barY + barHeight}px;
|
|
220
|
-
}
|
|
221
|
-
`}
|
|
222
|
-
</style>
|
|
223
186
|
<Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}-${barY}--${index}`}>
|
|
224
|
-
|
|
187
|
+
{createBarElement({
|
|
188
|
+
config: config,
|
|
189
|
+
index: newIndex,
|
|
190
|
+
id: `barGroup${barGroup.index}`,
|
|
191
|
+
background: getBarBackgroundColor(barColor),
|
|
192
|
+
borderColor,
|
|
193
|
+
borderStyle: 'solid',
|
|
194
|
+
borderWidth: `${borderWidth}px`,
|
|
195
|
+
width: barWidth,
|
|
196
|
+
height: barHeight,
|
|
197
|
+
x: barX,
|
|
198
|
+
y: barY,
|
|
199
|
+
onMouseOver: () => onMouseOverBar(xAxisValue, bar.key),
|
|
200
|
+
onMouseLeave: onMouseLeaveBar,
|
|
201
|
+
tooltipHtml: tooltip,
|
|
202
|
+
tooltipId: `cdc-open-viz-tooltip-${config.runtime.uniqueId}`,
|
|
203
|
+
onClick: e => {
|
|
204
|
+
e.preventDefault()
|
|
205
|
+
if (setSharedFilter) {
|
|
206
|
+
bar[config.xAxis.dataKey] = xAxisValue
|
|
207
|
+
setSharedFilter(config.uid, bar)
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
styleOverrides: {
|
|
211
|
+
transformOrigin: `0 ${barY + barHeight}px`,
|
|
212
|
+
opacity: transparentBar ? 0.2 : 1,
|
|
213
|
+
display: displayBar ? 'block' : 'none',
|
|
214
|
+
cursor: dashboardConfig ? 'pointer' : 'default'
|
|
215
|
+
}
|
|
216
|
+
})}
|
|
217
|
+
<g
|
|
218
|
+
transform={`translate(${barX},${yMax - suppresedBarHeight})`}
|
|
225
219
|
onMouseOver={() => onMouseOverBar(xAxisValue, bar.key)}
|
|
226
220
|
onMouseLeave={onMouseLeaveBar}
|
|
227
|
-
style={{ overflow: 'visible', transition: 'all 0.2s linear' }}
|
|
228
|
-
id={`barGroup${barGroup.index}`}
|
|
229
|
-
key={`bar-group-bar-${barGroup.index}-${bar.index}-${bar.value}-${bar.key}`}
|
|
230
|
-
x={barWidth * bar.index + offset}
|
|
231
|
-
y={barY}
|
|
232
|
-
width={barWidth}
|
|
233
|
-
height={barHeight}
|
|
234
221
|
opacity={transparentBar ? 0.2 : 1}
|
|
235
222
|
display={displayBar ? 'block' : 'none'}
|
|
236
223
|
data-tooltip-html={tooltip}
|
|
@@ -243,16 +230,13 @@ export const BarChartVertical = () => {
|
|
|
243
230
|
}
|
|
244
231
|
}}
|
|
245
232
|
>
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
<div style={{ ...finalStyle }}></div>
|
|
249
|
-
</div>
|
|
250
|
-
</foreignObject>
|
|
233
|
+
{getIcon(bar, barWidth)}
|
|
234
|
+
</g>
|
|
251
235
|
|
|
252
236
|
<Text // prettier-ignore
|
|
253
237
|
display={config.labels && displayBar ? 'block' : 'none'}
|
|
254
238
|
opacity={transparentBar ? 0.5 : 1}
|
|
255
|
-
x={
|
|
239
|
+
x={barX + barWidth / 2}
|
|
256
240
|
y={barY - 5}
|
|
257
241
|
fill={labelColor}
|
|
258
242
|
textAnchor='middle'
|
|
@@ -263,7 +247,7 @@ export const BarChartVertical = () => {
|
|
|
263
247
|
{config.isLollipopChart && config.lollipopShape === 'circle' && (
|
|
264
248
|
<circle
|
|
265
249
|
display={displaylollipopShape}
|
|
266
|
-
cx={
|
|
250
|
+
cx={barX + lollipopShapeSize / 3.5}
|
|
267
251
|
cy={bar.y}
|
|
268
252
|
r={lollipopShapeSize / 2}
|
|
269
253
|
fill={barColor}
|
|
@@ -276,7 +260,7 @@ export const BarChartVertical = () => {
|
|
|
276
260
|
{config.isLollipopChart && config.lollipopShape === 'square' && (
|
|
277
261
|
<rect
|
|
278
262
|
display={displaylollipopShape}
|
|
279
|
-
x={
|
|
263
|
+
x={barX - lollipopBarWidth / 2}
|
|
280
264
|
y={barY}
|
|
281
265
|
width={lollipopShapeSize}
|
|
282
266
|
height={lollipopShapeSize}
|
|
@@ -304,7 +288,7 @@ export const BarChartVertical = () => {
|
|
|
304
288
|
let upperPos
|
|
305
289
|
let lowerPos
|
|
306
290
|
let tickWidth = 5
|
|
307
|
-
xPos = xScale(getXAxisData(d))
|
|
291
|
+
xPos = xScale(getXAxisData(d)) + (config.xAxis.type !== 'date' || config.xAxis.type !== 'date-time' ? seriesScale.range()[1] / 2 : 0)
|
|
308
292
|
upperPos = yScale(getYAxisData(d, config.confidenceKeys.lower))
|
|
309
293
|
lowerPos = yScale(getYAxisData(d, config.confidenceKeys.upper))
|
|
310
294
|
return (
|
|
@@ -7,6 +7,7 @@ import { colorPalettesChart } from '@cdc/core/data/colorPalettes'
|
|
|
7
7
|
|
|
8
8
|
const CoveBoxPlot = ({ xScale, yScale }) => {
|
|
9
9
|
const { config, setConfig } = useContext(ConfigContext)
|
|
10
|
+
const { boxplot } = config
|
|
10
11
|
|
|
11
12
|
useEffect(() => {
|
|
12
13
|
if (config.legend.hide === false) {
|
|
@@ -25,10 +26,10 @@ const CoveBoxPlot = ({ xScale, yScale }) => {
|
|
|
25
26
|
const handleTooltip = d => {
|
|
26
27
|
return `
|
|
27
28
|
<strong>${d.columnCategory}</strong></br>
|
|
28
|
-
${
|
|
29
|
-
${
|
|
30
|
-
${
|
|
31
|
-
${
|
|
29
|
+
${boxplot.labels.q1}: ${d.columnFirstQuartile}<br/>
|
|
30
|
+
${boxplot.labels.q3}: ${d.columnThirdQuartile}<br/>
|
|
31
|
+
${boxplot.labels.iqr}: ${d.columnIqr}<br/>
|
|
32
|
+
${boxplot.labels.median}: ${d.columnMedian}
|
|
32
33
|
`
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -46,12 +47,12 @@ const CoveBoxPlot = ({ xScale, yScale }) => {
|
|
|
46
47
|
return (
|
|
47
48
|
<ErrorBoundary component='BoxPlot'>
|
|
48
49
|
<Group className='boxplot' key={`boxplot-group`}>
|
|
49
|
-
{
|
|
50
|
+
{boxplot.plots.map((d, i) => {
|
|
50
51
|
const offset = boxWidth - constrainedWidth
|
|
51
52
|
const radius = 4
|
|
52
53
|
return (
|
|
53
54
|
<Group key={`boxplotplot-${i}`}>
|
|
54
|
-
{
|
|
55
|
+
{boxplot.plotNonOutlierValues &&
|
|
55
56
|
d.nonOutlierValues.map((value, index) => {
|
|
56
57
|
return <circle cx={xScale(d.columnCategory) + Number(config.yAxis.size) + boxWidth / 2} cy={yScale(value)} r={radius} fill={'#ccc'} style={{ opacity: 1, fillOpacity: 1, stroke: 'black' }} key={`boxplot-${i}--circle-${index}`} />
|
|
57
58
|
})}
|
|
@@ -69,7 +70,7 @@ const CoveBoxPlot = ({ xScale, yScale }) => {
|
|
|
69
70
|
fillOpacity={fillOpacity}
|
|
70
71
|
stroke='black'
|
|
71
72
|
valueScale={yScale}
|
|
72
|
-
outliers={
|
|
73
|
+
outliers={boxplot.plotOutlierValues ? d.columnOutliers : []}
|
|
73
74
|
outlierProps={{
|
|
74
75
|
style: {
|
|
75
76
|
fill: `${color_0}`,
|
|
@@ -84,7 +85,7 @@ const CoveBoxPlot = ({ xScale, yScale }) => {
|
|
|
84
85
|
boxProps={{
|
|
85
86
|
style: {
|
|
86
87
|
stroke: 'black',
|
|
87
|
-
strokeWidth:
|
|
88
|
+
strokeWidth: boxplot.borders === 'true' ? 1 : 0
|
|
88
89
|
}
|
|
89
90
|
}}
|
|
90
91
|
maxProps={{
|
|
@@ -95,7 +96,8 @@ const CoveBoxPlot = ({ xScale, yScale }) => {
|
|
|
95
96
|
container
|
|
96
97
|
containerProps={{
|
|
97
98
|
'data-tooltip-html': handleTooltip(d),
|
|
98
|
-
'data-tooltip-id': tooltip_id
|
|
99
|
+
'data-tooltip-id': tooltip_id,
|
|
100
|
+
tabIndex: -1
|
|
99
101
|
}}
|
|
100
102
|
/>
|
|
101
103
|
</Group>
|
|
@@ -4,8 +4,8 @@ import { useContext, useEffect, useRef, useState } from 'react'
|
|
|
4
4
|
import ConfigContext from '../ConfigContext'
|
|
5
5
|
import { Text } from '@visx/text'
|
|
6
6
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
7
|
-
import chroma from 'chroma-js'
|
|
8
7
|
import useIntersectionObserver from '../hooks/useIntersectionObserver'
|
|
8
|
+
import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
|
|
9
9
|
|
|
10
10
|
export default function DeviationBar({ height, xScale }) {
|
|
11
11
|
const { transformedData: data, config, formatNumber, twoColorPalette, getTextWidth, updateConfig, parseDate, formatDate, currentViewport } = useContext(ConfigContext)
|
|
@@ -160,8 +160,7 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
160
160
|
// colors
|
|
161
161
|
const [leftColor, rightColor] = twoColorPalette[twoColor.palette]
|
|
162
162
|
const barColor = { left: leftColor, right: rightColor }
|
|
163
|
-
const
|
|
164
|
-
const fill = isBarColorDark ? '#FFFFFF' : '#000000'
|
|
163
|
+
const fill = getContrastColor('#000', barColor[barPosition])
|
|
165
164
|
|
|
166
165
|
let textProps = getTextProps(config.isLollipopChart, textFits, lollipopShapeSize, fill)
|
|
167
166
|
// tooltips
|
|
@@ -187,6 +186,7 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
187
186
|
height={barHeight}
|
|
188
187
|
data-tooltip-html={tooltip}
|
|
189
188
|
data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
189
|
+
tabIndex={-1}
|
|
190
190
|
>
|
|
191
191
|
<div style={{ width: barWidth, height: barHeight, border: `${borderWidth}px solid #333`, backgroundColor: barColor[barPosition], ...borderRadius }}></div>
|
|
192
192
|
</foreignObject>
|