@cdc/chart 4.23.10 → 4.23.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/dist/cdcchart.js +30989 -29057
- package/examples/feature/bar/example-bar-chart.json +1 -46
- package/examples/feature/bar/lollipop.json +156 -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/{broken.json → linear.json} +55 -50
- package/examples/feature/forest-plot/logarithmic.json +306 -0
- package/examples/feature/line/line-points.json +340 -0
- package/examples/feature/regions/index.json +462 -0
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +181 -48
- package/examples/sparkline-multilple.json +846 -0
- package/index.html +10 -6
- package/package.json +3 -3
- package/src/CdcChart.tsx +75 -63
- 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/ChartSuppress.stories.tsx +19 -0
- package/src/_stories/_mock/brush_mock.json +393 -0
- package/src/_stories/_mock/suppress_mock.json +911 -0
- package/src/components/AreaChart.Stacked.jsx +4 -5
- package/src/components/AreaChart.jsx +6 -35
- package/src/components/{BarChart.Horizontal.jsx → BarChart.Horizontal.tsx} +106 -29
- package/src/components/{BarChart.StackedHorizontal.jsx → BarChart.StackedHorizontal.tsx} +22 -17
- package/src/components/{BarChart.StackedVertical.jsx → BarChart.StackedVertical.tsx} +22 -26
- package/src/components/{BarChart.Vertical.jsx → BarChart.Vertical.tsx} +175 -31
- package/src/components/BarChart.jsx +1 -1
- package/src/components/DeviationBar.jsx +4 -3
- package/src/components/EditorPanel.jsx +176 -50
- package/src/components/ForestPlot/ForestPlotProps.ts +11 -0
- package/src/components/ForestPlot/Readme.md +0 -0
- package/src/components/ForestPlot/index.scss +1 -0
- package/src/components/{ForestPlot.jsx → ForestPlot/index.tsx} +51 -31
- package/src/components/ForestPlotSettings.jsx +162 -113
- package/src/components/Legend.jsx +36 -3
- package/src/components/{LineChart.Circle.tsx → LineChart/LineChart.Circle.tsx} +26 -29
- package/src/components/LineChart/LineChartProps.ts +17 -0
- package/src/components/LineChart/index.scss +1 -0
- package/src/components/{LineChart.tsx → LineChart/index.tsx} +64 -35
- package/src/components/LinearChart.jsx +120 -60
- package/src/components/PairedBarChart.jsx +2 -2
- package/src/components/Series.jsx +22 -3
- package/src/components/ZoomBrush.tsx +168 -0
- package/src/data/initial-state.js +27 -12
- package/src/hooks/useBarChart.js +71 -7
- package/src/hooks/useColorScale.ts +50 -0
- package/src/hooks/useEditorPermissions.js +22 -4
- 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 +68 -41
- package/src/scss/main.scss +3 -35
- package/src/types/ChartConfig.ts +43 -0
- package/src/types/ChartContext.ts +38 -0
- package/src/types/ChartProps.ts +7 -0
- package/src/types/ForestPlot.ts +60 -0
package/index.html
CHANGED
|
@@ -34,19 +34,22 @@
|
|
|
34
34
|
-->
|
|
35
35
|
|
|
36
36
|
<!-- GENERIC CHART TYPES -->
|
|
37
|
-
|
|
37
|
+
<div class="react-container" data-config="/examples/private/highlight.json"></div>
|
|
38
|
+
<div class="react-container" data-config="/examples/private/aggregate.json"></div>
|
|
39
|
+
<!-- <div class="react-container" data-config="/examples/private/missing-color.json"></div> -->
|
|
38
40
|
<!-- <div class="react-container" data-config="/examples/private/combo.json"></div> -->
|
|
39
41
|
<!-- <div class="react-container" data-config="/examples/feature/legend-highlights/highlights.json"></div> -->
|
|
40
42
|
<!-- <div class="react-container" data-config="/examples/private/tooltip-issue.json"></div> -->
|
|
41
43
|
<!-- <div class="react-container" data-config="https://cdc.gov/poxvirus/mpox/modules/data-viz/mpx-trends_1.json"></div> -->
|
|
42
44
|
<!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date-city-temperature.json"></div> -->
|
|
43
45
|
<!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date-apple.json"></div> -->
|
|
44
|
-
<!-- <div class="react-container" data-config="/examples/feature/
|
|
46
|
+
<!-- <div class="react-container" data-config="/examples/feature/forest-plot/linear.json"></div> -->
|
|
47
|
+
<!-- <div class="react-container" data-config="/examples/feature/forest-plot/logarithmic.json"></div> -->
|
|
45
48
|
<!-- <div class="react-container" data-config="/examples/feature/forest-plot/forest-plot.json"></div> -->
|
|
46
49
|
<!-- <div class="react-container" data-config="/examples/feature/pie/planet-pie-example-config.json"></div> -->
|
|
47
50
|
<!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Viz.json></div> -->
|
|
51
|
+
<!-- <div class="react-container" data-config=/examples/feature/regions/index.json></div> -->
|
|
48
52
|
<!-- <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
53
|
<!-- <div class="react-container" data-config="/examples/feature/forecasting/forecasting.json"></div> -->
|
|
51
54
|
<!-- <div class="react-container" data-config="/examples/feature/forecasting/combo-forecasting.json"></div> -->
|
|
52
55
|
<!-- <div class="react-container" data-config="/examples/feature/forecasting/effective_reproduction.json"></div> -->
|
|
@@ -69,7 +72,7 @@
|
|
|
69
72
|
<!-- <div class="react-container" data-config="/examples/feature/bar/planet-chart-horizontal-example-config.json"></div> -->
|
|
70
73
|
|
|
71
74
|
<!-- SPARKLINE -->
|
|
72
|
-
<!-- <div class="react-container" data-config="/examples/feature/
|
|
75
|
+
<!-- <div class="react-container" data-config="/examples/feature/dev-4261.json"></div> -->
|
|
73
76
|
|
|
74
77
|
<!-- TESTS DATA TABLE SORTING -->
|
|
75
78
|
<!-- Bar Chart with Confidence Intervals (bottom of page) -->
|
|
@@ -103,6 +106,7 @@
|
|
|
103
106
|
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/example-combo-bar-nonnumeric.json"></div> -->
|
|
104
107
|
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/example-bar-chart-nonnumeric.json"></div> -->
|
|
105
108
|
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/sparkline-chart-nonnumeric.json"></div> -->
|
|
109
|
+
<!-- <div class="react-container" data-config="/examples/feature/bar/lollipop.json"></div> -->
|
|
106
110
|
<!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json"></div> -->
|
|
107
111
|
|
|
108
112
|
<!-- TESTS CUTOFF -->
|
|
@@ -130,10 +134,10 @@
|
|
|
130
134
|
<!-- VERTICAL BAR CHARTS -->
|
|
131
135
|
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/combo-line-chart.json"></div> -->
|
|
132
136
|
<!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json"></div> -->
|
|
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.23.
|
|
3
|
+
"version": "4.23.11",
|
|
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": "ecad213667a3cb96c921eaddba43a31c84caaa08",
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"resize-observer-polyfill": "^1.5.1"
|
|
65
65
|
}
|
package/src/CdcChart.tsx
CHANGED
|
@@ -43,6 +43,7 @@ import './scss/main.scss'
|
|
|
43
43
|
// load both then config below determines which to use
|
|
44
44
|
import DataTable from '@cdc/core/components/DataTable'
|
|
45
45
|
import { getFileExtension } from '@cdc/core/helpers/getFileExtension'
|
|
46
|
+
import Title from '@cdc/core/components/ui/Title'
|
|
46
47
|
|
|
47
48
|
const generateColorsArray = (color = '#000000', special = false) => {
|
|
48
49
|
let colorObj = chroma(color)
|
|
@@ -50,29 +51,6 @@ const generateColorsArray = (color = '#000000', special = false) => {
|
|
|
50
51
|
|
|
51
52
|
return [color, hoverColor, colorObj.darken(0.3).hex()]
|
|
52
53
|
}
|
|
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
|
|
76
54
|
|
|
77
55
|
export default function CdcChart({ configUrl, config: configObj, isEditor = false, isDebug = false, isDashboard = false, setConfig: setParentConfig, setEditing, hostname, link, setSharedFilter, setSharedFilterValue, dashboardConfig }) {
|
|
78
56
|
const transform = new DataTransform()
|
|
@@ -90,7 +68,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
90
68
|
const [coveLoadedEventRan, setCoveLoadedEventRan] = useState(false)
|
|
91
69
|
const [dynamicLegendItems, setDynamicLegendItems] = useState<any[]>([])
|
|
92
70
|
const [imageId] = useState(`cove-${Math.random().toString(16).slice(-4)}`)
|
|
93
|
-
|
|
71
|
+
type Config = typeof config
|
|
94
72
|
let legendMemo = useRef(new Map()) // map collection
|
|
95
73
|
let innerContainerRef = useRef()
|
|
96
74
|
|
|
@@ -140,7 +118,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
140
118
|
|
|
141
119
|
const reloadURLData = async () => {
|
|
142
120
|
if (config.dataUrl) {
|
|
143
|
-
const dataUrl = new URL(config.runtimeDataUrl || config.dataUrl)
|
|
121
|
+
const dataUrl = new URL(config.runtimeDataUrl || config.dataUrl, window.location.origin)
|
|
144
122
|
let qsParams = Object.fromEntries(new URLSearchParams(dataUrl.search))
|
|
145
123
|
|
|
146
124
|
let isUpdateNeeded = false
|
|
@@ -310,8 +288,13 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
310
288
|
|
|
311
289
|
newConfig.series.map(series => {
|
|
312
290
|
if (!series.tooltip) series.tooltip = true
|
|
291
|
+
if (!series.axis) series.axis = 'Left'
|
|
313
292
|
})
|
|
314
293
|
|
|
294
|
+
if (!newConfig.data && data) {
|
|
295
|
+
newConfig.data = data
|
|
296
|
+
}
|
|
297
|
+
|
|
315
298
|
const processedConfig = { ...(await coveUpdateWorker(newConfig)) }
|
|
316
299
|
|
|
317
300
|
updateConfig(processedConfig, data)
|
|
@@ -563,6 +546,11 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
563
546
|
if ((newConfig.visualizationType === 'Bar' && newConfig.orientation === 'horizontal') || ['Deviation Bar', 'Paired Bar', 'Forest Plot'].includes(newConfig.visualizationType)) {
|
|
564
547
|
newConfig.runtime.xAxis = newConfig.yAxis
|
|
565
548
|
newConfig.runtime.yAxis = newConfig.xAxis
|
|
549
|
+
|
|
550
|
+
if (newConfig.visualizationType === 'Forest Plot') {
|
|
551
|
+
newConfig.runtime.xAxis.type = newConfig.forestPlot.type
|
|
552
|
+
newConfig.runtime.xAxis.tickRotation = newConfig.xAxis.tickRotation
|
|
553
|
+
}
|
|
566
554
|
newConfig.runtime.horizontal = true
|
|
567
555
|
newConfig.orientation = 'horizontal'
|
|
568
556
|
} else if (['Box Plot', 'Scatter Plot', 'Area Chart', 'Line', 'Forecasting'].includes(newConfig.visualizationType)) {
|
|
@@ -739,7 +727,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
739
727
|
// Generates color palette to pass to child chart component
|
|
740
728
|
useEffect(() => {
|
|
741
729
|
if (stateData && config.xAxis && config.runtime.seriesKeys) {
|
|
742
|
-
const configPalette = config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar' ? config.twoColor.palette : config.palette
|
|
730
|
+
const configPalette = config.customColors ? config.customColors : config.visualizationType === 'Paired Bar' || config.visualizationType === 'Deviation Bar' ? config.twoColor.palette : config.palette
|
|
743
731
|
const allPalettes = { ...colorPalettes, ...twoColorPalette }
|
|
744
732
|
let palette = config.customColors || allPalettes[configPalette]
|
|
745
733
|
let numberOfKeys = config.runtime.seriesKeys.length
|
|
@@ -754,7 +742,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
754
742
|
newColorScale = () =>
|
|
755
743
|
scaleOrdinal({
|
|
756
744
|
domain: config.runtime.seriesLabelsAll,
|
|
757
|
-
range: palette
|
|
745
|
+
range: palette,
|
|
746
|
+
unknown: null
|
|
758
747
|
})
|
|
759
748
|
|
|
760
749
|
setColorScale(newColorScale)
|
|
@@ -1127,18 +1116,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1127
1116
|
return generateColorsArray(mapColorPalette[3])
|
|
1128
1117
|
}
|
|
1129
1118
|
|
|
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
1119
|
// Fail state
|
|
1143
1120
|
return generateColorsArray()
|
|
1144
1121
|
} catch (e) {
|
|
@@ -1159,6 +1136,61 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1159
1136
|
return key
|
|
1160
1137
|
}
|
|
1161
1138
|
|
|
1139
|
+
const computeMarginBottom = (config: Config): string => {
|
|
1140
|
+
const isLegendBottom = legend.position === 'bottom' || ['sm', 'xs', 'xxs'].includes(currentViewport)
|
|
1141
|
+
const isHorizontal = config.orientation === 'horizontal'
|
|
1142
|
+
const tickRotation = Number(config.xAxis.tickRotation) > 0 ? Number(config.xAxis.tickRotation) : 0
|
|
1143
|
+
const isBrush = config.brush.active
|
|
1144
|
+
const offset = 20
|
|
1145
|
+
const brushHeight = config.brush.height
|
|
1146
|
+
let bottom = 0
|
|
1147
|
+
if (!isLegendBottom && isHorizontal && !config.yAxis.label) {
|
|
1148
|
+
bottom = Number(config.xAxis.labelOffset)
|
|
1149
|
+
}
|
|
1150
|
+
if (!isLegendBottom && isHorizontal && config.yAxis.label && !config.isResponsiveTicks) {
|
|
1151
|
+
bottom = Number(config.runtime.xAxis.size) + Number(config.xAxis.labelOffset)
|
|
1152
|
+
}
|
|
1153
|
+
if (!isLegendBottom && isHorizontal && config.yAxis.label && config.isResponsiveTicks) {
|
|
1154
|
+
bottom = config.dynamicMarginTop + offset
|
|
1155
|
+
}
|
|
1156
|
+
if (!isLegendBottom && isHorizontal && !config.yAxis.label && config.isResponsiveTicks) {
|
|
1157
|
+
bottom = config.dynamicMarginTop ? config.dynamicMarginTop - offset : Number(config.xAxis.labelOffset) - offset
|
|
1158
|
+
}
|
|
1159
|
+
if (!isLegendBottom && isHorizontal && config.yAxis.label && config.isResponsiveTicks) {
|
|
1160
|
+
bottom = config.dynamicMarginTop ? config.dynamicMarginTop + offset : Number(config.xAxis.labelOffset)
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
if (!isHorizontal && !isLegendBottom && config.xAxis.label && tickRotation && !config.isResponsiveTicks) {
|
|
1164
|
+
bottom = isBrush ? brushHeight + config.xAxis.tickWidthMax + -config.xAxis.size + config.xAxis.labelOffset + offset : config.xAxis.tickWidthMax + offset + -config.xAxis.size + config.xAxis.labelOffset
|
|
1165
|
+
}
|
|
1166
|
+
if (!isHorizontal && !isLegendBottom && !config.xAxis.label && tickRotation && !config.isResponsiveTicks) {
|
|
1167
|
+
}
|
|
1168
|
+
if (!isHorizontal && !isLegendBottom && !config.xAxis.label && tickRotation && !config.dynamicMarginTop && !config.isResponsiveTicks) {
|
|
1169
|
+
bottom = isBrush ? config.xAxis.tickWidthMax + brushHeight + offset + -config.xAxis.size : 0
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
if (!isHorizontal && !isLegendBottom && config.xAxis.label && !tickRotation && !config.isResponsiveTicks) {
|
|
1173
|
+
bottom = isBrush ? brushHeight + -config.xAxis.size + config.xAxis.labelOffset + offset : -config.xAxis.size + config.xAxis.labelOffset + offset
|
|
1174
|
+
}
|
|
1175
|
+
if (!isHorizontal && !isLegendBottom && config.xAxis.label && config.dynamicMarginTop && config.isResponsiveTicks) {
|
|
1176
|
+
bottom = isBrush ? brushHeight + config.xAxis.labelOffset + -config.xAxis.size + config.xAxis.tickWidthMax : config.dynamicMarginTop + -config.xAxis.size + offset
|
|
1177
|
+
}
|
|
1178
|
+
if (!isHorizontal && !isLegendBottom && !config.xAxis.label && config.dynamicMarginTop && config.isResponsiveTicks) {
|
|
1179
|
+
bottom = isBrush ? brushHeight + config.xAxis.labelOffset + -config.xAxis.size + config.xAxis.tickWidthMax : config.dynamicMarginTop + -config.xAxis.size - offset
|
|
1180
|
+
}
|
|
1181
|
+
if (!isHorizontal && !isLegendBottom && config.xAxis.label && !config.dynamicMarginTop && config.isResponsiveTicks) {
|
|
1182
|
+
bottom = isBrush ? brushHeight + config.xAxis.labelOffset + -config.xAxis.size + 25 : config.xAxis.labelOffset + -config.xAxis.size + offset
|
|
1183
|
+
}
|
|
1184
|
+
if (!isHorizontal && !isLegendBottom && !config.xAxis.label && !config.dynamicMarginTop && config.isResponsiveTicks) {
|
|
1185
|
+
bottom = -config.xAxis.size + offset + config.xAxis.labelOffset
|
|
1186
|
+
}
|
|
1187
|
+
if (!isHorizontal && !isLegendBottom && !config.xAxis.label && !tickRotation && !config.dynamicMarginTop && !config.isResponsiveTicks) {
|
|
1188
|
+
bottom = isBrush ? brushHeight + -config.xAxis.size + config.xAxis.labelOffset : 0
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
return `${bottom}px`
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1162
1194
|
// Prevent render if loading
|
|
1163
1195
|
let body = <Loading />
|
|
1164
1196
|
|
|
@@ -1173,13 +1205,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1173
1205
|
{isEditor && <EditorPanel />}
|
|
1174
1206
|
{!missingRequiredSections() && !config.newViz && (
|
|
1175
1207
|
<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
|
-
)}
|
|
1208
|
+
<Title showTitle={config.showTitle} isDashboard={isDashboard} title={title} superTitle={config.superTitle} classes={['chart-title', `${config.theme}`, 'cove-component__header']} style={undefined} />
|
|
1209
|
+
|
|
1183
1210
|
<a id='skip-chart-container' className='cdcdataviz-sr-only-focusable' href={handleChartTabbing}>
|
|
1184
1211
|
Skip Over Chart Container
|
|
1185
1212
|
</a>
|
|
@@ -1187,10 +1214,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1187
1214
|
{config.filters && !externalFilters && <Filters config={config} setConfig={setConfig} setFilteredData={setFilteredData} filteredData={filteredData} excludedData={excludedData} filterData={filterData} dimensions={dimensions} />}
|
|
1188
1215
|
{/* Visualization */}
|
|
1189
1216
|
{config?.introText && config.visualizationType !== 'Spark Line' && <section className='introText'>{parse(config.introText)}</section>}
|
|
1190
|
-
<div
|
|
1191
|
-
style={{ marginBottom: config.legend.position !== 'bottom' && config.orientation === 'horizontal' ? `${config.runtime.xAxis.size}px` : '0px' }}
|
|
1192
|
-
className={`chart-container p-relative ${config.legend.position === 'bottom' ? 'bottom' : ''}${config.legend.hide ? ' legend-hidden' : ''}${lineDatapointClass}${barBorderClass} ${contentClasses.join(' ')}`}
|
|
1193
|
-
>
|
|
1217
|
+
<div style={{ marginBottom: computeMarginBottom(config) }} className={`chart-container p-relative ${config.legend.position === 'bottom' ? 'bottom' : ''}${config.legend.hide ? ' legend-hidden' : ''}${lineDatapointClass}${barBorderClass} ${contentClasses.join(' ')}`}>
|
|
1194
1218
|
{/* All charts except sparkline */}
|
|
1195
1219
|
{config.visualizationType !== 'Spark Line' && chartComponents[config.visualizationType]}
|
|
1196
1220
|
|
|
@@ -1231,11 +1255,9 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1231
1255
|
<DataTable
|
|
1232
1256
|
config={config}
|
|
1233
1257
|
rawData={config.data}
|
|
1234
|
-
runtimeData={filteredData || excludedData}
|
|
1258
|
+
runtimeData={transform.applySuppression(filteredData || excludedData, config.suppressedData)}
|
|
1235
1259
|
expandDataTable={config.table.expanded}
|
|
1236
1260
|
columns={config.columns}
|
|
1237
|
-
showDownloadButton={config.general.showDownloadButton}
|
|
1238
|
-
runtimeLegend={dynamicLegendItems}
|
|
1239
1261
|
displayDataAsText={displayDataAsText}
|
|
1240
1262
|
displayGeoName={displayGeoName}
|
|
1241
1263
|
applyLegendToRow={applyLegendToRow}
|
|
@@ -1243,18 +1265,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
|
|
|
1243
1265
|
indexTitle={config.table.indexLabel}
|
|
1244
1266
|
vizTitle={title}
|
|
1245
1267
|
viewport={currentViewport}
|
|
1246
|
-
parseDate={parseDate}
|
|
1247
|
-
formatDate={formatDate}
|
|
1248
|
-
formatNumber={formatNumber}
|
|
1249
1268
|
tabbingId={handleChartTabbing}
|
|
1250
|
-
showDownloadImgButton={config.showDownloadImgButton}
|
|
1251
|
-
showDownloadPdfButton={config.showDownloadPdfButton}
|
|
1252
|
-
innerContainerRef={innerContainerRef}
|
|
1253
|
-
outerContainerRef={outerContainerRef}
|
|
1254
|
-
imageRef={imageId}
|
|
1255
1269
|
colorScale={colorScale}
|
|
1256
|
-
isDebug={isDebug}
|
|
1257
|
-
isEditor={isEditor}
|
|
1258
1270
|
/>
|
|
1259
1271
|
)}
|
|
1260
1272
|
{config?.footnotes && <section className='footnotes'>{parse(config.footnotes)}</section>}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
|
|
3
|
+
import Chart from '../CdcChart'
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Chart> = {
|
|
6
|
+
title: 'Components/Templates/Chart',
|
|
7
|
+
component: Chart
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type Story = StoryObj<typeof Chart>
|
|
11
|
+
|
|
12
|
+
export const Lollipop: Story = {
|
|
13
|
+
args: {
|
|
14
|
+
config: {
|
|
15
|
+
type: 'chart',
|
|
16
|
+
title: 'Lollipop Style Horizontal Bar Chart - Number of Spills Occurring in the Home',
|
|
17
|
+
showTitle: true,
|
|
18
|
+
showDownloadMediaButton: false,
|
|
19
|
+
theme: 'theme-blue',
|
|
20
|
+
animate: true,
|
|
21
|
+
fontSize: 'medium',
|
|
22
|
+
lineDatapointStyle: 'hover',
|
|
23
|
+
barHasBorder: 'false',
|
|
24
|
+
isLollipopChart: true,
|
|
25
|
+
lollipopShape: 'circle',
|
|
26
|
+
lollipopColorStyle: 'two-tone',
|
|
27
|
+
visualizationSubType: 'horizontal',
|
|
28
|
+
barStyle: '',
|
|
29
|
+
roundingStyle: 'standard',
|
|
30
|
+
tipRounding: 'top',
|
|
31
|
+
isResponsiveTicks: false,
|
|
32
|
+
general: { showDownloadButton: false },
|
|
33
|
+
padding: { left: 5, right: 5 },
|
|
34
|
+
yAxis: {
|
|
35
|
+
hideAxis: true,
|
|
36
|
+
displayNumbersOnBar: true,
|
|
37
|
+
hideLabel: false,
|
|
38
|
+
hideTicks: false,
|
|
39
|
+
size: '13',
|
|
40
|
+
gridLines: false,
|
|
41
|
+
enablePadding: false,
|
|
42
|
+
min: '',
|
|
43
|
+
max: '',
|
|
44
|
+
labelColor: '#333',
|
|
45
|
+
tickLabelColor: '#333',
|
|
46
|
+
tickColor: '#333',
|
|
47
|
+
rightHideAxis: true,
|
|
48
|
+
rightAxisSize: 50,
|
|
49
|
+
rightLabel: '',
|
|
50
|
+
rightLabelOffsetSize: 0,
|
|
51
|
+
rightAxisLabelColor: '#333',
|
|
52
|
+
rightAxisTickLabelColor: '#333',
|
|
53
|
+
rightAxisTickColor: '#333',
|
|
54
|
+
numTicks: '9',
|
|
55
|
+
axisPadding: 0,
|
|
56
|
+
tickRotation: 0,
|
|
57
|
+
anchors: [],
|
|
58
|
+
type: 'chart',
|
|
59
|
+
title: 'Lollipop Style Horizontal Bar Chart',
|
|
60
|
+
theme: 'theme-blue',
|
|
61
|
+
fontSize: 'medium',
|
|
62
|
+
lineDatapointStyle: 'hover',
|
|
63
|
+
barHasBorder: 'false',
|
|
64
|
+
isLollipopChart: false,
|
|
65
|
+
lollipopShape: 'circle',
|
|
66
|
+
lollipopColorStyle: 'two-tone',
|
|
67
|
+
visualizationSubType: 'horizontal',
|
|
68
|
+
padding: { left: 5, right: 5 },
|
|
69
|
+
yAxis: { size: 50, gridLines: false },
|
|
70
|
+
barThickness: 0.35,
|
|
71
|
+
height: 260,
|
|
72
|
+
xAxis: { type: 'categorical', size: 75, tickRotation: 0, dataKey: 'Vehicle' },
|
|
73
|
+
table: { label: 'Data Table', expanded: true, show: true },
|
|
74
|
+
legend: { behavior: 'isolate', position: 'right' },
|
|
75
|
+
exclusions: { active: false, keys: [] },
|
|
76
|
+
palette: 'qualitative-bold',
|
|
77
|
+
labels: false,
|
|
78
|
+
dataFormat: {},
|
|
79
|
+
confidenceKeys: {},
|
|
80
|
+
data: [
|
|
81
|
+
{ Group: 'Combined Total of Group A', Vehicle: '100', Home: '120', Work: '140', Office: '120' },
|
|
82
|
+
{ Group: 'Combined Total of Group B', Vehicle: '150', Home: '140', Work: '100', Office: '90' },
|
|
83
|
+
{ Group: 'Combined Total of Group C', Vehicle: '90', Home: '90', Work: '80', Office: '80' },
|
|
84
|
+
{ Group: 'Combined Total of Group D', Vehicle: '70', Home: '60', Work: '50', Office: '70' }
|
|
85
|
+
],
|
|
86
|
+
dataFileName: 'CSV_Source_Example_for_Horizontal_Bar_viz-cdcwp1619811744363.csv',
|
|
87
|
+
dataFileSourceType: 'file',
|
|
88
|
+
visualizationType: 'Bar',
|
|
89
|
+
runtime: {
|
|
90
|
+
seriesLabels: { Vehicle: 'Vehicle' },
|
|
91
|
+
seriesLabelsAll: ['Vehicle'],
|
|
92
|
+
originalXAxis: { type: 'categorical', size: 75, tickRotation: 0, dataKey: 'Vehicle' },
|
|
93
|
+
seriesKeys: ['Vehicle'],
|
|
94
|
+
xAxis: { size: 50, gridLines: false },
|
|
95
|
+
yAxis: { type: 'categorical', size: 75, tickRotation: 0, dataKey: 'Vehicle' },
|
|
96
|
+
horizontal: true,
|
|
97
|
+
uniqueId: 1651765968212,
|
|
98
|
+
editorErrorMessage: ''
|
|
99
|
+
},
|
|
100
|
+
description: 'Subtext can be added here for options like citing data sources or insight into reading the bar chart.',
|
|
101
|
+
series: [{ dataKey: 'Vehicle', type: 'Bar' }],
|
|
102
|
+
barHeight: 25,
|
|
103
|
+
barPadding: 40,
|
|
104
|
+
labelPlacement: 'Below Bar',
|
|
105
|
+
label: 'Number of Accidents'
|
|
106
|
+
},
|
|
107
|
+
boxplot: [],
|
|
108
|
+
topAxis: { hasLine: false },
|
|
109
|
+
isLegendValue: false,
|
|
110
|
+
barThickness: 0.35,
|
|
111
|
+
barHeight: 6,
|
|
112
|
+
barSpace: 15,
|
|
113
|
+
heights: { vertical: 300, horizontal: 170.39999999999998 },
|
|
114
|
+
xAxis: {
|
|
115
|
+
anchors: [],
|
|
116
|
+
type: 'categorical',
|
|
117
|
+
showTargetLabel: true,
|
|
118
|
+
targetLabel: 'Target',
|
|
119
|
+
hideAxis: true,
|
|
120
|
+
hideLabel: true,
|
|
121
|
+
hideTicks: true,
|
|
122
|
+
size: '16',
|
|
123
|
+
tickRotation: 0,
|
|
124
|
+
min: '',
|
|
125
|
+
max: '160',
|
|
126
|
+
labelColor: '#333',
|
|
127
|
+
tickLabelColor: '#333',
|
|
128
|
+
tickColor: '#333',
|
|
129
|
+
numTicks: '',
|
|
130
|
+
labelOffset: 65,
|
|
131
|
+
axisPadding: 0,
|
|
132
|
+
target: 0,
|
|
133
|
+
maxTickRotation: 0,
|
|
134
|
+
dataKey: 'Group'
|
|
135
|
+
},
|
|
136
|
+
table: { label: 'Data Table', expanded: false, limitHeight: false, height: '', caption: '', showDownloadUrl: false, showDataTableLink: true, indexLabel: 'Group', download: false, showVertical: true, show: true },
|
|
137
|
+
orientation: 'horizontal',
|
|
138
|
+
color: 'pinkpurple',
|
|
139
|
+
columns: {},
|
|
140
|
+
legend: {
|
|
141
|
+
behavior: 'isolate',
|
|
142
|
+
singleRow: false,
|
|
143
|
+
colorCode: '',
|
|
144
|
+
reverseLabelOrder: false,
|
|
145
|
+
description: '',
|
|
146
|
+
dynamicLegend: false,
|
|
147
|
+
dynamicLegendDefaultText: 'Show All',
|
|
148
|
+
dynamicLegendItemLimit: 5,
|
|
149
|
+
dynamicLegendItemLimitMessage: 'Dynamic Legend Item Limit Hit.',
|
|
150
|
+
dynamicLegendChartMessage: 'Select Options from the Legend',
|
|
151
|
+
position: 'right',
|
|
152
|
+
hide: true,
|
|
153
|
+
label: 'Accident Location'
|
|
154
|
+
},
|
|
155
|
+
exclusions: { active: false, keys: [] },
|
|
156
|
+
palette: 'qualitative-bold',
|
|
157
|
+
isPaletteReversed: false,
|
|
158
|
+
twoColor: { palette: 'monochrome-1', isPaletteReversed: false },
|
|
159
|
+
labels: false,
|
|
160
|
+
dataFormat: { commas: false, prefix: '', suffix: '', abbreviated: false, bottomSuffix: '', bottomPrefix: '', bottomAbbreviated: false },
|
|
161
|
+
confidenceKeys: {},
|
|
162
|
+
visual: { border: true, accent: true, background: true, verticalHoverLine: false, horizontalHoverLine: false },
|
|
163
|
+
useLogScale: false,
|
|
164
|
+
filterBehavior: 'Filter Change',
|
|
165
|
+
highlightedBarValues: [],
|
|
166
|
+
series: [{ dataKey: 'Home', type: 'Bar', tooltip: true }],
|
|
167
|
+
tooltips: { opacity: 90 },
|
|
168
|
+
height: 212,
|
|
169
|
+
data: [
|
|
170
|
+
{ Group: 'Combined Total of Group A', Vehicle: '100', Home: '120', Work: '140', Office: '120' },
|
|
171
|
+
{ Group: 'Combined Total of Group B', Vehicle: '150', Home: '140', Work: '100', Office: '90' },
|
|
172
|
+
{ Group: 'Combined Total of Group C', Vehicle: '90', Home: '90', Work: '80', Office: '80' },
|
|
173
|
+
{ Group: 'Combined Total of Group D', Vehicle: '70', Home: '60', Work: '50', Office: '70' }
|
|
174
|
+
],
|
|
175
|
+
dataFileName: 'CSV_Source_Example_for_Horizontal_Bar_viz-cdcwp1619811744363.csv',
|
|
176
|
+
dataFileSourceType: 'file',
|
|
177
|
+
visualizationType: 'Bar',
|
|
178
|
+
description: 'Subtext can be added here for options like citing data sources or insight into reading the bar chart.',
|
|
179
|
+
barPadding: 47,
|
|
180
|
+
filters: [],
|
|
181
|
+
lollipopSize: 'medium',
|
|
182
|
+
validated: 4.23,
|
|
183
|
+
dynamicMarginTop: 0
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export default meta
|