@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.
Files changed (56) hide show
  1. package/dist/cdcchart.js +30989 -29057
  2. package/examples/feature/bar/example-bar-chart.json +1 -46
  3. package/examples/feature/bar/lollipop.json +156 -0
  4. package/examples/feature/combo/planet-combo-example-config.json +99 -9
  5. package/examples/feature/dev-4261.json +399 -0
  6. package/examples/feature/forest-plot/{broken.json → linear.json} +55 -50
  7. package/examples/feature/forest-plot/logarithmic.json +306 -0
  8. package/examples/feature/line/line-points.json +340 -0
  9. package/examples/feature/regions/index.json +462 -0
  10. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +181 -48
  11. package/examples/sparkline-multilple.json +846 -0
  12. package/index.html +10 -6
  13. package/package.json +3 -3
  14. package/src/CdcChart.tsx +75 -63
  15. package/src/_stories/Chart.stories.tsx +188 -0
  16. package/src/_stories/Chart.tooltip.stories.tsx +305 -0
  17. package/src/_stories/ChartBrush.stories.tsx +19 -0
  18. package/src/_stories/ChartSuppress.stories.tsx +19 -0
  19. package/src/_stories/_mock/brush_mock.json +393 -0
  20. package/src/_stories/_mock/suppress_mock.json +911 -0
  21. package/src/components/AreaChart.Stacked.jsx +4 -5
  22. package/src/components/AreaChart.jsx +6 -35
  23. package/src/components/{BarChart.Horizontal.jsx → BarChart.Horizontal.tsx} +106 -29
  24. package/src/components/{BarChart.StackedHorizontal.jsx → BarChart.StackedHorizontal.tsx} +22 -17
  25. package/src/components/{BarChart.StackedVertical.jsx → BarChart.StackedVertical.tsx} +22 -26
  26. package/src/components/{BarChart.Vertical.jsx → BarChart.Vertical.tsx} +175 -31
  27. package/src/components/BarChart.jsx +1 -1
  28. package/src/components/DeviationBar.jsx +4 -3
  29. package/src/components/EditorPanel.jsx +176 -50
  30. package/src/components/ForestPlot/ForestPlotProps.ts +11 -0
  31. package/src/components/ForestPlot/Readme.md +0 -0
  32. package/src/components/ForestPlot/index.scss +1 -0
  33. package/src/components/{ForestPlot.jsx → ForestPlot/index.tsx} +51 -31
  34. package/src/components/ForestPlotSettings.jsx +162 -113
  35. package/src/components/Legend.jsx +36 -3
  36. package/src/components/{LineChart.Circle.tsx → LineChart/LineChart.Circle.tsx} +26 -29
  37. package/src/components/LineChart/LineChartProps.ts +17 -0
  38. package/src/components/LineChart/index.scss +1 -0
  39. package/src/components/{LineChart.tsx → LineChart/index.tsx} +64 -35
  40. package/src/components/LinearChart.jsx +120 -60
  41. package/src/components/PairedBarChart.jsx +2 -2
  42. package/src/components/Series.jsx +22 -3
  43. package/src/components/ZoomBrush.tsx +168 -0
  44. package/src/data/initial-state.js +27 -12
  45. package/src/hooks/useBarChart.js +71 -7
  46. package/src/hooks/useColorScale.ts +50 -0
  47. package/src/hooks/useEditorPermissions.js +22 -4
  48. package/src/hooks/{useMinMax.js → useMinMax.ts} +75 -23
  49. package/src/hooks/{useRightAxis.js → useRightAxis.ts} +10 -2
  50. package/src/hooks/{useScales.js → useScales.ts} +64 -17
  51. package/src/hooks/useTooltip.jsx +68 -41
  52. package/src/scss/main.scss +3 -35
  53. package/src/types/ChartConfig.ts +43 -0
  54. package/src/types/ChartContext.ts +38 -0
  55. package/src/types/ChartProps.ts +7 -0
  56. 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
- <!-- <div class="react-container" data-config="/examples/private/line-breaks.json"></div> -->
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/area/area-chart-stacked.json"></div> -->
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/sparkline/example-sparkline.json"></div> -->
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
- <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json"></div> -->
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.10",
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.10.1",
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": "ff5b1ca0c84bb0629bc69e5a26a4a81254dbf69f",
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
- {/* Title */}
1177
- {title && config.showTitle && (
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