@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.
- package/dist/cdcchart.js +29981 -29995
- package/examples/feature/__data__/area-chart-date-apple.json +5122 -0
- package/examples/feature/__data__/city-temperature.json +2198 -0
- package/examples/feature/__data__/planet-example-data.json +1 -1
- package/examples/feature/area/area-chart-category.json +45 -45
- package/examples/feature/area/area-chart-date-apple.json +10376 -0
- package/examples/feature/area/area-chart-date-city-temperature.json +4528 -0
- package/examples/feature/area/area-chart-date.json +111 -3
- package/examples/feature/combo/right-issues.json +1 -1
- package/examples/feature/forecasting/combo-forecasting.json +72 -46
- package/examples/feature/forecasting/effective_reproduction.json +57 -8
- package/examples/feature/forecasting/forecasting.json +12 -3
- package/examples/feature/forest-plot/broken.json +700 -0
- package/examples/feature/forest-plot/data.csv +24 -0
- package/examples/feature/forest-plot/forest-plot.json +717 -0
- package/examples/feature/line/line-chart.json +11 -11
- package/examples/feature/pie/planet-pie-example-config.json +1 -1
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +167 -20
- package/examples/private/confidence_interval_test.json +248 -0
- package/examples/private/tooltip-issue.json +45275 -0
- package/index.html +13 -11
- package/package.json +4 -3
- package/src/CdcChart.jsx +78 -27
- package/src/components/AreaChart.jsx +65 -151
- package/src/components/BarChart.Horizontal.jsx +251 -0
- package/src/components/BarChart.StackedHorizontal.jsx +118 -0
- package/src/components/BarChart.StackedVertical.jsx +93 -0
- package/src/components/BarChart.Vertical.jsx +204 -0
- package/src/components/BarChart.jsx +17 -667
- package/src/components/BarChartType.jsx +15 -0
- package/src/components/BrushHandle.jsx +17 -0
- package/src/components/DataTable.jsx +67 -22
- package/src/components/EditorPanel.jsx +426 -358
- package/src/components/Forecasting.jsx +23 -86
- package/src/components/ForestPlot.jsx +191 -0
- package/src/components/ForestPlotSettings.jsx +508 -0
- package/src/components/Legend.jsx +10 -8
- package/src/components/LineChart.jsx +31 -6
- package/src/components/LinearChart.jsx +317 -230
- package/src/components/Series.jsx +40 -4
- package/src/data/initial-state.js +50 -3
- package/src/hooks/useBarChart.js +186 -0
- package/src/hooks/useEditorPermissions.js +218 -0
- package/src/hooks/useMinMax.js +18 -5
- package/src/hooks/useRightAxis.js +2 -1
- package/src/hooks/useScales.js +45 -2
- package/src/hooks/useTooltip.jsx +407 -0
- 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
|
|
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
|
|
268
|
-
{...(column.isSorted
|
|
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
|
-
{
|
|
271
|
-
<
|
|
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>
|