@cdc/core 4.24.2 → 4.24.3
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/assets/icon-sankey.svg +1 -0
- package/assets/icon-table.svg +1 -0
- package/components/DataTable/DataTable.tsx +28 -10
- package/components/DataTable/DataTableStandAlone.tsx +15 -0
- package/components/DataTable/components/CellAnchor.tsx +3 -1
- package/components/DataTable/components/ChartHeader.tsx +48 -12
- package/components/DataTable/components/DataTableEditorPanel.tsx +42 -0
- package/components/DataTable/components/MapHeader.tsx +10 -5
- package/components/DataTable/helpers/customColumns.ts +4 -2
- package/components/DataTable/helpers/getChartCellValue.ts +4 -2
- package/components/DataTable/helpers/getDataSeriesColumns.ts +9 -1
- package/components/DataTable/types/TableConfig.ts +6 -7
- package/components/EditorPanel/ColumnsEditor.tsx +311 -0
- package/components/EditorPanel/DataTableEditor.tsx +27 -28
- package/components/Filters.jsx +27 -10
- package/components/MultiSelect/MultiSelect.tsx +39 -20
- package/components/MultiSelect/multiselect.styles.css +44 -27
- package/components/NestedDropdown/NestedDropdown.tsx +257 -0
- package/components/NestedDropdown/index.ts +1 -0
- package/components/NestedDropdown/nesteddropdown.styles.css +70 -0
- package/components/Table/Table.tsx +1 -1
- package/components/_stories/MultiSelect.stories.tsx +10 -1
- package/components/_stories/NestedDropdown.stories.tsx +58 -0
- package/components/createBarElement.jsx +117 -0
- package/components/elements/ScreenReaderText.tsx +8 -0
- package/components/elements/SkipTo.tsx +14 -0
- package/components/ui/Icon.tsx +5 -1
- package/components/ui/Title/Title.scss +7 -1
- package/components/ui/Title/index.tsx +3 -3
- package/components/ui/Tooltip.jsx +1 -1
- package/data/colorPalettes.js +1 -6
- package/helpers/cove/accessibility.ts +23 -0
- package/helpers/cove/date.ts +19 -0
- package/helpers/coveUpdateWorker.js +4 -0
- package/helpers/isDomainExternal.js +14 -0
- package/helpers/queryStringUtils.js +26 -0
- package/helpers/tests/updateFieldFactory.test.ts +89 -0
- package/helpers/updateFieldFactory.ts +38 -0
- package/helpers/useDataVizClasses.js +2 -2
- package/helpers/ver/4.24.3.js +25 -0
- package/package.json +4 -3
- package/styles/_data-table.scss +0 -13
- package/styles/base.scss +8 -0
- package/types/Axis.ts +1 -0
- package/types/BaseVisualizationType.ts +1 -0
- package/types/ConfidenceInterval.ts +1 -0
- package/types/Legend.ts +18 -0
- package/types/Region.ts +10 -0
- package/types/Runtime.ts +2 -0
- package/types/Table.ts +1 -1
- package/types/UpdateFieldFunc.ts +1 -1
- package/types/Visualization.ts +17 -5
- package/components/DataTable/components/SkipNav.tsx +0 -7
- package/helpers/cove/date.js +0 -9
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
position: relative;
|
|
3
3
|
padding: 0.6em 0.8em;
|
|
4
4
|
margin: 0;
|
|
5
|
-
color:
|
|
5
|
+
color: var(--white);
|
|
6
6
|
font-size: 1.1em;
|
|
7
7
|
|
|
8
|
+
h2 {
|
|
9
|
+
font-size: 1.1rem;
|
|
10
|
+
color: var(--white);
|
|
11
|
+
margin: 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
8
14
|
border-top-left-radius: 3px;
|
|
9
15
|
border-top-right-radius: 3px;
|
|
10
16
|
|
|
@@ -21,11 +21,11 @@ const Title = (props: HeaderProps) => {
|
|
|
21
21
|
return (
|
|
22
22
|
title &&
|
|
23
23
|
showTitle && (
|
|
24
|
-
<header className={updatedClasses.join(' ')}
|
|
24
|
+
<header className={updatedClasses.join(' ')} style={props.style}>
|
|
25
25
|
{superTitle && <sup>{parse(superTitle)}</sup>}
|
|
26
|
-
<
|
|
26
|
+
<h2>
|
|
27
27
|
{parse(title)} {isDashboard}
|
|
28
|
-
</
|
|
28
|
+
</h2>
|
|
29
29
|
</header>
|
|
30
30
|
)
|
|
31
31
|
)
|
|
@@ -26,7 +26,7 @@ const Tooltip = ({ place = 'top', trigger = 'hover', float = false, shadow = tru
|
|
|
26
26
|
|
|
27
27
|
return (
|
|
28
28
|
<span className='cove-tooltip' style={style} {...attributes}>
|
|
29
|
-
<a id={uid} className='cove-tooltip--target' data-tooltip-float={float} data-tooltip-place={place} data-tooltip-events={generateTriggerEvent()}>
|
|
29
|
+
<a id={uid} role='dialog' tabIndex={0} className='cove-tooltip--target' data-tooltip-float={float} data-tooltip-place={place} data-tooltip-events={generateTriggerEvent()}>
|
|
30
30
|
{tooltipTargetChildren ? tooltipTargetChildren.props.children : null}
|
|
31
31
|
</a>
|
|
32
32
|
{/* prettier-ignore */}
|
package/data/colorPalettes.js
CHANGED
|
@@ -11,17 +11,12 @@ const colorPalettesMap = {
|
|
|
11
11
|
greenblue: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#267BA6', '#0868ac', '#084081'],
|
|
12
12
|
yellowpurple: ['#FFF0B0', '#F5CC76', '#EDAE4B', '#E3683C', '#BF2A48', '#6D2059', '#8F0C4B', '#310958', '#0E0943'],
|
|
13
13
|
qualitative1: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#6a3d9a', '#cab2d6', '#E31A90', '#15017A', '#C2C0FC'],
|
|
14
|
-
|
|
15
14
|
qualitative2: ['#7fc97f', '#beaed4', '#ff9', '#386cb0', '#f0027f', '#bf5b17', '#666', '#fedab8'],
|
|
16
|
-
|
|
17
15
|
qualitative3: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d', '#666'],
|
|
18
|
-
|
|
19
16
|
qualitative4: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ff3', '#a65628', '#f781bf'],
|
|
20
|
-
|
|
17
|
+
// qualitative9 doesn't appear to be used anywhere...
|
|
21
18
|
qualitative9: ['#497d0c', '#84BC49', '#88c3ea', '#fcad90', '#f26b4f', '#c31b1f', '#c31b1f'],
|
|
22
|
-
|
|
23
19
|
'sequential-blue-2(MPX)': ['#F5FEFF', '#E1FBFF', '#C0F2FD', '#94E2ED', '#5EBAD4', '#3695BE', '#2273A0', '#0E5181', '#093460'],
|
|
24
|
-
|
|
25
20
|
'sequential-orange(MPX)': ['#FFFDF0', '#FFF7DC', '#FFE9C2', '#FFD097', '#F7A866', '#EB7723', '#B95117', '#853209', '#661F00']
|
|
26
21
|
}
|
|
27
22
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import chroma from 'chroma-js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* WCAG 2.0 Standard requires 4.5:1 contrast ratio
|
|
5
|
+
* https://www.w3.org/TR/WCAG20-TECHS/G18.html
|
|
6
|
+
*
|
|
7
|
+
* !important - DO NOT CHANGE.
|
|
8
|
+
*/
|
|
9
|
+
export const WCAG_CONTRAST_RATIO = 4.5
|
|
10
|
+
|
|
11
|
+
export const getContrastColor = (textColor: string, bgColor: string) => {
|
|
12
|
+
if (chroma.contrast(textColor, bgColor) < WCAG_CONTRAST_RATIO) {
|
|
13
|
+
switch (textColor) {
|
|
14
|
+
case '#FFF':
|
|
15
|
+
return '#000'
|
|
16
|
+
case '#000':
|
|
17
|
+
return '#FFF'
|
|
18
|
+
default:
|
|
19
|
+
return textColor
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return textColor
|
|
23
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { timeFormat, timeParse } from 'd3-time-format'
|
|
2
|
+
import { type Axis } from '@cdc/core/types/Axis'
|
|
3
|
+
|
|
4
|
+
export function formatDate(format = undefined, date) {
|
|
5
|
+
return timeFormat(format)(date)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function parseDate(format = undefined, dateString) {
|
|
9
|
+
return timeParse(format)(dateString) || new Date()
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const isDateScale = (axis: Axis) => {
|
|
13
|
+
try {
|
|
14
|
+
if (!axis) throw new Error('COVE: No axis passed to isDateScale')
|
|
15
|
+
return ['date', 'date-time'].includes(axis.type)
|
|
16
|
+
} catch ({ message }) {
|
|
17
|
+
console.warn(message) // eslint-disable-line
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// If config key names or position in the config have been changed with a version change,
|
|
2
2
|
// process those config entries and format old values into new
|
|
3
3
|
import update_4_23 from './ver/4.23'
|
|
4
|
+
import update_4_24_3 from './ver/4.24.3'
|
|
4
5
|
|
|
5
6
|
// 4.23.6 ------------------------------------------------------
|
|
6
7
|
const coveUpdateWorker = async config => {
|
|
@@ -9,6 +10,9 @@ const coveUpdateWorker = async config => {
|
|
|
9
10
|
// v4.23
|
|
10
11
|
genConfig = await update_4_23(genConfig)
|
|
11
12
|
|
|
13
|
+
// v4.24.3
|
|
14
|
+
genConfig = await update_4_24_3(genConfig)
|
|
15
|
+
|
|
12
16
|
return genConfig
|
|
13
17
|
}
|
|
14
18
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default function isDomainExternal(domain) {
|
|
2
|
+
const internalDomains = ['cdc.gov', 'localhost', 'facebook.com', 'twitter.com', 'linkedin.com', 'pinterest.com', 'youtube.com', 'youtube-nocookie.com', 'plus.google.com', 'instagram.com', 'flickr.com', 'tumblr.com', 'cdc.sharepoint.com', 'vaccines.gov', 'vacunas.gov']
|
|
3
|
+
|
|
4
|
+
const hostname = new URL(domain, window.location.origin).hostname
|
|
5
|
+
let external = true
|
|
6
|
+
|
|
7
|
+
internalDomains.forEach(internalDomain => {
|
|
8
|
+
if (hostname.indexOf(internalDomain) !== -1 && hostname.indexOf(internalDomain) === hostname.length - internalDomain.length) {
|
|
9
|
+
external = false
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
return external
|
|
14
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function getQueryStringFilterValue(filter) {
|
|
2
|
+
const urlParams = new URLSearchParams(window.location.search)
|
|
3
|
+
if(filter.setByQueryParameter){ // Only check the query string if the filter is supposed to be set by QS param
|
|
4
|
+
const filterValue = urlParams.get(filter.setByQueryParameter)
|
|
5
|
+
if(filterValue && filter.values){
|
|
6
|
+
for(let i = 0; i < filter.values.length; i++){
|
|
7
|
+
if(filter.values[i] && filter.values[i].toLowerCase() === filterValue.toLowerCase()){
|
|
8
|
+
return filter.values[i]
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getQueryParams(filter) {
|
|
16
|
+
const queryParams = {};
|
|
17
|
+
for (const [key, value] of (new URLSearchParams(window.location.search)).entries()) {
|
|
18
|
+
queryParams[key] = value
|
|
19
|
+
}
|
|
20
|
+
return queryParams;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function updateQueryString(queryParams) {
|
|
24
|
+
const updateUrl = `${window.location.origin}${window.location.pathname}?${Object.keys(queryParams).map(queryParam => `${queryParam}=${encodeURIComponent(queryParams[queryParam])}`).join('&')}`;
|
|
25
|
+
window.history.pushState({path: updateUrl}, '', updateUrl);
|
|
26
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { updateFieldFactory } from '../updateFieldFactory'
|
|
2
|
+
|
|
3
|
+
describe('updateFieldFactory', () => {
|
|
4
|
+
it('should update the top level field when section and subsection are null', () => {
|
|
5
|
+
const config = { filterColumn: 'oldValue', filterValue: 'oldValue' }
|
|
6
|
+
let updatedConfig = {}
|
|
7
|
+
const updateConfig = newConfig => {
|
|
8
|
+
updatedConfig = newConfig
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const updateField = updateFieldFactory(config, updateConfig)
|
|
12
|
+
updateField(null, null, 'filterColumn', 'newValue')
|
|
13
|
+
|
|
14
|
+
expect(updatedConfig).toEqual({ filterColumn: 'newValue', filterValue: '' })
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('should update the second level when section is not null and subsection is null', () => {
|
|
18
|
+
const config = { section: { filterColumn: 'oldValue', filterValue: 'oldValue' } }
|
|
19
|
+
let updatedConfig = {}
|
|
20
|
+
const updateConfig = newConfig => {
|
|
21
|
+
updatedConfig = newConfig
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const updateField = updateFieldFactory(config, updateConfig)
|
|
25
|
+
updateField('section', null, 'filterColumn', 'newValue')
|
|
26
|
+
|
|
27
|
+
expect(updatedConfig).toEqual({ section: { filterColumn: 'newValue', filterValue: 'oldValue' } })
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should add to the second level when section is an array and subsection is null', () => {
|
|
31
|
+
const config = { section: ['oldValue'] }
|
|
32
|
+
let updatedConfig = {}
|
|
33
|
+
const updateConfig = newConfig => {
|
|
34
|
+
updatedConfig = newConfig
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const updateField = updateFieldFactory(config, updateConfig)
|
|
38
|
+
updateField('section', null, 'thisParamDoesNotMatter', 'newValue')
|
|
39
|
+
|
|
40
|
+
expect(updatedConfig).toEqual({ section: ['oldValue', 'newValue'] })
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('should update the third level when section and subsection are not null', () => {
|
|
44
|
+
const config = { section: { subsection: { filterColumn: 'oldValue', filterValue: 'oldValue' } } }
|
|
45
|
+
let updatedConfig = {}
|
|
46
|
+
const updateConfig = newConfig => {
|
|
47
|
+
updatedConfig = newConfig
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const updateField = updateFieldFactory(config, updateConfig)
|
|
51
|
+
updateField('section', 'subsection', 'filterColumn', 'newValue')
|
|
52
|
+
|
|
53
|
+
expect(updatedConfig).toEqual({ section: { subsection: { filterColumn: 'newValue', filterValue: 'oldValue' } } })
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('should update the third level when section is an array', () => {
|
|
57
|
+
const config = { section: [{ filterColumn: 'oldValue', filterValue: 'oldValue' }] }
|
|
58
|
+
let updatedConfig = {}
|
|
59
|
+
const updateConfig = newConfig => {
|
|
60
|
+
updatedConfig = newConfig
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const updateField = updateFieldFactory(config, updateConfig)
|
|
64
|
+
updateField('section', 0, 'filterColumn', 'newValue')
|
|
65
|
+
|
|
66
|
+
expect(updatedConfig).toEqual({ section: [{ filterColumn: 'newValue', filterValue: 'oldValue' }] })
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should update the second level when newValue is a string and legacy is true', () => {
|
|
70
|
+
// test for legacy use case
|
|
71
|
+
// puts the newValue in two places for some reason
|
|
72
|
+
const config = { section: { subsection: 'oldValue' } }
|
|
73
|
+
let updatedConfig = {}
|
|
74
|
+
const updateConfig = newConfig => {
|
|
75
|
+
updatedConfig = newConfig
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const updateField = updateFieldFactory(config, updateConfig, true)
|
|
79
|
+
updateField('section', 'subsection', 'filterColumn', 'newValue')
|
|
80
|
+
|
|
81
|
+
expect(updatedConfig).toEqual({ section: { subsection: 'newValue', filterColumn: 'newValue' } })
|
|
82
|
+
|
|
83
|
+
updateField('section', null, 'filterColumn', 'newValue2')
|
|
84
|
+
expect(updatedConfig).toEqual({ section: { subsection: 'oldValue', filterColumn: 'newValue2' } })
|
|
85
|
+
|
|
86
|
+
updateField('section', 'subsection', null, 'newValue2')
|
|
87
|
+
expect(updatedConfig).toEqual({ section: { subsection: 'newValue2', null: 'newValue2' } })
|
|
88
|
+
})
|
|
89
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { UpdateFieldFunc } from '../types/UpdateFieldFunc'
|
|
2
|
+
|
|
3
|
+
export const updateFieldFactory =
|
|
4
|
+
(config, updateConfig, legacy = false): UpdateFieldFunc<any> =>
|
|
5
|
+
(section, subsection, fieldName, newValue) => {
|
|
6
|
+
// Top level
|
|
7
|
+
if (null === section && null === subsection) {
|
|
8
|
+
const updatedConfig = { ...config, [fieldName]: newValue }
|
|
9
|
+
|
|
10
|
+
if ('filterColumn' === fieldName) {
|
|
11
|
+
updatedConfig.filterValue = ''
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
updateConfig(updatedConfig)
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const isArray = Array.isArray(config[section])
|
|
19
|
+
|
|
20
|
+
let sectionValue = isArray ? [...config[section], newValue] : { ...config[section], [fieldName]: newValue }
|
|
21
|
+
|
|
22
|
+
if (null !== subsection) {
|
|
23
|
+
if (isArray) {
|
|
24
|
+
sectionValue = [...config[section]]
|
|
25
|
+
sectionValue[subsection] = { ...sectionValue[subsection], [fieldName]: newValue }
|
|
26
|
+
} else if (typeof newValue === 'string' && legacy) {
|
|
27
|
+
// supports data-bite, filter-text, markup-include, and waffle-chart.
|
|
28
|
+
// i'm not sure what the use case for this could be considering you should be able to
|
|
29
|
+
// update by not passing the subsection. Therefore I'm labeling it as legacy.
|
|
30
|
+
sectionValue[subsection] = newValue
|
|
31
|
+
} else {
|
|
32
|
+
sectionValue = { ...config[section], [subsection]: { ...config[section][subsection], [fieldName]: newValue } }
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const updatedConfig = { ...config, [section]: sectionValue }
|
|
36
|
+
|
|
37
|
+
updateConfig(updatedConfig)
|
|
38
|
+
}
|
|
@@ -65,8 +65,8 @@ export default function useDataVizClasses(config, viewport = null) {
|
|
|
65
65
|
ul: getUlClasses(),
|
|
66
66
|
li: ['single-legend-item', 'legend-container__li'],
|
|
67
67
|
title: ['legend-container__title'],
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
description: ['legend-container__description'],
|
|
69
|
+
div: [legend?.position === 'bottom' && legend?.singleRow ? 'shape-container single-row' : 'shape-container']
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
return { innerContainerClasses, contentClasses, barBorderClass, lineDatapointClass, sparkLineStyles, legendClasses }
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const update_4_24_3 = async config => {
|
|
2
|
+
const ver = '4.24.3'
|
|
3
|
+
|
|
4
|
+
let newConfig = { ...config }
|
|
5
|
+
|
|
6
|
+
newConfig.validated = ver
|
|
7
|
+
|
|
8
|
+
if (newConfig.type === 'chart') {
|
|
9
|
+
if (newConfig.xAxis.sortDates) {
|
|
10
|
+
newConfig.xAxis.type = 'date-time'
|
|
11
|
+
}
|
|
12
|
+
newConfig.table.download = true
|
|
13
|
+
|
|
14
|
+
delete newConfig.xAxis.sortDates
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (newConfig.type === 'map') {
|
|
18
|
+
newConfig.table.download = true
|
|
19
|
+
newConfig.general.showDownloadButton = true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return newConfig
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default update_4_24_3
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/core",
|
|
3
|
-
"version": "4.24.
|
|
3
|
+
"version": "4.24.3",
|
|
4
4
|
"description": "Core components, styles, hooks, and helpers, for the CDC Open Visualization project",
|
|
5
5
|
"moduleName": "CdcCore",
|
|
6
6
|
"main": "dist/cdccore",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "
|
|
8
|
+
"test": "vitest watch --reporter verbose --globals true",
|
|
9
|
+
"test:ui": "vitest --ui"
|
|
9
10
|
},
|
|
10
11
|
"repository": {
|
|
11
12
|
"type": "git",
|
|
@@ -30,5 +31,5 @@
|
|
|
30
31
|
"react": "^18.2.0",
|
|
31
32
|
"react-dom": "^18.2.0"
|
|
32
33
|
},
|
|
33
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "9c7ef7ca74f2d2a1e04d923b133fe0fc557a62bf"
|
|
34
35
|
}
|
package/styles/_data-table.scss
CHANGED
|
@@ -31,7 +31,6 @@ div.data-table-heading {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
table.horizontal {
|
|
34
|
-
|
|
35
34
|
th,
|
|
36
35
|
td {
|
|
37
36
|
min-width: 200px;
|
|
@@ -103,18 +102,6 @@ table.data-table {
|
|
|
103
102
|
background-size: 10px 5px;
|
|
104
103
|
}
|
|
105
104
|
|
|
106
|
-
/* doesnt work
|
|
107
|
-
th.sort-asc,
|
|
108
|
-
td.sort-asc {
|
|
109
|
-
background-image: url(../assets/icon-caret-filled-up.svg);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
th.sort-desc,
|
|
113
|
-
td.sort-desc {
|
|
114
|
-
background-image: url(../assets/icon-caret-filled-down.svg);
|
|
115
|
-
}
|
|
116
|
-
*/
|
|
117
|
-
|
|
118
105
|
// format the white triangle sort icon in data table headers
|
|
119
106
|
.sort-icon {
|
|
120
107
|
fill: white;
|
package/styles/base.scss
CHANGED
|
@@ -77,10 +77,18 @@ body.post-type-cdc_visualization .cdc-editor .configure .editor-panel {
|
|
|
77
77
|
@import 'series-list';
|
|
78
78
|
@import 'typography';
|
|
79
79
|
|
|
80
|
+
// Force printing chart images
|
|
81
|
+
-webkit-print-color-adjust: exact !important; /* Chrome, Safari 6 – 15.3, Edge */
|
|
82
|
+
color-adjust: exact !important; /* Firefox 48 – 96 */
|
|
83
|
+
print-color-adjust: exact !important; /* Firefox 97+, Safari 15.4+ */
|
|
84
|
+
|
|
80
85
|
.editor-panel.cove {
|
|
81
86
|
position: absolute;
|
|
82
87
|
height: 100vh;
|
|
83
88
|
top: 0;
|
|
89
|
+
max-width: 350px;
|
|
90
|
+
width: 350px;
|
|
91
|
+
|
|
84
92
|
.editor-toggle {
|
|
85
93
|
position: absolute !important;
|
|
86
94
|
top: 10px !important;
|
package/types/Axis.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type BaseVisualizationType = 'dashboard' | 'chart' | 'map' | 'data-bite' | 'waffle-chart' | 'markup-include' | 'filtered-text' | 'filter-dropdowns' | 'table' | 'navigation'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ConfidenceInterval = Record<'lower' | 'upper', number | string>
|
package/types/Legend.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type Legend = {
|
|
2
|
+
additionalCategories: string[]
|
|
3
|
+
// general legend onClick behavior
|
|
4
|
+
behavior: 'highlight' | 'isolate' | string
|
|
5
|
+
axisAlign: boolean
|
|
6
|
+
colorCode: string
|
|
7
|
+
description: string
|
|
8
|
+
// show or hide the legend
|
|
9
|
+
hide: boolean
|
|
10
|
+
highlightOnHover: boolean
|
|
11
|
+
label: string
|
|
12
|
+
lineMode: boolean
|
|
13
|
+
position: string
|
|
14
|
+
reverseLabelOrder: boolean
|
|
15
|
+
singleRow: boolean
|
|
16
|
+
type: string
|
|
17
|
+
verticalSorted: boolean
|
|
18
|
+
}
|
package/types/Region.ts
ADDED
package/types/Runtime.ts
CHANGED
package/types/Table.ts
CHANGED
package/types/UpdateFieldFunc.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type UpdateFieldFunc<T> = (section: string | null, subsection: string | null, fieldName: string, value: T) => void
|
|
1
|
+
export type UpdateFieldFunc<T> = (section: string | null, subsection: string | number | null, fieldName: string | number, value: T) => void
|
package/types/Visualization.ts
CHANGED
|
@@ -1,27 +1,39 @@
|
|
|
1
|
+
import { Legend } from './Legend'
|
|
2
|
+
import { Axis } from './Axis'
|
|
3
|
+
import { Column } from './Column'
|
|
4
|
+
import { Series } from './Series'
|
|
5
|
+
import { Table } from './Table'
|
|
6
|
+
import { ConfidenceInterval } from './ConfidenceInterval'
|
|
7
|
+
import { BaseVisualizationType } from './BaseVisualizationType'
|
|
8
|
+
|
|
1
9
|
export type Visualization = {
|
|
2
10
|
autoLoad: boolean
|
|
11
|
+
columns: Record<string, Column>
|
|
12
|
+
confidenceKeys: ConfidenceInterval
|
|
3
13
|
data: any
|
|
4
14
|
dataDescription: Object
|
|
5
15
|
dataFileName: string
|
|
6
16
|
dataFileSourceType: string
|
|
17
|
+
dataFormat: any
|
|
7
18
|
dataKey: string
|
|
8
19
|
datasets: Record<string, any>
|
|
9
20
|
editing: boolean
|
|
10
|
-
formattedData?: Object[]
|
|
21
|
+
formattedData?: Object[] & Record<string, Object>
|
|
11
22
|
general: any
|
|
12
23
|
hide: any[]
|
|
24
|
+
legend: Legend
|
|
13
25
|
multiDashboards?: any[]
|
|
14
26
|
newViz: boolean
|
|
15
27
|
openModal: boolean
|
|
16
28
|
originalFormattedData: any
|
|
17
29
|
orientation: 'vertical' | 'horizontal'
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
30
|
+
series: Series
|
|
31
|
+
table: Table
|
|
21
32
|
title: string
|
|
22
|
-
type:
|
|
33
|
+
type: BaseVisualizationType
|
|
23
34
|
uid: string
|
|
24
35
|
usesSharedFilter: any
|
|
25
36
|
visualizationType: string
|
|
26
37
|
visualizationSubType: string
|
|
38
|
+
xAxis: Axis
|
|
27
39
|
}
|
package/helpers/cove/date.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { timeFormat, timeParse } from 'd3-time-format'
|
|
2
|
-
|
|
3
|
-
export function formatDate(format = undefined, date) {
|
|
4
|
-
return timeFormat(format)(date)
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function parseDate(format = undefined, dateString) {
|
|
8
|
-
return timeParse(format)(dateString) || new Date()
|
|
9
|
-
}
|