@cdc/chart 4.23.7 → 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/LICENSE +201 -0
- package/dist/cdcchart.js +27964 -26942
- package/examples/feature/__data__/area-chart-date-apple.json +5122 -0
- package/examples/feature/__data__/city-temperature.json +2198 -0
- 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/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/pie/planet-pie-example-config.json +1 -1
- 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 +24 -14
- package/src/components/AreaChart.jsx +84 -59
- 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 +14 -674
- package/src/components/BarChartType.jsx +15 -0
- package/src/components/BrushHandle.jsx +17 -0
- package/src/components/DataTable.jsx +63 -21
- package/src/components/EditorPanel.jsx +351 -303
- package/src/components/ForestPlot.jsx +191 -0
- package/src/components/ForestPlotSettings.jsx +508 -0
- package/src/components/LineChart.jsx +2 -2
- package/src/components/LinearChart.jsx +115 -310
- package/src/data/initial-state.js +43 -0
- package/src/hooks/useBarChart.js +186 -0
- package/src/hooks/useEditorPermissions.js +218 -0
- package/src/hooks/useMinMax.js +15 -3
- package/src/hooks/useScales.js +45 -2
- package/src/hooks/useTooltip.jsx +407 -0
- package/src/scss/main.scss +7 -0
|
@@ -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,6 +7,7 @@ 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
|
|
|
@@ -19,6 +20,7 @@ export default function DataTable() {
|
|
|
19
20
|
const [tableExpanded, setTableExpanded] = useState(config.table.expanded)
|
|
20
21
|
const [accessibilityLabel, setAccessibilityLabel] = useState('')
|
|
21
22
|
const isLegendBottom = ['sm', 'xs', 'xxs'].includes(currentViewport)
|
|
23
|
+
const transform = new DataTransform()
|
|
22
24
|
|
|
23
25
|
const DownloadButton = ({ data }, type) => {
|
|
24
26
|
const fileName = `${config.title.substring(0, 50)}.csv`
|
|
@@ -34,19 +36,13 @@ export default function DataTable() {
|
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
|
|
39
|
+
// - trying to eliminate console error that occurs if formatted with prettier
|
|
40
|
+
// prettier-ignore
|
|
37
41
|
switch (type) {
|
|
38
42
|
case 'download':
|
|
39
|
-
return (
|
|
40
|
-
<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`}>
|
|
41
|
-
Download Data (CSV)
|
|
42
|
-
</a>
|
|
43
|
-
)
|
|
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>)
|
|
44
44
|
default:
|
|
45
|
-
return (
|
|
46
|
-
<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`}>
|
|
47
|
-
Download Data (CSV)
|
|
48
|
-
</a>
|
|
49
|
-
)
|
|
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>)
|
|
50
46
|
}
|
|
51
47
|
}
|
|
52
48
|
|
|
@@ -93,7 +89,7 @@ export default function DataTable() {
|
|
|
93
89
|
]
|
|
94
90
|
: [
|
|
95
91
|
{
|
|
96
|
-
Header: '',
|
|
92
|
+
Header: ' ',
|
|
97
93
|
Cell: ({ row }) => {
|
|
98
94
|
const getSeriesLabel = () => {
|
|
99
95
|
let userUpdatedSeriesName = config.series.filter(series => series.dataKey === row.original)?.[0]?.name
|
|
@@ -121,7 +117,9 @@ export default function DataTable() {
|
|
|
121
117
|
</>
|
|
122
118
|
)
|
|
123
119
|
},
|
|
124
|
-
id: 'series-label'
|
|
120
|
+
id: 'series-label',
|
|
121
|
+
sortType: 'custom',
|
|
122
|
+
canSort: true
|
|
125
123
|
}
|
|
126
124
|
]
|
|
127
125
|
if (config.visualizationType !== 'Box Plot') {
|
|
@@ -151,6 +149,7 @@ export default function DataTable() {
|
|
|
151
149
|
return <>{numberFormatter(d[row.original], resolvedAxis)}</>
|
|
152
150
|
},
|
|
153
151
|
id: `${d[config.runtime.originalXAxis.dataKey]}--${index}`,
|
|
152
|
+
sortType: 'custom',
|
|
154
153
|
canSort: true
|
|
155
154
|
}
|
|
156
155
|
|
|
@@ -222,7 +221,52 @@ export default function DataTable() {
|
|
|
222
221
|
}),
|
|
223
222
|
[]
|
|
224
223
|
)
|
|
225
|
-
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
|
+
)
|
|
226
270
|
|
|
227
271
|
// sort continuous x axis scaling for data tables, ie. xAxis should read 1,2,3,4,5
|
|
228
272
|
if (config.xAxis.type === 'continuous' && headerGroups) {
|
|
@@ -236,7 +280,7 @@ export default function DataTable() {
|
|
|
236
280
|
{config.table.download && <DownloadButton data={rawData} type='link' />}
|
|
237
281
|
</MediaControls.Section>
|
|
238
282
|
|
|
239
|
-
<section style={{ marginTop: !isLegendBottom ? config.dynamicMarginTop + 'px' : '0px' }} 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}>
|
|
240
284
|
<div
|
|
241
285
|
role='button'
|
|
242
286
|
className={tableExpanded ? 'data-table-heading' : 'collapsed data-table-heading'}
|
|
@@ -259,6 +303,7 @@ export default function DataTable() {
|
|
|
259
303
|
<thead>
|
|
260
304
|
{headerGroups.map((headerGroup, index) => (
|
|
261
305
|
<tr {...headerGroup.getHeaderGroupProps()} key={`headerGroups--${index}`}>
|
|
306
|
+
{' '}
|
|
262
307
|
{headerGroup.headers.map((column, index) => (
|
|
263
308
|
<th
|
|
264
309
|
tabIndex='0'
|
|
@@ -267,14 +312,11 @@ export default function DataTable() {
|
|
|
267
312
|
role='columnheader'
|
|
268
313
|
scope='col'
|
|
269
314
|
{...column.getHeaderProps(column.getSortByToggleProps())}
|
|
270
|
-
className={column.isSorted
|
|
271
|
-
{...(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' })}
|
|
272
317
|
>
|
|
273
|
-
{
|
|
274
|
-
<
|
|
275
|
-
<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>
|
|
276
|
-
</button>
|
|
277
|
-
<div {...column.getResizerProps()} className='resizer' />
|
|
318
|
+
{column.render('Header')}
|
|
319
|
+
{column.isSorted && <span className={'sort-icon'}>{column.isSortedDesc ? downIcon : upIcon}</span>}
|
|
278
320
|
</th>
|
|
279
321
|
))}
|
|
280
322
|
</tr>
|