@cdc/chart 4.24.2 → 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 +47386 -36618
- package/examples/chart-regression-1.json +378 -0
- package/examples/chart-regression-2.json +2360 -0
- package/examples/feature/filters/url-filter.json +1076 -0
- package/examples/feature/line/line-chart.json +2 -1
- package/examples/feature/regions/index.json +50 -4
- 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 -123
- package/package.json +4 -2
- package/src/CdcChart.tsx +40 -22
- package/src/_stories/ChartEditor.stories.tsx +14 -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 -1
- 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 +32 -39
- package/src/components/BarChart/components/BarChart.Vertical.tsx +40 -55
- package/src/components/BoxPlot/BoxPlot.jsx +2 -1
- package/src/components/DeviationBar.jsx +3 -3
- package/src/components/EditorPanel/EditorPanel.tsx +167 -15
- package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +108 -0
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +48 -4
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +41 -0
- package/src/components/EditorPanel/components/Panels/index.tsx +9 -7
- package/src/components/EditorPanel/components/panels.scss +11 -0
- package/src/components/EditorPanel/useEditorPermissions.js +40 -14
- package/src/components/Legend/Legend.Component.tsx +23 -15
- package/src/components/Legend/Legend.tsx +4 -4
- package/src/components/LineChart/LineChartProps.ts +1 -0
- package/src/components/LineChart/helpers.ts +2 -2
- package/src/components/LineChart/index.tsx +7 -7
- package/src/components/LinearChart.jsx +9 -30
- package/src/components/PairedBarChart.jsx +6 -10
- package/src/components/PieChart/PieChart.tsx +3 -3
- package/src/components/Regions/components/Regions.tsx +120 -78
- 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 +46 -2
- package/src/helpers/computeMarginBottom.ts +2 -1
- package/src/helpers/tests/computeMarginBottom.test.ts +2 -1
- package/src/hooks/useBarChart.js +5 -2
- package/src/hooks/useScales.ts +15 -18
- package/src/hooks/useTooltip.tsx +9 -8
- package/src/scss/main.scss +8 -29
- package/src/types/ChartConfig.ts +32 -14
- package/src/types/ChartContext.ts +7 -0
package/index.html
CHANGED
|
@@ -1,27 +1,36 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
/* max-width: 1000px; */
|
|
9
|
+
margin: 0 auto !important;
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.react-container + .react-container {
|
|
16
|
+
margin-top: 3rem;
|
|
17
|
+
}
|
|
18
|
+
</style>
|
|
19
|
+
<link rel="stylesheet prefetch" href="https://www.cdc.gov/TemplatePackage/contrib/libs/bootstrap/latest/css/bootstrap.min.css?_=39423" />
|
|
20
|
+
<link rel="stylesheet prefetch" href="https://www.cdc.gov/TemplatePackage/4.0/assets/css/app.min.css?_=39423" />
|
|
21
|
+
</head>
|
|
22
|
+
|
|
23
|
+
<body>
|
|
24
|
+
<!-- SANKEY EXAMPLE -->
|
|
25
|
+
<!-- <div class="container d-flex flex-wrap body-wrapper bg-white">
|
|
26
|
+
<main class="col-lg-9 order-lg-2" role="main" aria-label="Main Content Area">
|
|
27
|
+
<div class="row">
|
|
28
|
+
<div class="col-md-12"> -->
|
|
29
|
+
<!-- <div class="react-container" data-config="/examples/feature/sankey/sankey-example-data.json"></div> -->
|
|
30
|
+
<!-- </div>
|
|
31
|
+
</div>
|
|
32
|
+
</main>
|
|
33
|
+
</div> -->
|
|
25
34
|
|
|
26
35
|
<!--
|
|
27
36
|
EXAMPLES:
|
|
@@ -35,87 +44,86 @@
|
|
|
35
44
|
|
|
36
45
|
-->
|
|
37
46
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
47
|
+
<!-- GENERIC CHART TYPES -->
|
|
48
|
+
<!-- <div class="react-container" data-config="/examples/private/rvr.json"></div> -->
|
|
49
|
+
<!-- <div class="react-container" data-config="/examples/feature/filters/url-filter.json"></div> -->
|
|
50
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/additional-column-tooltip.json"></div> -->
|
|
51
|
+
<!-- <div class="react-container" data-config="https://cdc.gov/poxvirus/mpox/modules/data-viz/mpx-trends_1.json"></div> -->
|
|
52
|
+
<!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date-city-temperature.json"></div> -->
|
|
53
|
+
<!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date-apple.json"></div> -->
|
|
54
|
+
<!-- <div class="react-container" data-config="/examples/feature/forest-plot/linear.json"></div> -->
|
|
55
|
+
<!-- <div class="react-container" data-config="/examples/feature/forest-plot/logarithmic.json"></div> -->
|
|
56
|
+
<!-- <div class="react-container" data-config="/examples/feature/forest-plot/forest-plot.json"></div> -->
|
|
57
|
+
<!-- <div class="react-container" data-config="/examples/feature/pie/planet-pie-example-config.json"></div> -->
|
|
58
|
+
<!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Viz.json></div> -->
|
|
59
|
+
<!-- <div class="react-container" data-config=/examples/feature/regions/index.json></div> -->
|
|
60
|
+
<!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Regions_Viz.json></div> -->
|
|
61
|
+
<!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Regions_Viz.json></div> -->
|
|
62
|
+
<!-- <div class="react-container" data-config="/examples/feature/forecasting/forecasting.json"></div> -->
|
|
63
|
+
<!-- <div class="react-container" data-config="/examples/feature/forecasting/combo-forecasting.json"></div> -->
|
|
64
|
+
<!-- <div class="react-container" data-config="/examples/feature/forecasting/effective_reproduction.json"></div> -->
|
|
65
|
+
<!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date.json"></div> -->
|
|
66
|
+
<!-- <div class="react-container" data-config="/examples/feature/area/area-chart-category.json"></div> -->
|
|
67
|
+
<!-- <div class="react-container" data-config="/examples/feature/scatterplot/scatterplot.json"></div> -->
|
|
68
|
+
<!-- <div class="react-container" data-config="/examples/feature/deviation/planet-deviation-config.json"></div> -->
|
|
69
|
+
<!-- <div class="react-container" data-config="/examples/feature/boxplot/boxplot.json"></div> -->
|
|
70
|
+
<!-- <div class="react-container" data-config="/examples/feature/combo/planet-combo-example-config.json"></div> -->
|
|
71
|
+
<!-- <div class="react-container" data-config="/examples/feature/combo/right-issues.json"></div> -->
|
|
72
|
+
<div class="react-container" data-config="/examples/region-issue.json"></div>
|
|
73
|
+
|
|
74
|
+
<!-- BAR -->
|
|
75
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/planet-example-config.json"></div> -->
|
|
76
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/planet-chart-horizontal-example-config.json"></div> -->
|
|
77
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/example-bar-chart.json"></div> -->
|
|
78
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/horizontal-chart-max-increase.json"></div> -->
|
|
79
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/horizontal-chart.json"></div> -->
|
|
80
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/horizontal-stacked-bar-chart.json"></div> -->
|
|
81
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/planet-chart-horizontal-example-config.json"></div> -->
|
|
82
|
+
|
|
83
|
+
<!-- SPARKLINE -->
|
|
84
|
+
<!-- <div class="react-container" data-config="/examples/feature/dev-4261.json"></div> -->
|
|
85
|
+
|
|
86
|
+
<!-- TESTS DATA TABLE SORTING -->
|
|
87
|
+
<!-- Bar Chart with Confidence Intervals (bottom of page) -->
|
|
88
|
+
<!-- <div class="react-container" data-config="https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Example_Bar_CI.json"></div> -->
|
|
89
|
+
<!-- TPOXX Patient Data -->
|
|
90
|
+
<!-- <div class="react-container" data-config="https://www.cdc.gov/poxvirus/mpox/modules/data-viz/tpoxx_weekly_race_eth.json"></div> -->
|
|
91
|
+
<!-- <div class="react-container" data-config="https://www.cdc.gov/poxvirus/mpox/modules/data-viz/mpx-tpoxx-age-gender.json"></div> -->
|
|
92
|
+
<!-- Non-Variola Orthopoxvirus (NVO) Laboratory Testing by Demographics -->
|
|
93
|
+
<!-- <div class="react-container" data-config="https://wwwdev-cdc.msappproxy.net/poxvirus/mpox/modules/data-viz/lab-data.json"></div> -->
|
|
94
|
+
<!-- <div class="react-container" data-config="https://wwwdev-cdc.msappproxy.net/poxvirus/mpox/modules/data-viz/lab-data-age.json"></div> -->
|
|
95
|
+
<!-- PROBLEM WITH THEIR PAGE CONFIG or CONFLICT with -->
|
|
96
|
+
<!-- CORS ERROR pulling data on Covid Flu RSV page at https://wwwdev-cdc.msappproxy.net/respiratory-viruses/index.html-->
|
|
97
|
+
<!-- <div class="react-container" data-config="https://wwwdev-cdc.msappproxy.net/respiratory-viruses/modules/emergency-dept-visits_live.json"></div> -->
|
|
98
|
+
<!-- MPOX -->
|
|
99
|
+
<!-- <div class="react-container" data-config="https://www.cdc.gov/poxvirus/mpox/modules/data-viz/mpox-demographics-monthly.json"></div> -->
|
|
100
|
+
<!-- <div class="react-container" data-config="/https://www.cdc.gov/poxvirus/mpox/modules/data-viz/mpx-age-sex1.json"></div> -->
|
|
101
|
+
|
|
102
|
+
<!-- TESTS DATE EXCLUSIONS -->
|
|
103
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-date-exclusions/date-exclusions-config.json"></div> -->
|
|
104
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-case-rate/case-rate-example-config.json"></div> -->
|
|
105
|
+
|
|
106
|
+
<!-- TESTS BIG SMALL-->
|
|
107
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-big-small/big-small-test-line.json"></div> -->
|
|
108
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-big-small/big-small-test-bar.json"></div> -->
|
|
109
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-big-small/big-small-test-negative.json"></div> -->
|
|
110
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-big-small/line-chart-max-increase.json"></div> -->
|
|
111
|
+
|
|
112
|
+
<!-- TESTS NONNUMERICS -->
|
|
113
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json"></div> -->
|
|
114
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/example-combo-bar-nonnumeric.json"></div> -->
|
|
115
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/example-bar-chart-nonnumeric.json"></div> -->
|
|
116
|
+
<!-- <div class="react-container" data-config="/examples/sparkline.json"></div> -->
|
|
117
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/sparkline-chart-nonnumeric.json"></div> -->
|
|
118
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/lollipop.json"></div> -->
|
|
119
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json"></div> -->
|
|
120
|
+
|
|
121
|
+
<!-- TESTS CUTOFF -->
|
|
122
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-cutoff/cutoff-example-config.json"></div> -->
|
|
123
|
+
|
|
124
|
+
<!-- TESTS COVID -->
|
|
125
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-covid/covid-confidence-example-config.json"></div> -->
|
|
126
|
+
<!-- <div class="react-container" data-config="/examples/feature/tests-covid/covid-example-config.json"></div> -->
|
|
119
127
|
|
|
120
128
|
<!--
|
|
121
129
|
GALLERY EXAMPLES BELOW THIS LINE...
|
|
@@ -123,28 +131,25 @@
|
|
|
123
131
|
|
|
124
132
|
-->
|
|
125
133
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<div class="react-container" data-config="/examples/feature/line/line-chart
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<!-- HORIZONTAL BAR CHARTS -->
|
|
132
|
-
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json"></div> -->
|
|
133
|
-
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json"></div> -->
|
|
134
|
-
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-stacked.json"></div> -->
|
|
134
|
+
<!-- GENERIC CHART TYPES -->
|
|
135
|
+
<!-- <div class="react-container" data-config="/examples/gallery/paired-bar/paired-bar-chart.json"></div> -->
|
|
136
|
+
<!-- <div class="react-container" data-config="/examples/feature/line/line-chart.json"></div> -->
|
|
135
137
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json"></div> -->
|
|
141
|
-
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart.json"></div> -->
|
|
142
|
-
<!-- <div class="react-container" data-config="https://www.cdc.gov/respiratory-viruses/modules/respiratory-virus-activity/emergency-dept-visits_live.json"></div> -->
|
|
138
|
+
<!-- HORIZONTAL BAR CHARTS -->
|
|
139
|
+
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json"></div> -->
|
|
140
|
+
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json"></div> -->
|
|
141
|
+
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-stacked.json"></div> -->
|
|
143
142
|
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
<!-- VERTICAL BAR CHARTS -->
|
|
144
|
+
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/combo-line-chart.json"></div> -->
|
|
145
|
+
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json"></div> -->
|
|
146
|
+
<div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json"></div>
|
|
147
|
+
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json"></div> -->
|
|
148
|
+
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart.json"></div> -->
|
|
149
|
+
<!-- <div class="react-container" data-config="https://www.cdc.gov/respiratory-viruses/modules/respiratory-virus-activity/emergency-dept-visits_live.json"></div> -->
|
|
146
150
|
|
|
147
|
-
<
|
|
148
|
-
</body>
|
|
151
|
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
149
152
|
|
|
153
|
+
<script type="module" src="./src/index.jsx"></script>
|
|
154
|
+
</body>
|
|
150
155
|
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/chart",
|
|
3
|
-
"version": "4.24.
|
|
3
|
+
"version": "4.24.3",
|
|
4
4
|
"description": "React component for visualizing tabular data in various types of charts",
|
|
5
5
|
"moduleName": "CdcChart",
|
|
6
6
|
"main": "dist/cdcchart",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"chroma-js": "^2.1.2",
|
|
44
44
|
"d3-array": "^2.8.0",
|
|
45
45
|
"d3-format": "^3.1.0",
|
|
46
|
+
"d3-sankey": "^0.12.3",
|
|
46
47
|
"d3-time-format": "^3.0.0",
|
|
47
48
|
"html-react-parser": "^3.0.8",
|
|
48
49
|
"js-base64": "^2.5.2",
|
|
@@ -59,8 +60,9 @@
|
|
|
59
60
|
"react": "^18.2.0",
|
|
60
61
|
"react-dom": "^18.2.0"
|
|
61
62
|
},
|
|
62
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "9c7ef7ca74f2d2a1e04d923b133fe0fc557a62bf",
|
|
63
64
|
"devDependencies": {
|
|
65
|
+
"@types/d3-sankey": "^0.12.4",
|
|
64
66
|
"resize-observer-polyfill": "^1.5.1"
|
|
65
67
|
}
|
|
66
68
|
}
|
package/src/CdcChart.tsx
CHANGED
|
@@ -15,8 +15,10 @@ import 'react-tooltip/dist/react-tooltip.css'
|
|
|
15
15
|
|
|
16
16
|
// Primary Components
|
|
17
17
|
import ConfigContext from './ConfigContext'
|
|
18
|
-
import PieChart from './components/PieChart
|
|
18
|
+
import PieChart from './components/PieChart'
|
|
19
|
+
import SankeyChart from './components/Sankey'
|
|
19
20
|
import LinearChart from './components/LinearChart'
|
|
21
|
+
import { isDateScale } from '@cdc/core/helpers/cove/date'
|
|
20
22
|
|
|
21
23
|
import { colorPalettesChart as colorPalettes, twoColorPalette } from '@cdc/core/data/colorPalettes'
|
|
22
24
|
|
|
@@ -46,6 +48,7 @@ import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
|
46
48
|
import cacheBustingString from '@cdc/core/helpers/cacheBustingString'
|
|
47
49
|
import isNumber from '@cdc/core/helpers/isNumber'
|
|
48
50
|
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
51
|
+
import { getQueryStringFilterValue } from '@cdc/core/helpers/queryStringUtils'
|
|
49
52
|
|
|
50
53
|
import './scss/main.scss'
|
|
51
54
|
// load both then config below determines which to use
|
|
@@ -55,6 +58,7 @@ import Title from '@cdc/core/components/ui/Title'
|
|
|
55
58
|
import { ChartConfig } from './types/ChartConfig'
|
|
56
59
|
import { Label } from './types/Label'
|
|
57
60
|
import { isSolrCsv, isSolrJson } from '@cdc/core/helpers/isSolr'
|
|
61
|
+
import SkipTo from '@cdc/core/components/elements/SkipTo'
|
|
58
62
|
|
|
59
63
|
export default function CdcChart({ configUrl, config: configObj, isEditor = false, isDebug = false, isDashboard = false, setConfig: setParentConfig, setEditing, hostname, link, setSharedFilter, setSharedFilterValue, dashboardConfig }) {
|
|
60
64
|
const transform = new DataTransform()
|
|
@@ -64,7 +68,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
64
68
|
const [stateData, setStateData] = useState(config.data || [])
|
|
65
69
|
const [excludedData, setExcludedData] = useState<Record<string, number>[] | undefined>(undefined)
|
|
66
70
|
const [filteredData, setFilteredData] = useState<Record<string, any>[] | undefined>(undefined)
|
|
67
|
-
const [seriesHighlight, setSeriesHighlight] = useState<string[]>([])
|
|
71
|
+
const [seriesHighlight, setSeriesHighlight] = useState<string[]>(configObj && configObj?.legend?.seriesHighlight?.length ? [...configObj?.legend?.seriesHighlight] : [])
|
|
68
72
|
const [currentViewport, setCurrentViewport] = useState('lg')
|
|
69
73
|
const [dimensions, setDimensions] = useState<[number?, number?]>([])
|
|
70
74
|
const [externalFilters, setExternalFilters] = useState<any[]>()
|
|
@@ -75,6 +79,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
75
79
|
type Config = typeof config
|
|
76
80
|
let legendMemo = useRef(new Map()) // map collection
|
|
77
81
|
let innerContainerRef = useRef()
|
|
82
|
+
const legendRef = useRef(null)
|
|
78
83
|
|
|
79
84
|
if (isDebug) console.log('Chart config, isEditor', config, isEditor)
|
|
80
85
|
|
|
@@ -90,7 +95,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
90
95
|
|
|
91
96
|
const { barBorderClass, lineDatapointClass, contentClasses, sparkLineStyles } = useDataVizClasses(config)
|
|
92
97
|
|
|
93
|
-
const handleChartTabbing = config.
|
|
98
|
+
const handleChartTabbing = !config.legend?.hide ? `legend` : config?.title ? `dataTableSection__${config.title.replace(/\s/g, '')}` : `dataTableSection`
|
|
94
99
|
|
|
95
100
|
const reloadURLData = async () => {
|
|
96
101
|
if (config.dataUrl) {
|
|
@@ -219,6 +224,15 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
219
224
|
}
|
|
220
225
|
}
|
|
221
226
|
let newConfig = { ...defaults, ...response }
|
|
227
|
+
if (newConfig.filters) {
|
|
228
|
+
newConfig.filters.forEach((filter, index) => {
|
|
229
|
+
const queryStringFilterValue = getQueryStringFilterValue(filter)
|
|
230
|
+
if (queryStringFilterValue) {
|
|
231
|
+
newConfig.filters[index].active = queryStringFilterValue
|
|
232
|
+
}
|
|
233
|
+
})
|
|
234
|
+
}
|
|
235
|
+
|
|
222
236
|
if (newConfig.visualizationType === 'Box Plot') {
|
|
223
237
|
newConfig.legend.hide = true
|
|
224
238
|
}
|
|
@@ -253,7 +267,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
253
267
|
if (newConfig.exclusions && newConfig.exclusions.active) {
|
|
254
268
|
if (newConfig.xAxis.type === 'categorical' && newConfig.exclusions.keys?.length > 0) {
|
|
255
269
|
newExcludedData = data.filter(e => !newConfig.exclusions.keys.includes(e[newConfig.xAxis.dataKey]))
|
|
256
|
-
} else if (newConfig.xAxis
|
|
270
|
+
} else if (isDateScale(newConfig.xAxis) && (newConfig.exclusions.dateStart || newConfig.exclusions.dateEnd) && newConfig.xAxis.dateParseFormat) {
|
|
257
271
|
// Filter dates
|
|
258
272
|
const timestamp = e => new Date(e).getTime()
|
|
259
273
|
|
|
@@ -297,13 +311,9 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
297
311
|
setFilteredData(currentData)
|
|
298
312
|
}
|
|
299
313
|
|
|
300
|
-
if (
|
|
301
|
-
newConfig.xAxis.sortDates = false
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (newConfig.xAxis.sortDates && newConfig.barThickness > 0.1) {
|
|
314
|
+
if (newConfig.xAxis.type === 'date-time' && newConfig.barThickness > 0.1) {
|
|
305
315
|
newConfig.barThickness = 0.035
|
|
306
|
-
} else if (
|
|
316
|
+
} else if (newConfig.xAxis.type !== 'date-time' && newConfig.barThickness < 0.1) {
|
|
307
317
|
newConfig.barThickness = 0.35
|
|
308
318
|
}
|
|
309
319
|
|
|
@@ -483,6 +493,13 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
483
493
|
newConfig.runtime.uniqueId = Date.now()
|
|
484
494
|
newConfig.runtime.editorErrorMessage = newConfig.visualizationType === 'Pie' && !newConfig.yAxis.dataKey ? 'Data Key property in Y Axis section must be set for pie charts.' : ''
|
|
485
495
|
|
|
496
|
+
// Sankey Description box error message
|
|
497
|
+
newConfig.runtime.editorErrorMessage = newConfig.visualizationType === 'Sankey' && !newConfig.description ? 'SUBTEXT/CITATION field is empty: A description of the Sankey Diagram data must be inputted.' : ''
|
|
498
|
+
|
|
499
|
+
if (newConfig.legend.seriesHighlight?.length) {
|
|
500
|
+
setSeriesHighlight(newConfig.legend?.seriesHighlight)
|
|
501
|
+
}
|
|
502
|
+
|
|
486
503
|
setConfig(newConfig)
|
|
487
504
|
}
|
|
488
505
|
|
|
@@ -698,7 +715,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
698
715
|
// Called on reset button click, unhighlights all data series
|
|
699
716
|
const highlightReset = () => {
|
|
700
717
|
try {
|
|
701
|
-
const legend =
|
|
718
|
+
const legend = legendRef.current
|
|
702
719
|
if (!legend) throw new Error('No legend available to set previous focus on.')
|
|
703
720
|
legend.focus()
|
|
704
721
|
} catch (e) {
|
|
@@ -903,6 +920,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
903
920
|
}
|
|
904
921
|
|
|
905
922
|
const missingRequiredSections = () => {
|
|
923
|
+
if (config.visualizationType === 'Sankey') return false // skip checks for now
|
|
906
924
|
if (config.visualizationType === 'Forecasting') return false // skip required checks for now.
|
|
907
925
|
if (config.visualizationType === 'Forest Plot') return false // skip required checks for now.
|
|
908
926
|
if (config.visualizationType === 'Pie') {
|
|
@@ -1034,14 +1052,12 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1034
1052
|
<>
|
|
1035
1053
|
{isEditor && <EditorPanel />}
|
|
1036
1054
|
{!missingRequiredSections() && !config.newViz && (
|
|
1037
|
-
<div className='cdc-chart-inner-container'>
|
|
1055
|
+
<div className='cdc-chart-inner-container' aria-label={handleChartAriaLabels(config)} tabIndex={0}>
|
|
1038
1056
|
<Title showTitle={config.showTitle} isDashboard={isDashboard} title={title} superTitle={config.superTitle} classes={['chart-title', `${config.theme}`, 'cove-component__header']} style={undefined} />
|
|
1057
|
+
<SkipTo skipId={handleChartTabbing} skipMessage='Skip Over Chart Container' />
|
|
1039
1058
|
|
|
1040
|
-
<a id='skip-chart-container' className='cdcdataviz-sr-only-focusable' href={handleChartTabbing}>
|
|
1041
|
-
Skip Over Chart Container
|
|
1042
|
-
</a>
|
|
1043
1059
|
{/* Filters */}
|
|
1044
|
-
{config.filters && !externalFilters && <Filters config={config} setConfig={setConfig} setFilteredData={setFilteredData} filteredData={filteredData} excludedData={excludedData} filterData={filterData} dimensions={dimensions} />}
|
|
1060
|
+
{config.filters && !externalFilters && config.visualizationType !== 'Spark Line' && <Filters config={config} setConfig={setConfig} setFilteredData={setFilteredData} filteredData={filteredData} excludedData={excludedData} filterData={filterData} dimensions={dimensions} />}
|
|
1045
1061
|
{/* Visualization */}
|
|
1046
1062
|
{config?.introText && config.visualizationType !== 'Spark Line' && <section className='introText'>{parse(config.introText)}</section>}
|
|
1047
1063
|
<div
|
|
@@ -1054,6 +1070,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1054
1070
|
{/* Sparkline */}
|
|
1055
1071
|
{config.visualizationType === 'Spark Line' && (
|
|
1056
1072
|
<>
|
|
1073
|
+
<Filters config={config} setConfig={setConfig} setFilteredData={setFilteredData} filteredData={filteredData} excludedData={excludedData} filterData={filterData} dimensions={dimensions} />
|
|
1057
1074
|
{config?.introText && (
|
|
1058
1075
|
<section className='introText' style={{ padding: '0px 0 35px' }}>
|
|
1059
1076
|
{parse(config.introText)}
|
|
@@ -1069,7 +1086,9 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1069
1086
|
)}
|
|
1070
1087
|
</>
|
|
1071
1088
|
)}
|
|
1072
|
-
{
|
|
1089
|
+
{/* Sankey */}
|
|
1090
|
+
{config.visualizationType === 'Sankey' && <ParentSize aria-hidden='true'>{parent => <SankeyChart runtime={config.runtime} width={parent.width} height={parent.height} />}</ParentSize>}
|
|
1091
|
+
{!config.legend.hide && config.visualizationType !== 'Spark Line' && config.visualizationType !== 'Sankey' && <Legend ref={legendRef} />}
|
|
1073
1092
|
</div>
|
|
1074
1093
|
{/* Link */}
|
|
1075
1094
|
{isDashboard && config.table && config.table.show && config.table.showDataTableLink ? tableLink : link && link}
|
|
@@ -1084,11 +1103,11 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1084
1103
|
</MediaControls.Section>
|
|
1085
1104
|
|
|
1086
1105
|
{/* Data Table */}
|
|
1087
|
-
{config.xAxis.dataKey && config.table.show && config.visualizationType !== 'Spark Line' && (
|
|
1106
|
+
{((config.xAxis.dataKey && config.table.show && config.visualizationType !== 'Spark Line' && config.visualizationType !== 'Sankey') || (config.visualizationType === 'Sankey' && config.table.show)) && (
|
|
1088
1107
|
<DataTable
|
|
1089
1108
|
config={config}
|
|
1090
|
-
rawData={config.table.customTableConfig ? filterData(config.filters, config.data) : config.data}
|
|
1091
|
-
runtimeData={transform.applySuppression(filteredData || excludedData, config.suppressedData)}
|
|
1109
|
+
rawData={config.visualizationType === 'Sankey' ? config?.data?.[0]?.tableData : config.table.customTableConfig ? filterData(config.filters, config.data) : config.data}
|
|
1110
|
+
runtimeData={config.visualizationType === 'Sankey' ? config?.data?.[0]?.tableData : transform.applySuppression(filteredData || excludedData, config.suppressedData)}
|
|
1092
1111
|
expandDataTable={config.table.expanded}
|
|
1093
1112
|
columns={config.columns}
|
|
1094
1113
|
displayDataAsText={displayDataAsText}
|
|
@@ -1110,13 +1129,12 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1110
1129
|
)
|
|
1111
1130
|
}
|
|
1112
1131
|
|
|
1113
|
-
const getXAxisData = d => (config.runtime.xAxis
|
|
1132
|
+
const getXAxisData = d => (isDateScale(config.runtime.xAxis) ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
|
|
1114
1133
|
const getYAxisData = (d, seriesKey) => d[seriesKey]
|
|
1115
1134
|
|
|
1116
1135
|
const capitalize = str => {
|
|
1117
1136
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
1118
1137
|
}
|
|
1119
|
-
|
|
1120
1138
|
const contextValues = {
|
|
1121
1139
|
capitalize,
|
|
1122
1140
|
computeMarginBottom,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
-
|
|
2
|
+
import { userEvent, within } from '@storybook/testing-library'
|
|
3
3
|
import Chart from '../CdcChart'
|
|
4
|
-
|
|
5
4
|
import pieChartExample from './_mock/pie_config.json'
|
|
6
5
|
import pieData from './_mock/pie_data.json'
|
|
6
|
+
import urlFilterExample from './_mock/url_filter.json'
|
|
7
7
|
|
|
8
8
|
const meta: Meta<typeof Chart> = {
|
|
9
|
-
title: 'Components/Templates/Editor
|
|
9
|
+
title: 'Components/Templates/Chart/Editor',
|
|
10
10
|
component: Chart
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -19,4 +19,15 @@ export const Primary: Story = {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
const sleep = ms => {
|
|
23
|
+
return new Promise(r => setTimeout(r, ms))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const Url_Filter: Story = {
|
|
27
|
+
args: {
|
|
28
|
+
config: urlFilterExample,
|
|
29
|
+
isEditor: true
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
export default meta
|