@cdc/chart 4.23.6 → 4.23.8

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 (48) hide show
  1. package/dist/cdcchart.js +29981 -29995
  2. package/examples/feature/__data__/area-chart-date-apple.json +5122 -0
  3. package/examples/feature/__data__/city-temperature.json +2198 -0
  4. package/examples/feature/__data__/planet-example-data.json +1 -1
  5. package/examples/feature/area/area-chart-category.json +45 -45
  6. package/examples/feature/area/area-chart-date-apple.json +10376 -0
  7. package/examples/feature/area/area-chart-date-city-temperature.json +4528 -0
  8. package/examples/feature/area/area-chart-date.json +111 -3
  9. package/examples/feature/combo/right-issues.json +1 -1
  10. package/examples/feature/forecasting/combo-forecasting.json +72 -46
  11. package/examples/feature/forecasting/effective_reproduction.json +57 -8
  12. package/examples/feature/forecasting/forecasting.json +12 -3
  13. package/examples/feature/forest-plot/broken.json +700 -0
  14. package/examples/feature/forest-plot/data.csv +24 -0
  15. package/examples/feature/forest-plot/forest-plot.json +717 -0
  16. package/examples/feature/line/line-chart.json +11 -11
  17. package/examples/feature/pie/planet-pie-example-config.json +1 -1
  18. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +167 -20
  19. package/examples/private/confidence_interval_test.json +248 -0
  20. package/examples/private/tooltip-issue.json +45275 -0
  21. package/index.html +13 -11
  22. package/package.json +4 -3
  23. package/src/CdcChart.jsx +78 -27
  24. package/src/components/AreaChart.jsx +65 -151
  25. package/src/components/BarChart.Horizontal.jsx +251 -0
  26. package/src/components/BarChart.StackedHorizontal.jsx +118 -0
  27. package/src/components/BarChart.StackedVertical.jsx +93 -0
  28. package/src/components/BarChart.Vertical.jsx +204 -0
  29. package/src/components/BarChart.jsx +17 -667
  30. package/src/components/BarChartType.jsx +15 -0
  31. package/src/components/BrushHandle.jsx +17 -0
  32. package/src/components/DataTable.jsx +67 -22
  33. package/src/components/EditorPanel.jsx +426 -358
  34. package/src/components/Forecasting.jsx +23 -86
  35. package/src/components/ForestPlot.jsx +191 -0
  36. package/src/components/ForestPlotSettings.jsx +508 -0
  37. package/src/components/Legend.jsx +10 -8
  38. package/src/components/LineChart.jsx +31 -6
  39. package/src/components/LinearChart.jsx +317 -230
  40. package/src/components/Series.jsx +40 -4
  41. package/src/data/initial-state.js +50 -3
  42. package/src/hooks/useBarChart.js +186 -0
  43. package/src/hooks/useEditorPermissions.js +218 -0
  44. package/src/hooks/useMinMax.js +18 -5
  45. package/src/hooks/useRightAxis.js +2 -1
  46. package/src/hooks/useScales.js +45 -2
  47. package/src/hooks/useTooltip.jsx +407 -0
  48. package/src/scss/main.scss +11 -17
@@ -0,0 +1,15 @@
1
+ import React from 'react'
2
+
3
+ import BarChartStackedVertical from './BarChart.StackedVertical'
4
+ import BarChartStackedHorizontal from './BarChart.StackedHorizontal'
5
+ import BarChartVertical from './BarChart.Vertical'
6
+ import BarChartHorizontal from './BarChart.Horizontal'
7
+
8
+ const BarChartType = {
9
+ Vertical: BarChartVertical,
10
+ Horizontal: BarChartHorizontal,
11
+ StackedVertical: BarChartStackedVertical,
12
+ StackedHorizontal: BarChartStackedHorizontal
13
+ }
14
+
15
+ export default BarChartType
@@ -0,0 +1,17 @@
1
+ import { Group } from '@visx/group'
2
+
3
+ const BrushHandle = props => {
4
+ const { x, height, isBrushActive } = props
5
+ const pathWidth = 8
6
+ const pathHeight = 15
7
+ if (!isBrushActive) {
8
+ return null
9
+ }
10
+ return (
11
+ <Group left={x + pathWidth / 2} top={(height - pathHeight) / 2}>
12
+ <path fill='#f2f2f2' d='M -4.5 0.5 L 3.5 0.5 L 3.5 15.5 L -4.5 15.5 L -4.5 0.5 M -1.5 4 L -1.5 12 M 0.5 4 L 0.5 12' stroke='#999999' strokeWidth='1' style={{ cursor: 'ew-resize' }} />
13
+ </Group>
14
+ )
15
+ }
16
+
17
+ export default BrushHandle
@@ -7,17 +7,20 @@ import { colorPalettesChart } from '@cdc/core/data/colorPalettes'
7
7
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
8
8
  import LegendCircle from '@cdc/core/components/LegendCircle'
9
9
  import Icon from '@cdc/core/components/ui/Icon'
10
+ import { DataTransform } from '@cdc/core/helpers/DataTransform'
10
11
 
11
12
  import ConfigContext from '../ConfigContext'
12
13
 
13
14
  import MediaControls from '@cdc/core/components/MediaControls'
14
15
 
15
16
  export default function DataTable() {
16
- const { rawData, tableData: data, config, colorScale, parseDate, formatDate, formatNumber: numberFormatter, colorPalettes } = useContext(ConfigContext)
17
+ const { rawData, tableData: data, config, colorScale, parseDate, formatDate, formatNumber: numberFormatter, colorPalettes, currentViewport } = useContext(ConfigContext)
17
18
 
18
19
  const section = config.orientation === 'horizontal' ? 'yAxis' : 'xAxis'
19
20
  const [tableExpanded, setTableExpanded] = useState(config.table.expanded)
20
21
  const [accessibilityLabel, setAccessibilityLabel] = useState('')
22
+ const isLegendBottom = ['sm', 'xs', 'xxs'].includes(currentViewport)
23
+ const transform = new DataTransform()
21
24
 
22
25
  const DownloadButton = ({ data }, type) => {
23
26
  const fileName = `${config.title.substring(0, 50)}.csv`
@@ -33,19 +36,13 @@ export default function DataTable() {
33
36
  }
34
37
  }
35
38
 
39
+ // - trying to eliminate console error that occurs if formatted with prettier
40
+ // prettier-ignore
36
41
  switch (type) {
37
42
  case 'download':
38
- return (
39
- <a download={fileName} onClick={saveBlob} href={`data:text/csv;base64,${Base64.encode(csvData)}`} aria-label='Download this data in a CSV file format.' className={`btn btn-download no-border margin-sm`}>
40
- Download Data (CSV)
41
- </a>
42
- )
43
+ return (<a download={fileName} onClick={saveBlob} href={`data:text/csv;base64,${Base64.encode(csvData)}`} aria-label='Download this data in a CSV file format.' className={`btn btn-download no-border margin-sm`}>Download Data (CSV)</a>)
43
44
  default:
44
- return (
45
- <a download={fileName} onClick={saveBlob} href={`data:text/csv;base64,${Base64.encode(csvData)}`} aria-label='Download this data in a CSV file format.' className={`no-border`}>
46
- Download Data (CSV)
47
- </a>
48
- )
45
+ return (<a download={fileName} onClick={saveBlob} href={`data:text/csv;base64,${Base64.encode(csvData)}`} aria-label='Download this data in a CSV file format.' className={`no-border`}>Download Data (CSV)</a>)
49
46
  }
50
47
  }
51
48
 
@@ -92,7 +89,7 @@ export default function DataTable() {
92
89
  ]
93
90
  : [
94
91
  {
95
- Header: '',
92
+ Header: ' ',
96
93
  Cell: ({ row }) => {
97
94
  const getSeriesLabel = () => {
98
95
  let userUpdatedSeriesName = config.series.filter(series => series.dataKey === row.original)?.[0]?.name
@@ -120,7 +117,9 @@ export default function DataTable() {
120
117
  </>
121
118
  )
122
119
  },
123
- id: 'series-label'
120
+ id: 'series-label',
121
+ sortType: 'custom',
122
+ canSort: true
124
123
  }
125
124
  ]
126
125
  if (config.visualizationType !== 'Box Plot') {
@@ -145,9 +144,12 @@ export default function DataTable() {
145
144
  if (rightSeriesItem.dataKey === row.original) resolvedAxis = 'right'
146
145
  })
147
146
 
147
+ if (config.visualizationType !== 'Combo') resolvedAxis = 'left'
148
+
148
149
  return <>{numberFormatter(d[row.original], resolvedAxis)}</>
149
150
  },
150
151
  id: `${d[config.runtime.originalXAxis.dataKey]}--${index}`,
152
+ sortType: 'custom',
151
153
  canSort: true
152
154
  }
153
155
 
@@ -219,7 +221,52 @@ export default function DataTable() {
219
221
  }),
220
222
  []
221
223
  )
222
- const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable({ columns: tableColumns, data: tableData, defaultColumn }, useSortBy, useBlockLayout, useResizeColumns)
224
+ const upIcon = (
225
+ <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 5'>
226
+ <path d='M0 5l5-5 5 5z' />
227
+ </svg>
228
+ )
229
+ const downIcon = (
230
+ <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 5'>
231
+ <path d='M0 0l5 5 5-5z' />
232
+ </svg>
233
+ )
234
+
235
+ const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable(
236
+ {
237
+ columns: tableColumns,
238
+ data: tableData,
239
+ defaultColumn,
240
+ disableSortRemove: true, // otherwise 3rd click on header removes sorting entirely
241
+ sortTypes: {
242
+ custom: (rowA, rowB, columnId) => {
243
+ // rowA.original - is the row data field name to access the value
244
+ // columnId = the column indicator
245
+ let dataKey = config.xAxis.dataKey
246
+ let colObj = config.data.filter(obj => {
247
+ return obj[dataKey] === columnId.split('--')[0] // have to remove index
248
+ })
249
+ if (colObj === undefined || colObj[0] === undefined) {
250
+ return -1
251
+ }
252
+ // NOW we can get the sort values
253
+ const a = transform.cleanDataPoint(colObj[0][rowA.original]) // issue was that a was UNDEFINED therefore it CANT SORT
254
+ const b = transform.cleanDataPoint(colObj[0][rowB.original])
255
+
256
+ if (a === undefined) {
257
+ return -1
258
+ }
259
+ if (!isNaN(Number(a)) && !isNaN(Number(b))) {
260
+ return Number(a) - Number(b)
261
+ }
262
+ return a.localeCompare(b)
263
+ }
264
+ }
265
+ },
266
+ useSortBy,
267
+ useBlockLayout,
268
+ useResizeColumns
269
+ )
223
270
 
224
271
  // sort continuous x axis scaling for data tables, ie. xAxis should read 1,2,3,4,5
225
272
  if (config.xAxis.type === 'continuous' && headerGroups) {
@@ -233,7 +280,7 @@ export default function DataTable() {
233
280
  {config.table.download && <DownloadButton data={rawData} type='link' />}
234
281
  </MediaControls.Section>
235
282
 
236
- <section id={config?.title ? `dataTableSection__${config?.title.replace(/\s/g, '')}` : `dataTableSection`} className={`data-table-container`} aria-label={accessibilityLabel}>
283
+ <section style={{ marginTop: !isLegendBottom ? config.dynamicMarginTop / 4 + 'px' : '0px' }} id={config?.title ? `dataTableSection__${config?.title.replace(/\s/g, '')}` : `dataTableSection`} className={`data-table-container`} aria-label={accessibilityLabel}>
237
284
  <div
238
285
  role='button'
239
286
  className={tableExpanded ? 'data-table-heading' : 'collapsed data-table-heading'}
@@ -256,6 +303,7 @@ export default function DataTable() {
256
303
  <thead>
257
304
  {headerGroups.map((headerGroup, index) => (
258
305
  <tr {...headerGroup.getHeaderGroupProps()} key={`headerGroups--${index}`}>
306
+ {' '}
259
307
  {headerGroup.headers.map((column, index) => (
260
308
  <th
261
309
  tabIndex='0'
@@ -264,14 +312,11 @@ export default function DataTable() {
264
312
  role='columnheader'
265
313
  scope='col'
266
314
  {...column.getHeaderProps(column.getSortByToggleProps())}
267
- className={column.isSorted ? (column.isSortedDesc ? 'sort sort-desc' : 'sort sort-asc') : 'sort'}
268
- {...(column.isSorted ? (column.isSortedDesc ? { 'aria-sort': 'descending' } : { 'aria-sort': 'ascending' }) : null)}
315
+ className={column.isSorted && column.isSortedDesc ? 'sort sort-desc' : 'sort sort-asc'}
316
+ {...(column.isSorted && column.isSortedDesc ? { 'aria-sort': 'descending' } : { 'aria-sort': 'ascending' })}
269
317
  >
270
- {index === 0 ? (config.table.indexLabel ? config.table.indexLabel : column.render('Header')) : column.render('Header')}
271
- <button>
272
- <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>
273
- </button>
274
- <div {...column.getResizerProps()} className='resizer' />
318
+ {column.render('Header')}
319
+ {column.isSorted && <span className={'sort-icon'}>{column.isSortedDesc ? downIcon : upIcon}</span>}
275
320
  </th>
276
321
  ))}
277
322
  </tr>