@cdc/chart 4.23.10 → 4.24.1
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/dist/cdcchart.js +34606 -32218
- package/examples/feature/bar/additional-column-tooltip.json +446 -0
- package/examples/feature/bar/example-bar-chart.json +1 -46
- package/examples/feature/bar/lollipop.json +156 -0
- package/examples/feature/bar/tall-data.json +98 -0
- package/examples/feature/combo/planet-combo-example-config.json +99 -9
- package/examples/feature/dev-4261.json +399 -0
- package/examples/feature/forest-plot/forest-plot.json +63 -19
- package/examples/feature/forest-plot/{broken.json → linear.json} +77 -23
- package/examples/feature/forest-plot/log.json +26 -0
- package/examples/feature/forest-plot/logarithmic.json +271 -0
- package/examples/feature/line/line-chart-preliminary.json +346 -0
- package/examples/feature/line/line-points.json +340 -0
- package/examples/feature/regions/index.json +462 -0
- package/examples/feature/scatterplot/scatterplot.json +272 -33
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +181 -48
- package/examples/private/chart-t.json +3740 -0
- package/examples/private/combo.json +369 -0
- package/examples/private/epi-data.csv +13 -0
- package/examples/private/epi-data.json +62 -0
- package/examples/private/epi.json +403 -0
- package/examples/private/occupancy.json +109283 -0
- package/examples/private/prod-line-config.json +401 -0
- package/examples/private/region-data.json +822 -0
- package/examples/private/region-testing.json +312 -0
- package/examples/private/scaling.json +45325 -0
- package/examples/private/testing-data.json +1739 -0
- package/examples/private/testing.json +816 -0
- package/examples/sparkline-multilple.json +846 -0
- package/index.html +12 -8
- package/package.json +3 -3
- package/src/CdcChart.tsx +42 -211
- package/src/ConfigContext.tsx +6 -0
- package/src/_stories/Chart.stories.tsx +188 -0
- package/src/_stories/Chart.tooltip.stories.tsx +305 -0
- package/src/_stories/ChartBrush.stories.tsx +19 -0
- package/src/_stories/ChartEditor.stories.tsx +22 -0
- package/src/_stories/ChartLine.preliminary.tsx +19 -0
- package/src/_stories/ChartSuppress.stories.tsx +19 -0
- package/src/_stories/_mock/brush_mock.json +393 -0
- package/src/_stories/_mock/pie_config.json +191 -0
- package/src/_stories/_mock/pie_data.json +218 -0
- package/src/_stories/_mock/preliminary_mock.json +346 -0
- package/src/_stories/_mock/suppress_mock.json +911 -0
- package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +6 -7
- package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +7 -36
- package/src/components/AreaChart/index.tsx +4 -0
- package/src/components/{BarChart.Horizontal.jsx → BarChart/components/BarChart.Horizontal.tsx} +111 -34
- package/src/components/{BarChart.StackedHorizontal.jsx → BarChart/components/BarChart.StackedHorizontal.tsx} +55 -20
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +106 -0
- package/src/components/{BarChart.Vertical.jsx → BarChart/components/BarChart.Vertical.tsx} +162 -34
- package/src/components/BarChart/components/BarChart.jsx +39 -0
- package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
- package/src/components/BarChart/components/context.tsx +13 -0
- package/src/components/BarChart/index.tsx +3 -0
- package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +1 -1
- package/src/components/BoxPlot/index.tsx +3 -0
- package/src/components/DeviationBar.jsx +4 -3
- package/src/components/{EditorPanel.jsx → EditorPanel/EditorPanel.tsx} +807 -865
- package/src/components/EditorPanel/components/Panel.DateHighlighting.tsx +109 -0
- package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panel.ForestPlotSettings.tsx} +190 -220
- package/src/components/EditorPanel/components/Panel.Regions.tsx +168 -0
- package/src/components/{Series.jsx → EditorPanel/components/Panel.Series.tsx} +23 -4
- package/src/components/EditorPanel/components/PanelProps.ts +3 -0
- package/src/components/EditorPanel/components/Panels.tsx +13 -0
- package/src/components/EditorPanel/components/panels.scss +72 -0
- package/src/components/EditorPanel/editor-panel.scss +751 -0
- package/src/components/EditorPanel/index.tsx +3 -0
- package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +50 -5
- package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
- package/src/components/Forecasting/index.tsx +3 -0
- package/src/components/ForestPlot/ForestPlot.tsx +254 -0
- package/src/components/ForestPlot/ForestPlotProps.ts +18 -0
- package/src/components/ForestPlot/index.scss +1 -0
- package/src/components/ForestPlot/index.tsx +3 -0
- package/src/components/Legend/Legend.tsx +347 -0
- package/src/components/Legend/index.tsx +3 -0
- package/src/components/LineChart/LineChartProps.ts +46 -0
- package/src/components/{LineChart.Circle.tsx → LineChart/components/LineChart.Circle.tsx} +36 -30
- package/src/components/LineChart/helpers.ts +45 -0
- package/src/components/LineChart/index.scss +1 -0
- package/src/components/{LineChart.tsx → LineChart/index.tsx} +83 -42
- package/src/components/LinearChart.jsx +125 -82
- package/src/components/PairedBarChart.jsx +2 -2
- package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +16 -7
- package/src/components/PieChart/index.tsx +3 -0
- package/src/components/Regions/components/Regions.tsx +135 -0
- package/src/components/Regions/index.tsx +3 -0
- package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
- package/src/components/ScatterPlot/index.tsx +3 -0
- package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
- package/src/components/Sparkline/index.tsx +3 -0
- package/src/components/ZoomBrush.tsx +168 -0
- package/src/data/initial-state.js +30 -16
- package/src/helpers/abbreviateNumber.ts +17 -0
- package/src/helpers/computeMarginBottom.ts +55 -0
- package/src/helpers/filterData.ts +18 -0
- package/src/helpers/generateColorsArray.ts +8 -0
- package/src/helpers/getQuartiles.ts +30 -0
- package/src/helpers/handleChartAriaLabels.ts +19 -0
- package/src/helpers/handleLineType.ts +18 -0
- package/src/helpers/lineOptions.ts +18 -0
- package/src/helpers/sort.ts +7 -0
- package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
- package/src/hooks/useBarChart.js +72 -7
- package/src/hooks/useColorScale.ts +50 -0
- package/src/hooks/{useMinMax.js → useMinMax.ts} +75 -23
- package/src/hooks/{useRightAxis.js → useRightAxis.ts} +10 -2
- package/src/hooks/{useScales.js → useScales.ts} +64 -17
- package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +84 -55
- package/src/scss/main.scss +70 -38
- package/src/types/ChartConfig.ts +178 -0
- package/src/types/ChartContext.ts +54 -0
- package/src/types/ForestPlot.ts +53 -0
- package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
- package/src/ConfigContext.jsx +0 -5
- package/src/components/BarChart.StackedVertical.jsx +0 -95
- package/src/components/BarChart.jsx +0 -30
- package/src/components/ForestPlot.jsx +0 -191
- package/src/components/Legend.jsx +0 -277
- package/src/scss/LinearChart.scss +0 -0
- package/src/scss/editor-panel.scss +0 -745
- package/src/scss/legend.scss +0 -206
- package/src/scss/mixins.scss +0 -0
- package/src/scss/variables.scss +0 -1
package/index.html
CHANGED
|
@@ -34,19 +34,20 @@
|
|
|
34
34
|
-->
|
|
35
35
|
|
|
36
36
|
<!-- GENERIC CHART TYPES -->
|
|
37
|
-
<!-- <div class="react-container" data-config="/examples/private/line-
|
|
38
|
-
<!-- <div class="react-container" data-config="/examples/private/
|
|
39
|
-
<!-- <div class="react-container" data-config="/examples/feature/
|
|
40
|
-
<!-- <div class="react-container" data-config="/examples/private/tooltip-issue.json"></div> -->
|
|
37
|
+
<!-- <div class="react-container" data-config="/examples/private/prod-line-config.json"></div> -->
|
|
38
|
+
<!-- <div class="react-container" data-config="/examples/private/chart-t.json"></div> -->
|
|
39
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/additional-column-tooltip.json"></div> -->
|
|
41
40
|
<!-- <div class="react-container" data-config="https://cdc.gov/poxvirus/mpox/modules/data-viz/mpx-trends_1.json"></div> -->
|
|
42
41
|
<!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date-city-temperature.json"></div> -->
|
|
43
42
|
<!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date-apple.json"></div> -->
|
|
44
|
-
<!-- <div class="react-container" data-config="/examples/feature/
|
|
43
|
+
<!-- <div class="react-container" data-config="/examples/feature/forest-plot/linear.json"></div> -->
|
|
44
|
+
<!-- <div class="react-container" data-config="/examples/feature/forest-plot/logarithmic.json"></div> -->
|
|
45
45
|
<!-- <div class="react-container" data-config="/examples/feature/forest-plot/forest-plot.json"></div> -->
|
|
46
46
|
<!-- <div class="react-container" data-config="/examples/feature/pie/planet-pie-example-config.json"></div> -->
|
|
47
47
|
<!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Viz.json></div> -->
|
|
48
|
+
<!-- <div class="react-container" data-config=/examples/feature/regions/index.json></div> -->
|
|
49
|
+
<!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Regions_Viz.json></div> -->
|
|
48
50
|
<!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Regions_Viz.json></div> -->
|
|
49
|
-
<!-- <div class="react-container" data-config="/examples/feature/line/line-chart.json"></div> -->
|
|
50
51
|
<!-- <div class="react-container" data-config="/examples/feature/forecasting/forecasting.json"></div> -->
|
|
51
52
|
<!-- <div class="react-container" data-config="/examples/feature/forecasting/combo-forecasting.json"></div> -->
|
|
52
53
|
<!-- <div class="react-container" data-config="/examples/feature/forecasting/effective_reproduction.json"></div> -->
|
|
@@ -69,7 +70,7 @@
|
|
|
69
70
|
<!-- <div class="react-container" data-config="/examples/feature/bar/planet-chart-horizontal-example-config.json"></div> -->
|
|
70
71
|
|
|
71
72
|
<!-- SPARKLINE -->
|
|
72
|
-
<!-- <div class="react-container" data-config="/examples/feature/
|
|
73
|
+
<!-- <div class="react-container" data-config="/examples/feature/dev-4261.json"></div> -->
|
|
73
74
|
|
|
74
75
|
<!-- TESTS DATA TABLE SORTING -->
|
|
75
76
|
<!-- Bar Chart with Confidence Intervals (bottom of page) -->
|
|
@@ -103,6 +104,7 @@
|
|
|
103
104
|
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/example-combo-bar-nonnumeric.json"></div> -->
|
|
104
105
|
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/example-bar-chart-nonnumeric.json"></div> -->
|
|
105
106
|
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/sparkline-chart-nonnumeric.json"></div> -->
|
|
107
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/lollipop.json"></div> -->
|
|
106
108
|
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json"></div> -->
|
|
107
109
|
|
|
108
110
|
<!-- TESTS CUTOFF -->
|
|
@@ -121,6 +123,8 @@
|
|
|
121
123
|
|
|
122
124
|
<!-- GENERIC CHART TYPES -->
|
|
123
125
|
<!-- <div class="react-container" data-config="/examples/gallery/paired-bar/paired-bar-chart.json"></div> -->
|
|
126
|
+
<div class="react-container" data-config="/examples/feature/line/line-chart-preliminary.json"></div>
|
|
127
|
+
|
|
124
128
|
|
|
125
129
|
<!-- HORIZONTAL BAR CHARTS -->
|
|
126
130
|
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json"></div> -->
|
|
@@ -133,7 +137,7 @@
|
|
|
133
137
|
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json"></div> -->
|
|
134
138
|
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json"></div> -->
|
|
135
139
|
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart.json"></div> -->
|
|
136
|
-
<div class="react-container" data-config="https://www.cdc.gov/respiratory-viruses/modules/respiratory-virus-activity/emergency-dept-visits_live.json"></div>
|
|
140
|
+
<!-- <div class="react-container" data-config="https://www.cdc.gov/respiratory-viruses/modules/respiratory-virus-activity/emergency-dept-visits_live.json"></div> -->
|
|
137
141
|
|
|
138
142
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
139
143
|
</body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdc/chart",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.24.1",
|
|
4
4
|
"description": "React component for visualizing tabular data in various types of charts",
|
|
5
5
|
"moduleName": "CdcChart",
|
|
6
6
|
"main": "dist/cdcchart",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"js-base64": "^2.5.2",
|
|
49
49
|
"papaparse": "^5.3.0",
|
|
50
50
|
"react-accessible-accordion": "^3.3.4",
|
|
51
|
-
"react-icons": "^4.
|
|
51
|
+
"react-icons": "^4.11.0",
|
|
52
52
|
"react-spring": "^8.0.27",
|
|
53
53
|
"react-table": "^7.5.0",
|
|
54
54
|
"react-tooltip": "5.8.2-beta.3",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"react": "^18.2.0",
|
|
60
60
|
"react-dom": "^18.2.0"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "a352a3f74f4b681191e3244061dbb3621f36eec3",
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"resize-observer-polyfill": "^1.5.1"
|
|
65
65
|
}
|
package/src/CdcChart.tsx
CHANGED
|
@@ -12,19 +12,27 @@ import { timeParse, timeFormat } from 'd3-time-format'
|
|
|
12
12
|
import Papa from 'papaparse'
|
|
13
13
|
import parse from 'html-react-parser'
|
|
14
14
|
import 'react-tooltip/dist/react-tooltip.css'
|
|
15
|
-
import chroma from 'chroma-js'
|
|
16
15
|
|
|
17
16
|
// Primary Components
|
|
18
17
|
import ConfigContext from './ConfigContext'
|
|
19
|
-
import PieChart from './components/PieChart'
|
|
18
|
+
import PieChart from './components/PieChart/PieChart'
|
|
20
19
|
import LinearChart from './components/LinearChart'
|
|
21
20
|
|
|
22
21
|
import { colorPalettesChart as colorPalettes, twoColorPalette } from '@cdc/core/data/colorPalettes'
|
|
23
22
|
|
|
24
|
-
import SparkLine from './components/
|
|
23
|
+
import SparkLine from './components/Sparkline'
|
|
25
24
|
import Legend from './components/Legend'
|
|
26
25
|
import defaults from './data/initial-state'
|
|
27
26
|
import EditorPanel from './components/EditorPanel'
|
|
27
|
+
import { abbreviateNumber } from './helpers/abbreviateNumber'
|
|
28
|
+
import { getQuartiles } from './helpers/getQuartiles'
|
|
29
|
+
import { sortAsc, sortDesc } from './helpers/sort'
|
|
30
|
+
import { filterData } from './helpers/filterData'
|
|
31
|
+
import { handleChartAriaLabels } from './helpers/handleChartAriaLabels'
|
|
32
|
+
import { lineOptions } from './helpers/lineOptions'
|
|
33
|
+
import { handleLineType } from './helpers/handleLineType'
|
|
34
|
+
import { generateColorsArray } from './helpers/generateColorsArray'
|
|
35
|
+
import { computeMarginBottom } from './helpers/computeMarginBottom'
|
|
28
36
|
import Loading from '@cdc/core/components/Loading'
|
|
29
37
|
import Filters from '@cdc/core/components/Filters'
|
|
30
38
|
import MediaControls from '@cdc/core/components/MediaControls'
|
|
@@ -43,36 +51,7 @@ import './scss/main.scss'
|
|
|
43
51
|
// load both then config below determines which to use
|
|
44
52
|
import DataTable from '@cdc/core/components/DataTable'
|
|
45
53
|
import { getFileExtension } from '@cdc/core/helpers/getFileExtension'
|
|
46
|
-
|
|
47
|
-
const generateColorsArray = (color = '#000000', special = false) => {
|
|
48
|
-
let colorObj = chroma(color)
|
|
49
|
-
let hoverColor = special ? colorObj.brighten(0.5).hex() : colorObj.saturate(1.3).hex()
|
|
50
|
-
|
|
51
|
-
return [color, hoverColor, colorObj.darken(0.3).hex()]
|
|
52
|
-
}
|
|
53
|
-
const hashObj = row => {
|
|
54
|
-
try {
|
|
55
|
-
if (!row) throw new Error('No row supplied to hashObj')
|
|
56
|
-
|
|
57
|
-
let str = JSON.stringify(row)
|
|
58
|
-
let hash = 0
|
|
59
|
-
|
|
60
|
-
if (str.length === 0) return hash
|
|
61
|
-
|
|
62
|
-
for (let i = 0; i < str.length; i++) {
|
|
63
|
-
let char = str.charCodeAt(i)
|
|
64
|
-
hash = (hash << 5) - hash + char
|
|
65
|
-
hash = hash & hash
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return hash
|
|
69
|
-
} catch (e) {
|
|
70
|
-
console.error('COVE: ', e) // eslint-disable-line
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// * FILE REVIEW
|
|
75
|
-
// TODO: @tturnerswdev33 - remove/fix mentions of runtimeLegend that were added
|
|
54
|
+
import Title from '@cdc/core/components/ui/Title'
|
|
76
55
|
|
|
77
56
|
export default function CdcChart({ configUrl, config: configObj, isEditor = false, isDebug = false, isDashboard = false, setConfig: setParentConfig, setEditing, hostname, link, setSharedFilter, setSharedFilterValue, dashboardConfig }) {
|
|
78
57
|
const transform = new DataTransform()
|
|
@@ -90,7 +69,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
90
69
|
const [coveLoadedEventRan, setCoveLoadedEventRan] = useState(false)
|
|
91
70
|
const [dynamicLegendItems, setDynamicLegendItems] = useState<any[]>([])
|
|
92
71
|
const [imageId] = useState(`cove-${Math.random().toString(16).slice(-4)}`)
|
|
93
|
-
|
|
72
|
+
type Config = typeof config
|
|
94
73
|
let legendMemo = useRef(new Map()) // map collection
|
|
95
74
|
let innerContainerRef = useRef()
|
|
96
75
|
|
|
@@ -110,37 +89,9 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
110
89
|
|
|
111
90
|
const handleChartTabbing = config.showSidebar ? `#legend` : config?.title ? `#dataTableSection__${config.title.replace(/\s/g, '')}` : `#dataTableSection`
|
|
112
91
|
|
|
113
|
-
const sortAsc = (a, b) => {
|
|
114
|
-
return a.toString().localeCompare(b.toString(), 'en', { numeric: true })
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const sortDesc = (a, b) => {
|
|
118
|
-
return b.toString().localeCompare(a.toString(), 'en', { numeric: true })
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const handleChartAriaLabels = (state, testing = false) => {
|
|
122
|
-
if (testing) console.log(`handleChartAriaLabels Testing On:`, state) // eslint-disable-line
|
|
123
|
-
try {
|
|
124
|
-
if (!state.visualizationType) throw Error('handleChartAriaLabels: no visualization type found in state')
|
|
125
|
-
let ariaLabel = ''
|
|
126
|
-
|
|
127
|
-
if (state.visualizationType) {
|
|
128
|
-
ariaLabel += `${state.visualizationType} chart`
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (state.title && state.visualizationType) {
|
|
132
|
-
ariaLabel += ` with the title: ${state.title}`
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return ariaLabel
|
|
136
|
-
} catch (e) {
|
|
137
|
-
console.error('COVE: ', e.message) // eslint-disable-line
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
92
|
const reloadURLData = async () => {
|
|
142
93
|
if (config.dataUrl) {
|
|
143
|
-
const dataUrl = new URL(config.runtimeDataUrl || config.dataUrl)
|
|
94
|
+
const dataUrl = new URL(config.runtimeDataUrl || config.dataUrl, window.location.origin)
|
|
144
95
|
let qsParams = Object.fromEntries(new URLSearchParams(dataUrl.search))
|
|
145
96
|
|
|
146
97
|
let isUpdateNeeded = false
|
|
@@ -165,7 +116,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
165
116
|
let data: any[] = []
|
|
166
117
|
|
|
167
118
|
try {
|
|
168
|
-
const ext = getFileExtension(dataUrl.
|
|
119
|
+
const ext = getFileExtension(dataUrl.href)
|
|
169
120
|
if ('csv' === ext) {
|
|
170
121
|
data = await fetch(dataUrlFinal)
|
|
171
122
|
.then(response => response.text())
|
|
@@ -204,44 +155,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
204
155
|
}
|
|
205
156
|
}
|
|
206
157
|
|
|
207
|
-
const handleLineType = lineType => {
|
|
208
|
-
switch (lineType) {
|
|
209
|
-
case 'dashed-sm':
|
|
210
|
-
return '5 5'
|
|
211
|
-
case 'Dashed Small':
|
|
212
|
-
return '5 5'
|
|
213
|
-
case 'dashed-md':
|
|
214
|
-
return '10 5'
|
|
215
|
-
case 'Dashed Medium':
|
|
216
|
-
return '10 5'
|
|
217
|
-
case 'dashed-lg':
|
|
218
|
-
return '15 5'
|
|
219
|
-
case 'Dashed Large':
|
|
220
|
-
return '15 5'
|
|
221
|
-
default:
|
|
222
|
-
return 0
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
const lineOptions = [
|
|
227
|
-
{
|
|
228
|
-
value: 'Dashed Small',
|
|
229
|
-
key: 'dashed-sm'
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
value: 'Dashed Medium',
|
|
233
|
-
key: 'dashed-md'
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
value: 'Dashed Large',
|
|
237
|
-
key: 'dashed-lg'
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
value: 'Solid Line',
|
|
241
|
-
key: 'solid-line'
|
|
242
|
-
}
|
|
243
|
-
]
|
|
244
|
-
|
|
245
158
|
const loadConfig = async () => {
|
|
246
159
|
let response = configObj || (await (await fetch(configUrl)).json())
|
|
247
160
|
|
|
@@ -310,8 +223,13 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
310
223
|
|
|
311
224
|
newConfig.series.map(series => {
|
|
312
225
|
if (!series.tooltip) series.tooltip = true
|
|
226
|
+
if (!series.axis) series.axis = 'Left'
|
|
313
227
|
})
|
|
314
228
|
|
|
229
|
+
if (!newConfig.data && data) {
|
|
230
|
+
newConfig.data = data
|
|
231
|
+
}
|
|
232
|
+
|
|
315
233
|
const processedConfig = { ...(await coveUpdateWorker(newConfig)) }
|
|
316
234
|
|
|
317
235
|
updateConfig(processedConfig, data)
|
|
@@ -409,37 +327,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
409
327
|
let tableData: any[] = []
|
|
410
328
|
const plots: any[] = []
|
|
411
329
|
|
|
412
|
-
/**
|
|
413
|
-
* Calculates the first quartile (q1) and third quartile (q3) from an array of integers or decimals.
|
|
414
|
-
*
|
|
415
|
-
* @param {Array} arr - The array of integers or decimals.
|
|
416
|
-
* @returns {Object} An object containing the q1 and q3 values.
|
|
417
|
-
*/
|
|
418
|
-
const getQuartiles = arr => {
|
|
419
|
-
arr.sort((a, b) => a - b)
|
|
420
|
-
|
|
421
|
-
// Calculate the index of the median value of the array
|
|
422
|
-
const medianIndex = Math.floor(arr.length / 2)
|
|
423
|
-
|
|
424
|
-
// Check if the length of the array is even or odd
|
|
425
|
-
const isEvenLength = arr.length % 2 === 0
|
|
426
|
-
|
|
427
|
-
// Split the array into two subarrays based on the median index
|
|
428
|
-
const q1Array = isEvenLength ? arr.slice(0, medianIndex) : arr.slice(0, medianIndex + 1)
|
|
429
|
-
const q3Array = isEvenLength ? arr.slice(medianIndex) : arr.slice(medianIndex + 1)
|
|
430
|
-
|
|
431
|
-
// Calculate the median of the first subarray to get the q1 value
|
|
432
|
-
const q1Index = Math.floor(q1Array.length / 2)
|
|
433
|
-
const q1 = isEvenLength ? (q1Array[q1Index - 1] + q1Array[q1Index]) / 2 : q1Array[q1Index]
|
|
434
|
-
|
|
435
|
-
// Calculate the median of the second subarray to get the q3 value
|
|
436
|
-
const q3Index = Math.floor(q3Array.length / 2)
|
|
437
|
-
const q3 = isEvenLength ? (q3Array[q3Index - 1] + q3Array[q3Index]) / 2 : q3Array[q3Index]
|
|
438
|
-
|
|
439
|
-
// Return an object containing the q1 and q3 values
|
|
440
|
-
return { q1, q3 }
|
|
441
|
-
}
|
|
442
|
-
|
|
443
330
|
// group specific statistics
|
|
444
331
|
// prevent re-renders
|
|
445
332
|
if (!groups) return
|
|
@@ -563,7 +450,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
563
450
|
if ((newConfig.visualizationType === 'Bar' && newConfig.orientation === 'horizontal') || ['Deviation Bar', 'Paired Bar', 'Forest Plot'].includes(newConfig.visualizationType)) {
|
|
564
451
|
newConfig.runtime.xAxis = newConfig.yAxis
|
|
565
452
|
newConfig.runtime.yAxis = newConfig.xAxis
|
|
566
|
-
|
|
453
|
+
|
|
454
|
+
newConfig.runtime.horizontal = false
|
|
567
455
|
newConfig.orientation = 'horizontal'
|
|
568
456
|
} else if (['Box Plot', 'Scatter Plot', 'Area Chart', 'Line', 'Forecasting'].includes(newConfig.visualizationType)) {
|
|
569
457
|
newConfig.runtime.xAxis = newConfig.xAxis
|
|
@@ -581,25 +469,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
581
469
|
setConfig(newConfig)
|
|
582
470
|
}
|
|
583
471
|
|
|
584
|
-
const filterData = (filters, data) => {
|
|
585
|
-
let filteredData: any[] = []
|
|
586
|
-
|
|
587
|
-
data.forEach(row => {
|
|
588
|
-
let add = true
|
|
589
|
-
filters
|
|
590
|
-
.filter(filter => filter.type !== 'url')
|
|
591
|
-
.forEach(filter => {
|
|
592
|
-
if (row[filter.columnName] != filter.active) {
|
|
593
|
-
add = false
|
|
594
|
-
}
|
|
595
|
-
})
|
|
596
|
-
|
|
597
|
-
if (add) filteredData.push(row)
|
|
598
|
-
})
|
|
599
|
-
|
|
600
|
-
return filteredData
|
|
601
|
-
}
|
|
602
|
-
|
|
603
472
|
// Gets filter values from dataset
|
|
604
473
|
const generateValuesForFilter = (columnName, data = this.state.data) => {
|
|
605
474
|
const values: any[] = []
|
|
@@ -739,7 +608,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
739
608
|
// Generates color palette to pass to child chart component
|
|
740
609
|
useEffect(() => {
|
|
741
610
|
if (stateData && config.xAxis && config.runtime.seriesKeys) {
|
|
742
|
-
const configPalette = config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar' ? config.twoColor.palette : config.palette
|
|
611
|
+
const configPalette = config.customColors ? config.customColors : config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar' ? config.twoColor.palette : config.palette
|
|
743
612
|
const allPalettes = { ...colorPalettes, ...twoColorPalette }
|
|
744
613
|
let palette = config.customColors || allPalettes[configPalette]
|
|
745
614
|
let numberOfKeys = config.runtime.seriesKeys.length
|
|
@@ -754,7 +623,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
754
623
|
newColorScale = () =>
|
|
755
624
|
scaleOrdinal({
|
|
756
625
|
domain: config.runtime.seriesLabelsAll,
|
|
757
|
-
range: palette
|
|
626
|
+
range: palette,
|
|
627
|
+
unknown: null
|
|
758
628
|
})
|
|
759
629
|
|
|
760
630
|
setColorScale(newColorScale)
|
|
@@ -856,24 +726,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
856
726
|
return Math.ceil(context.measureText(text).width)
|
|
857
727
|
}
|
|
858
728
|
|
|
859
|
-
const abbreviateNumber = num => {
|
|
860
|
-
let unit = ''
|
|
861
|
-
let absNum = Math.abs(num)
|
|
862
|
-
|
|
863
|
-
if (absNum >= 1e9) {
|
|
864
|
-
unit = 'B'
|
|
865
|
-
num = num / 1e9
|
|
866
|
-
} else if (absNum >= 1e6) {
|
|
867
|
-
unit = 'M'
|
|
868
|
-
num = num / 1e6
|
|
869
|
-
} else if (absNum >= 1e3) {
|
|
870
|
-
unit = 'K'
|
|
871
|
-
num = num / 1e3
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
return num + unit
|
|
875
|
-
}
|
|
876
|
-
|
|
877
729
|
// Format numeric data based on settings in config OR from passed in settings for Additional Columns
|
|
878
730
|
// - use only for old horizontal data - newer formatNumber is in helper/formatNumber
|
|
879
731
|
// TODO: we should combine various formatNumber functions across this project.
|
|
@@ -925,11 +777,17 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
925
777
|
}
|
|
926
778
|
}
|
|
927
779
|
|
|
780
|
+
const resolveBottomTickRounding = () => {
|
|
781
|
+
if (config.forestPlot.type === 'Logarithmic' && !bottomRoundTo) return 2
|
|
782
|
+
if (Number(bottomRoundTo)) return Number(bottomRoundTo)
|
|
783
|
+
return 0
|
|
784
|
+
}
|
|
785
|
+
|
|
928
786
|
if (axis === 'bottom') {
|
|
929
787
|
stringFormattingOptions = {
|
|
930
788
|
useGrouping: config.dataFormat.bottomCommas ? true : false,
|
|
931
|
-
minimumFractionDigits:
|
|
932
|
-
maximumFractionDigits:
|
|
789
|
+
minimumFractionDigits: resolveBottomTickRounding(),
|
|
790
|
+
maximumFractionDigits: resolveBottomTickRounding()
|
|
933
791
|
}
|
|
934
792
|
}
|
|
935
793
|
|
|
@@ -1127,18 +985,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1127
985
|
return generateColorsArray(mapColorPalette[3])
|
|
1128
986
|
}
|
|
1129
987
|
|
|
1130
|
-
let hash = hashObj(rowObj)
|
|
1131
|
-
|
|
1132
|
-
if (legendMemo.current.has(hash)) {
|
|
1133
|
-
let idx = legendMemo.current.get(hash)
|
|
1134
|
-
if (runtimeLegend[idx]?.disabled) return false
|
|
1135
|
-
|
|
1136
|
-
// DEV-784 changed to use bin prop to get color instead of idx
|
|
1137
|
-
// bc we re-order legend when showSpecialClassesLast is checked
|
|
1138
|
-
let legendBinColor = runtimeLegend.find(o => o.bin === idx)?.color
|
|
1139
|
-
return generateColorsArray(legendBinColor, runtimeLegend[idx]?.special)
|
|
1140
|
-
}
|
|
1141
|
-
|
|
1142
988
|
// Fail state
|
|
1143
989
|
return generateColorsArray()
|
|
1144
990
|
} catch (e) {
|
|
@@ -1173,13 +1019,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1173
1019
|
{isEditor && <EditorPanel />}
|
|
1174
1020
|
{!missingRequiredSections() && !config.newViz && (
|
|
1175
1021
|
<div className='cdc-chart-inner-container'>
|
|
1176
|
-
{
|
|
1177
|
-
|
|
1178
|
-
<div role='heading' className={`chart-title ${config.theme} cove-component__header`} aria-level={2}>
|
|
1179
|
-
{config && <sup className='superTitle'>{parse(config.superTitle || '')}</sup>}
|
|
1180
|
-
<div>{parse(title)}</div>
|
|
1181
|
-
</div>
|
|
1182
|
-
)}
|
|
1022
|
+
<Title showTitle={config.showTitle} isDashboard={isDashboard} title={title} superTitle={config.superTitle} classes={['chart-title', `${config.theme}`, 'cove-component__header']} style={undefined} />
|
|
1023
|
+
|
|
1183
1024
|
<a id='skip-chart-container' className='cdcdataviz-sr-only-focusable' href={handleChartTabbing}>
|
|
1184
1025
|
Skip Over Chart Container
|
|
1185
1026
|
</a>
|
|
@@ -1188,8 +1029,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1188
1029
|
{/* Visualization */}
|
|
1189
1030
|
{config?.introText && config.visualizationType !== 'Spark Line' && <section className='introText'>{parse(config.introText)}</section>}
|
|
1190
1031
|
<div
|
|
1191
|
-
style={{ marginBottom: config
|
|
1192
|
-
className={`chart-container p-relative ${config.legend.position === 'bottom' ? 'bottom' : ''}${config.legend.hide ? ' legend-hidden' : ''}${lineDatapointClass}${barBorderClass} ${contentClasses.join(' ')}`}
|
|
1032
|
+
style={{ marginBottom: computeMarginBottom(config, legend, currentViewport) }}
|
|
1033
|
+
className={`chart-container p-relative ${config.legend.position === 'bottom' ? 'bottom' : ''}${config.legend.hide ? ' legend-hidden' : ''}${lineDatapointClass}${barBorderClass} ${contentClasses.join(' ')} ${isDebug ? 'debug' : ''}`}
|
|
1193
1034
|
>
|
|
1194
1035
|
{/* All charts except sparkline */}
|
|
1195
1036
|
{config.visualizationType !== 'Spark Line' && chartComponents[config.visualizationType]}
|
|
@@ -1212,7 +1053,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1212
1053
|
)}
|
|
1213
1054
|
</>
|
|
1214
1055
|
)}
|
|
1215
|
-
{!config.legend.hide && config.visualizationType !== 'Spark Line' && <Legend />}
|
|
1056
|
+
{!config.legend.hide && config.visualizationType !== 'Spark Line' && config.visualizationType !== 'Forest Plot' && <Legend />}
|
|
1216
1057
|
</div>
|
|
1217
1058
|
{/* Link */}
|
|
1218
1059
|
{isDashboard && config.table && config.table.show && config.table.showDataTableLink ? tableLink : link && link}
|
|
@@ -1231,11 +1072,9 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1231
1072
|
<DataTable
|
|
1232
1073
|
config={config}
|
|
1233
1074
|
rawData={config.data}
|
|
1234
|
-
runtimeData={filteredData || excludedData}
|
|
1075
|
+
runtimeData={transform.applySuppression(filteredData || excludedData, config.suppressedData)}
|
|
1235
1076
|
expandDataTable={config.table.expanded}
|
|
1236
1077
|
columns={config.columns}
|
|
1237
|
-
showDownloadButton={config.general.showDownloadButton}
|
|
1238
|
-
runtimeLegend={dynamicLegendItems}
|
|
1239
1078
|
displayDataAsText={displayDataAsText}
|
|
1240
1079
|
displayGeoName={displayGeoName}
|
|
1241
1080
|
applyLegendToRow={applyLegendToRow}
|
|
@@ -1243,18 +1082,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1243
1082
|
indexTitle={config.table.indexLabel}
|
|
1244
1083
|
vizTitle={title}
|
|
1245
1084
|
viewport={currentViewport}
|
|
1246
|
-
parseDate={parseDate}
|
|
1247
|
-
formatDate={formatDate}
|
|
1248
|
-
formatNumber={formatNumber}
|
|
1249
1085
|
tabbingId={handleChartTabbing}
|
|
1250
|
-
showDownloadImgButton={config.showDownloadImgButton}
|
|
1251
|
-
showDownloadPdfButton={config.showDownloadPdfButton}
|
|
1252
|
-
innerContainerRef={innerContainerRef}
|
|
1253
|
-
outerContainerRef={outerContainerRef}
|
|
1254
|
-
imageRef={imageId}
|
|
1255
1086
|
colorScale={colorScale}
|
|
1256
|
-
isDebug={isDebug}
|
|
1257
|
-
isEditor={isEditor}
|
|
1258
1087
|
/>
|
|
1259
1088
|
)}
|
|
1260
1089
|
{config?.footnotes && <section className='footnotes'>{parse(config.footnotes)}</section>}
|
|
@@ -1274,6 +1103,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1274
1103
|
|
|
1275
1104
|
const contextValues = {
|
|
1276
1105
|
capitalize,
|
|
1106
|
+
computeMarginBottom,
|
|
1277
1107
|
getXAxisData,
|
|
1278
1108
|
getYAxisData,
|
|
1279
1109
|
config,
|
|
@@ -1316,7 +1146,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1316
1146
|
isDebug,
|
|
1317
1147
|
setSharedFilter,
|
|
1318
1148
|
setSharedFilterValue,
|
|
1319
|
-
dashboardConfig
|
|
1149
|
+
dashboardConfig,
|
|
1150
|
+
debugSvg: isDebug
|
|
1320
1151
|
}
|
|
1321
1152
|
|
|
1322
1153
|
const classes = ['cdc-open-viz-module', 'type-chart', `${currentViewport}`, `font-${config.fontSize}`, `${config.theme}`]
|