@cdc/chart 4.23.3 → 4.23.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.
- package/dist/cdcchart.js +52543 -50830
- package/examples/feature/__data__/area-chart.json +56 -0
- package/examples/{planet-example-data.json → feature/__data__/planet-example-data.json} +3 -8
- package/examples/feature/__data__/planet-logaritmic-data.json +56 -0
- package/examples/feature/area/area-chart-category.json +240 -0
- package/examples/{area-chart.json → feature/area/area-chart-date.json} +70 -13
- package/examples/feature/bar/example-bar-chart.json +558 -0
- package/examples/{horizontal-chart-max-increase.json → feature/bar/horizontal-chart-max-increase.json} +10 -4
- package/examples/{horizontal-chart.json → feature/bar/horizontal-chart.json} +10 -4
- package/examples/{horizontal-stacked-bar-chart.json → feature/bar/horizontal-stacked-bar-chart.json} +7 -3
- package/examples/{planet-chart-horizontal-example-config.json → feature/bar/planet-chart-horizontal-example-config.json} +8 -3
- package/examples/feature/bar/planet-chart-logaritmic-config.json +170 -0
- package/examples/{planet-example-config.json → feature/bar/planet-example-config.json} +2 -2
- package/examples/{box-plot.json → feature/boxplot/boxplot.json} +7 -7
- package/examples/feature/boxplot/testing.csv +38 -0
- package/examples/feature/boxplot/valid-boxplot.csv +17 -0
- package/examples/feature/combo/combochart-categories_are_numbers .json +18 -0
- package/examples/{planet-combo-example-config.json → feature/combo/planet-combo-example-config.json} +1 -1
- package/examples/{planet-deviation-config.json → feature/deviation/planet-deviation-config.json} +2 -2
- package/examples/{planet-deviation-data.json → feature/deviation/planet-deviation-data.json} +9 -9
- package/examples/feature/filters/filter-testing.json +212 -0
- package/examples/feature/forecasting/case_date_example.csv +130 -0
- package/examples/feature/forecasting/effective_reproduction.json +202 -0
- package/examples/feature/forecasting/r_data.csv +130 -0
- package/examples/feature/forecasting/random_data.csv +366 -0
- package/examples/feature/line/line-chart.json +124 -0
- package/examples/{paired-bar-example.json → feature/paired-bar/paired-bar-example.json} +10 -4
- package/examples/{planet-pie-example-config.json → feature/pie/planet-pie-example-config.json} +2 -2
- package/examples/{scatterplot.json → feature/scatterplot/scatterplot.json} +1 -1
- package/examples/feature/test-highlight/test-highlight-2.json +789 -0
- package/examples/feature/test-highlight/test-highlight-vertical.json +561 -0
- package/examples/feature/test-highlight/test-highlight.json +100 -0
- package/examples/{case-rate-example-config.json → feature/tests-case-rate/case-rate-example-config.json} +2 -2
- package/examples/{covid-confidence-example-config.json → feature/tests-covid/covid-confidence-example-config.json} +8 -3
- package/examples/{covid-example-config.json → feature/tests-covid/covid-example-config.json} +7 -3
- package/examples/{cutoff-example-config.json → feature/tests-cutoff/cutoff-example-config.json} +7 -3
- package/examples/{date-exclusions-config.json → feature/tests-date-exclusions/date-exclusions-config.json} +2 -2
- package/examples/{example-bar-chart-nonnumeric.json → feature/tests-non-numerics/example-bar-chart-nonnumeric.json} +1 -1
- package/examples/{planet-pie-example-config-nonnumeric.json → feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json} +2 -2
- package/examples/{sparkline-chart-nonnumeric.json → feature/tests-non-numerics/sparkline-chart-nonnumeric.json} +1 -1
- package/examples/{stacked-vertical-bar-example-nonnumerics.json → feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json} +1 -2
- package/examples/gallery/bar-chart-horizontal/horizontal-highlight.json +345 -0
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +145 -7
- package/examples/gallery/paired-bar/paired-bar-chart.json +1 -0
- package/index.html +73 -49
- package/package.json +2 -2
- package/src/CdcChart.jsx +405 -40
- package/src/components/AreaChart.jsx +122 -80
- package/src/components/BarChart.jsx +126 -49
- package/src/components/BoxPlot.jsx +28 -20
- package/src/components/DataTable.jsx +7 -6
- package/src/components/DeviationBar.jsx +34 -34
- package/src/components/EditorPanel.jsx +1332 -352
- package/src/components/Legend.jsx +40 -4
- package/src/components/LineChart.jsx +10 -23
- package/src/components/LinearChart.jsx +133 -286
- package/src/components/PairedBarChart.jsx +6 -6
- package/src/components/PieChart.jsx +2 -4
- package/src/components/SparkLine.jsx +6 -42
- package/src/data/initial-state.js +23 -4
- package/src/hooks/useHighlightedBars.js +154 -0
- package/src/hooks/useMinMax.js +92 -0
- package/src/hooks/useReduceData.js +31 -57
- package/src/hooks/useScales.js +202 -0
- package/src/index.jsx +2 -1
- package/src/scss/editor-panel.scss +15 -0
- package/src/scss/main.scss +8 -6
- package/examples/box-plot.csv +0 -5
- package/examples/dynamic-legends.json +0 -125
- package/examples/example-bar-chart.json +0 -36
- package/examples/line-chart.json +0 -34
- package/examples/temp-example-config.json +0 -64
- package/examples/temp-example-data.json +0 -130
- package/src/components/Filters.jsx +0 -126
- /package/examples/{age-adjusted-rates.json → feature/__data__/age-adjusted-rates.json} +0 -0
- /package/examples/{new-data.csv → feature/__data__/new-data.csv} +0 -0
- /package/examples/{planet-example-data-max-increase.json → feature/__data__/planet-example-data-max-increase.json} +0 -0
- /package/examples/{Barchart_with_negative.json → feature/bar/Barchart_with_negative.json} +0 -0
- /package/examples/{stacked-vertical-bar-example-negative.json → feature/bar/stacked-vertical-bar-example-negative.json} +0 -0
- /package/examples/{stacked-vertical-bar-example.json → feature/bar/stacked-vertical-bar-example.json} +0 -0
- /package/examples/{box-plot-data.json → feature/boxplot/box-plot-data.json} +0 -0
- /package/examples/{newdata.json → feature/boxplot/boxplot-data.json} +0 -0
- /package/examples/{line-chart-max-increase.json → feature/line/line-chart-max-increase.json} +0 -0
- /package/examples/{paired-bar-data.json → feature/paired-bar/paired-bar-data.json} +0 -0
- /package/examples/{paired-bar-formatted.json → feature/paired-bar/paired-bar-formatted.json} +0 -0
- /package/examples/{scatterplot-continuous.csv → feature/scatterplot/scatterplot-continuous.csv} +0 -0
- /package/examples/{example-sparkline.json → feature/sparkline/example-sparkline.json} +0 -0
- /package/examples/{big-small-test-bar.json → feature/tests-big-small/big-small-test-bar.json} +0 -0
- /package/examples/{big-small-test-line.json → feature/tests-big-small/big-small-test-line.json} +0 -0
- /package/examples/{big-small-test-negative.json → feature/tests-big-small/big-small-test-negative.json} +0 -0
- /package/examples/{case-rate-example-data.json → feature/tests-case-rate/case-rate-example-data.json} +0 -0
- /package/examples/{covid-example-data-confidence.json → feature/tests-covid/covid-example-data-confidence.json} +0 -0
- /package/examples/{covid-example-data.json → feature/tests-covid/covid-example-data.json} +0 -0
- /package/examples/{cutoff-example-data.json → feature/tests-cutoff/cutoff-example-data.json} +0 -0
- /package/examples/{date-exclusions-data.json → feature/tests-date-exclusions/date-exclusions-data.json} +0 -0
- /package/examples/{example-combo-bar-nonnumeric.json → feature/tests-non-numerics/example-combo-bar-nonnumeric.json} +0 -0
- /package/examples/{line-chart-nonnumeric.json → feature/tests-non-numerics/line-chart-nonnumeric.json} +0 -0
- /package/examples/{planet-example-data-nonnumeric.json → feature/tests-non-numerics/planet-example-data-nonnumeric.json} +0 -0
|
@@ -5,9 +5,10 @@ import { LegendOrdinal, LegendItem, LegendLabel } from '@visx/legend'
|
|
|
5
5
|
import LegendCircle from '@cdc/core/components/LegendCircle'
|
|
6
6
|
|
|
7
7
|
import useLegendClasses from './../hooks/useLegendClasses'
|
|
8
|
+
import { useHighlightedBars } from '../hooks/useHighlightedBars'
|
|
8
9
|
|
|
9
10
|
const Legend = () => {
|
|
10
|
-
const { config, legend, colorScale, seriesHighlight, highlight, twoColorPalette, highlightReset, setSeriesHighlight, dynamicLegendItems, setDynamicLegendItems, transformedData: data, colorPalettes, rawData, setConfig, currentViewport } = useContext(ConfigContext)
|
|
11
|
+
const { config, legend, colorScale, seriesHighlight, highlight, twoColorPalette, tableData, highlightReset, setSeriesHighlight, dynamicLegendItems, setDynamicLegendItems, transformedData: data, colorPalettes, rawData, setConfig, currentViewport } = useContext(ConfigContext)
|
|
11
12
|
|
|
12
13
|
const { innerClasses, containerClasses } = useLegendClasses(config)
|
|
13
14
|
|
|
@@ -103,14 +104,14 @@ const Legend = () => {
|
|
|
103
104
|
if (config.visualizationType === 'Bar' && config.visualizationSubType === 'regular' && colorCode && config.series?.length === 1) {
|
|
104
105
|
let palette = colorPalettes[config.palette]
|
|
105
106
|
|
|
106
|
-
while (
|
|
107
|
+
while (tableData.length > palette.length) {
|
|
107
108
|
palette = palette.concat(palette)
|
|
108
109
|
}
|
|
109
110
|
palette = palette.slice(0, data.length)
|
|
110
111
|
//store uniq values to Set by colorCode
|
|
111
112
|
const set = new Set()
|
|
112
113
|
|
|
113
|
-
|
|
114
|
+
tableData.forEach(d => set.add(d[colorCode]))
|
|
114
115
|
|
|
115
116
|
// create labels with uniq values
|
|
116
117
|
const uniqeLabels = Array.from(set).map((val, i) => {
|
|
@@ -128,11 +129,15 @@ const Legend = () => {
|
|
|
128
129
|
return defaultLabels
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
const isBottomOrSmallViewport = config.legend.position === 'bottom' || currentViewport === 'sm' || currentViewport === 'xs'
|
|
132
|
+
const isBottomOrSmallViewport = config.legend.position === 'bottom' || currentViewport === 'sm' || currentViewport === 'xs' || currentViewport === 'xxs'
|
|
132
133
|
const isHorizontal = config.orientation === 'horizontal'
|
|
133
134
|
const marginTop = isBottomOrSmallViewport && isHorizontal ? `${config.runtime.xAxis.size}px` : '0px'
|
|
134
135
|
const marginBottom = isBottomOrSmallViewport ? '15px' : '0px'
|
|
135
136
|
|
|
137
|
+
const { HighLightedBarUtils } = useHighlightedBars(config)
|
|
138
|
+
|
|
139
|
+
let highLightedLegendItems = HighLightedBarUtils.findDuplicates(config.highlightedBarValues)
|
|
140
|
+
|
|
136
141
|
if (!legend) return null
|
|
137
142
|
|
|
138
143
|
if (!legend.dynamicLegend)
|
|
@@ -182,6 +187,37 @@ const Legend = () => {
|
|
|
182
187
|
</LegendItem>
|
|
183
188
|
)
|
|
184
189
|
})}
|
|
190
|
+
|
|
191
|
+
{highLightedLegendItems.map((bar, i) => {
|
|
192
|
+
// if duplicates only return first item
|
|
193
|
+
let className = 'legend-item'
|
|
194
|
+
let itemName = bar.legendLabel
|
|
195
|
+
|
|
196
|
+
if (!itemName) return
|
|
197
|
+
if (seriesHighlight.length > 0 && false === seriesHighlight.includes(itemName)) {
|
|
198
|
+
className += ' inactive'
|
|
199
|
+
}
|
|
200
|
+
return (
|
|
201
|
+
<LegendItem
|
|
202
|
+
className={className}
|
|
203
|
+
tabIndex={0}
|
|
204
|
+
key={`legend-quantile-${i}`}
|
|
205
|
+
onKeyPress={e => {
|
|
206
|
+
if (e.key === 'Enter') {
|
|
207
|
+
highlight(bar.legendLabel)
|
|
208
|
+
}
|
|
209
|
+
}}
|
|
210
|
+
onClick={() => {
|
|
211
|
+
highlight(bar.legendLabel)
|
|
212
|
+
}}
|
|
213
|
+
>
|
|
214
|
+
<LegendCircle fill='transparent' borderColor={bar.color ? bar.color : `rgba(255, 102, 1)`} />{' '}
|
|
215
|
+
<LegendLabel align='left' margin='0 0 0 4px'>
|
|
216
|
+
{bar.legendLabel ? bar.legendLabel : bar.value}
|
|
217
|
+
</LegendLabel>
|
|
218
|
+
</LegendItem>
|
|
219
|
+
)
|
|
220
|
+
})}
|
|
185
221
|
{seriesHighlight.length > 0 && (
|
|
186
222
|
<button className={`legend-reset ${config.theme}`} onClick={labels => highlightReset(labels)} tabIndex={0}>
|
|
187
223
|
Reset
|
|
@@ -6,16 +6,12 @@ import { LinePath } from '@visx/shape'
|
|
|
6
6
|
import { Text } from '@visx/text'
|
|
7
7
|
|
|
8
8
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
9
|
-
|
|
10
9
|
import ConfigContext from '../ConfigContext'
|
|
11
|
-
|
|
12
10
|
import useRightAxis from '../hooks/useRightAxis'
|
|
13
11
|
|
|
14
12
|
export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData, xMax, yMax, seriesStyle = 'Line' }) {
|
|
15
|
-
const { colorPalettes, transformedData: data, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, isNumber,
|
|
16
|
-
|
|
17
|
-
// calling clean several times on same set of data (TT)
|
|
18
|
-
const cleanedData = cleanData(data, config.xAxis.dataKey)
|
|
13
|
+
const { colorPalettes, transformedData: data, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, isNumber, updateConfig, handleLineType } = useContext(ConfigContext)
|
|
14
|
+
|
|
19
15
|
const { yScaleRight } = useRightAxis({ config, yMax, data, updateConfig })
|
|
20
16
|
|
|
21
17
|
const handleAxisFormating = (axis = 'left', label, value) => {
|
|
@@ -45,14 +41,13 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
45
41
|
opacity={config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(seriesKey) === -1 ? 0.5 : 1}
|
|
46
42
|
display={config.legend.behavior === 'highlight' || (seriesHighlight.length === 0 && !config.legend.dynamicLegend) || seriesHighlight.indexOf(seriesKey) !== -1 ? 'block' : 'none'}
|
|
47
43
|
>
|
|
48
|
-
{
|
|
44
|
+
{data.map((d, dataIndex) => {
|
|
49
45
|
// Find the series object from the config.series array that has a dataKey matching the seriesKey variable.
|
|
50
46
|
const series = config.series.find(({ dataKey }) => dataKey === seriesKey)
|
|
51
47
|
const { axis } = series
|
|
52
48
|
|
|
53
49
|
const xAxisValue = config.runtime.xAxis.type === 'date' ? formatDate(parseDate(d[config.runtime.xAxis.dataKey])) : d[config.runtime.xAxis.dataKey]
|
|
54
50
|
const yAxisValue = getYAxisData(d, seriesKey)
|
|
55
|
-
|
|
56
51
|
const hasMultipleSeries = Object.keys(config.runtime.seriesLabels).length > 1
|
|
57
52
|
const labeltype = axis === 'Right' ? 'rightLabel' : 'label'
|
|
58
53
|
let label = config.runtime.yAxis[labeltype]
|
|
@@ -72,16 +67,11 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
72
67
|
return (
|
|
73
68
|
d[seriesKey] !== undefined &&
|
|
74
69
|
d[seriesKey] !== '' &&
|
|
75
|
-
d[seriesKey] !== null &&
|
|
70
|
+
d[seriesKey] !== null &&
|
|
71
|
+
isNumber(d[seriesKey]) && (
|
|
76
72
|
<Group key={`series-${seriesKey}-point-${dataIndex}`}>
|
|
77
73
|
{/* Render legend */}
|
|
78
|
-
<Text
|
|
79
|
-
display={config.labels ? 'block' : 'none'}
|
|
80
|
-
x={xScale(getXAxisData(d))}
|
|
81
|
-
y={seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey))}
|
|
82
|
-
fill={colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[seriesKey] : seriesKey) : '#000'}
|
|
83
|
-
textAnchor='middle'
|
|
84
|
-
>
|
|
74
|
+
<Text display={config.labels ? 'block' : 'none'} x={xScale(getXAxisData(d))} y={seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey))} fill={'#000'} textAnchor='middle'>
|
|
85
75
|
{formatNumber(d[seriesKey], 'left')}
|
|
86
76
|
</Text>
|
|
87
77
|
|
|
@@ -99,10 +89,9 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
99
89
|
)
|
|
100
90
|
)
|
|
101
91
|
})}
|
|
102
|
-
|
|
103
92
|
<LinePath
|
|
104
|
-
curve={allCurves.
|
|
105
|
-
data={
|
|
93
|
+
curve={allCurves[seriesData[0].lineType]}
|
|
94
|
+
data={data}
|
|
106
95
|
x={d => xScale(getXAxisData(d))}
|
|
107
96
|
y={d => (seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey)))}
|
|
108
97
|
stroke={
|
|
@@ -116,7 +105,6 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
116
105
|
}
|
|
117
106
|
strokeWidth={2}
|
|
118
107
|
strokeOpacity={1}
|
|
119
|
-
shapeRendering='geometricPrecision'
|
|
120
108
|
strokeDasharray={lineType ? handleLineType(lineType) : 0}
|
|
121
109
|
defined={(item, i) => {
|
|
122
110
|
return item[config.runtime.seriesLabels[seriesKey]] !== '' && item[config.runtime.seriesLabels[seriesKey]] !== null && item[config.runtime.seriesLabels[seriesKey]] !== undefined
|
|
@@ -125,8 +113,8 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
125
113
|
{config.animate && (
|
|
126
114
|
<LinePath
|
|
127
115
|
className='animation'
|
|
128
|
-
curve={
|
|
129
|
-
data={
|
|
116
|
+
curve={seriesData.lineType}
|
|
117
|
+
data={data}
|
|
130
118
|
x={d => xScale(getXAxisData(d))}
|
|
131
119
|
y={d => (seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey)))}
|
|
132
120
|
stroke='#fff'
|
|
@@ -139,7 +127,6 @@ export default function LineChart({ xScale, yScale, getXAxisData, getYAxisData,
|
|
|
139
127
|
}}
|
|
140
128
|
/>
|
|
141
129
|
)}
|
|
142
|
-
|
|
143
130
|
{/* Render series labels at end if each line if selected in the editor */}
|
|
144
131
|
{config.showLineSeriesLabels &&
|
|
145
132
|
(config.runtime.lineSeriesKeys || config.runtime.seriesKeys).map(seriesKey => {
|