@cdc/chart 1.3.2 → 1.3.4
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 +77 -4
- package/examples/age-adjusted-rates.json +1218 -0
- package/examples/case-rate-example-config.json +36 -0
- package/examples/case-rate-example-data.json +33602 -0
- package/examples/date-exclusions-config.json +62 -0
- package/examples/date-exclusions-data.json +162 -0
- package/examples/horizontal-chart.json +35 -0
- package/examples/horizontal-stacked-bar-chart.json +36 -0
- package/examples/line-chart.json +76 -0
- package/examples/paired-bar-data.json +14 -0
- package/examples/paired-bar-example.json +48 -0
- package/examples/paired-bar-formatted.json +37 -0
- package/examples/planet-chart-horizontal-example-config.json +35 -0
- package/examples/planet-example-config.json +1 -0
- package/examples/private/newtest.csv +101 -0
- package/examples/private/test.json +10124 -0
- package/package.json +9 -5
- package/src/CdcChart.tsx +417 -149
- package/src/components/BarChart.tsx +431 -24
- package/src/components/BarStackVertical.js +0 -0
- package/src/components/DataTable.tsx +55 -28
- package/src/components/EditorPanel.js +914 -260
- package/src/components/LineChart.tsx +4 -3
- package/src/components/LinearChart.tsx +258 -88
- package/src/components/PairedBarChart.tsx +144 -0
- package/src/components/PieChart.tsx +30 -16
- package/src/components/SparkLine.js +206 -0
- package/src/data/initial-state.js +59 -32
- package/src/hooks/useActiveElement.js +19 -0
- package/src/hooks/useColorPalette.ts +83 -0
- package/src/hooks/useReduceData.ts +43 -0
- package/src/index.html +49 -13
- package/src/index.tsx +6 -2
- package/src/scss/editor-panel.scss +12 -4
- package/src/scss/main.scss +112 -3
- package/LICENSE +0 -201
|
@@ -3,7 +3,8 @@ import React, {
|
|
|
3
3
|
useEffect,
|
|
4
4
|
useState,
|
|
5
5
|
useMemo,
|
|
6
|
-
memo
|
|
6
|
+
memo,
|
|
7
|
+
Fragment} from 'react';
|
|
7
8
|
import {
|
|
8
9
|
useTable,
|
|
9
10
|
useSortBy,
|
|
@@ -19,23 +20,25 @@ import LegendCircle from '@cdc/core/components/LegendCircle';
|
|
|
19
20
|
import Context from '../context';
|
|
20
21
|
|
|
21
22
|
export default function DataTable() {
|
|
22
|
-
const { rawData,
|
|
23
|
+
const { rawData, transformedData: data, config, colorScale, parseDate, formatDate, formatNumber:numberFormatter } = useContext<any>(Context);
|
|
23
24
|
|
|
24
25
|
const legendGlyphSize = 15;
|
|
25
26
|
const legendGlyphSizeHalf = legendGlyphSize / 2;
|
|
26
|
-
|
|
27
|
+
const section = config.orientation ==='horizontal' ? 'yAxis' :'xAxis';
|
|
27
28
|
const [tableExpanded, setTableExpanded] = useState<boolean>(config.table.expanded);
|
|
28
29
|
const [accessibilityLabel, setAccessibilityLabel] = useState('');
|
|
29
30
|
|
|
30
|
-
const DownloadButton =
|
|
31
|
+
const DownloadButton = ({ data }: any) => {
|
|
31
32
|
const fileName = `${config.title.substring(0, 50)}.csv`;
|
|
32
33
|
|
|
33
34
|
const csvData = Papa.unparse(data);
|
|
34
35
|
|
|
35
36
|
const saveBlob = () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
//@ts-ignore
|
|
38
|
+
if (typeof window.navigator.msSaveBlob === 'function') {
|
|
39
|
+
const dataBlob = new Blob([csvData], { type: "text/csv;charset=utf-8;" });
|
|
40
|
+
//@ts-ignore
|
|
41
|
+
window.navigator.msSaveBlob(dataBlob, fileName);
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
|
|
@@ -50,7 +53,7 @@ export default function DataTable() {
|
|
|
50
53
|
Download Data (CSV)
|
|
51
54
|
</a>
|
|
52
55
|
)
|
|
53
|
-
}
|
|
56
|
+
};
|
|
54
57
|
|
|
55
58
|
// Creates columns structure for the table
|
|
56
59
|
const tableColumns = useMemo(() => {
|
|
@@ -59,18 +62,18 @@ export default function DataTable() {
|
|
|
59
62
|
Cell: ({ row }) => {
|
|
60
63
|
const seriesLabel = config.runtime.seriesLabels ? config.runtime.seriesLabels[row.original] : row.original;
|
|
61
64
|
return (
|
|
62
|
-
|
|
65
|
+
<Fragment>
|
|
63
66
|
{config.visualizationType !== 'Pie' && <LegendCircle fill={colorScale(seriesLabel)} />}
|
|
64
67
|
<span>{seriesLabel}</span>
|
|
65
|
-
|
|
68
|
+
</Fragment>
|
|
66
69
|
)
|
|
67
70
|
},
|
|
68
71
|
id: 'series-label'
|
|
69
72
|
}];
|
|
70
73
|
|
|
71
|
-
data.
|
|
74
|
+
data.forEach((d) => {
|
|
72
75
|
const newCol = {
|
|
73
|
-
Header: config.runtime.
|
|
76
|
+
Header: config.runtime[section].type === 'date' ? formatDate(parseDate(d[config.runtime.originalXAxis.dataKey])) : d[config.runtime.originalXAxis.dataKey],
|
|
74
77
|
Cell: ({ row }) => {
|
|
75
78
|
return (
|
|
76
79
|
<>
|
|
@@ -86,10 +89,12 @@ export default function DataTable() {
|
|
|
86
89
|
});
|
|
87
90
|
|
|
88
91
|
return newTableColumns;
|
|
89
|
-
}, [config]);
|
|
92
|
+
}, [config,colorScale]);
|
|
93
|
+
|
|
94
|
+
|
|
90
95
|
|
|
91
96
|
const tableData = useMemo(
|
|
92
|
-
|
|
97
|
+
() => config.visualizationType === 'Pie' ? [config.yAxis.dataKey] : config.runtime.seriesKeys,
|
|
93
98
|
[config.runtime.seriesKeys]
|
|
94
99
|
);
|
|
95
100
|
|
|
@@ -124,30 +129,48 @@ export default function DataTable() {
|
|
|
124
129
|
rows,
|
|
125
130
|
prepareRow,
|
|
126
131
|
} = useTable({ columns: tableColumns, data: tableData, defaultColumn }, useSortBy, useBlockLayout, useResizeColumns);
|
|
127
|
-
|
|
128
132
|
return (
|
|
129
133
|
<ErrorBoundary component="DataTable">
|
|
130
|
-
<section className={`data-table-container`} aria-label={accessibilityLabel}>
|
|
134
|
+
<section id={config?.title ? `dataTableSection__${config?.title.replace(/\s/g, '')}` : `dataTableSection`} className={`data-table-container`} aria-label={accessibilityLabel}>
|
|
131
135
|
<div
|
|
136
|
+
role="button"
|
|
132
137
|
className={tableExpanded ? 'data-table-heading' : 'collapsed data-table-heading'}
|
|
133
|
-
onClick={() => { setTableExpanded(!tableExpanded); }}
|
|
134
138
|
tabIndex={0}
|
|
139
|
+
onClick={() => { setTableExpanded(!tableExpanded); }}
|
|
135
140
|
onKeyDown={(e) => { if (e.keyCode === 13) { setTableExpanded(!tableExpanded); } }}
|
|
136
141
|
>
|
|
137
142
|
{config.table.label}
|
|
138
143
|
</div>
|
|
139
144
|
<div className="table-container">
|
|
140
|
-
<table
|
|
145
|
+
<table
|
|
146
|
+
className={tableExpanded ? 'data-table' : 'data-table cdcdataviz-sr-only'}
|
|
147
|
+
hidden={!tableExpanded}
|
|
148
|
+
{...getTableProps()}
|
|
149
|
+
aria-rowcount={ config?.series?.length ? config?.series?.length : '-1' }
|
|
150
|
+
>
|
|
141
151
|
<caption className="visually-hidden">{config.table.label}</caption>
|
|
142
152
|
<thead>
|
|
143
|
-
{headerGroups.map((headerGroup) => (
|
|
144
|
-
<tr {...headerGroup.getHeaderGroupProps()}>
|
|
153
|
+
{headerGroups.map((headerGroup,index) => (
|
|
154
|
+
<tr {...headerGroup.getHeaderGroupProps()} key={`headerGroups--${index}`}>
|
|
145
155
|
{headerGroup.headers.map((column, index) => (
|
|
146
|
-
<th
|
|
156
|
+
<th
|
|
157
|
+
tabIndex="0"
|
|
158
|
+
title={column.Header}
|
|
159
|
+
key={`trth--${index}`}
|
|
160
|
+
role="columnheader"
|
|
161
|
+
scope="col"
|
|
162
|
+
{...column.getHeaderProps(column.getSortByToggleProps())}
|
|
163
|
+
className={column.isSorted ? column.isSortedDesc ? 'sort sort-desc' : 'sort sort-asc' : 'sort'}
|
|
164
|
+
{...(column.isSorted ? column.isSortedDesc ? { 'aria-sort': 'descending' } : { 'aria-sort': 'ascending' } : null)}
|
|
165
|
+
>
|
|
147
166
|
{index === 0
|
|
148
167
|
? config.table.indexLabel
|
|
168
|
+
? config.table.indexLabel : column.render('Header')
|
|
149
169
|
: column.render('Header')
|
|
150
170
|
}
|
|
171
|
+
<button>
|
|
172
|
+
<span className="cdcdataviz-sr-only">{`Sort by ${typeof column.render('Header') === 'string' ? column.render('Header').toLowerCase() : column.render('Header') } in ${ column.isSorted ? column.isSortedDesc ? 'descending' : 'ascending' : 'no'} `} order</span>
|
|
173
|
+
</button>
|
|
151
174
|
<div {...column.getResizerProps()} className="resizer" />
|
|
152
175
|
</th>
|
|
153
176
|
))}
|
|
@@ -155,12 +178,16 @@ export default function DataTable() {
|
|
|
155
178
|
))}
|
|
156
179
|
</thead>
|
|
157
180
|
<tbody {...getTableBodyProps()}>
|
|
158
|
-
{rows.map((row) => {
|
|
181
|
+
{rows.map((row, index) => {
|
|
159
182
|
prepareRow(row);
|
|
160
183
|
return (
|
|
161
|
-
<tr {...row.getRowProps()}>
|
|
162
|
-
{row.cells.map((cell) => (
|
|
163
|
-
<td
|
|
184
|
+
<tr {...row.getRowProps()} key={`tbody__tr-${index}`}>
|
|
185
|
+
{row.cells.map((cell, index) => (
|
|
186
|
+
<td
|
|
187
|
+
tabIndex="0"
|
|
188
|
+
{...cell.getCellProps()}
|
|
189
|
+
key={`tbody__tr__td-${index}`}
|
|
190
|
+
role="gridcell">
|
|
164
191
|
{cell.render('Cell')}
|
|
165
192
|
</td>
|
|
166
193
|
))}
|
|
@@ -169,7 +196,7 @@ export default function DataTable() {
|
|
|
169
196
|
})}
|
|
170
197
|
</tbody>
|
|
171
198
|
</table>
|
|
172
|
-
{config.regions ? (
|
|
199
|
+
{config.regions && config.regions.length > 0 ? (
|
|
173
200
|
<table className="region-table data-table">
|
|
174
201
|
<caption className="visually-hidden">Table of the highlighted regions in the visualization</caption>
|
|
175
202
|
<thead>
|
|
@@ -180,11 +207,11 @@ export default function DataTable() {
|
|
|
180
207
|
</tr>
|
|
181
208
|
</thead>
|
|
182
209
|
<tbody>
|
|
183
|
-
{config.regions.map((region) => {
|
|
210
|
+
{config.regions.map((region,index) => {
|
|
184
211
|
if(!Object.keys(region).includes('from') || !Object.keys(region).includes('to')) return null
|
|
185
212
|
|
|
186
213
|
return (
|
|
187
|
-
<tr key={`row-${region.label}`}>
|
|
214
|
+
<tr key={`row-${region.label}--${index}`}>
|
|
188
215
|
<td>{region.label}</td>
|
|
189
216
|
<td>{formatDate(parseDate(region.from))}</td>
|
|
190
217
|
<td>{formatDate(parseDate(region.to))}</td>
|