@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.
Files changed (36) hide show
  1. package/dist/cdcchart.js +77 -4
  2. package/examples/age-adjusted-rates.json +1218 -0
  3. package/examples/case-rate-example-config.json +36 -0
  4. package/examples/case-rate-example-data.json +33602 -0
  5. package/examples/date-exclusions-config.json +62 -0
  6. package/examples/date-exclusions-data.json +162 -0
  7. package/examples/horizontal-chart.json +35 -0
  8. package/examples/horizontal-stacked-bar-chart.json +36 -0
  9. package/examples/line-chart.json +76 -0
  10. package/examples/paired-bar-data.json +14 -0
  11. package/examples/paired-bar-example.json +48 -0
  12. package/examples/paired-bar-formatted.json +37 -0
  13. package/examples/planet-chart-horizontal-example-config.json +35 -0
  14. package/examples/planet-example-config.json +1 -0
  15. package/examples/private/newtest.csv +101 -0
  16. package/examples/private/test.json +10124 -0
  17. package/package.json +9 -5
  18. package/src/CdcChart.tsx +417 -149
  19. package/src/components/BarChart.tsx +431 -24
  20. package/src/components/BarStackVertical.js +0 -0
  21. package/src/components/DataTable.tsx +55 -28
  22. package/src/components/EditorPanel.js +914 -260
  23. package/src/components/LineChart.tsx +4 -3
  24. package/src/components/LinearChart.tsx +258 -88
  25. package/src/components/PairedBarChart.tsx +144 -0
  26. package/src/components/PieChart.tsx +30 -16
  27. package/src/components/SparkLine.js +206 -0
  28. package/src/data/initial-state.js +59 -32
  29. package/src/hooks/useActiveElement.js +19 -0
  30. package/src/hooks/useColorPalette.ts +83 -0
  31. package/src/hooks/useReduceData.ts +43 -0
  32. package/src/index.html +49 -13
  33. package/src/index.tsx +6 -2
  34. package/src/scss/editor-panel.scss +12 -4
  35. package/src/scss/main.scss +112 -3
  36. package/LICENSE +0 -201
@@ -3,7 +3,8 @@ import React, {
3
3
  useEffect,
4
4
  useState,
5
5
  useMemo,
6
- memo } from 'react';
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, filteredData:data, config, colorScale, parseDate, formatDate, formatNumber:numberFormatter } = useContext<any>(Context);
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 = memo(({ data }: any) => {
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
- if (navigator.msSaveBlob) {
37
- const dataBlob = new Blob([csvData], {type: "text/csv;charset=utf-8;"});
38
- navigator.msSaveBlob(dataBlob, fileName);
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.map((d) => {
74
+ data.forEach((d) => {
72
75
  const newCol = {
73
- Header: config.runtime.xAxis.type === 'date' ? formatDate(parseDate(d[config.runtime.originalXAxis.dataKey])) : d[config.runtime.originalXAxis.dataKey],
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
- () => config.visualizationType === 'Pie' ? [config.yAxis.dataKey] : config.runtime.seriesKeys,
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 className={tableExpanded ? 'data-table' : 'data-table cdcdataviz-sr-only'} hidden={!tableExpanded} {...getTableProps()}>
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 tabIndex="0" {...column.getHeaderProps(column.getSortByToggleProps())} className={column.isSorted ? column.isSortedDesc ? 'sort sort-desc' : 'sort sort-asc' : 'sort'} title={column.Header}>
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 tabIndex="0" {...cell.getCellProps()}>
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>