@cdc/chart 4.23.6 → 4.23.7

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/index.html CHANGED
@@ -38,10 +38,9 @@
38
38
  <!-- <div class="react-container" data-config="/examples/feature/filters/filter-testing.json"></div> -->
39
39
  <!-- <div class="react-container" data-config="/examples/feature/pie/planet-pie-example-config.json"></div> -->
40
40
  <!-- <div class="react-container" data-config="/examples/feature/line/line-chart.json"></div> -->
41
- <!-- <div class="react-container" data-config="/examples/feature/forecasting/index.json"></div> -->
41
+ <div class="react-container" data-config="/examples/feature/forecasting/index.json"></div>
42
42
  <!-- <div class="react-container" data-config="/examples/feature/forecasting/forecasting.json"></div> -->
43
43
  <!-- <div class="react-container" data-config="/examples/feature/forecasting/combo-forecasting.json"></div> -->
44
- <!-- <div class="react-container" data-config="/examples/feature/forecasting/non-combo-forecasting.json"></div> -->
45
44
  <!-- <div class="react-container" data-config="/examples/feature/forecasting/effective_reproduction.json"></div> -->
46
45
  <!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date.json"></div> -->
47
46
  <!-- <div class="react-container" data-config="/examples/feature/area/area-chart-category.json"></div> -->
@@ -66,18 +65,18 @@
66
65
  <!-- <div class="react-container" data-config="/examples/feature/sparkline/example-sparkline.json"></div> -->
67
66
 
68
67
  <!-- TESTS DATE EXCLUSIONS -->
69
- <!-- <div class="react-container" data-config="/examples/feature/tests-date-exclusions/date-exclusions-config.json"></div> -->
68
+ <div class="react-container" data-config="/examples/feature/tests-date-exclusions/date-exclusions-config.json"></div>
70
69
  <!-- <div class="react-container" data-config="/examples/feature/tests-case-rate/case-rate-example-config.json"></div> -->
71
70
 
72
71
  <!-- TESTS BIG SMALL-->
73
- <!-- <div class="react-container" data-config="/examples/feature/tests-big-small/big-small-test-line.json"></div> -->
72
+ <!-- <div class="react-container" data-config="/examples/feature/tests-big-small/big-small-test-line.json"></div> -->
74
73
  <!-- <div class="react-container" data-config="/examples/feature/tests-big-small/big-small-test-bar.json"></div> -->
75
74
  <!-- <div class="react-container" data-config="/examples/feature/tests-big-small/big-small-test-negative.json"></div> -->
76
75
  <!-- <div class="react-container" data-config="/examples/feature/tests-big-small/line-chart-max-increase.json"></div> -->
77
76
 
78
77
  <!-- TESTS NONNUMERICS -->
79
78
  <!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json"></div> -->
80
- <div class="react-container" data-config="/examples/feature/tests-non-numerics/example-combo-bar-nonnumeric.json"></div>
79
+ <!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/example-combo-bar-nonnumeric.json"></div> -->
81
80
  <!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/example-bar-chart-nonnumeric.json"></div> -->
82
81
  <!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/sparkline-chart-nonnumeric.json"></div> -->
83
82
  <!-- <div class="react-container" data-config="/examples/feature/tests-non-numerics/stacked-vertical-bar-example-nonnumerics.json"></div> -->
@@ -106,7 +105,8 @@
106
105
 
107
106
  <!-- VERTICAL BAR CHARTS -->
108
107
  <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/combo-line-chart.json"></div> -->
109
- <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json"></div> -->
108
+ <!-- <div class="react-container" data-config="/examples/private/problem.json"></div> -->
109
+ <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json"></div>
110
110
  <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json"></div> -->
111
111
  <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json"></div> -->
112
112
  <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json"></div> -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/chart",
3
- "version": "4.23.6",
3
+ "version": "4.23.7",
4
4
  "description": "React component for visualizing tabular data in various types of charts",
5
5
  "moduleName": "CdcChart",
6
6
  "main": "dist/cdcchart",
@@ -57,7 +57,7 @@
57
57
  "react": "^18.2.0",
58
58
  "react-dom": "^18.2.0"
59
59
  },
60
- "gitHead": "aaed0388b487adfeb3e7e278b4ce74df09cbaade",
60
+ "gitHead": "6c7ac5215dcf3bc1cc7d199089c8c2e75f53a93e",
61
61
  "devDependencies": {
62
62
  "resize-observer-polyfill": "^1.5.1"
63
63
  }
package/src/CdcChart.jsx CHANGED
@@ -316,6 +316,10 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
316
316
  }
317
317
  if (undefined === newConfig.table.show) newConfig.table.show = !isDashboard
318
318
 
319
+ newConfig.series.map(series => {
320
+ if (!series.tooltip) series.tooltip = true
321
+ })
322
+
319
323
  const processedConfig = { ...(await coveUpdateWorker(newConfig)) }
320
324
 
321
325
  updateConfig(processedConfig, data)
@@ -393,7 +397,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
393
397
  newConfig.runtime.seriesKeys = newConfig.series
394
398
  ? newConfig.series.map(series => {
395
399
  newConfig.runtime.seriesLabels[series.dataKey] = series.label || series.dataKey
396
- newConfig.runtime.seriesLabelsAll.push(series.label || series.dataKey)
400
+ newConfig.runtime.seriesLabelsAll.push(series.name || series.label || series.dataKey)
397
401
  return series.dataKey
398
402
  })
399
403
  : []
@@ -565,10 +569,11 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
565
569
  })
566
570
  }
567
571
 
568
- if (((newConfig.visualizationType === 'Bar' || newConfig.visualizationType === 'Deviation Bar') && newConfig.orientation === 'horizontal') || newConfig.visualizationType === 'Paired Bar') {
572
+ if ((newConfig.visualizationType === 'Bar' && newConfig.orientation === 'horizontal') || ['Deviation Bar', 'Paired Bar'].includes(newConfig.visualizationType)) {
569
573
  newConfig.runtime.xAxis = newConfig.yAxis
570
574
  newConfig.runtime.yAxis = newConfig.xAxis
571
575
  newConfig.runtime.horizontal = true
576
+ newConfig.orientation = 'horizontal'
572
577
  } else {
573
578
  newConfig.runtime.xAxis = newConfig.xAxis
574
579
  newConfig.runtime.yAxis = newConfig.yAxis
@@ -794,6 +799,21 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
794
799
  } else {
795
800
  newSeriesHighlight.push(newHighlight)
796
801
  }
802
+
803
+ /**
804
+ * pushDataKeyBySeriesName
805
+ * - pushes series.dataKey into the series highlight based on the found series.name
806
+ * @param {String} value
807
+ */
808
+ const pushDataKeyBySeriesName = value => {
809
+ let matchingSeries = config.series.filter(series => series.name === value.text)
810
+ if (matchingSeries?.length > 0) {
811
+ newSeriesHighlight.push(matchingSeries[0].dataKey)
812
+ }
813
+ }
814
+
815
+ pushDataKeyBySeriesName(label)
816
+
797
817
  setSeriesHighlight(newSeriesHighlight)
798
818
  }
799
819
 
@@ -852,8 +872,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
852
872
  return num + unit
853
873
  }
854
874
 
855
- // Format numeric data based on settings in config
856
- const formatNumber = (num, axis, shouldAbbreviate = false) => {
875
+ // Format numeric data based on settings in config OR from passed in settings for Additional Columns
876
+ const formatNumber = (num, axis, shouldAbbreviate = false, addColPrefix, addColSuffix, addColRoundTo) => {
857
877
  // if num is NaN return num
858
878
  if (isNaN(num) || !num) return num
859
879
  // Check if the input number is negative
@@ -875,10 +895,17 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
875
895
  let original = num
876
896
  let stringFormattingOptions
877
897
  if (axis === 'left') {
898
+ let roundToPlace
899
+ if (addColRoundTo !== undefined) {
900
+ // if its an Additional Column
901
+ roundToPlace = addColRoundTo ? Number(addColRoundTo) : 0
902
+ } else {
903
+ roundToPlace = roundTo ? Number(roundTo) : 0
904
+ }
878
905
  stringFormattingOptions = {
879
- useGrouping: config.dataFormat.commas ? true : false,
880
- minimumFractionDigits: roundTo ? Number(roundTo) : 0,
881
- maximumFractionDigits: roundTo ? Number(roundTo) : 0
906
+ useGrouping: addColRoundTo ? true : config.dataFormat.commas ? true : false,
907
+ minimumFractionDigits: roundToPlace,
908
+ maximumFractionDigits: roundToPlace
882
909
  }
883
910
  }
884
911
 
@@ -937,8 +964,12 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
937
964
  num = abbreviateNumber(parseFloat(num))
938
965
  }
939
966
 
940
- if (prefix && axis === 'left') {
941
- result += prefix
967
+ if (addColPrefix && axis === 'left') {
968
+ result = addColPrefix + result
969
+ } else {
970
+ if (prefix && axis === 'left') {
971
+ result = prefix + result
972
+ }
942
973
  }
943
974
 
944
975
  if (rightPrefix && axis === 'right') {
@@ -951,8 +982,12 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
951
982
 
952
983
  result += num
953
984
 
954
- if (suffix && axis === 'left') {
955
- result += suffix
985
+ if (addColSuffix && axis === 'left') {
986
+ result += addColSuffix
987
+ } else {
988
+ if (suffix && axis === 'left') {
989
+ result += suffix
990
+ }
956
991
  }
957
992
 
958
993
  if (rightSuffix && axis === 'right') {
@@ -1141,10 +1176,10 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1141
1176
  {config?.introText && <section className='introText'>{parse(config.introText)}</section>}
1142
1177
  <div
1143
1178
  style={{ marginBottom: config.legend.position !== 'bottom' && config.orientation === 'horizontal' ? `${config.runtime.xAxis.size}px` : '0px' }}
1144
- className={`chart-container ${config.legend.position === 'bottom' ? 'bottom' : ''}${config.legend.hide ? ' legend-hidden' : ''}${lineDatapointClass}${barBorderClass} ${contentClasses.join(' ')}`}
1179
+ className={`chart-container p-relative ${config.legend.position === 'bottom' ? 'bottom' : ''}${config.legend.hide ? ' legend-hidden' : ''}${lineDatapointClass}${barBorderClass} ${contentClasses.join(' ')}`}
1145
1180
  >
1146
1181
  {/* All charts except sparkline */}
1147
- {config.visualizationType !== 'Spark Line' && chartComponents[visualizationType]}
1182
+ {config.visualizationType !== 'Spark Line' && chartComponents[config.visualizationType]}
1148
1183
 
1149
1184
  {/* Sparkline */}
1150
1185
  {config.visualizationType === 'Spark Line' && (
@@ -1181,9 +1216,9 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1181
1216
  config={config}
1182
1217
  rawData={config.data}
1183
1218
  runtimeData={filteredData || excludedData}
1184
- //navigationHandler={navigationHandler}
1219
+ //navigationHandler={navigationHandler} // do we need this? What does it do?
1185
1220
  expandDataTable={config.table.expanded}
1186
- //headerColor={general.headerColor}
1221
+ //headerColor={general.headerColor} // have this in map but not chart
1187
1222
  columns={config.columns}
1188
1223
  showDownloadButton={config.general.showDownloadButton}
1189
1224
  runtimeLegend={dynamicLegendItems}
@@ -1204,6 +1239,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1204
1239
  outerContainerRef={outerContainerRef}
1205
1240
  imageRef={imageId}
1206
1241
  isDebug={isDebug}
1242
+ isEditor={isEditor}
1207
1243
  />
1208
1244
  )}
1209
1245
  {config?.footnotes && <section className='footnotes'>{parse(config.footnotes)}</section>}
@@ -1217,7 +1253,12 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1217
1253
  const getXAxisData = d => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
1218
1254
  const getYAxisData = (d, seriesKey) => d[seriesKey]
1219
1255
 
1256
+ const capitalize = str => {
1257
+ return str.charAt(0).toUpperCase() + str.slice(1)
1258
+ }
1259
+
1220
1260
  const contextValues = {
1261
+ capitalize,
1221
1262
  getXAxisData,
1222
1263
  getYAxisData,
1223
1264
  config,
@@ -1,126 +1,27 @@
1
- import React, { useContext, useEffect, useState } from 'react'
1
+ import React, { useContext, memo } from 'react'
2
2
 
3
3
  // cdc
4
4
  import ConfigContext from '../ConfigContext'
5
5
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
6
- import { colorPalettesChart } from '@cdc/core/data/colorPalettes'
7
6
 
8
7
  // visx & d3
9
8
  import * as allCurves from '@visx/curve'
10
9
  import { AreaClosed, LinePath, Bar } from '@visx/shape'
11
10
  import { Group } from '@visx/group'
12
- import { useTooltip, useTooltipInPortal, defaultStyles, Tooltip } from '@visx/tooltip'
13
- import { localPoint } from '@visx/event'
14
- import { bisector } from 'd3-array'
15
11
 
16
- const CoveAreaChart = ({ xScale, yScale, yMax, xMax, chartRef }) => {
12
+ const AreaChart = ({ xScale, yScale, yMax, xMax, chartRef, handleTooltipMouseOver, handleTooltipMouseOff, tooltipData }) => {
17
13
  // enable various console logs in the file
18
14
  const DEBUG = false
19
- const [chartPosition, setChartPosition] = useState(null)
20
-
21
- useEffect(() => {
22
- setChartPosition(chartRef.current.getBoundingClientRect())
23
- }, [chartRef])
24
15
 
25
16
  // import data from context
26
- const { transformedData: data, config, handleLineType, parseDate, formatDate, formatNumber, seriesHighlight, colorScale } = useContext(ConfigContext)
27
- const tooltip_id = `cdc-open-viz-tooltip-${config.runtime.uniqueId}`
28
-
29
- // import tooltip helpers
30
- const { tooltipData, showTooltip, hideTooltip } = useTooltip()
31
-
32
- // here we're inside of the svg,
33
- // it appears we need to use TooltipInPortal.
34
- const { TooltipInPortal } = useTooltipInPortal({
35
- detectBounds: true,
36
- // when tooltip containers are scrolled, this will correctly update the Tooltip position
37
- scroll: true
38
- })
17
+ const { transformedData: data, config, handleLineType, parseDate, seriesHighlight, colorScale, rawData } = useContext(ConfigContext)
39
18
 
40
19
  // Draw transparent bars over the chart to get tooltip data
41
20
  // Turn DEBUG on for additional context.
42
21
  if (!data) return
43
- let barThickness = xMax / data.length
44
-
45
- // Tooltip helper for getting data to the closest date/category hovered.
46
- const getXValueFromCoordinate = x => {
47
- if (config.xAxis.type === 'categorical' || config.visualizationType === 'Combo') {
48
- let eachBand = xScale.step()
49
- let numerator = x
50
- const index = Math.floor(Number(numerator) / eachBand)
51
- return xScale.domain()[index - 1] // fixes off by 1 error
52
- }
53
-
54
- if (config.xAxis.type === 'date' && config.visualizationType !== 'Combo') {
55
- const bisectDate = bisector(d => parseDate(d[config.xAxis.dataKey])).left
56
- const x0 = xScale.invert(x)
57
- const index = bisectDate(config.data, x0, 1)
58
- const val = parseDate(config.data[index - 1][config.xAxis.dataKey])
59
- return val
60
- }
61
- }
62
-
63
- const handleMouseOver = (e, data) => {
64
- // get the svg coordinates of the mouse
65
- // and get the closest values
66
- const eventSvgCoords = localPoint(e)
67
- const { x, y } = eventSvgCoords
68
-
69
- let closestXScaleValue = getXValueFromCoordinate(x)
70
- let formattedDate = formatDate(closestXScaleValue)
71
-
72
- let yScaleValues
73
- if (config.xAxis.type === 'categorical') {
74
- yScaleValues = data.filter(d => d[config.xAxis.dataKey] === closestXScaleValue)
75
- } else {
76
- yScaleValues = data.filter(d => formatDate(parseDate(d[config.xAxis.dataKey])) === formattedDate)
77
- }
78
-
79
- let seriesToInclude = []
80
- let yScaleMaxValues = []
81
- let itemsToLoop = [config.runtime.xAxis.dataKey, ...config.runtime.seriesKeys]
82
-
83
- itemsToLoop.map(seriesKey => {
84
- if (!seriesKey) return
85
- if (!yScaleValues[0]) return
86
- for (const item of Object.entries(yScaleValues[0])) {
87
- if (item[0] === seriesKey) {
88
- // let userUpdatedSeriesName = config.series.filter(series => series.dataKey === item[0])?.[0]?.name
89
- // if (userUpdatedSeriesName) item[0] = userUpdatedSeriesName
90
-
91
- seriesToInclude.push(item)
92
- }
93
- }
94
- })
95
-
96
- // filter out the series that aren't added to the map.
97
- seriesToInclude.map(series => yScaleMaxValues.push(Number(yScaleValues[0][series])))
98
- if (!seriesToInclude) return
99
-
100
- let tooltipDataFromSeries = Object.fromEntries(seriesToInclude) ? Object.fromEntries(seriesToInclude) : {}
101
-
102
- let tooltipData = {}
103
- tooltipData.data = tooltipDataFromSeries
104
- tooltipData.dataXPosition = x + 20
105
- tooltipData.dataYPosition = y - 100
106
-
107
- let tooltipInformation = {
108
- tooltipData: tooltipData,
109
- tooltipTop: 0,
110
- tooltipValues: yScaleValues,
111
- tooltipLeft: x
112
- }
113
-
114
- showTooltip(tooltipInformation)
115
- }
116
-
117
- const TooltipListItem = ({ item }) => {
118
- const [label, value] = item
119
- return label === config.xAxis.dataKey ? `${label}: ${value}` : `${label}: ${formatNumber(value, 'left')}`
120
- }
121
22
 
122
23
  const handleX = d => {
123
- return config.xAxis.type === 'date' ? xScale(parseDate(d[config.xAxis.dataKey])) : xScale(d[config.xAxis.dataKey])
24
+ return config.xAxis.type === 'date' ? xScale(parseDate(d[config.xAxis.dataKey], false)) : xScale(d[config.xAxis.dataKey])
124
25
  }
125
26
 
126
27
  const handleY = (d, index, s = undefined) => {
@@ -148,6 +49,7 @@ const CoveAreaChart = ({ xScale, yScale, yMax, xMax, chartRef }) => {
148
49
  } else {
149
50
  data.map(d => xScale(d[config.xAxis.dataKey]))
150
51
  }
52
+
151
53
  return (
152
54
  <React.Fragment key={index}>
153
55
  {/* prettier-ignore */}
@@ -174,52 +76,39 @@ const CoveAreaChart = ({ xScale, yScale, yMax, xMax, chartRef }) => {
174
76
  yScale={yScale}
175
77
  curve={curveType}
176
78
  strokeDasharray={s.type ? handleLineType(s.type) : 0}
177
- />
178
-
179
- {/* Transparent bar for tooltips */}
180
- {/* prettier-ignore */}
181
- <Bar
182
- width={ Number(xMax)}
183
- height={ Number(yMax)}
184
- fill={DEBUG ? 'red' : 'transparent'}
185
- fillOpacity={0.05}
186
- style={DEBUG ? { stroke: 'black', strokeWidth: 2 } : {}}
187
- onMouseMove={e => handleMouseOver(e, data)}
188
- onMouseOut={hideTooltip}
189
- />
79
+ />
190
80
 
191
81
  {/* circles that appear on hover */}
192
- {tooltipData && Object.entries(tooltipData.data).length > 0 && (
82
+ {/* {tooltipData && Object.entries(tooltipData.data).length > 0 && (
193
83
  <circle
194
84
  cx={config.xAxis.type === 'categorical' ? xScale(tooltipData.data[config.xAxis.dataKey]) : xScale(parseDate(tooltipData.data[config.xAxis.dataKey]))}
195
- cy={yScale(tooltipData.data[s.dataKey])}
85
+ cy={yScale(tooltipData.data[index][1])}
196
86
  r={4.5}
197
87
  opacity={1}
198
88
  fillOpacity={1}
199
89
  fill={displayArea ? (colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[s.dataKey] : s.dataKey) : '#000') : 'transparent'}
200
90
  style={{ filter: 'unset', opacity: 1 }}
201
91
  />
202
- )}
203
-
204
- {tooltipData && Object.entries(tooltipData.data).length > 0 && (
205
- <TooltipInPortal key={Math.random()} top={tooltipData.dataYPosition + chartPosition?.top} left={tooltipData.dataXPosition + chartPosition?.left} style={defaultStyles}>
206
- <ul style={{ listStyle: 'none', paddingLeft: 'unset', fontFamily: 'sans-serif', margin: 'auto', lineHeight: '1rem' }} data-tooltip-id={tooltip_id}>
207
- {typeof tooltipData === 'object' &&
208
- Object.entries(tooltipData.data).map(item => (
209
- <li style={{ padding: '2.5px 0' }}>
210
- <TooltipListItem item={item} />
211
- </li>
212
- ))}
213
- </ul>
214
- </TooltipInPortal>
215
- )}
92
+ )} */}
216
93
  </React.Fragment>
217
94
  )
218
95
  })}
96
+
97
+ {/* Transparent bar for tooltips */}
98
+ {/* prettier-ignore */}
99
+ <Bar
100
+ width={ Number(xMax)}
101
+ height={ Number(yMax)}
102
+ fill={DEBUG ? 'red' : 'transparent'}
103
+ fillOpacity={0.05}
104
+ style={DEBUG ? { stroke: 'black', strokeWidth: 2 } : {}}
105
+ onMouseMove={e => handleTooltipMouseOver(e, rawData)}
106
+ onMouseLeave={ handleTooltipMouseOff }
107
+ />
219
108
  </Group>
220
109
  </ErrorBoundary>
221
110
  )
222
111
  )
223
112
  }
224
113
 
225
- export default CoveAreaChart
114
+ export default memo(AreaChart)
@@ -1,15 +1,14 @@
1
1
  import React, { useContext, useState, useEffect } from 'react'
2
2
  import { Group } from '@visx/group'
3
- import { BarGroup, BarStack } from '@visx/shape'
3
+ import { BarGroup, BarStack, Bar } from '@visx/shape'
4
4
  import { Text } from '@visx/text'
5
5
  import chroma from 'chroma-js'
6
6
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
7
7
  import ConfigContext from '../ConfigContext'
8
8
  import { BarStackHorizontal } from '@visx/shape'
9
9
  import { useHighlightedBars } from '../hooks/useHighlightedBars'
10
- import { act } from 'react-dom/test-utils'
11
10
 
12
- export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getXAxisData, getYAxisData, animatedChart, visible }) {
11
+ const BarChart = ({ xScale, yScale, seriesScale, xMax, yMax, getXAxisData, getYAxisData, animatedChart, visible, handleTooltipMouseOver, handleTooltipMouseOff, handleTooltipClick }) => {
13
12
  const { transformedData: data, colorScale, seriesHighlight, config, formatNumber, updateConfig, colorPalettes, tableData, formatDate, isNumber, getTextWidth, parseDate, setSharedFilter, setSharedFilterValue, dashboardConfig } = useContext(ConfigContext)
14
13
  const { HighLightedBarUtils } = useHighlightedBars(config)
15
14
  const { orientation, visualizationSubType } = config
@@ -64,7 +63,7 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
64
63
  if (!colorMap.has(values[i])) {
65
64
  colorMap.set(values[i], palettesArr[colorMap.size % palettesArr.length])
66
65
  }
67
- // push the colosr to the result array
66
+ // push the color to the result array
68
67
  result.push(colorMap.get(values[i]))
69
68
  }
70
69
  return result
@@ -172,11 +171,17 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
172
171
  yAxisTooltip = config.isLegendValue ? `${bar.key}: ${yAxisValue}` : config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
173
172
  }
174
173
 
175
- const tooltip = `<div>
176
- ${config.legend.showLegendValuesTooltip && config.runtime.seriesLabels && hasMultipleSeries ? `${config.runtime.seriesLabels[bar.key] || ''}<br/>` : ''}
174
+ const {
175
+ legend: { showLegendValuesTooltip },
176
+ runtime: { seriesLabels }
177
+ } = config
178
+
179
+ const barStackTooltip = `<div>
180
+ <p class="tooltip-heading"><strong>${xAxisTooltip}</strong></p>
181
+ ${showLegendValuesTooltip && seriesLabels && hasMultipleSeries ? `${seriesLabels[bar.key] || ''}<br/>` : ''}
177
182
  ${yAxisTooltip}<br />
178
- ${xAxisTooltip}
179
183
  </div>`
184
+
180
185
  return (
181
186
  <Group key={`${barStack.index}--${bar.index}--${orientation}`}>
182
187
  <style>
@@ -201,7 +206,7 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
201
206
  style={{ background: bar.color, border: `${config.barHasBorder === 'true' ? barBorderWidth : 0}px solid #333`, ...style }}
202
207
  opacity={transparentBar ? 0.5 : 1}
203
208
  display={displayBar ? 'block' : 'none'}
204
- data-tooltip-html={tooltip}
209
+ data-tooltip-html={barStackTooltip}
205
210
  data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
206
211
  onClick={e => {
207
212
  e.preventDefault()
@@ -444,17 +449,17 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
444
449
  let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
445
450
  let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
446
451
  if (!hasMultipleSeries && config.runtime.horizontal) {
447
- xAxisTooltip = config.isLegendValue ? `${bar.key}: ${xAxisValue}` : config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
452
+ xAxisTooltip = config.isLegendValue ? `<p className="tooltip-heading">${bar.key}: ${xAxisValue}</p>` : config.runtime.xAxis.label ? `<p className="tooltip-heading">${config.runtime.xAxis.label}: ${xAxisValue}</p>` : xAxisValue
448
453
  }
449
454
  if (!hasMultipleSeries && !config.runtime.horizontal) {
450
455
  yAxisTooltip = config.isLegendValue ? `${bar.key}: ${yAxisValue}` : config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
451
456
  }
452
457
 
453
- const tooltip = `<div>
458
+ const tooltip = `<ul>
454
459
  ${config.legend.showLegendValuesTooltip && config.runtime.seriesLabels && hasMultipleSeries ? `${config.runtime.seriesLabels[bar.key] || ''}<br/>` : ''}
455
- ${yAxisTooltip}<br />
456
- ${xAxisTooltip}
457
- </div>`
460
+ <li class="tooltip-heading">${yAxisTooltip}</li>
461
+ <li class="tooltip-body">${xAxisTooltip}</li>
462
+ </li></ul>`
458
463
 
459
464
  const isRegularLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'regular'
460
465
  const isTwoToneLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'two-tone'
@@ -467,7 +472,7 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
467
472
  if (isTwoToneLollipopColor) return chroma(barColor).brighten(1)
468
473
  if (isHighlightedBar) return 'transparent'
469
474
  // loop through shared filters and get active values
470
- if (dashboardConfig && dashboardConfig?.dashboard.sharedFilters?.length > 0) {
475
+ /* if (dashboardConfig && dashboardConfig?.dashboard.sharedFilters?.length > 0) {
471
476
  let activeFilters = []
472
477
  let backgroundColor = barColor
473
478
 
@@ -500,7 +505,7 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
500
505
  }
501
506
  checkForResetValue()
502
507
  return backgroundColor
503
- }
508
+ } */
504
509
  return barColor
505
510
  }
506
511
 
@@ -674,7 +679,12 @@ export default function BarChart({ xScale, yScale, seriesScale, xMax, yMax, getX
674
679
  : ''}
675
680
  </Group>
676
681
  )}
682
+
683
+ {/* tooltips */}
684
+ {orientation !== 'horizontal' && <Bar key={'bars'} width={Number(xMax)} height={Number(yMax)} fill={false ? 'red' : 'transparent'} fillOpacity={0.05} onMouseMove={e => handleTooltipMouseOver(e, data)} onMouseOut={handleTooltipMouseOff} onClick={e => handleTooltipClick(e, data)} />}
677
685
  </Group>
678
686
  </ErrorBoundary>
679
687
  )
680
688
  }
689
+
690
+ export default BarChart
@@ -13,11 +13,12 @@ import ConfigContext from '../ConfigContext'
13
13
  import MediaControls from '@cdc/core/components/MediaControls'
14
14
 
15
15
  export default function DataTable() {
16
- const { rawData, tableData: data, config, colorScale, parseDate, formatDate, formatNumber: numberFormatter, colorPalettes } = useContext(ConfigContext)
16
+ const { rawData, tableData: data, config, colorScale, parseDate, formatDate, formatNumber: numberFormatter, colorPalettes, currentViewport } = useContext(ConfigContext)
17
17
 
18
18
  const section = config.orientation === 'horizontal' ? 'yAxis' : 'xAxis'
19
19
  const [tableExpanded, setTableExpanded] = useState(config.table.expanded)
20
20
  const [accessibilityLabel, setAccessibilityLabel] = useState('')
21
+ const isLegendBottom = ['sm', 'xs', 'xxs'].includes(currentViewport)
21
22
 
22
23
  const DownloadButton = ({ data }, type) => {
23
24
  const fileName = `${config.title.substring(0, 50)}.csv`
@@ -145,6 +146,8 @@ export default function DataTable() {
145
146
  if (rightSeriesItem.dataKey === row.original) resolvedAxis = 'right'
146
147
  })
147
148
 
149
+ if (config.visualizationType !== 'Combo') resolvedAxis = 'left'
150
+
148
151
  return <>{numberFormatter(d[row.original], resolvedAxis)}</>
149
152
  },
150
153
  id: `${d[config.runtime.originalXAxis.dataKey]}--${index}`,
@@ -233,7 +236,7 @@ export default function DataTable() {
233
236
  {config.table.download && <DownloadButton data={rawData} type='link' />}
234
237
  </MediaControls.Section>
235
238
 
236
- <section id={config?.title ? `dataTableSection__${config?.title.replace(/\s/g, '')}` : `dataTableSection`} className={`data-table-container`} aria-label={accessibilityLabel}>
239
+ <section style={{ marginTop: !isLegendBottom ? config.dynamicMarginTop + 'px' : '0px' }} id={config?.title ? `dataTableSection__${config?.title.replace(/\s/g, '')}` : `dataTableSection`} className={`data-table-container`} aria-label={accessibilityLabel}>
237
240
  <div
238
241
  role='button'
239
242
  className={tableExpanded ? 'data-table-heading' : 'collapsed data-table-heading'}