@cdc/core 4.24.9 → 4.24.11
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/assets/icon-combo-chart.svg +1 -0
- package/assets/icon-epi-chart.svg +27 -0
- package/components/AdvancedEditor/AdvancedEditor.tsx +17 -13
- package/components/Alert/components/Alert.tsx +34 -8
- package/components/BlurStrokeText.tsx +44 -0
- package/components/DataTable/DataTable.tsx +62 -36
- package/components/DataTable/DataTableStandAlone.tsx +37 -6
- package/components/DataTable/components/ChartHeader.tsx +31 -26
- package/components/DataTable/components/MapHeader.tsx +19 -10
- package/components/DataTable/components/SortIcon/index.tsx +25 -0
- package/components/DataTable/components/SortIcon/sort-icon.css +21 -0
- package/{styles/_data-table.scss → components/DataTable/data-table.css} +250 -298
- package/components/DataTable/helpers/boxplotCellMatrix.tsx +14 -13
- package/components/DataTable/helpers/customSort.ts +11 -15
- package/components/DataTable/helpers/getChartCellValue.ts +23 -5
- package/components/DataTable/helpers/getDataSeriesColumns.ts +5 -1
- package/components/DataTable/helpers/getNewSortBy.ts +35 -0
- package/components/DataTable/helpers/tests/customSort.test.ts +52 -0
- package/components/DataTable/helpers/tests/getNewSortBy.test.ts +26 -0
- package/components/EditorPanel/ColumnsEditor.tsx +81 -36
- package/components/EditorPanel/DataTableEditor.tsx +149 -43
- package/components/EditorPanel/FieldSetWrapper.tsx +2 -2
- package/components/EditorPanel/Inputs.tsx +68 -20
- package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +25 -7
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +30 -55
- package/components/{Filters.tsx → Filters/Filters.tsx} +60 -43
- package/components/Filters/helpers/applyQueuedActive.ts +12 -0
- package/components/Filters/helpers/getNestedOptions.ts +29 -0
- package/components/Filters/helpers/handleSorting.ts +18 -0
- package/components/Filters/helpers/tests/applyQueuedActive.test.ts +49 -0
- package/components/Filters/helpers/tests/getNestedOptions.test.ts +93 -0
- package/components/Filters/helpers/tests/handleSorting.test.ts +68 -0
- package/components/Filters/index.ts +5 -0
- package/components/Layout/components/Sidebar/components/sidebar.styles.scss +1 -7
- package/components/Layout/components/Visualization/visualizations.scss +1 -1
- package/components/Legend/Legend.Gradient.tsx +44 -36
- package/components/Loader/Loader.tsx +33 -0
- package/components/Loader/index.ts +1 -0
- package/components/Loader/loader.styles.css +13 -0
- package/components/MultiSelect/MultiSelect.tsx +85 -62
- package/components/MultiSelect/multiselect.styles.css +10 -7
- package/components/NestedDropdown/NestedDropdown.tsx +118 -56
- package/components/NestedDropdown/nestedDropdownHelpers.ts +34 -0
- package/components/NestedDropdown/nesteddropdown.styles.css +22 -13
- package/components/NestedDropdown/tests/nestedDropdownHelpers.test.ts +58 -0
- package/components/Table/Table.tsx +102 -34
- package/components/Table/components/GroupRow.tsx +1 -1
- package/components/_stories/BlurStrokeTest.stories.tsx +27 -0
- package/components/_stories/DataTable.stories.tsx +14 -0
- package/components/_stories/Filters.stories.tsx +57 -0
- package/components/_stories/NestedDropdown.stories.tsx +22 -46
- package/components/_stories/_mocks/DataTable/no-data.json +108 -0
- package/components/_stories/_mocks/nested-dropdown.json +30 -0
- package/components/_stories/styles.scss +0 -1
- package/components/ui/Icon.tsx +19 -6
- package/components/ui/{Tooltip.jsx → Tooltip.tsx} +38 -14
- package/data/colorPalettes.js +107 -10
- package/dist/cove-main.css +6080 -0
- package/dist/cove-main.css.map +1 -0
- package/helpers/DataTransform.ts +2 -1
- package/helpers/addValuesToFilters.ts +8 -3
- package/helpers/cove/{number.js → number.ts} +62 -27
- package/helpers/coveUpdateWorker.ts +6 -7
- package/helpers/fetchRemoteData.js +32 -37
- package/helpers/formatConfigBeforeSave.ts +17 -1
- package/helpers/gatherQueryParams.ts +12 -2
- package/helpers/pivotData.ts +52 -11
- package/helpers/queryStringUtils.ts +6 -0
- package/helpers/tests/gatherQueryParams.test.ts +34 -0
- package/helpers/tests/pivotData.test.ts +50 -0
- package/helpers/useDataVizClasses.ts +42 -20
- package/helpers/ver/4.24.10.ts +47 -0
- package/helpers/ver/4.24.9.ts +0 -3
- package/helpers/ver/tests/4.24.10.test.ts +45 -0
- package/helpers/viewports.ts +9 -0
- package/package.json +7 -3
- package/styles/_button-section.scss +5 -1
- package/styles/_global-variables.scss +20 -2
- package/styles/_global.scss +22 -30
- package/styles/_reset.scss +2 -26
- package/styles/base.scss +0 -1
- package/styles/cove-main.scss +6 -0
- package/styles/filters.scss +6 -26
- package/styles/v2/base/_reset.scss +0 -7
- package/styles/v2/components/editor.scss +0 -4
- package/styles/v2/components/icon.scss +1 -1
- package/styles/v2/components/ui/tooltip.scss +42 -40
- package/styles/v2/layout/_component.scss +0 -6
- package/styles/v2/layout/index.scss +0 -1
- package/types/Axis.ts +4 -0
- package/types/BoxPlot.ts +5 -3
- package/types/Color.ts +1 -1
- package/types/General.ts +1 -0
- package/types/Legend.ts +1 -2
- package/types/MarkupInclude.ts +1 -0
- package/types/Runtime.ts +3 -1
- package/types/Series.ts +8 -1
- package/types/Table.ts +3 -2
- package/types/Visualization.ts +19 -8
- package/types/VizFilter.ts +2 -1
- package/components/DataTable/components/Icons.tsx +0 -10
- package/components/_stories/EditorPanel.stories.tsx +0 -54
- package/components/_stories/Layout.Debug.stories.tsx +0 -91
- package/components/ui/Select.jsx +0 -30
- package/helpers/getGradientLegendWidth.ts +0 -15
|
@@ -15,25 +15,56 @@ type StandAloneProps = {
|
|
|
15
15
|
updateConfig?: (Visualization) => void
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const DataTableStandAlone: React.FC<StandAloneProps> = ({
|
|
19
|
-
|
|
18
|
+
const DataTableStandAlone: React.FC<StandAloneProps> = ({
|
|
19
|
+
visualizationKey,
|
|
20
|
+
config,
|
|
21
|
+
updateConfig,
|
|
22
|
+
viewport,
|
|
23
|
+
isEditor
|
|
24
|
+
}) => {
|
|
25
|
+
const [filteredData, setFilteredData] = useState<Record<string, any>[]>(
|
|
26
|
+
filterVizData(config.filters, config.formattedData || config.data)
|
|
27
|
+
)
|
|
20
28
|
|
|
21
29
|
useEffect(() => {
|
|
22
30
|
// when using editor changes to filter should update the data
|
|
23
|
-
setFilteredData(
|
|
31
|
+
setFilteredData(
|
|
32
|
+
filterVizData(config.filters, config?.formattedData?.length > 0 ? config.formattedData : config.data)
|
|
33
|
+
)
|
|
24
34
|
}, [config.filters])
|
|
25
35
|
|
|
26
36
|
if (isEditor)
|
|
27
37
|
return (
|
|
28
|
-
<EditorWrapper
|
|
38
|
+
<EditorWrapper
|
|
39
|
+
component={DataTableStandAlone}
|
|
40
|
+
visualizationKey={visualizationKey}
|
|
41
|
+
visualizationConfig={config}
|
|
42
|
+
updateConfig={updateConfig}
|
|
43
|
+
type={'Table'}
|
|
44
|
+
viewport={viewport}
|
|
45
|
+
>
|
|
29
46
|
<DataTableEditorPanel key={visualizationKey} config={config} updateConfig={updateConfig} />
|
|
30
47
|
</EditorWrapper>
|
|
31
48
|
)
|
|
32
49
|
|
|
33
50
|
return (
|
|
34
51
|
<>
|
|
35
|
-
<Filters
|
|
36
|
-
|
|
52
|
+
<Filters
|
|
53
|
+
config={config}
|
|
54
|
+
setConfig={updateConfig}
|
|
55
|
+
setFilteredData={setFilteredData}
|
|
56
|
+
filteredData={filteredData}
|
|
57
|
+
excludedData={config.formattedData}
|
|
58
|
+
/>
|
|
59
|
+
<DataTable
|
|
60
|
+
expandDataTable={config.table.expanded}
|
|
61
|
+
config={config}
|
|
62
|
+
rawData={config.data}
|
|
63
|
+
runtimeData={filteredData}
|
|
64
|
+
tabbingId={visualizationKey}
|
|
65
|
+
tableTitle={config.table.label}
|
|
66
|
+
viewport={viewport || 'lg'}
|
|
67
|
+
/>
|
|
37
68
|
</>
|
|
38
69
|
)
|
|
39
70
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { getChartCellValue } from '../helpers/getChartCellValue'
|
|
2
2
|
import { getSeriesName } from '../helpers/getSeriesName'
|
|
3
3
|
import { getDataSeriesColumns } from '../helpers/getDataSeriesColumns'
|
|
4
|
-
import { DownIcon, UpIcon } from './Icons'
|
|
5
4
|
import ScreenReaderText from '@cdc/core/components/elements/ScreenReaderText'
|
|
5
|
+
import { SortIcon } from './SortIcon'
|
|
6
|
+
import { getNewSortBy } from '../helpers/getNewSortBy'
|
|
6
7
|
|
|
7
8
|
type ChartHeaderProps = { data; isVertical; config; setSortBy; sortBy; hasRowType? }
|
|
8
9
|
|
|
@@ -19,17 +20,6 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
const handleHeaderClasses = (sortBy, text) => {
|
|
23
|
-
let classes = ['sort']
|
|
24
|
-
if (sortBy.column === text && sortBy.asc) {
|
|
25
|
-
classes.push('sort-asc')
|
|
26
|
-
}
|
|
27
|
-
if (sortBy.column === text && sortBy.desc) {
|
|
28
|
-
classes.push('sort-desc')
|
|
29
|
-
}
|
|
30
|
-
return classes.join(' ')
|
|
31
|
-
}
|
|
32
|
-
|
|
33
23
|
const ScreenReaderSortByText = ({ text, config, sortBy }) => {
|
|
34
24
|
const notApplicableText = 'Not Applicable'
|
|
35
25
|
let columnHeaderText = `${text} `
|
|
@@ -47,13 +37,19 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
47
37
|
|
|
48
38
|
if (columnHeaderText === notApplicableText) return
|
|
49
39
|
|
|
50
|
-
return
|
|
40
|
+
return (
|
|
41
|
+
<span className='cdcdataviz-sr-only'>{`Press command, modifier, or enter key to sort by ${columnHeaderText} in ${
|
|
42
|
+
sortBy.column !== columnHeaderText ? 'ascending' : sortBy.column === 'desc' ? 'descending' : 'ascending'
|
|
43
|
+
} order`}</span>
|
|
44
|
+
)
|
|
51
45
|
}
|
|
52
46
|
|
|
53
47
|
const ColumnHeadingText = ({ column, text, config }) => {
|
|
48
|
+
if (text === 'pivotColumn') return ''
|
|
54
49
|
let notApplicableText = 'Not Applicable'
|
|
55
50
|
if (text === '__series__' && config.table.indexLabel) return `${config.table.indexLabel} `
|
|
56
|
-
if (text === '__series__' && !config.table.indexLabel)
|
|
51
|
+
if (text === '__series__' && !config.table.indexLabel)
|
|
52
|
+
return <ScreenReaderText as='span'>{notApplicableText}</ScreenReaderText>
|
|
57
53
|
return text
|
|
58
54
|
}
|
|
59
55
|
|
|
@@ -71,7 +67,8 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
71
67
|
<tr>
|
|
72
68
|
{dataSeriesColumns.map((column, index) => {
|
|
73
69
|
const text = getSeriesName(column, config)
|
|
74
|
-
|
|
70
|
+
const newSortBy = getNewSortBy(sortBy, column, index)
|
|
71
|
+
const sortByAsc = sortBy.column === column ? sortBy.asc : undefined
|
|
75
72
|
return (
|
|
76
73
|
<th
|
|
77
74
|
style={{ minWidth: (config.table.cellMinWidth || 0) + 'px' }}
|
|
@@ -81,19 +78,22 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
81
78
|
scope='col'
|
|
82
79
|
onClick={() => {
|
|
83
80
|
if (hasRowType) return
|
|
84
|
-
setSortBy(
|
|
81
|
+
setSortBy(newSortBy)
|
|
85
82
|
}}
|
|
86
83
|
onKeyDown={e => {
|
|
87
84
|
if (hasRowType) return
|
|
88
85
|
if (e.keyCode === 13) {
|
|
89
|
-
setSortBy(
|
|
86
|
+
setSortBy(newSortBy)
|
|
90
87
|
}
|
|
91
88
|
}}
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
{...(sortBy.column === column
|
|
90
|
+
? sortBy.asc
|
|
91
|
+
? { 'aria-sort': 'ascending' }
|
|
92
|
+
: { 'aria-sort': 'descending' }
|
|
93
|
+
: null)}
|
|
94
94
|
>
|
|
95
95
|
<ColumnHeadingText text={text} column={column} config={config} />
|
|
96
|
-
{column === sortBy.column && <
|
|
96
|
+
{column === sortBy.column && !hasRowType && <SortIcon ascending={sortByAsc} />}
|
|
97
97
|
<ScreenReaderSortByText sortBy={sortBy} config={config} text={text} />
|
|
98
98
|
</th>
|
|
99
99
|
)
|
|
@@ -107,7 +107,8 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
107
107
|
{['__series__', ...Object.keys(data)].slice(sliceVal).map((row, index) => {
|
|
108
108
|
let column = config.xAxis?.dataKey
|
|
109
109
|
let text = row !== '__series__' ? getChartCellValue(row, column, config, data) : '__series__'
|
|
110
|
-
|
|
110
|
+
const newSortBy = getNewSortBy(sortBy, column, index)
|
|
111
|
+
const sortByAsc = sortBy.colIndex === index ? sortBy.asc : undefined
|
|
111
112
|
return (
|
|
112
113
|
<th
|
|
113
114
|
style={{ minWidth: (config.table.cellMinWidth || 0) + 'px' }}
|
|
@@ -116,18 +117,22 @@ const ChartHeader = ({ data, isVertical, config, setSortBy, sortBy, hasRowType }
|
|
|
116
117
|
role='columnheader'
|
|
117
118
|
scope='col'
|
|
118
119
|
onClick={() => {
|
|
119
|
-
setSortBy(
|
|
120
|
+
setSortBy(newSortBy)
|
|
120
121
|
}}
|
|
121
122
|
onKeyDown={e => {
|
|
122
123
|
if (e.keyCode === 13) {
|
|
123
|
-
setSortBy(
|
|
124
|
+
setSortBy(newSortBy)
|
|
124
125
|
}
|
|
125
126
|
}}
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
{...(sortBy.column === text
|
|
128
|
+
? sortBy.asc
|
|
129
|
+
? { 'aria-sort': 'ascending' }
|
|
130
|
+
: { 'aria-sort': 'descending' }
|
|
131
|
+
: null)}
|
|
128
132
|
>
|
|
129
133
|
<ColumnHeadingText text={text} column={column} config={config} />
|
|
130
|
-
{index === sortBy.colIndex && <
|
|
134
|
+
{index === sortBy.colIndex && !hasRowType && <SortIcon ascending={sortByAsc} />}
|
|
135
|
+
|
|
131
136
|
<ScreenReaderSortByText text={text} config={config} sortBy={sortBy} />
|
|
132
137
|
</th>
|
|
133
138
|
)
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { DataTableProps } from '../DataTable'
|
|
2
|
-
import { DownIcon, UpIcon } from './Icons'
|
|
3
2
|
import ScreenReaderText from '../../elements/ScreenReaderText'
|
|
3
|
+
import { SortIcon } from './SortIcon'
|
|
4
|
+
import { getNewSortBy } from '../helpers/getNewSortBy'
|
|
4
5
|
|
|
5
6
|
type MapHeaderProps = DataTableProps & {
|
|
6
7
|
sortBy: { column; asc }
|
|
7
8
|
setSortBy: Function
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
const ColumnHeadingText = ({
|
|
11
|
+
const ColumnHeadingText = ({ text, config }) => {
|
|
11
12
|
let notApplicableText = 'Not Applicable'
|
|
12
13
|
if (text === '__series__' && config.table.indexLabel) return `${config.table.indexLabel} `
|
|
13
|
-
if (text === '__series__' && !config.table.indexLabel)
|
|
14
|
+
if (text === '__series__' && !config.table.indexLabel)
|
|
15
|
+
return <ScreenReaderText as='span'>{notApplicableText}</ScreenReaderText>
|
|
14
16
|
return text
|
|
15
17
|
}
|
|
16
18
|
|
|
@@ -21,7 +23,7 @@ const MapHeader = ({ columns, config, indexTitle, sortBy, setSortBy }: MapHeader
|
|
|
21
23
|
.filter(column => columns[column].dataTable === true && columns[column].name)
|
|
22
24
|
.map((column, index) => {
|
|
23
25
|
let text
|
|
24
|
-
if (column !== 'geo') {
|
|
26
|
+
if (column && column !== 'geo') {
|
|
25
27
|
text = columns[column].label ? columns[column].label : columns[column].name
|
|
26
28
|
} else {
|
|
27
29
|
text = config.type === 'map' ? indexTitle : config.xAxis?.dataKey
|
|
@@ -29,7 +31,8 @@ const MapHeader = ({ columns, config, indexTitle, sortBy, setSortBy }: MapHeader
|
|
|
29
31
|
if (config.type === 'map' && (text === undefined || text === '')) {
|
|
30
32
|
text = 'Location'
|
|
31
33
|
}
|
|
32
|
-
|
|
34
|
+
const newSortBy = getNewSortBy(sortBy, column, index)
|
|
35
|
+
const sortByAsc = sortBy.column === column ? sortBy.asc : undefined
|
|
33
36
|
return (
|
|
34
37
|
<th
|
|
35
38
|
key={`col-header-${column}__${index}`}
|
|
@@ -38,19 +41,25 @@ const MapHeader = ({ columns, config, indexTitle, sortBy, setSortBy }: MapHeader
|
|
|
38
41
|
role='columnheader'
|
|
39
42
|
scope='col'
|
|
40
43
|
onClick={() => {
|
|
41
|
-
setSortBy(
|
|
44
|
+
setSortBy(newSortBy)
|
|
42
45
|
}}
|
|
43
46
|
onKeyDown={e => {
|
|
44
47
|
if (e.keyCode === 13) {
|
|
45
|
-
setSortBy(
|
|
48
|
+
setSortBy(newSortBy)
|
|
46
49
|
}
|
|
47
50
|
}}
|
|
48
51
|
className={sortBy.column === column ? (sortBy.asc ? 'sort sort-asc' : 'sort sort-desc') : 'sort'}
|
|
49
|
-
{...(sortBy.column === column
|
|
52
|
+
{...(sortBy.column === column
|
|
53
|
+
? sortBy.asc
|
|
54
|
+
? { 'aria-sort': 'ascending' }
|
|
55
|
+
: { 'aria-sort': 'descending' }
|
|
56
|
+
: null)}
|
|
50
57
|
>
|
|
51
58
|
<ColumnHeadingText text={text} config={config} column={column} />
|
|
52
|
-
|
|
53
|
-
<span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${
|
|
59
|
+
<SortIcon ascending={sortByAsc} />
|
|
60
|
+
<span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${
|
|
61
|
+
sortBy.column === column ? (!sortBy.asc ? 'descending' : 'ascending') : 'descending'
|
|
62
|
+
} order`}</span>
|
|
54
63
|
</th>
|
|
55
64
|
)
|
|
56
65
|
})}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import './sort-icon.css'
|
|
2
|
+
|
|
3
|
+
const UpIcon = ({ active }) => (
|
|
4
|
+
<svg className={'up' + (active ? ' active' : '')} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 5'>
|
|
5
|
+
<path d='M0 5l5-5 5 5z' />
|
|
6
|
+
</svg>
|
|
7
|
+
)
|
|
8
|
+
const DownIcon = ({ active }) => (
|
|
9
|
+
<svg className={'down' + (active ? ' active' : '')} xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 5'>
|
|
10
|
+
<path d='M0 0l5 5 5-5z' />
|
|
11
|
+
</svg>
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
type SortIconProps = {
|
|
15
|
+
ascending?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const SortIcon: React.FC<SortIconProps> = ({ ascending }) => {
|
|
19
|
+
return (
|
|
20
|
+
<span role='button' className={'sort-icon'}>
|
|
21
|
+
<UpIcon active={ascending === true} />
|
|
22
|
+
<DownIcon active={ascending === false} />
|
|
23
|
+
</span>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/* format the white triangle sort icon in data table headers */
|
|
2
|
+
.sort-icon {
|
|
3
|
+
fill: white;
|
|
4
|
+
position: relative;
|
|
5
|
+
margin: 0 0.5rem !important;
|
|
6
|
+
:is(svg) {
|
|
7
|
+
position: absolute;
|
|
8
|
+
fill: rgba(255, 255, 255, 0.5);
|
|
9
|
+
&.active {
|
|
10
|
+
fill: white;
|
|
11
|
+
}
|
|
12
|
+
width: 1rem;
|
|
13
|
+
height: 1rem;
|
|
14
|
+
}
|
|
15
|
+
.up {
|
|
16
|
+
bottom: 0.5rem;
|
|
17
|
+
}
|
|
18
|
+
.down {
|
|
19
|
+
top: 0.5rem;
|
|
20
|
+
}
|
|
21
|
+
}
|