@cdc/core 4.26.1 → 4.26.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/.claude/agents/qa-test-developer.md +126 -0
- package/CLAUDE.local.md +67 -0
- package/LICENSE +201 -0
- package/_stories/Gallery.Charts.stories.tsx +35 -42
- package/_stories/Gallery.DataBite.stories.tsx +15 -8
- package/_stories/Gallery.Maps.stories.tsx +37 -28
- package/_stories/Gallery.WaffleChart.stories.tsx +1 -1
- package/_stories/PageART.stories.tsx +5 -4
- package/_stories/PageBRFSS.stories.tsx +21 -16
- package/_stories/PageCancerRegistries.stories.tsx +15 -15
- package/_stories/PageEasternEquineEncephalitis.stories.tsx +33 -19
- package/_stories/PageExcessiveAlcoholUse.stories.tsx +148 -143
- package/_stories/PageMaternalMortality.stories.tsx +5 -4
- package/_stories/PageOralHealth.stories.tsx +15 -10
- package/_stories/PageRespiratory.stories.tsx +4 -4
- package/_stories/PageSmokingTobacco.stories.tsx +15 -10
- package/_stories/PageStateDiabetesProfiles.stories.tsx +15 -10
- package/_stories/PageWastewater.stories.tsx +44 -30
- package/_stories/VegaImport.stories.tsx +401 -0
- package/_stories/vega-fixtures/bars-with-line.json +444 -0
- package/_stories/vega-fixtures/bars.json +58 -0
- package/_stories/vega-fixtures/combo-bar-rolling-mean.json +88 -0
- package/_stories/vega-fixtures/combo.json +68 -0
- package/_stories/vega-fixtures/grouped-horizontal-bars.json +83 -0
- package/_stories/vega-fixtures/grouped-horizontal-bars2.json +231 -0
- package/_stories/vega-fixtures/horizontal-bar.json +427 -0
- package/_stories/vega-fixtures/horizontal-bars-with-bad-colors.json +197 -0
- package/_stories/vega-fixtures/horizontal-bars2.json +58 -0
- package/_stories/vega-fixtures/lines.json +227 -0
- package/_stories/vega-fixtures/measles-bars.json +348 -0
- package/_stories/vega-fixtures/measles-map.json +11101 -0
- package/_stories/vega-fixtures/measles-stacked-bars.json +2147 -0
- package/_stories/vega-fixtures/multi-dataset.json +255 -0
- package/_stories/vega-fixtures/no-data.json +14 -0
- package/_stories/vega-fixtures/pie-chart.json +94 -0
- package/_stories/vega-fixtures/repeat-spec.json +47 -0
- package/_stories/vega-fixtures/stacked-area.json +222 -0
- package/_stories/vega-fixtures/stacked-bar-with-rect.json +3412 -0
- package/_stories/vega-fixtures/stacked-bars-with-line.json +364 -0
- package/_stories/vega-fixtures/stacked-bars.json +212 -0
- package/_stories/vega-fixtures/stacked-horizontal-bars.json +140 -0
- package/_stories/vega-fixtures/warning-combo.json +59 -0
- package/_stories/vega-fixtures/warning-scatter-and-line.json +1182 -0
- package/assets/callout-flag.svg +7 -0
- package/assets/icon-chart-area.svg +1 -0
- package/assets/icon-chart-radar.svg +23 -0
- package/assets/logo2.svg +31 -0
- package/components/AdvancedEditor/EmbedEditor.tsx +270 -38
- package/components/Alert/components/Alert.styles.css +2 -2
- package/components/ComboBox/combobox.styles.css +48 -48
- package/components/CustomColorsEditor/CustomColorsEditor.css +53 -53
- package/components/CustomColorsEditor/CustomColorsEditor.tsx +3 -10
- package/components/DataTable/DataTable.tsx +46 -18
- package/components/DataTable/DataTableStandAlone.tsx +1 -0
- package/components/DataTable/components/ChartHeader.tsx +21 -12
- package/components/DataTable/components/MapHeader.tsx +34 -28
- package/components/DataTable/components/SortIcon/sort-icon.css +5 -5
- package/components/DataTable/data-table.css +50 -52
- package/components/DataTable/helpers/applyCustomOrder.ts +17 -0
- package/components/DataTable/helpers/getChartCellValue.ts +10 -7
- package/components/DataTable/helpers/getMapDataTableColumnKeys.ts +22 -0
- package/components/DataTable/helpers/getSeriesName.ts +6 -0
- package/components/DataTable/helpers/mapCellMatrix.tsx +33 -23
- package/components/DataTable/helpers/tests/mapCellMatrix.test.ts +33 -0
- package/components/DownloadButton.tsx +14 -6
- package/components/EditorPanel/ColumnsEditor.tsx +38 -31
- package/components/EditorPanel/CustomSortOrder.tsx +94 -0
- package/components/EditorPanel/DataTableEditor.tsx +139 -23
- package/components/EditorPanel/EditorPanel.styles.css +71 -71
- package/components/EditorPanel/EditorPanel.tsx +3 -8
- package/components/EditorPanel/EditorPanelDispatch.tsx +4 -4
- package/components/EditorPanel/FootnotesEditor.tsx +2 -2
- package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +21 -12
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +16 -10
- package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +33 -29
- package/components/EditorPanel/components/MarkupVariablesEditor.tsx +160 -106
- package/components/EditorPanel/components/PanelMarkup.tsx +5 -1
- package/{styles/v2/components → components/EditorPanel}/editor.scss +76 -22
- package/components/EditorPanel/sections/StyleTreatmentSection.tsx +99 -0
- package/components/EditorPanel/sections/VisualSection.tsx +11 -0
- package/components/EditorWrapper/editor-wrapper.style.css +1 -1
- package/components/Filters/Filters.tsx +3 -5
- package/components/Filters/components/Tabs.tsx +19 -7
- package/{styles → components/Filters}/filters.scss +3 -3
- package/components/Footnotes/FootnotesStandAlone.tsx +4 -2
- package/components/HeaderThemeSelector/HeaderThemeSelector.css +61 -5
- package/components/Layout/components/Responsive.tsx +14 -6
- package/components/Layout/components/Sidebar/components/Sidebar.tsx +1 -1
- package/components/Layout/components/Sidebar/components/sidebar.styles.scss +14 -20
- package/components/Layout/components/Visualization/index.tsx +50 -38
- package/components/Layout/components/Visualization/visualizations.scss +232 -15
- package/components/Layout/components/VisualizationContainer.test.tsx +67 -0
- package/components/Layout/components/VisualizationContainer.tsx +37 -0
- package/components/Layout/components/VisualizationContent.test.tsx +182 -0
- package/components/Layout/components/VisualizationContent.tsx +75 -0
- package/components/Layout/index.tsx +5 -5
- package/components/Layout/styles/editor-utils.scss +3 -3
- package/components/Layout/styles/editor.scss +4 -4
- package/components/Legend/Legend.Gradient.tsx +7 -1
- package/components/Loader/loader.styles.css +2 -2
- package/components/Loading.jsx +1 -1
- package/components/MediaControls.tsx +10 -3
- package/components/MultiSelect/multiselect.styles.css +19 -19
- package/components/NestedDropdown/nesteddropdown.styles.css +15 -15
- package/components/PaletteSelector/PaletteSelector.css +15 -15
- package/components/RichTooltip/richTooltip.css +6 -6
- package/components/Table/table.styles.css +2 -2
- package/components/Waiting.tsx +1 -1
- package/components/_stories/CustomColorsEditor.stories.tsx +37 -0
- package/components/_stories/DataTable.stories.tsx +1 -0
- package/components/_stories/Filters.stories.tsx +1 -1
- package/components/_stories/styles.scss +0 -1
- package/components/elements/Button.jsx +1 -1
- package/components/elements/Card.jsx +1 -1
- package/{styles/v2/components → components/elements}/button.scss +9 -8
- package/components/inputs/InputCheckbox.jsx +1 -1
- package/components/inputs/InputSelect.tsx +1 -1
- package/components/inputs/InputText.jsx +1 -1
- package/components/inputs/InputToggle.tsx +1 -1
- package/{styles/v2/components/input → components/inputs}/_input-check-radio.scss +2 -2
- package/{styles/v2/components/input → components/inputs}/_input-group.scss +3 -3
- package/{styles/v2/components/input → components/inputs}/_input-slider.scss +2 -2
- package/{styles/v2/components/input → components/inputs}/_input.scss +5 -5
- package/{styles/v2/components/input → components/inputs}/index.scss +2 -2
- package/{styles → components}/loading.scss +1 -1
- package/components/managers/DataDesigner.tsx +1 -1
- package/{styles/v2/components → components/managers}/data-designer.scss +6 -7
- package/components/ui/Accordion.jsx +1 -1
- package/components/ui/Icon.tsx +1 -1
- package/components/ui/LoadSpin.jsx +1 -1
- package/components/ui/Modal.jsx +1 -1
- package/components/ui/Overlay.jsx +1 -1
- package/components/ui/Title/index.test.tsx +34 -0
- package/components/ui/Title/index.tsx +24 -7
- package/components/ui/Title/title.styles.css +119 -25
- package/components/ui/Tooltip.tsx +1 -1
- package/components/ui/_stories/Title.stories.tsx +1 -1
- package/{styles/v2/components → components/ui}/accordion.scss +3 -3
- package/components/ui/accordion.styles.css +11 -11
- package/{styles/v2/components → components/ui}/modal.scss +2 -2
- package/{styles/v2/components → components/ui}/overlay.scss +6 -6
- package/{styles/v2/components → components}/ui/tooltip.scss +1 -1
- package/{styles → components}/waiting.scss +9 -3
- package/data/colorPalettes.ts +18 -5
- package/data/mapColorPalettes.ts +10 -0
- package/devTemplate/dev.js +285 -0
- package/devTemplate/index.html +30 -0
- package/devTemplate/preview.html +1503 -0
- package/devTemplate/sidebar.css +151 -0
- package/dist/cove-main.css +2530 -3901
- package/dist/cove-main.css.map +1 -1
- package/generateViteConfig.js +111 -2
- package/helpers/DataTransform.ts +1 -5
- package/helpers/backfillDefaults.ts +35 -0
- package/helpers/constants.ts +12 -0
- package/helpers/cove/date.ts +64 -3
- package/helpers/cove/number.ts +29 -15
- package/helpers/cove/string.ts +29 -0
- package/helpers/coveUpdateWorker.ts +14 -8
- package/helpers/displayDataAsText.ts +1 -1
- package/helpers/embed/embedCodeGenerator.ts +80 -0
- package/helpers/embed/embedHelper.js +169 -0
- package/helpers/embed/filterUtils.ts +121 -0
- package/helpers/embed/index.ts +17 -0
- package/helpers/embed/urlValidation.ts +119 -0
- package/helpers/extractDataAndMetadata.ts +20 -0
- package/helpers/fetchRemoteData.ts +14 -8
- package/helpers/filterVizData.ts +6 -1
- package/helpers/getFileExtension.ts +0 -6
- package/helpers/labelHash.ts +9 -0
- package/helpers/markupProcessor.ts +56 -38
- package/helpers/metrics/types.ts +3 -0
- package/helpers/palettes/colorDistributions.ts +1 -1
- package/helpers/palettes/utils.ts +12 -12
- package/helpers/parseCsvWithQuotes.ts +15 -14
- package/helpers/prepareScreenshot.ts +33 -10
- package/helpers/testing.ts +44 -0
- package/helpers/tests/DataTransform.test.ts +125 -0
- package/helpers/tests/abbreviateNumber.test.ts +59 -0
- package/helpers/tests/backfillDefaults.test.ts +253 -0
- package/helpers/tests/date.test.ts +110 -0
- package/helpers/tests/extractDataAndMetadata.test.ts +93 -0
- package/helpers/tests/markupProcessor.test.ts +315 -124
- package/helpers/tests/number.test.ts +42 -0
- package/helpers/tests/prepareScreenshot.test.ts +28 -28
- package/helpers/tests/testStandaloneBuild.ts +36 -26
- package/helpers/tests/useDataVizClasses.test.ts +66 -0
- package/helpers/tests/visualizationWrapperUsage.test.ts +57 -0
- package/helpers/useDataVizClasses.ts +13 -7
- package/helpers/vegaConfig.ts +1 -1
- package/helpers/vegaConfigImport.ts +160 -0
- package/helpers/ver/4.24.4.ts +24 -0
- package/helpers/ver/4.26.1.ts +1 -1
- package/helpers/ver/4.26.2.ts +84 -0
- package/helpers/ver/4.26.3.ts +44 -0
- package/helpers/ver/4.26.4.ts +31 -0
- package/helpers/ver/tests/4.26.1.test.ts +105 -0
- package/helpers/ver/tests/4.26.2.test.ts +298 -0
- package/helpers/ver/tests/4.26.3.test.ts +168 -0
- package/helpers/ver/tests/4.26.4.test.ts +88 -0
- package/helpers/ver/tests/coveUpdateWorker.test.ts +57 -0
- package/helpers/viewports.ts +2 -0
- package/package.json +27 -32
- package/styles/_global.scss +7 -7
- package/styles/_reset.scss +2 -2
- package/styles/{v2/base → base}/_file-selector.scss +4 -4
- package/styles/{v2/base → base}/_general.scss +2 -4
- package/styles/{v2/base → base}/index.scss +1 -1
- package/styles/base.scss +107 -165
- package/styles/cove-main.scss +3 -6
- package/styles/layout/_component.scss +110 -0
- package/styles/{v2/layout → layout}/_data-table.scss +7 -7
- package/styles/layout/_wrapper-padding.scss +27 -0
- package/styles/{v2/main.scss → main.scss} +3 -1
- package/styles/{v2/themes → themes}/_color-definitions.scss +46 -41
- package/styles/{_accessibility.scss → utils/_accessibility.scss} +1 -1
- package/styles/{v2/utils → utils}/_grid.scss +8 -3
- package/styles/{_global-variables.scss → utils/_properties.scss} +133 -112
- package/styles/{v2/utils → utils}/index.scss +2 -1
- package/types/Annotation.ts +10 -11
- package/types/Axis.ts +2 -0
- package/types/ComponentStyles.ts +1 -0
- package/types/ConfigureData.ts +1 -0
- package/types/General.ts +2 -0
- package/types/MarkupInclude.ts +1 -0
- package/types/MarkupVariable.ts +2 -1
- package/types/Palette.ts +22 -0
- package/types/Table.ts +9 -0
- package/types/Visualization.ts +7 -0
- package/_stories/StoryRenderingTests.stories.tsx +0 -164
- package/helpers/embedCodeGenerator.ts +0 -109
- package/styles/_common-components.css +0 -73
- package/styles/_variables.scss +0 -63
- package/styles/v2/layout/_component.scss +0 -21
- package/styles/v2/utils/_variables.scss +0 -9
- package/{styles/v2/components/card.scss → components/elements/card.css} +2 -2
- /package/{styles/v2/components → components/ui}/icon.scss +0 -0
- /package/{styles/v2/components → components/ui}/loadspin.scss +0 -0
- /package/styles/{v2/base → base}/_heading.scss +0 -0
- /package/styles/{v2/base → base}/_reset.scss +0 -0
- /package/styles/{v2/layout → layout}/_alert.scss +0 -0
- /package/styles/{v2/layout → layout}/_progression.scss +0 -0
- /package/styles/{v2/layout → layout}/_tooltip.scss +0 -0
- /package/styles/{v2/layout → layout}/index.scss +0 -0
- /package/styles/{v2/themes → themes}/index.scss +0 -0
- /package/styles/{v2/utils → utils}/_align.scss +0 -0
- /package/styles/{v2/utils → utils}/_animations.scss +0 -0
- /package/styles/{v2/utils → utils}/_breakpoints.scss +0 -0
- /package/styles/{v2/utils → utils}/_mixins.scss +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { DataTableProps } from '../DataTable'
|
|
2
2
|
import ScreenReaderText from '../../elements/ScreenReaderText'
|
|
3
|
-
import { SortIcon } from './SortIcon'
|
|
4
|
-
import { getNewSortBy } from '../helpers/getNewSortBy'
|
|
5
|
-
import { publishAnalyticsEvent } from '../../../helpers/metrics/helpers'
|
|
6
|
-
import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
|
|
3
|
+
import { SortIcon } from './SortIcon'
|
|
4
|
+
import { getNewSortBy } from '../helpers/getNewSortBy'
|
|
5
|
+
import { publishAnalyticsEvent } from '../../../helpers/metrics/helpers'
|
|
6
|
+
import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
|
|
7
|
+
import { getMapDataTableColumnKeys } from '../helpers/getMapDataTableColumnKeys'
|
|
7
8
|
|
|
8
9
|
type MapHeaderProps = DataTableProps & {
|
|
9
10
|
sortBy: { column; asc }
|
|
@@ -19,23 +20,23 @@ const ColumnHeadingText = ({ text, config }) => {
|
|
|
19
20
|
return text
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
const MapHeader = ({
|
|
23
|
-
columns,
|
|
24
|
-
config,
|
|
23
|
+
const MapHeader = ({
|
|
24
|
+
columns,
|
|
25
|
+
config,
|
|
25
26
|
indexTitle,
|
|
26
27
|
sortBy,
|
|
27
28
|
setSortBy,
|
|
28
29
|
rightAlignedCols,
|
|
29
|
-
interactionLabel = ''
|
|
30
|
-
}: MapHeaderProps) => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
let text
|
|
37
|
-
if (column && column !== 'geo') {
|
|
38
|
-
text = columns[column].label ? columns[column].label : columns[column].name
|
|
30
|
+
interactionLabel = ''
|
|
31
|
+
}: MapHeaderProps) => {
|
|
32
|
+
const orderedColumnKeys = getMapDataTableColumnKeys(columns)
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<tr>
|
|
36
|
+
{orderedColumnKeys.map((column, index) => {
|
|
37
|
+
let text
|
|
38
|
+
if (column && column !== 'geo') {
|
|
39
|
+
text = columns[column].label ? columns[column].label : columns[column].name
|
|
39
40
|
} else {
|
|
40
41
|
text = config.type === 'map' ? indexTitle : config.xAxis?.dataKey
|
|
41
42
|
}
|
|
@@ -49,7 +50,7 @@ const MapHeader = ({
|
|
|
49
50
|
style={{
|
|
50
51
|
minWidth: (config.table.cellMinWidth || 0) + 'px',
|
|
51
52
|
textAlign: rightAlignedCols && rightAlignedCols[index] ? 'right' : '',
|
|
52
|
-
paddingRight: '1.
|
|
53
|
+
paddingRight: '1.8em'
|
|
53
54
|
}}
|
|
54
55
|
key={`col-header-${column}__${index}`}
|
|
55
56
|
id={column}
|
|
@@ -64,7 +65,9 @@ const MapHeader = ({
|
|
|
64
65
|
eventAction: 'click',
|
|
65
66
|
eventLabel: interactionLabel,
|
|
66
67
|
vizTitle: getVizTitle(config),
|
|
67
|
-
specifics: `column: ${newSortBy.column || 'none'}, order: ${
|
|
68
|
+
specifics: `column: ${newSortBy.column || 'none'}, order: ${
|
|
69
|
+
newSortBy.asc === true ? 'asc' : newSortBy.asc === false ? 'desc' : 'none'
|
|
70
|
+
}`
|
|
68
71
|
})
|
|
69
72
|
setSortBy(newSortBy)
|
|
70
73
|
}}
|
|
@@ -77,7 +80,9 @@ const MapHeader = ({
|
|
|
77
80
|
eventAction: 'keyboard',
|
|
78
81
|
eventLabel: interactionLabel,
|
|
79
82
|
vizTitle: getVizTitle(config),
|
|
80
|
-
specifics: `column: ${newSortBy.column || 'none'}, order: ${
|
|
83
|
+
specifics: `column: ${newSortBy.column || 'none'}, order: ${
|
|
84
|
+
newSortBy.asc === true ? 'asc' : newSortBy.asc === false ? 'desc' : 'none'
|
|
85
|
+
}`
|
|
81
86
|
})
|
|
82
87
|
setSortBy(newSortBy)
|
|
83
88
|
}
|
|
@@ -91,13 +96,14 @@ const MapHeader = ({
|
|
|
91
96
|
>
|
|
92
97
|
<ColumnHeadingText text={text} config={config} />
|
|
93
98
|
<SortIcon ascending={sortByAsc} />
|
|
94
|
-
<span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
<span className='cdcdataviz-sr-only'>{`Sort by ${text} in ${
|
|
100
|
+
sortBy.column === column ? (!sortBy.asc ? 'descending' : 'ascending') : 'descending'
|
|
101
|
+
} order`}</span>
|
|
102
|
+
</th>
|
|
103
|
+
)
|
|
104
|
+
})}
|
|
105
|
+
</tr>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
102
108
|
|
|
103
109
|
export default MapHeader
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
.sort-icon {
|
|
2
|
+
align-items: center;
|
|
2
3
|
display: flex;
|
|
3
4
|
flex-direction: column;
|
|
4
|
-
align-items: center;
|
|
5
5
|
justify-content: center;
|
|
6
6
|
|
|
7
7
|
position: absolute;
|
|
8
|
-
right:
|
|
8
|
+
right: 13px;
|
|
9
9
|
top: 50%;
|
|
10
10
|
transform: translateY(-50%);
|
|
11
11
|
z-index: 1;
|
|
12
12
|
|
|
13
13
|
svg {
|
|
14
|
-
width: 0.75rem;
|
|
15
|
-
height: 0.75rem;
|
|
16
14
|
fill: rgba(255, 255, 255, 0.5);
|
|
15
|
+
height: 0.75rem;
|
|
16
|
+
line-height: 1;
|
|
17
17
|
margin: 0;
|
|
18
18
|
padding: 0;
|
|
19
|
-
|
|
19
|
+
width: 0.75rem;
|
|
20
20
|
|
|
21
21
|
&.active {
|
|
22
22
|
fill: white;
|
|
@@ -1,46 +1,44 @@
|
|
|
1
|
-
.cove
|
|
2
|
-
.cdc-open-viz-module {
|
|
1
|
+
.cove-visualization {
|
|
3
2
|
.table {
|
|
4
|
-
width: unset;
|
|
5
3
|
min-width: 100%;
|
|
4
|
+
width: unset;
|
|
6
5
|
}
|
|
7
6
|
|
|
8
7
|
.bs4 .table.table-width-unset {
|
|
9
8
|
width: unset;
|
|
10
9
|
}
|
|
11
10
|
|
|
12
|
-
.collapsed
|
|
11
|
+
.collapsed + .table-container {
|
|
13
12
|
border-bottom: none;
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
.table-container {
|
|
17
|
-
overflow-x: auto;
|
|
18
|
-
border-right: 1px solid var(--lightGray);
|
|
19
|
-
border-left: 1px solid var(--lightGray);
|
|
20
16
|
border-bottom: 1px solid var(--lightGray);
|
|
17
|
+
border-left: 1px solid var(--lightGray);
|
|
18
|
+
border-right: 1px solid var(--lightGray);
|
|
19
|
+
overflow-x: auto;
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
div.data-table-heading {
|
|
24
|
-
position: relative;
|
|
25
23
|
border: var(--cool-gray-10) 1px solid;
|
|
26
24
|
border-radius: 6px;
|
|
25
|
+
position: relative;
|
|
27
26
|
|
|
28
27
|
svg {
|
|
29
|
-
position: absolute;
|
|
30
28
|
height: 100%;
|
|
31
|
-
|
|
32
|
-
top: 0;
|
|
29
|
+
position: absolute;
|
|
33
30
|
right: 1em;
|
|
31
|
+
top: 0;
|
|
32
|
+
width: 15px;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
&:focus {
|
|
37
|
-
z-index: 2;
|
|
38
36
|
position: relative;
|
|
37
|
+
z-index: 2;
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
table.horizontal {
|
|
43
|
-
|
|
44
42
|
th,
|
|
45
43
|
td {
|
|
46
44
|
min-width: 200px;
|
|
@@ -48,12 +46,12 @@
|
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
table.data-table {
|
|
51
|
-
|
|
49
|
+
appearance: none;
|
|
52
50
|
background: #fff;
|
|
53
|
-
position: relative;
|
|
54
51
|
border: none;
|
|
55
52
|
border-collapse: collapse;
|
|
56
|
-
|
|
53
|
+
margin-bottom: 0;
|
|
54
|
+
position: relative;
|
|
57
55
|
table-layout: fixed;
|
|
58
56
|
|
|
59
57
|
* {
|
|
@@ -61,15 +59,15 @@
|
|
|
61
59
|
}
|
|
62
60
|
|
|
63
61
|
thead {
|
|
64
|
-
user-select: none;
|
|
65
62
|
-moz-user-select: none;
|
|
66
63
|
user-select: none;
|
|
64
|
+
user-select: none;
|
|
67
65
|
|
|
68
66
|
button {
|
|
69
67
|
background: none;
|
|
70
|
-
font-size: initial;
|
|
71
|
-
color: #fff !important;
|
|
72
68
|
border: 0;
|
|
69
|
+
color: #fff !important;
|
|
70
|
+
font-size: initial;
|
|
73
71
|
}
|
|
74
72
|
|
|
75
73
|
tr {
|
|
@@ -81,13 +79,13 @@
|
|
|
81
79
|
color: #fff !important;
|
|
82
80
|
|
|
83
81
|
.resizer {
|
|
82
|
+
bottom: 0;
|
|
84
83
|
cursor: e-resize;
|
|
85
|
-
width: 10px;
|
|
86
84
|
position: absolute;
|
|
87
|
-
top: 0;
|
|
88
|
-
bottom: 0;
|
|
89
85
|
right: 0;
|
|
86
|
+
top: 0;
|
|
90
87
|
touch-action: none;
|
|
88
|
+
width: 10px;
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
tr {
|
|
@@ -96,19 +94,20 @@
|
|
|
96
94
|
|
|
97
95
|
th,
|
|
98
96
|
td {
|
|
99
|
-
|
|
97
|
+
border-right: 1px solid var(--lightGray) !important;
|
|
100
98
|
line-height: normal;
|
|
99
|
+
padding: 0.5em 0.7em;
|
|
101
100
|
position: relative;
|
|
102
101
|
text-align: left;
|
|
103
|
-
border-right: 1px solid var(--lightGray) !important;
|
|
104
102
|
}
|
|
105
103
|
|
|
106
104
|
th {
|
|
107
105
|
background-color: var(--primary);
|
|
108
|
-
background-repeat: no-repeat;
|
|
109
106
|
background-position: right 0.5em center;
|
|
107
|
+
background-repeat: no-repeat;
|
|
110
108
|
background-size: 10px 5px;
|
|
111
|
-
color: #fff !important
|
|
109
|
+
color: #fff !important;
|
|
110
|
+
cursor: pointer;
|
|
112
111
|
}
|
|
113
112
|
|
|
114
113
|
th:last-child,
|
|
@@ -134,8 +133,8 @@
|
|
|
134
133
|
|
|
135
134
|
th,
|
|
136
135
|
td {
|
|
137
|
-
padding: 0.3em 0.7em;
|
|
138
136
|
border-right: 1px solid rgba(0, 0, 0, 0.1);
|
|
137
|
+
padding: 0.3em 0.7em;
|
|
139
138
|
white-space: nowrap;
|
|
140
139
|
|
|
141
140
|
&:last-child {
|
|
@@ -154,36 +153,35 @@
|
|
|
154
153
|
margin-left: 0 !important;
|
|
155
154
|
}
|
|
156
155
|
}
|
|
157
|
-
|
|
158
156
|
}
|
|
159
157
|
|
|
160
158
|
td a {
|
|
159
|
+
bottom: 0;
|
|
160
|
+
color: inherit;
|
|
161
|
+
display: block;
|
|
162
|
+
left: 0;
|
|
161
163
|
padding: 0.3em 0.7em;
|
|
162
164
|
position: absolute;
|
|
163
|
-
top: 0;
|
|
164
|
-
bottom: 0;
|
|
165
165
|
right: 0;
|
|
166
|
-
left: 0;
|
|
167
|
-
display: block;
|
|
168
|
-
color: inherit;
|
|
169
166
|
text-decoration: none;
|
|
167
|
+
top: 0;
|
|
170
168
|
}
|
|
171
169
|
|
|
172
170
|
td div a {
|
|
173
|
-
position: relative;
|
|
174
|
-
padding: 0;
|
|
175
171
|
display: inline;
|
|
172
|
+
padding: 0;
|
|
173
|
+
position: relative;
|
|
176
174
|
}
|
|
177
175
|
|
|
178
176
|
td span.table-link {
|
|
179
|
-
text-decoration: underline;
|
|
180
|
-
cursor: pointer;
|
|
181
177
|
color: #075290;
|
|
178
|
+
cursor: pointer;
|
|
179
|
+
text-decoration: underline;
|
|
182
180
|
|
|
183
181
|
svg {
|
|
182
|
+
margin-left: 5px;
|
|
184
183
|
max-width: 13px;
|
|
185
184
|
vertical-align: baseline;
|
|
186
|
-
margin-left: 5px;
|
|
187
185
|
}
|
|
188
186
|
}
|
|
189
187
|
|
|
@@ -197,16 +195,16 @@
|
|
|
197
195
|
position: relative;
|
|
198
196
|
|
|
199
197
|
.no-data-message {
|
|
198
|
+
align-items: center;
|
|
200
199
|
background: rgba(255, 255, 255, 0.5);
|
|
201
|
-
top: 0;
|
|
202
|
-
left: 0;
|
|
203
|
-
right: 0;
|
|
204
200
|
bottom: 0;
|
|
205
|
-
position: absolute;
|
|
206
|
-
text-align: center;
|
|
207
201
|
display: flex;
|
|
208
|
-
align-items: center;
|
|
209
202
|
justify-content: center;
|
|
203
|
+
left: 0;
|
|
204
|
+
position: absolute;
|
|
205
|
+
right: 0;
|
|
206
|
+
text-align: center;
|
|
207
|
+
top: 0;
|
|
210
208
|
z-index: 7;
|
|
211
209
|
|
|
212
210
|
:is(h3) {
|
|
@@ -231,16 +229,16 @@
|
|
|
231
229
|
}
|
|
232
230
|
|
|
233
231
|
.data-table-pagination {
|
|
234
|
-
margin: 1rem 0;
|
|
235
|
-
display: flex;
|
|
236
232
|
align-items: center;
|
|
233
|
+
display: flex;
|
|
234
|
+
margin: 1rem 0;
|
|
237
235
|
|
|
238
236
|
ul {
|
|
237
|
+
display: flex;
|
|
239
238
|
list-style: none;
|
|
240
239
|
margin: 0 1rem 0 0;
|
|
241
|
-
display: flex;
|
|
242
240
|
|
|
243
|
-
li+li {
|
|
241
|
+
li + li {
|
|
244
242
|
margin-left: 0.3rem;
|
|
245
243
|
}
|
|
246
244
|
|
|
@@ -258,8 +256,8 @@
|
|
|
258
256
|
|
|
259
257
|
button[disabled] {
|
|
260
258
|
background: var(--mediumGray);
|
|
261
|
-
opacity: 0.3;
|
|
262
259
|
cursor: default;
|
|
260
|
+
opacity: 0.3;
|
|
263
261
|
|
|
264
262
|
&:hover {
|
|
265
263
|
background: var(--mediumGray);
|
|
@@ -271,9 +269,9 @@
|
|
|
271
269
|
.btn-download {
|
|
272
270
|
color: #fff;
|
|
273
271
|
float: right;
|
|
272
|
+
margin: 1em 0;
|
|
274
273
|
text-decoration: none;
|
|
275
274
|
transition: 0.3s all;
|
|
276
|
-
margin: 1em 0;
|
|
277
275
|
|
|
278
276
|
&:hover {
|
|
279
277
|
transition: 0.3s all;
|
|
@@ -281,7 +279,7 @@
|
|
|
281
279
|
}
|
|
282
280
|
|
|
283
281
|
.download-links a:not(:last-child) {
|
|
284
|
-
margin-right: 10px;
|
|
285
282
|
display: inline-block;
|
|
283
|
+
margin-right: 10px;
|
|
286
284
|
}
|
|
287
|
-
}
|
|
285
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sorts two values based on a user-defined custom order array.
|
|
3
|
+
* Values not found in customOrder are pushed to the end.
|
|
4
|
+
*/
|
|
5
|
+
export const applyCustomOrder = (valueA: string, valueB: string, customOrder: string[]): number => {
|
|
6
|
+
const indexA = customOrder.indexOf(String(valueA))
|
|
7
|
+
const indexB = customOrder.indexOf(String(valueB))
|
|
8
|
+
|
|
9
|
+
// Both found in custom order — sort by position
|
|
10
|
+
if (indexA !== -1 && indexB !== -1) return indexA - indexB
|
|
11
|
+
// Only A found — A comes first
|
|
12
|
+
if (indexA !== -1) return -1
|
|
13
|
+
// Only B found — B comes first
|
|
14
|
+
if (indexB !== -1) return 1
|
|
15
|
+
// Neither found — maintain relative order
|
|
16
|
+
return 0
|
|
17
|
+
}
|
|
@@ -31,8 +31,13 @@ const isAdditionalColumn = (column: string, config, rowData) => {
|
|
|
31
31
|
return formattingParams
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export const getChartCellValue = (
|
|
35
|
-
|
|
34
|
+
export const getChartCellValue = (
|
|
35
|
+
row: string,
|
|
36
|
+
column: string,
|
|
37
|
+
config: TableConfig,
|
|
38
|
+
runtimeData: Object[],
|
|
39
|
+
rightAxisItemsMap
|
|
40
|
+
) => {
|
|
36
41
|
// Variables for xAxis config
|
|
37
42
|
const { type, dateDisplayFormat, dateParseFormat, dataKey: xAxisDataKey } = config.xAxis || {}
|
|
38
43
|
const { showMissingDataLabel } = config.general || {}
|
|
@@ -54,14 +59,13 @@ export const getChartCellValue = (row: string, column: string, config: TableConf
|
|
|
54
59
|
if (column === xAxisDataKey) {
|
|
55
60
|
const dateFormat = config.table?.dateDisplayFormat || dateDisplayFormat
|
|
56
61
|
if (type === 'date' || type === 'date-time') {
|
|
57
|
-
cellValue = formatDate(dateFormat, parseDate(dateParseFormat, labelValue))
|
|
62
|
+
cellValue = formatDate(dateFormat, parseDate(dateParseFormat, labelValue), config.locale)
|
|
58
63
|
} else if (type === 'continuous') {
|
|
59
64
|
cellValue = formatNumber(runtimeData[row][column], 'bottom', false, config)
|
|
60
65
|
} else {
|
|
61
66
|
cellValue = labelValue
|
|
62
67
|
}
|
|
63
68
|
} else {
|
|
64
|
-
|
|
65
69
|
let addColParams = isAdditionalColumn(column, config, rowObj)
|
|
66
70
|
|
|
67
71
|
let piePercent = 0
|
|
@@ -69,9 +73,8 @@ export const getChartCellValue = (row: string, column: string, config: TableConf
|
|
|
69
73
|
piePercent = (_.toNumber(runtimeData[row][column]) / _.sumBy(runtimeData, d => _.toNumber(d[column]))) * 100 || 0
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
const valueToFormat =
|
|
73
|
-
? piePercent
|
|
74
|
-
: runtimeData[row][column]
|
|
76
|
+
const valueToFormat =
|
|
77
|
+
config.visualizationType === 'Pie' && !config.dataFormat.showPiePercent ? piePercent : runtimeData[row][column]
|
|
75
78
|
|
|
76
79
|
const hasAdditionalParams = Object.keys(addColParams).length > 0
|
|
77
80
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Column } from '../../../types/Column'
|
|
2
|
+
|
|
3
|
+
const isVisibleDataTableColumn = ([, column]: [string, Column]) => {
|
|
4
|
+
return column?.dataTable === true && !!column?.name
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const getMapDataTableColumnKeys = (columns: Record<string, Column> = {}): string[] => {
|
|
8
|
+
return Object.entries(columns)
|
|
9
|
+
.filter(isVisibleDataTableColumn)
|
|
10
|
+
.map(([key, column], declarationIndex) => ({ key, order: column.order, declarationIndex }))
|
|
11
|
+
.sort((a, b) => {
|
|
12
|
+
const aOrder = a.order ?? Number.MAX_SAFE_INTEGER
|
|
13
|
+
const bOrder = b.order ?? Number.MAX_SAFE_INTEGER
|
|
14
|
+
|
|
15
|
+
if (aOrder !== bOrder) {
|
|
16
|
+
return aOrder - bOrder
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return a.declarationIndex - b.declarationIndex
|
|
20
|
+
})
|
|
21
|
+
.map(({ key }) => key)
|
|
22
|
+
}
|
|
@@ -16,6 +16,12 @@ export const getSeriesName = (column: string, config: TableConfig) => {
|
|
|
16
16
|
return userDefinedSeries.name
|
|
17
17
|
}
|
|
18
18
|
if (config.runtimeSeriesLabels && config.runtimeSeriesLabels[column]) return config.runtimeSeriesLabels[column]
|
|
19
|
+
|
|
20
|
+
// For pie charts, use yAxis.label if the column is the yAxis data key
|
|
21
|
+
if (config.visualizationType === 'Pie' && column === config.yAxis?.dataKey && config.yAxis?.label) {
|
|
22
|
+
return config.yAxis.label
|
|
23
|
+
}
|
|
24
|
+
|
|
19
25
|
const columnIsDataKey = column === config.xAxis?.dataKey
|
|
20
26
|
const indexLabel = config.table?.indexLabel
|
|
21
27
|
return columnIsDataKey && indexLabel ? indexLabel : getLabel(column, config)
|
|
@@ -3,8 +3,11 @@ import CellAnchor from '../components/CellAnchor'
|
|
|
3
3
|
import { DataTableProps } from '../DataTable'
|
|
4
4
|
import { ReactNode } from 'react'
|
|
5
5
|
import { displayDataAsText } from '@cdc/core/helpers/displayDataAsText'
|
|
6
|
+
import parse from 'html-react-parser'
|
|
6
7
|
import _ from 'lodash'
|
|
7
8
|
import { hashObj } from '../../../helpers/hashObj'
|
|
9
|
+
import { sanitizeToSvgId } from '../../../helpers/cove/string'
|
|
10
|
+
import { getMapDataTableColumnKeys } from './getMapDataTableColumnKeys'
|
|
8
11
|
|
|
9
12
|
type MapRowsProps = DataTableProps & {
|
|
10
13
|
rows: string[]
|
|
@@ -22,9 +25,10 @@ const getGeoLabel = (config, row, formatLegendLocation, displayGeoName, runtimeD
|
|
|
22
25
|
const { geoType, type } = config.general
|
|
23
26
|
|
|
24
27
|
let labelValue
|
|
28
|
+
const displayOverride = runtimeData?.[row]?.[config.columns?.geo?.displayColumn]
|
|
25
29
|
if (!['single-state', 'us-county'].includes(geoType) || type === 'us-geocode') {
|
|
26
30
|
// Use the row (UID) for lookup - this allows "US-AL" to become "Alabama"
|
|
27
|
-
labelValue = displayGeoName(row)
|
|
31
|
+
labelValue = displayGeoName(row, displayOverride)
|
|
28
32
|
|
|
29
33
|
// If displayGeoName returned the same value (not found in lookups), use the raw imported data
|
|
30
34
|
if (labelValue === row && runtimeData && config.columns?.geo?.name) {
|
|
@@ -67,11 +71,13 @@ export const getMapRowData = (
|
|
|
67
71
|
displayGeoName: (row: string) => string,
|
|
68
72
|
filterColumns: string[]
|
|
69
73
|
) => {
|
|
74
|
+
const orderedColumnKeys = getMapDataTableColumnKeys(columns as any)
|
|
75
|
+
|
|
70
76
|
return rows.map((row: string) => {
|
|
71
77
|
const dataRow = {}
|
|
72
78
|
;[
|
|
73
79
|
...filterColumns,
|
|
74
|
-
...
|
|
80
|
+
...orderedColumnKeys
|
|
75
81
|
].map(column => {
|
|
76
82
|
const label = columns[column]?.label || columns[column]?.name || column
|
|
77
83
|
if (column === 'geo') {
|
|
@@ -103,10 +109,10 @@ const mapCellArray = ({
|
|
|
103
109
|
getPatternForRow
|
|
104
110
|
}: MapRowsProps): ReactNode[][] => {
|
|
105
111
|
const { allowMapZoom, geoType, type } = config.general
|
|
112
|
+
const orderedColumnKeys = getMapDataTableColumnKeys(columns as any)
|
|
113
|
+
|
|
106
114
|
return rows.map(row =>
|
|
107
|
-
|
|
108
|
-
.filter(column => columns[column].dataTable === true && columns[column].name)
|
|
109
|
-
.map(column => {
|
|
115
|
+
orderedColumnKeys.map(column => {
|
|
110
116
|
if (column === 'geo') {
|
|
111
117
|
const rowObj = runtimeData[row]
|
|
112
118
|
if (!rowObj) {
|
|
@@ -128,26 +134,29 @@ const mapCellArray = ({
|
|
|
128
134
|
// Check for pattern information
|
|
129
135
|
const patternInfo = getPatternForRow(rowObj, config)
|
|
130
136
|
const mapId = config.runtime?.uniqueId || 'map'
|
|
137
|
+
const sanitizedPatternDataKey = sanitizeToSvgId(patternInfo?.dataKey || '')
|
|
131
138
|
|
|
132
139
|
return (
|
|
133
|
-
<div
|
|
134
|
-
{
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
<div style={{ display: 'flex', alignItems: 'flex-start', flexWrap: 'nowrap', whiteSpace: 'nowrap' }}>
|
|
141
|
+
<div style={{ flexShrink: 0 }}>
|
|
142
|
+
{validColor ? (
|
|
143
|
+
patternInfo ? (
|
|
144
|
+
<LegendShape
|
|
145
|
+
fill={legendColor[0]}
|
|
146
|
+
patternInfo={{
|
|
147
|
+
pattern: patternInfo.pattern,
|
|
148
|
+
patternId: `${mapId}--${sanitizedPatternDataKey}--${patternInfo.patternIndex}--table`,
|
|
149
|
+
size: patternInfo.size,
|
|
150
|
+
color: patternInfo.color
|
|
151
|
+
}}
|
|
152
|
+
/>
|
|
153
|
+
) : (
|
|
154
|
+
<LegendShape fill={legendColor[0]} />
|
|
155
|
+
)
|
|
145
156
|
) : (
|
|
146
|
-
<
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
<div className='d-inline-block me-2' style={{ width: '1rem', height: '1rem' }} />
|
|
150
|
-
)}
|
|
157
|
+
<div className='me-2' style={{ width: '1rem', height: '1rem' }} />
|
|
158
|
+
)}
|
|
159
|
+
</div>
|
|
151
160
|
<CellAnchor
|
|
152
161
|
markup={labelValue}
|
|
153
162
|
row={rowObj}
|
|
@@ -160,7 +169,8 @@ const mapCellArray = ({
|
|
|
160
169
|
} else {
|
|
161
170
|
const rowData = runtimeData[row]
|
|
162
171
|
const dataValue = getDataValue(config, rowData, column)
|
|
163
|
-
|
|
172
|
+
const text = displayDataAsText(dataValue, column, config)
|
|
173
|
+
return typeof text === 'string' ? parse(text) : text
|
|
164
174
|
}
|
|
165
175
|
})
|
|
166
176
|
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest'
|
|
2
2
|
import { getMapRowData } from '../mapCellMatrix'
|
|
3
|
+
import { getMapDataTableColumnKeys } from '../getMapDataTableColumnKeys'
|
|
3
4
|
|
|
4
5
|
describe('getMapRowData', () => {
|
|
5
6
|
const columns = {
|
|
@@ -77,4 +78,36 @@ describe('getMapRowData', () => {
|
|
|
77
78
|
}
|
|
78
79
|
])
|
|
79
80
|
})
|
|
81
|
+
|
|
82
|
+
it('orders visible columns using display order instead of config key order', () => {
|
|
83
|
+
const orderedConfig = {
|
|
84
|
+
...config,
|
|
85
|
+
general: { ...config.general, geoType: 'us-state' }
|
|
86
|
+
}
|
|
87
|
+
const orderedColumns = {
|
|
88
|
+
geo: { dataTable: true, name: 'geo', label: 'Geo', order: 3 },
|
|
89
|
+
column1: { dataTable: true, name: 'column1', label: 'Column 1', order: 2 },
|
|
90
|
+
column2: { dataTable: true, name: 'column2', label: 'Column 2', order: 1 },
|
|
91
|
+
hidden: { dataTable: false, name: 'hidden', label: 'Hidden', order: 4 }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
expect(getMapDataTableColumnKeys(orderedColumns)).toEqual(['column2', 'column1', 'geo'])
|
|
95
|
+
|
|
96
|
+
const orderedResult = getMapRowData(
|
|
97
|
+
rows,
|
|
98
|
+
orderedColumns,
|
|
99
|
+
orderedConfig,
|
|
100
|
+
formatLegendLocation,
|
|
101
|
+
runtimeData,
|
|
102
|
+
displayGeoName,
|
|
103
|
+
[]
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
expect(Object.keys(orderedResult[0])).toEqual(['Column 2', 'Column 1', 'Geo'])
|
|
107
|
+
expect(orderedResult[0]).toEqual({
|
|
108
|
+
'Column 2': 'data4',
|
|
109
|
+
'Column 1': 'data3',
|
|
110
|
+
Geo: 'displayGeoName -> row2'
|
|
111
|
+
})
|
|
112
|
+
})
|
|
80
113
|
})
|
|
@@ -6,14 +6,22 @@ import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
|
|
|
6
6
|
type DownloadButtonProps = {
|
|
7
7
|
rawData: any[]
|
|
8
8
|
fileName: string
|
|
9
|
-
|
|
10
|
-
skipId: string | number
|
|
9
|
+
skipId?: string | number
|
|
11
10
|
configUrl?: string
|
|
12
11
|
interactionLabel?: string
|
|
13
12
|
title?: string
|
|
13
|
+
config?: any
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const DownloadButton = ({
|
|
16
|
+
const DownloadButton = ({
|
|
17
|
+
rawData,
|
|
18
|
+
fileName,
|
|
19
|
+
skipId,
|
|
20
|
+
interactionLabel,
|
|
21
|
+
configUrl,
|
|
22
|
+
title,
|
|
23
|
+
config
|
|
24
|
+
}: DownloadButtonProps) => {
|
|
17
25
|
const linkRef = useRef<HTMLAnchorElement>(null)
|
|
18
26
|
|
|
19
27
|
const handleDownload = (event: React.MouseEvent<HTMLAnchorElement>) => {
|
|
@@ -59,13 +67,13 @@ const DownloadButton = ({ rawData, fileName, headerColor, skipId, interactionLab
|
|
|
59
67
|
type='button'
|
|
60
68
|
onClick={handleDownload}
|
|
61
69
|
aria-label='Download this data in a CSV file format.'
|
|
62
|
-
className=
|
|
63
|
-
id={`${skipId}`}
|
|
70
|
+
className='no-border'
|
|
71
|
+
id={skipId != null ? `${skipId}` : undefined}
|
|
64
72
|
data-html2canvas-ignore
|
|
65
73
|
role='button'
|
|
66
74
|
style={{ cursor: 'pointer' }}
|
|
67
75
|
>
|
|
68
|
-
Download Data (CSV)
|
|
76
|
+
{config?.table?.downloadDataLabel || 'Download Data (CSV)'}
|
|
69
77
|
</a>
|
|
70
78
|
)
|
|
71
79
|
}
|