@cdc/core 4.25.8 → 4.25.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/_stories/StoryRenderingTests.stories.tsx +164 -0
- package/components/AdvancedEditor/AdvancedEditor.tsx +32 -9
- package/components/CustomColorsEditor/CustomColorsEditor.css +299 -0
- package/components/CustomColorsEditor/CustomColorsEditor.tsx +209 -0
- package/components/CustomColorsEditor/index.ts +1 -0
- package/components/DataTable/DataTable.tsx +56 -38
- package/components/DataTable/DataTableStandAlone.tsx +8 -3
- package/components/DataTable/components/ChartHeader.tsx +44 -14
- package/components/DataTable/components/DataTableEditorPanel.tsx +12 -2
- package/components/DataTable/components/ExpandCollapse.tsx +10 -1
- package/components/DataTable/components/MapHeader.tsx +24 -13
- package/components/DataTable/data-table.css +12 -0
- package/components/DataTable/helpers/chartCellMatrix.tsx +11 -8
- package/components/DataTable/helpers/mapCellMatrix.tsx +33 -4
- package/components/DataTable/helpers/standardizeState.js +2 -2
- package/components/DataTable/helpers/tests/standardizeState.test.js +54 -0
- package/components/DownloadButton.tsx +40 -14
- package/components/EditorPanel/DataTableEditor.tsx +3 -3
- package/components/EditorPanel/EditorPanel.styles.css +423 -0
- package/components/EditorPanel/FootnotesEditor.tsx +44 -37
- package/components/EditorPanel/Inputs.tsx +12 -2
- package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +35 -62
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +12 -2
- package/components/EditorPanel/components/MarkupHighlightedTextField.tsx +227 -0
- package/components/EditorPanel/components/MarkupVariablesEditor.tsx +450 -0
- package/components/EditorPanel/components/PanelMarkup.tsx +59 -0
- package/components/ErrorBoundary.jsx +3 -1
- package/components/Filters/Filters.tsx +52 -24
- package/components/Filters/components/Dropdown.tsx +6 -1
- package/components/Filters/components/Tabs.tsx +1 -0
- package/components/Footnotes/Footnotes.tsx +35 -25
- package/components/Footnotes/FootnotesStandAlone.tsx +42 -6
- package/components/HeaderThemeSelector/HeaderThemeSelector.css +43 -0
- package/components/HeaderThemeSelector/HeaderThemeSelector.stories.tsx +74 -0
- package/components/HeaderThemeSelector/HeaderThemeSelector.tsx +61 -0
- package/components/HeaderThemeSelector/index.ts +2 -0
- package/components/Layout/styles/editor.scss +2 -1
- package/components/Legend/Legend.Gradient.tsx +3 -6
- package/components/LegendShape.tsx +121 -3
- package/components/Loader/Loader.tsx +1 -1
- package/components/MediaControls.tsx +72 -21
- package/components/PaletteConversionModal.tsx +90 -0
- package/components/PaletteSelector/DeveloperPaletteRollback.tsx +114 -0
- package/components/PaletteSelector/PaletteSelector.css +94 -0
- package/components/PaletteSelector/PaletteSelector.tsx +112 -0
- package/components/PaletteSelector/index.ts +2 -0
- package/components/RichTooltip/RichTooltip.tsx +1 -0
- package/components/Table/Table.tsx +3 -1
- package/components/Table/components/Cell.tsx +23 -2
- package/components/Table/components/Row.tsx +5 -3
- package/components/_stories/BlurStrokeTest.stories.tsx +1 -1
- package/components/_stories/DataTable.stories.tsx +1 -1
- package/components/_stories/Filters.stories.tsx +21 -2
- package/components/_stories/Footnotes.CSV.stories.tsx +247 -0
- package/components/_stories/Footnotes.stories.tsx +769 -4
- package/components/_stories/Inputs.stories.tsx +3 -3
- package/components/_stories/MultiSelect.stories.tsx +3 -3
- package/components/_stories/NestedDropdown.stories.tsx +1 -1
- package/components/_stories/Table.stories.tsx +1 -1
- package/components/_stories/styles.scss +0 -1
- package/components/elements/_stories/Button.stories.tsx +1 -1
- package/components/elements/_stories/Card.stories.tsx +1 -1
- package/components/inputs/InputToggle.tsx +2 -0
- package/components/managers/DataDesigner.tsx +10 -9
- package/components/managers/_stories/DataDesigner.stories.tsx +1 -1
- package/components/ui/Accordion.jsx +1 -1
- package/components/ui/Tooltip.tsx +2 -1
- package/components/ui/_stories/Accordion.stories.tsx +1 -1
- package/components/ui/_stories/ColorPaletteMigration.stories.mdx +275 -0
- package/components/ui/_stories/Colors.stories.tsx +330 -0
- package/components/ui/_stories/IconGallery.stories.tsx +316 -0
- package/components/ui/_stories/Title.stories.tsx +1 -1
- package/components/ui/accordion.styles.css +57 -0
- package/contexts/EditorContext.ts +18 -0
- package/contexts/editor.actions.ts +28 -0
- package/contexts/editor.reducer.ts +94 -0
- package/data/chartColorPalettes.ts +118 -0
- package/data/colorPalettes.ts +9 -0
- package/data/mapColorPalettes.ts +45 -0
- package/data/sharedPalettes.ts +50 -0
- package/dist/cove-main.css +63 -14
- package/dist/cove-main.css.map +1 -1
- package/generateViteConfig.js +80 -0
- package/helpers/addValuesToFilters.ts +7 -3
- package/helpers/cloneConfig.ts +31 -0
- package/helpers/configDataHelpers.ts +128 -0
- package/helpers/configHelpers.ts +27 -0
- package/helpers/constants.ts +42 -2
- package/helpers/cove/number.ts +33 -12
- package/helpers/coveUpdateWorker.ts +15 -3
- package/helpers/fetchRemoteData.ts +3 -15
- package/helpers/filterColorPalettes.ts +152 -0
- package/helpers/generateColorsArray.ts +13 -0
- package/helpers/getColorPaletteVersion.ts +33 -0
- package/helpers/getPaletteAccessor.ts +18 -0
- package/helpers/markupProcessor.ts +220 -0
- package/helpers/mergeCustomOrderValues.ts +37 -0
- package/helpers/metrics/helpers.ts +42 -19
- package/helpers/metrics/types.ts +48 -9
- package/helpers/metrics/utils.ts +34 -0
- package/helpers/palettes/colorDistributions.ts +56 -0
- package/helpers/palettes/migratePaletteName.ts +150 -0
- package/helpers/palettes/standardizePaletteNames.ts +77 -0
- package/helpers/palettes/utils.ts +267 -0
- package/helpers/parseCsvWithQuotes.ts +65 -0
- package/helpers/queryStringUtils.ts +13 -0
- package/helpers/testing.ts +358 -0
- package/helpers/tests/addValuesToFilters.test.ts +1 -2
- package/helpers/tests/generateColorsArray.test.ts +24 -0
- package/helpers/tests/markupProcessor.test.ts +538 -0
- package/helpers/tests/testStandaloneBuild.ts +44 -0
- package/helpers/useMarkupVariables.ts +31 -0
- package/helpers/vegaConfig.ts +0 -1
- package/helpers/ver/4.24.10.ts +2 -1
- package/helpers/ver/4.24.11.ts +2 -1
- package/helpers/ver/4.24.3.ts +2 -1
- package/helpers/ver/4.24.4.ts +2 -1
- package/helpers/ver/4.24.5.ts +2 -1
- package/helpers/ver/4.24.7.ts +2 -1
- package/helpers/ver/4.24.9.ts +2 -1
- package/helpers/ver/4.25.1.ts +2 -1
- package/helpers/ver/4.25.10.ts +36 -0
- package/helpers/ver/4.25.11.ts +13 -0
- package/helpers/ver/4.25.3.ts +2 -1
- package/helpers/ver/4.25.4.ts +2 -1
- package/helpers/ver/4.25.6.ts +2 -1
- package/helpers/ver/4.25.7.ts +2 -1
- package/helpers/ver/4.25.8.ts +2 -1
- package/helpers/ver/4.25.9.ts +293 -0
- package/helpers/ver/tests/4.25.10.test.ts +204 -0
- package/helpers/ver/tests/4.25.8.test.ts +1 -1
- package/helpers/ver/tests/4.25.9.test.ts +51 -0
- package/helpers/viewports.ts +2 -0
- package/hooks/useColorPalette.ts +79 -0
- package/package.json +13 -4
- package/styles/_common-components.css +73 -0
- package/styles/_global.scss +32 -10
- package/styles/base.scss +8 -55
- package/styles/cove-main.scss +3 -1
- package/styles/filters.scss +10 -3
- package/styles/v2/base/index.scss +0 -1
- package/styles/v2/components/button.scss +4 -3
- package/styles/v2/components/editor.scss +16 -7
- package/styles/v2/layout/_data-table.scss +3 -2
- package/styles/v2/themes/_color-definitions.scss +18 -17
- package/styles/v2/utils/_breakpoints.scss +1 -1
- package/styles/v2/utils/index.scss +0 -1
- package/styles/waiting.scss +1 -1
- package/testing-setup.js +32 -0
- package/types/MarkupInclude.ts +8 -2
- package/types/MarkupVariable.ts +19 -0
- package/types/VizFilter.ts +2 -0
- package/vitest.config.ts +16 -0
- package/components/ui/_stories/Colors.stories.mdx +0 -220
- package/components/ui/_stories/IconGallery.stories.mdx +0 -14
- package/data/colorPalettes.js +0 -171
- package/helpers/formatConfigBeforeSave.ts +0 -135
- package/helpers/tests/formatConfigBeforeSave.test.ts +0 -68
- package/styles/_mixins.scss +0 -13
- package/styles/v2/base/_typography.scss +0 -0
- package/styles/v2/components/guidance-block.scss +0 -74
- package/styles/v2/utils/_functions.scss +0 -0
- /package/{styles/_typography.scss → testBuild.js} +0 -0
|
@@ -31,7 +31,6 @@ const chartCellArray = ({
|
|
|
31
31
|
const groupBy = config.table?.groupBy
|
|
32
32
|
const dataSeriesColumns = getDataSeriesColumns(config, isVertical, runtimeData)
|
|
33
33
|
|
|
34
|
-
|
|
35
34
|
const dataSeriesColumnsSorted = () => {
|
|
36
35
|
if (!sortBy && sortBy.colIndex === null) return dataSeriesColumns
|
|
37
36
|
return dataSeriesColumns.sort((a, b) => {
|
|
@@ -73,10 +72,14 @@ const chartCellArray = ({
|
|
|
73
72
|
return rows.map(row => {
|
|
74
73
|
if (hasRowType) {
|
|
75
74
|
const rowType = getRowType(runtimeData[row])
|
|
76
|
-
const rowValues = dataSeriesColumns.map(column =>
|
|
75
|
+
const rowValues = dataSeriesColumns.map(column =>
|
|
76
|
+
getChartCellValue(row, column, config, runtimeData, rightAxisItemsMap)
|
|
77
|
+
)
|
|
77
78
|
return [rowType, ...rowValues]
|
|
78
79
|
} else {
|
|
79
|
-
return dataSeriesColumns.map((column, j) =>
|
|
80
|
+
return dataSeriesColumns.map((column, j) =>
|
|
81
|
+
getChartCellValue(row, column, config, runtimeData, rightAxisItemsMap)
|
|
82
|
+
)
|
|
80
83
|
}
|
|
81
84
|
})
|
|
82
85
|
}
|
|
@@ -86,11 +89,11 @@ const chartCellArray = ({
|
|
|
86
89
|
let nodes: ReactNode[] =
|
|
87
90
|
config.visualizationType !== 'Pie'
|
|
88
91
|
? [
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
<>
|
|
93
|
+
{colorScale && colorScale(seriesName) && <LegendShape fill={colorScale(seriesName)} />}
|
|
94
|
+
{parse(String(seriesName))}
|
|
95
|
+
</>
|
|
96
|
+
]
|
|
94
97
|
: []
|
|
95
98
|
return nodes.concat(rows.map((row, i) => getChartCellValue(row, column, config, runtimeData, rightAxisItemsMap)))
|
|
96
99
|
})
|
|
@@ -6,16 +6,28 @@ import { displayDataAsText } from '@cdc/core/helpers/displayDataAsText'
|
|
|
6
6
|
import _ from 'lodash'
|
|
7
7
|
import { applyLegendToRow } from '@cdc/map/src/helpers/applyLegendToRow'
|
|
8
8
|
import { hashObj } from '@cdc/map/src/helpers'
|
|
9
|
+
import { getPatternForRow } from '@cdc/map/src/helpers/getPatternForRow'
|
|
9
10
|
|
|
10
11
|
type MapRowsProps = DataTableProps & {
|
|
11
12
|
rows: string[]
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
const getGeoLabel = (config, row, formatLegendLocation, displayGeoName) => {
|
|
15
|
+
const getGeoLabel = (config, row, formatLegendLocation, displayGeoName, runtimeData = null) => {
|
|
15
16
|
const { geoType, type } = config.general
|
|
17
|
+
|
|
16
18
|
let labelValue
|
|
17
19
|
if (!['single-state', 'us-county'].includes(geoType) || type === 'us-geocode') {
|
|
20
|
+
// Use the row (UID) for lookup - this allows "US-AL" to become "Alabama"
|
|
18
21
|
labelValue = displayGeoName(row)
|
|
22
|
+
|
|
23
|
+
// If displayGeoName returned the same value (not found in lookups), use the raw imported data
|
|
24
|
+
if (labelValue === row && runtimeData && config.columns?.geo?.name) {
|
|
25
|
+
const rawGeoValue = runtimeData[row]?.[config.columns.geo.name]
|
|
26
|
+
if (rawGeoValue && rawGeoValue !== row) {
|
|
27
|
+
labelValue = rawGeoValue
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
19
31
|
labelValue = String(labelValue).startsWith('region') ? _.capitalize(labelValue) : labelValue
|
|
20
32
|
} else {
|
|
21
33
|
labelValue = formatLegendLocation(row)
|
|
@@ -57,7 +69,7 @@ export const getMapRowData = (
|
|
|
57
69
|
].map(column => {
|
|
58
70
|
const label = columns[column]?.label || columns[column]?.name || column
|
|
59
71
|
if (column === 'geo') {
|
|
60
|
-
dataRow[label] = getGeoLabel(config, row, formatLegendLocation, displayGeoName)
|
|
72
|
+
dataRow[label] = getGeoLabel(config, row, formatLegendLocation, displayGeoName, runtimeData)
|
|
61
73
|
} else if (filterColumns.includes(column)) {
|
|
62
74
|
dataRow[label] = runtimeData[row][column]
|
|
63
75
|
} else {
|
|
@@ -99,15 +111,32 @@ const mapCellArray = ({
|
|
|
99
111
|
if (!legendColor) {
|
|
100
112
|
console.error('No legend color found') // eslint-disable-line no-console
|
|
101
113
|
}
|
|
102
|
-
const labelValue = getGeoLabel(config, row, formatLegendLocation, displayGeoName)
|
|
114
|
+
const labelValue = getGeoLabel(config, row, formatLegendLocation, displayGeoName, runtimeData)
|
|
103
115
|
const mapZoomHandler =
|
|
104
116
|
type === 'bubble' && allowMapZoom && geoType === 'world' ? () => setFilteredCountryCode(row) : undefined
|
|
105
117
|
|
|
106
118
|
const validColor = legendColor && legendColor.length > 0 && !noColor
|
|
119
|
+
|
|
120
|
+
// Check for pattern information
|
|
121
|
+
const patternInfo = getPatternForRow(rowObj, config)
|
|
122
|
+
const mapId = config.runtime?.uniqueId || 'map'
|
|
123
|
+
|
|
107
124
|
return (
|
|
108
125
|
<div className='col-12'>
|
|
109
126
|
{validColor ? (
|
|
110
|
-
|
|
127
|
+
patternInfo ? (
|
|
128
|
+
<LegendShape
|
|
129
|
+
fill={legendColor[0]}
|
|
130
|
+
patternInfo={{
|
|
131
|
+
pattern: patternInfo.pattern,
|
|
132
|
+
patternId: `${mapId}--${patternInfo.dataKey}--${patternInfo.patternIndex}--table`,
|
|
133
|
+
size: patternInfo.size,
|
|
134
|
+
color: patternInfo.color
|
|
135
|
+
}}
|
|
136
|
+
/>
|
|
137
|
+
) : (
|
|
138
|
+
<LegendShape fill={legendColor[0]} />
|
|
139
|
+
)
|
|
111
140
|
) : (
|
|
112
141
|
<div className='d-inline-block me-2' style={{ width: '1rem', height: '1rem' }} />
|
|
113
142
|
)}
|
|
@@ -8,8 +8,8 @@ const states = {
|
|
|
8
8
|
CO: 'Colorado',
|
|
9
9
|
CT: 'Connecticut',
|
|
10
10
|
DE: 'Delaware',
|
|
11
|
-
DC: 'District
|
|
12
|
-
FM: 'Federated States
|
|
11
|
+
DC: 'District of Columbia',
|
|
12
|
+
FM: 'Federated States of Micronesia',
|
|
13
13
|
FL: 'Florida',
|
|
14
14
|
GA: 'Georgia',
|
|
15
15
|
GU: 'Guam',
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { standardizeStateName } from '../standardizeState'
|
|
2
|
+
|
|
3
|
+
describe('standardizeStateName', () => {
|
|
4
|
+
it('should return non-string values unchanged', () => {
|
|
5
|
+
expect(standardizeStateName(123)).toBe(123)
|
|
6
|
+
expect(standardizeStateName(null)).toBe(null)
|
|
7
|
+
expect(standardizeStateName(undefined)).toBe(undefined)
|
|
8
|
+
expect(standardizeStateName(true)).toBe(true)
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('should return numeric strings unchanged', () => {
|
|
12
|
+
expect(standardizeStateName('123')).toBe('123')
|
|
13
|
+
expect(standardizeStateName('456.78')).toBe('456.78')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should convert state abbreviations to full names', () => {
|
|
17
|
+
expect(standardizeStateName('DC')).toBe('District of Columbia')
|
|
18
|
+
expect(standardizeStateName('dc')).toBe('District of Columbia')
|
|
19
|
+
expect(standardizeStateName('CA')).toBe('California')
|
|
20
|
+
expect(standardizeStateName('ca')).toBe('California')
|
|
21
|
+
expect(standardizeStateName('FM')).toBe('Federated States of Micronesia')
|
|
22
|
+
expect(standardizeStateName('fm')).toBe('Federated States of Micronesia')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('should handle Virgin Islands variations', () => {
|
|
26
|
+
expect(standardizeStateName('VI')).toBe('U.S. VIRGIN ISLANDS')
|
|
27
|
+
expect(standardizeStateName('vi')).toBe('U.S. VIRGIN ISLANDS')
|
|
28
|
+
expect(standardizeStateName('Virgin Islands')).toBe('U.S. VIRGIN ISLANDS')
|
|
29
|
+
expect(standardizeStateName('VIRGIN ISLANDS')).toBe('U.S. VIRGIN ISLANDS')
|
|
30
|
+
expect(standardizeStateName('U.S. Virgin Islands')).toBe('U.S. VIRGIN ISLANDS')
|
|
31
|
+
expect(standardizeStateName('US VIRGIN ISLANDS')).toBe('U.S. VIRGIN ISLANDS')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should verify "of" is lowercase in state names', () => {
|
|
35
|
+
const dcName = standardizeStateName('DC')
|
|
36
|
+
expect(dcName).toContain('of')
|
|
37
|
+
expect(dcName).not.toContain('Of')
|
|
38
|
+
|
|
39
|
+
const fmName = standardizeStateName('FM')
|
|
40
|
+
expect(fmName).toContain('of')
|
|
41
|
+
expect(fmName).not.toContain('Of')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('should return original value for unknown state codes', () => {
|
|
45
|
+
expect(standardizeStateName('ZZ')).toBe('ZZ')
|
|
46
|
+
expect(standardizeStateName('Unknown State')).toBe('Unknown State')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('should handle mixed case state names', () => {
|
|
50
|
+
expect(standardizeStateName('California')).toBe('California')
|
|
51
|
+
expect(standardizeStateName('CALIFORNIA')).toBe('CALIFORNIA')
|
|
52
|
+
expect(standardizeStateName('cAlIfOrNiA')).toBe('cAlIfOrNiA')
|
|
53
|
+
})
|
|
54
|
+
})
|
|
@@ -1,43 +1,69 @@
|
|
|
1
|
+
import { useRef } from 'react'
|
|
1
2
|
import Papa from 'papaparse'
|
|
2
3
|
import { publishAnalyticsEvent } from '../helpers/metrics/helpers'
|
|
4
|
+
import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
|
|
3
5
|
|
|
4
6
|
type DownloadButtonProps = {
|
|
5
|
-
rawData:
|
|
7
|
+
rawData: any[]
|
|
6
8
|
fileName: string
|
|
7
9
|
headerColor: string
|
|
8
10
|
skipId: string | number
|
|
9
11
|
configUrl?: string
|
|
12
|
+
interactionLabel?: string
|
|
13
|
+
title?: string
|
|
10
14
|
}
|
|
11
15
|
|
|
12
|
-
const DownloadButton = ({ rawData, fileName, headerColor, skipId, configUrl }: DownloadButtonProps) => {
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
const DownloadButton = ({ rawData, fileName, headerColor, skipId, interactionLabel, configUrl, title, config }: DownloadButtonProps) => {
|
|
17
|
+
const linkRef = useRef<HTMLAnchorElement>(null)
|
|
18
|
+
|
|
19
|
+
const handleDownload = (event: React.MouseEvent<HTMLAnchorElement>) => {
|
|
20
|
+
event.preventDefault()
|
|
21
|
+
|
|
22
|
+
const csvData = Papa.unparse(rawData)
|
|
23
|
+
|
|
24
|
+
// Prepend a Byte Order Mark (BOM) to the CSV data.
|
|
25
|
+
// The BOM is a special marker that helps applications like Excel recognize the file as UTF-8 encoded.
|
|
26
|
+
// Adding the BOM ensures that Excel interprets special characters correctly.
|
|
27
|
+
const bom = '\uFEFF'
|
|
28
|
+
const utf8EncodedCsvData = new TextEncoder().encode(bom + csvData)
|
|
29
|
+
const blob = new Blob([utf8EncodedCsvData], { type: 'text/csv;charset=utf-8;' })
|
|
30
|
+
|
|
31
|
+
const url = URL.createObjectURL(blob)
|
|
20
32
|
|
|
21
|
-
const saveBlob = () => {
|
|
22
33
|
//@ts-ignore
|
|
23
34
|
if (typeof window.navigator.msSaveBlob === 'function') {
|
|
24
35
|
//@ts-ignore
|
|
25
36
|
navigator.msSaveBlob(blob, fileName)
|
|
37
|
+
} else {
|
|
38
|
+
const downloadLink = document.createElement('a')
|
|
39
|
+
downloadLink.href = url
|
|
40
|
+
downloadLink.download = fileName
|
|
41
|
+
document.body.appendChild(downloadLink)
|
|
42
|
+
downloadLink.click()
|
|
43
|
+
document.body.removeChild(downloadLink)
|
|
26
44
|
}
|
|
27
|
-
|
|
45
|
+
URL.revokeObjectURL(url)
|
|
46
|
+
publishAnalyticsEvent({
|
|
47
|
+
vizType: config.type,
|
|
48
|
+
vizSubType: getVizSubType(config),
|
|
49
|
+
eventType: 'data_downloaded',
|
|
50
|
+
eventAction: 'click',
|
|
51
|
+
eventLabel: interactionLabel || configUrl,
|
|
52
|
+
vizTitle: getVizTitle(config)
|
|
53
|
+
})
|
|
28
54
|
}
|
|
29
55
|
|
|
30
56
|
return (
|
|
31
57
|
<a
|
|
32
|
-
|
|
58
|
+
ref={linkRef}
|
|
33
59
|
type='button'
|
|
34
|
-
onClick={
|
|
35
|
-
href={URL.createObjectURL(blob)}
|
|
60
|
+
onClick={handleDownload}
|
|
36
61
|
aria-label='Download this data in a CSV file format.'
|
|
37
62
|
className={`${headerColor} no-border`}
|
|
38
63
|
id={`${skipId}`}
|
|
39
64
|
data-html2canvas-ignore
|
|
40
65
|
role='button'
|
|
66
|
+
style={{ cursor: 'pointer' }}
|
|
41
67
|
>
|
|
42
68
|
Download Data (CSV)
|
|
43
69
|
</a>
|
|
@@ -21,9 +21,9 @@ const DataTableEditor: React.FC<DataTableProps> = ({ config, updateField, isDash
|
|
|
21
21
|
const isLoadedFromUrl = config.dataKey?.includes('http://') || config?.dataKey?.includes('https://')
|
|
22
22
|
const excludedColumns = useMemo(() => {
|
|
23
23
|
return Object.keys(config.columns)
|
|
24
|
-
.map<[string, boolean]>(key => [key, config.columns[key].dataTable])
|
|
25
|
-
.filter(([
|
|
26
|
-
.map(([
|
|
24
|
+
.map<[string, boolean]>(key => [config.columns[key].name, config.columns[key].dataTable])
|
|
25
|
+
.filter(([columnName, dataTable]) => !dataTable && columnName) // also filter out undefined names
|
|
26
|
+
.map(([columnName]) => columnName)
|
|
27
27
|
}, [config.columns])
|
|
28
28
|
|
|
29
29
|
const groupPivotColumns = useMemo(() => {
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
/* EditorPanel component styles */
|
|
2
|
+
/* Shared editor panel component styles used across all visualization packages */
|
|
3
|
+
|
|
4
|
+
/* Color palette in editor panel context */
|
|
5
|
+
.editor-panel .header .color-palette li {
|
|
6
|
+
width: 1.5em;
|
|
7
|
+
height: 1.5em;
|
|
8
|
+
display: inline-block;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.editor-panel .color-palette {
|
|
12
|
+
display: flex;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.editor-panel .color-palette li {
|
|
16
|
+
width: 1.5em;
|
|
17
|
+
height: 1.5em;
|
|
18
|
+
display: inline-block;
|
|
19
|
+
margin-right: 0.5em;
|
|
20
|
+
cursor: pointer;
|
|
21
|
+
border: rgba(0, 0, 0, 0.3) 3px solid;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.editor-panel .color-palette li.active {
|
|
25
|
+
border: rgba(0, 0, 0, 0.8) 3px solid;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.editor-panel .color-palette a {
|
|
29
|
+
display: inline-block;
|
|
30
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.8);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.editor-panel .color-palette.series-list {
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
padding: 0;
|
|
36
|
+
border: none;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.editor-panel .color-palette.series-list li {
|
|
40
|
+
padding: 0.3em 0.5em;
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: space-between;
|
|
44
|
+
width: auto;
|
|
45
|
+
height: auto;
|
|
46
|
+
border: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.editor-panel .color-palette.series-list li:not(:last-child) {
|
|
50
|
+
border-bottom: rgba(0, 0, 0, 0.2) 1px solid;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.editor-panel .form-container {
|
|
54
|
+
border-right: var(--lightGray) 1px solid;
|
|
55
|
+
flex-grow: 1;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.editor-panel .guidance-link {
|
|
59
|
+
margin: 2em 1em 0;
|
|
60
|
+
padding: 0.75em 1em;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.editor-panel .guidance-link svg {
|
|
64
|
+
width: 60px;
|
|
65
|
+
color: var(--blue);
|
|
66
|
+
margin-right: 1rem;
|
|
67
|
+
height: 60px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.editor-panel .guidance-link svg path {
|
|
71
|
+
fill: currentColor;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.editor-panel .warning {
|
|
75
|
+
color: #d8000c;
|
|
76
|
+
background-color: #ffd2d2;
|
|
77
|
+
padding: 0.75em 1em;
|
|
78
|
+
margin: 1em 0;
|
|
79
|
+
font-size: 0.8em;
|
|
80
|
+
border: #d8000c 1px solid;
|
|
81
|
+
border-radius: 0.4em;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.editor-panel .warning strong {
|
|
85
|
+
font-weight: 600;
|
|
86
|
+
display: block;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.editor-panel .advanced {
|
|
90
|
+
padding: 0 1em 1em;
|
|
91
|
+
text-align: left;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.editor-panel .advanced p {
|
|
95
|
+
font-size: 0.8rem;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.editor-panel .advanced .advanced-toggle-link {
|
|
99
|
+
padding-top: 1em;
|
|
100
|
+
display: block;
|
|
101
|
+
text-align: left;
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
text-decoration: underline;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.editor-panel .advanced .advanced-toggle-link span {
|
|
107
|
+
text-decoration: none;
|
|
108
|
+
display: inline-block;
|
|
109
|
+
font-family: monospace;
|
|
110
|
+
padding-right: 5px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.editor-panel .advanced .advanced-toggle-link:hover {
|
|
114
|
+
color: rgba(0, 0, 0, 0.7);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.editor-panel .advanced textarea {
|
|
118
|
+
height: 400px;
|
|
119
|
+
width: 100%;
|
|
120
|
+
font-size: 0.9em;
|
|
121
|
+
padding: 0.5em;
|
|
122
|
+
font-family: monospace;
|
|
123
|
+
box-sizing: border-box;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.editor-panel .heading-2 {
|
|
127
|
+
background: #565656;
|
|
128
|
+
color: #fff;
|
|
129
|
+
font-size: 1.1em;
|
|
130
|
+
padding: 0.6em 1em;
|
|
131
|
+
position: relative;
|
|
132
|
+
border-bottom: #565656 3px solid;
|
|
133
|
+
z-index: 3;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.editor-panel label {
|
|
137
|
+
text-transform: uppercase;
|
|
138
|
+
display: block;
|
|
139
|
+
font-size: 0.8em;
|
|
140
|
+
font-weight: 600;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.editor-panel label:not(:first-child) {
|
|
144
|
+
margin-top: 1em;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.editor-panel label span.edit-label {
|
|
148
|
+
margin-bottom: 0.3em;
|
|
149
|
+
display: block;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.editor-panel label span.column-heading {
|
|
153
|
+
font-size: 1em;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.editor-panel label.checkbox {
|
|
157
|
+
display: flex;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.editor-panel label.checkbox span {
|
|
161
|
+
text-transform: none;
|
|
162
|
+
font-size: 1em;
|
|
163
|
+
font-weight: 400;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.editor-panel label.checkbox input {
|
|
167
|
+
margin-top: 0;
|
|
168
|
+
margin-right: 0.5em;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.editor-panel input[type='checkbox'],
|
|
172
|
+
.editor-panel input[type='radio'] {
|
|
173
|
+
display: inline-block;
|
|
174
|
+
width: auto !important;
|
|
175
|
+
height: auto !important;
|
|
176
|
+
padding: 0;
|
|
177
|
+
margin-right: 0.5em;
|
|
178
|
+
cursor: pointer;
|
|
179
|
+
user-select: none;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.editor-panel input[type='text'],
|
|
183
|
+
.editor-panel input[role='combobox'],
|
|
184
|
+
.editor-panel input[type='number'],
|
|
185
|
+
.editor-panel textarea {
|
|
186
|
+
padding: 0.5em;
|
|
187
|
+
width: 100%;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.editor-panel fieldset {
|
|
191
|
+
padding-left: 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.editor-panel .primary-fieldset {
|
|
195
|
+
border-top: rgba(0, 0, 0, 0.3) 2px solid;
|
|
196
|
+
padding-top: 2em;
|
|
197
|
+
margin-top: 2em;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.editor-panel ul.column-edit {
|
|
201
|
+
list-style: none;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.editor-panel ul.column-edit li {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex-wrap: wrap;
|
|
207
|
+
justify-content: space-between;
|
|
208
|
+
padding: 0.3em 0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.editor-panel ul.column-edit li label {
|
|
212
|
+
display: inline-block;
|
|
213
|
+
width: 48%;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.editor-panel ul.column-edit li label:nth-child(odd) {
|
|
217
|
+
margin-top: 1em;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.editor-panel ul.column-edit.three-col li label {
|
|
221
|
+
width: 31%;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.editor-panel .edit-block {
|
|
225
|
+
border: 1px solid rgba(0, 0, 0, 0.3);
|
|
226
|
+
padding: 1em;
|
|
227
|
+
margin-top: 1em;
|
|
228
|
+
position: relative;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.editor-panel .edit-block .remove-column {
|
|
232
|
+
position: absolute;
|
|
233
|
+
top: 0;
|
|
234
|
+
right: 0;
|
|
235
|
+
border: 0;
|
|
236
|
+
background: rgba(0, 0, 0, 0.1);
|
|
237
|
+
color: #000;
|
|
238
|
+
font-size: 0.8em;
|
|
239
|
+
padding: 0.3em;
|
|
240
|
+
cursor: pointer;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.editor-panel span.subtext {
|
|
244
|
+
text-transform: none;
|
|
245
|
+
display: block;
|
|
246
|
+
font-size: 0.8em;
|
|
247
|
+
font-weight: 400;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.editor-panel .sort-list {
|
|
251
|
+
list-style: none;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.editor-panel .sort-list li {
|
|
255
|
+
border: 1px solid rgba(0, 0, 0, 0.2);
|
|
256
|
+
padding: 0.3em;
|
|
257
|
+
display: flex;
|
|
258
|
+
align-items: center;
|
|
259
|
+
cursor: move;
|
|
260
|
+
margin-bottom: 0.3em;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.editor-panel .sort-list li svg {
|
|
264
|
+
margin-right: 0.5em;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.editor-panel .info {
|
|
268
|
+
margin-top: 1em;
|
|
269
|
+
font-size: 0.9em;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* React Tags Component styles (third-party library) */
|
|
273
|
+
.editor-panel .react-tags__search {
|
|
274
|
+
width: 100%;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.editor-panel .react-tags {
|
|
278
|
+
position: relative;
|
|
279
|
+
cursor: text;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.editor-panel .react-tags input.react-tags__search-input {
|
|
283
|
+
font-size: 0.8rem;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.editor-panel .react-tags span {
|
|
287
|
+
display: inline;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.editor-panel .react-tags.is-focused {
|
|
291
|
+
border-color: rgba(0, 0, 0, 0.7);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.editor-panel .react-tags__selected {
|
|
295
|
+
display: inline;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.editor-panel .react-tags__selected-tag {
|
|
299
|
+
display: inline-block;
|
|
300
|
+
box-sizing: border-box;
|
|
301
|
+
border: 1px solid #d1d1d1;
|
|
302
|
+
border-radius: 2px;
|
|
303
|
+
background: #f1f1f1;
|
|
304
|
+
padding: 0.4em 0.6em;
|
|
305
|
+
font-size: 0.8em;
|
|
306
|
+
margin-right: 0.3em;
|
|
307
|
+
margin-bottom: 0.3em;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.editor-panel .react-tags__selected-tag:after {
|
|
311
|
+
content: '\2715';
|
|
312
|
+
color: #aaa;
|
|
313
|
+
margin-left: 8px;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.editor-panel .react-tags__selected-tag:hover,
|
|
317
|
+
.editor-panel .react-tags__selected-tag:focus {
|
|
318
|
+
border-color: #b1b1b1;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.editor-panel .react-tags__search {
|
|
322
|
+
display: inline-block;
|
|
323
|
+
max-width: 100%;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@media screen and (min-width: 30em) {
|
|
327
|
+
.editor-panel .react-tags__search {
|
|
328
|
+
position: relative;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.editor-panel .react-tags__search input {
|
|
333
|
+
max-width: 100%;
|
|
334
|
+
margin: 0;
|
|
335
|
+
outline: none;
|
|
336
|
+
padding: 0.5em 0.3em;
|
|
337
|
+
font-size: inherit;
|
|
338
|
+
line-height: inherit;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.editor-panel .react-tags__search input::-ms-clear {
|
|
342
|
+
display: none;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.editor-panel .react-tags__suggestions {
|
|
346
|
+
position: absolute;
|
|
347
|
+
top: 100%;
|
|
348
|
+
left: 0;
|
|
349
|
+
width: 100%;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
@media screen and (min-width: 30em) {
|
|
353
|
+
.editor-panel .react-tags__suggestions {
|
|
354
|
+
width: 240px;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.editor-panel .react-tags__suggestions ul {
|
|
359
|
+
margin: 4px -1px;
|
|
360
|
+
padding: 0;
|
|
361
|
+
list-style: none;
|
|
362
|
+
background: white;
|
|
363
|
+
border: 1px solid #d1d1d1;
|
|
364
|
+
border-radius: 2px;
|
|
365
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.editor-panel .react-tags__suggestions li {
|
|
369
|
+
border-bottom: 1px solid #ddd;
|
|
370
|
+
padding: 6px 8px;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.editor-panel .react-tags__suggestions li mark {
|
|
374
|
+
text-decoration: underline;
|
|
375
|
+
background: none;
|
|
376
|
+
font-weight: 600;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.editor-panel .react-tags__suggestions li:hover {
|
|
380
|
+
cursor: pointer;
|
|
381
|
+
background: #eee;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.editor-panel .react-tags__suggestions li.is-active {
|
|
385
|
+
background: #b7cfe0;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.editor-panel .react-tags__suggestions li.is-disabled {
|
|
389
|
+
opacity: 0.5;
|
|
390
|
+
cursor: auto;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.editor-toggle {
|
|
394
|
+
position: fixed;
|
|
395
|
+
top: 1em;
|
|
396
|
+
right: 1em;
|
|
397
|
+
background: var(--blue);
|
|
398
|
+
color: white;
|
|
399
|
+
border: 0;
|
|
400
|
+
border-radius: 0.5em;
|
|
401
|
+
padding: 0.5em 1em;
|
|
402
|
+
font-size: 1em;
|
|
403
|
+
cursor: pointer;
|
|
404
|
+
z-index: 9999999999;
|
|
405
|
+
display: none;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.editor-toggle.active {
|
|
409
|
+
display: block;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.editor-toggle:hover {
|
|
413
|
+
background: var(--darkBlue);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.editor-toggle svg {
|
|
417
|
+
height: 1em;
|
|
418
|
+
width: 1em;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
.editor-toggle svg path {
|
|
422
|
+
fill: currentColor;
|
|
423
|
+
}
|