@cdc/chart 4.24.5 → 4.24.9

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 (87) hide show
  1. package/dist/cdcchart.js +44197 -38258
  2. package/examples/cases-year.json +13379 -0
  3. package/examples/feature/annotations/index.json +542 -0
  4. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +76 -15
  5. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +5 -5
  6. package/examples/xaxis.json +493 -0
  7. package/index.html +20 -10
  8. package/package.json +5 -4
  9. package/src/CdcChart.tsx +462 -172
  10. package/src/_stories/Chart.Legend.Gradient.tsx +19 -0
  11. package/src/_stories/Chart.stories.tsx +18 -171
  12. package/src/_stories/ChartAnnotation.stories.tsx +32 -0
  13. package/src/_stories/_mock/annotation_category_mock.json +473 -0
  14. package/src/_stories/_mock/annotation_date-linear_mock.json +530 -0
  15. package/{examples/feature/line/line-chart.json → src/_stories/_mock/annotation_date-time_mock.json} +150 -69
  16. package/src/_stories/_mock/legend.gradient_mock.json +236 -0
  17. package/src/_stories/_mock/line_chart_two_points_new_chart.json +128 -0
  18. package/src/_stories/_mock/line_chart_two_points_regression_test.json +127 -0
  19. package/src/_stories/_mock/lollipop.json +171 -0
  20. package/src/components/Annotations/components/AnnotationDraggable.styles.css +31 -0
  21. package/src/components/Annotations/components/AnnotationDraggable.tsx +207 -0
  22. package/src/components/Annotations/components/AnnotationDropdown.styles.css +14 -0
  23. package/src/components/Annotations/components/AnnotationDropdown.tsx +72 -0
  24. package/src/components/Annotations/components/AnnotationList.styles.css +45 -0
  25. package/src/components/Annotations/components/AnnotationList.tsx +42 -0
  26. package/src/components/Annotations/components/findNearestDatum.ts +138 -0
  27. package/src/components/Annotations/components/helpers/index.tsx +46 -0
  28. package/src/components/Annotations/index.tsx +13 -0
  29. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +1 -1
  30. package/src/components/AreaChart/components/AreaChart.jsx +1 -1
  31. package/src/components/Axis/Categorical.Axis.tsx +145 -0
  32. package/src/components/BarChart/components/BarChart.Horizontal.tsx +47 -44
  33. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +0 -1
  34. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +11 -14
  35. package/src/components/BarChart/components/BarChart.Vertical.tsx +67 -30
  36. package/src/components/BarChart/helpers/index.ts +91 -0
  37. package/src/components/BrushChart.tsx +205 -0
  38. package/src/components/EditorPanel/EditorPanel.tsx +1794 -403
  39. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +320 -0
  40. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +282 -18
  41. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +43 -8
  42. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +4 -4
  43. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +4 -13
  44. package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
  45. package/src/components/EditorPanel/components/panels.scss +4 -0
  46. package/src/components/EditorPanel/editor-panel.scss +35 -3
  47. package/src/components/EditorPanel/{useEditorPermissions.js → useEditorPermissions.ts} +105 -17
  48. package/src/components/Legend/Legend.Component.tsx +185 -194
  49. package/src/components/Legend/Legend.Suppression.tsx +146 -0
  50. package/src/components/Legend/Legend.tsx +21 -5
  51. package/src/components/Legend/helpers/createFormatLabels.tsx +1 -1
  52. package/src/components/Legend/helpers/index.ts +35 -0
  53. package/src/components/LegendWrapper.tsx +26 -0
  54. package/src/components/LineChart/LineChartProps.ts +1 -15
  55. package/src/components/LineChart/components/LineChart.BumpCircle.tsx +103 -0
  56. package/src/components/LineChart/components/LineChart.Circle.tsx +47 -8
  57. package/src/components/LineChart/helpers.ts +72 -14
  58. package/src/components/LineChart/index.tsx +117 -42
  59. package/src/components/LinearChart.jsx +179 -136
  60. package/src/components/LinearChart.tsx +1366 -0
  61. package/src/components/PairedBarChart.jsx +9 -9
  62. package/src/components/PieChart/PieChart.tsx +75 -18
  63. package/src/components/Sankey/index.tsx +89 -30
  64. package/src/components/ScatterPlot/ScatterPlot.jsx +22 -8
  65. package/src/components/Sparkline/components/SparkLine.tsx +2 -2
  66. package/src/components/ZoomBrush.tsx +90 -44
  67. package/src/data/initial-state.js +25 -7
  68. package/src/helpers/handleChartTabbing.ts +8 -0
  69. package/src/helpers/isConvertLineToBarGraph.ts +4 -0
  70. package/src/hooks/{useBarChart.js → useBarChart.ts} +2 -40
  71. package/src/hooks/useColorScale.ts +1 -1
  72. package/src/hooks/useLegendClasses.ts +68 -0
  73. package/src/hooks/useMinMax.ts +12 -7
  74. package/src/hooks/useScales.ts +58 -26
  75. package/src/hooks/useTooltip.tsx +135 -25
  76. package/src/scss/DataTable.scss +2 -1
  77. package/src/scss/main.scss +128 -28
  78. package/src/types/ChartConfig.ts +83 -10
  79. package/src/types/ChartContext.ts +14 -4
  80. package/tests-examples/helpers/testZeroValue.test.ts +30 -0
  81. package/LICENSE +0 -201
  82. package/src/components/BrushHandle.jsx +0 -17
  83. package/src/components/LineChart/index.scss +0 -1
  84. package/src/helpers/filterData.ts +0 -18
  85. package/src/helpers/tests/computeMarginBottom.test.ts +0 -21
  86. package/src/hooks/useLegendClasses.js +0 -31
  87. /package/src/hooks/{useReduceData.js → useReduceData.ts} +0 -0
@@ -3,7 +3,7 @@ import { useContext } from 'react'
3
3
  import ConfigContext from '../ConfigContext'
4
4
  import { ChartConfig } from '../types/ChartConfig'
5
5
  import { ChartContext } from '../types/ChartContext'
6
-
6
+ import * as d3 from 'd3'
7
7
  const scaleTypes = {
8
8
  TIME: 'time',
9
9
  LOG: 'log',
@@ -27,12 +27,10 @@ const useScales = (properties: useScaleProps) => {
27
27
 
28
28
  const { rawData, dimensions } = useContext<ChartContext>(ConfigContext)
29
29
 
30
- const [screenWidth, screenHeight] = dimensions
30
+ const [screenWidth] = dimensions
31
31
  const seriesDomain = config.runtime.barSeriesKeys || config.runtime.seriesKeys
32
32
  const xAxisType = config.runtime.xAxis.type
33
33
  const isHorizontal = config.orientation === 'horizontal'
34
- const getXAxisDataKeys = d => d[config.runtime.originalXAxis.dataKey]
35
- const xAxisDataKeysMapped = data.map(d => getXAxisDataKeys(d))
36
34
 
37
35
  const { visualizationType } = config
38
36
 
@@ -43,12 +41,15 @@ const useScales = (properties: useScaleProps) => {
43
41
  let g1xScale = null
44
42
  let seriesScale = null
45
43
  let xScaleNoPadding = null
46
- let xScaleBrush = null
44
+ let xScaleAnnotation = scaleLinear({
45
+ domain: [0, 100],
46
+ range: [0, xMax]
47
+ })
47
48
 
48
49
  // handle Horizontal bars
49
50
  if (isHorizontal) {
50
51
  xScale = composeXScale({ min: min * 1.03, ...properties })
51
- xScale.type = config.useLogScale ? scaleTypes.LOG : scaleTypes.LINEAR
52
+ xScale.type = config.yAxis.type === 'logarithmic' ? scaleTypes.LOG : scaleTypes.LINEAR
52
53
  yScale = getYScaleFunction(xAxisType, xAxisDataMapped)
53
54
  yScale.rangeRound([0, yMax])
54
55
  seriesScale = composeScalePoint(seriesDomain, [0, yMax])
@@ -56,16 +57,20 @@ const useScales = (properties: useScaleProps) => {
56
57
 
57
58
  // handle Vertical bars
58
59
  if (!isHorizontal) {
59
- xScaleBrush = composeScalePoint(xAxisDataKeysMapped, [0, xMax], 0.5)
60
60
  xScale = composeScaleBand(xAxisDataMapped, [0, xMax], 1 - config.barThickness)
61
61
  yScale = composeYScale(properties)
62
62
  seriesScale = composeScaleBand(seriesDomain, [0, xScale.bandwidth()], 0)
63
63
  }
64
64
 
65
- // handle Area chart
65
+ // handle Linear scaled viz
66
+ if (config.xAxis.type === 'date' && !isHorizontal) {
67
+ const xAxisDataMappedSorted = xAxisDataMapped ? xAxisDataMapped.sort() : []
68
+ xScale = composeScaleBand(xAxisDataMappedSorted, [0, xMax], 1 - config.barThickness)
69
+ }
70
+
66
71
  if (config.xAxis.type === 'date-time') {
67
- let xAxisMin = Math.min(...xAxisDataMapped)
68
- let xAxisMax = Math.max(...xAxisDataMapped)
72
+ let xAxisMin = Math.min(...xAxisDataMapped.map(Number))
73
+ let xAxisMax = Math.max(...xAxisDataMapped.map(Number))
69
74
  xAxisMin -= (config.xAxis.padding ? config.xAxis.padding * 0.01 : 0) * (xAxisMax - xAxisMin)
70
75
  xAxisMax += (config.xAxis.padding ? config.xAxis.padding * 0.01 : 0) * (xAxisMax - xAxisMin)
71
76
  xScale = scaleTime({
@@ -74,7 +79,20 @@ const useScales = (properties: useScaleProps) => {
74
79
  })
75
80
 
76
81
  xScale.type = scaleTypes.TIME
77
- seriesScale = composeScaleBand(seriesDomain, [0, config.barThickness * xMax], 0)
82
+
83
+ let minDistance = Number.MAX_VALUE
84
+ let xAxisDataMappedSorted = xAxisDataMapped ? xAxisDataMapped.sort() : []
85
+ for (let i = 0; i < xAxisDataMappedSorted.length - 1; i++) {
86
+ let distance = xScale(xAxisDataMappedSorted[i + 1]) - xScale(xAxisDataMappedSorted[i])
87
+
88
+ if (distance < minDistance) minDistance = distance
89
+ }
90
+
91
+ if (xAxisDataMapped.length === 1 || minDistance > xMax / 4) {
92
+ minDistance = xMax / 4
93
+ }
94
+
95
+ seriesScale = composeScaleBand(seriesDomain, [0, (config.barThickness || 1) * minDistance], 0)
78
96
  }
79
97
 
80
98
  // handle Deviation bar
@@ -107,7 +125,9 @@ const useScales = (properties: useScaleProps) => {
107
125
  // handle Box plot
108
126
  if (visualizationType === 'Box Plot') {
109
127
  const allOutliers = []
110
- const hasOutliers = config.boxplot.plots.map(b => b.columnOutliers.map(outlier => allOutliers.push(outlier))) && !config.boxplot.hideOutliers
128
+ const hasOutliers =
129
+ config.boxplot.plots.map(b => b.columnOutliers.map(outlier => allOutliers.push(outlier))) &&
130
+ !config.boxplot.hideOutliers
111
131
 
112
132
  // check if outliers are lower
113
133
  if (hasOutliers) {
@@ -193,8 +213,11 @@ const useScales = (properties: useScaleProps) => {
193
213
  if (screenWidth > 480) {
194
214
  if (config.forestPlot.type === 'Linear') {
195
215
  xScale = scaleLinear({
196
- domain: [Math.min(...data.map(d => parseFloat(d[config.forestPlot.lower]))) - xAxisPadding, Math.max(...data.map(d => parseFloat(d[config.forestPlot.upper]))) + xAxisPadding],
197
- range: [leftWidthOffset, dimensions[0] - rightWidthOffset]
216
+ domain: [
217
+ Math.min(...data.map(d => parseFloat(d[config.forestPlot.lower]))) - xAxisPadding,
218
+ Math.max(...data.map(d => parseFloat(d[config.forestPlot.upper]))) + xAxisPadding
219
+ ],
220
+ range: [leftWidthOffset, Number(screenWidth) - rightWidthOffset]
198
221
  })
199
222
  xScale.type = scaleTypes.LINEAR
200
223
  }
@@ -212,7 +235,10 @@ const useScales = (properties: useScaleProps) => {
212
235
  } else {
213
236
  if (config.forestPlot.type === 'Linear') {
214
237
  xScale = scaleLinear({
215
- domain: [Math.min(...data.map(d => parseFloat(d[config.forestPlot.lower]))) - xAxisPadding, Math.max(...data.map(d => parseFloat(d[config.forestPlot.upper]))) + xAxisPadding],
238
+ domain: [
239
+ Math.min(...data.map(d => parseFloat(d[config.forestPlot.lower]))) - xAxisPadding,
240
+ Math.max(...data.map(d => parseFloat(d[config.forestPlot.upper]))) + xAxisPadding
241
+ ],
216
242
  range: [leftWidthOffsetMobile, xMax - rightWidthOffsetMobile],
217
243
  type: scaleTypes.LINEAR
218
244
  })
@@ -233,7 +259,7 @@ const useScales = (properties: useScaleProps) => {
233
259
  }
234
260
  }
235
261
  }
236
- return { xScale, yScale, seriesScale, g1xScale, g2xScale, xScaleNoPadding, xScaleBrush }
262
+ return { xScale, yScale, seriesScale, g1xScale, g2xScale, xScaleNoPadding, xScaleAnnotation }
237
263
  }
238
264
 
239
265
  export default useScales
@@ -273,31 +299,37 @@ export const getTickValues = (xAxisDataMapped, xScale, num) => {
273
299
  /// helper functions
274
300
  const composeXScale = ({ min, max, xMax, config }) => {
275
301
  // Adjust min value if using logarithmic scale
276
- min = config.useLogScale && min >= 0 && min < 1 ? min + 0.1 : min
302
+ const isLogarithmicAxis = config.yAxis.type === 'logarithmic'
303
+ min = isLogarithmicAxis && min >= 0 && min < 1 ? min + 0.1 : min
277
304
  // Select the appropriate scale function
278
- const scaleFunc = config.useLogScale ? scaleLog : scaleLinear
305
+ const scaleFunc = isLogarithmicAxis ? scaleLog : scaleLinear
279
306
  // Return the configured scale function
280
307
  return scaleFunc({
281
308
  domain: [min, max],
282
309
  range: [0, xMax],
283
- nice: config.useLogScale,
284
- zero: config.useLogScale
310
+ nice: isLogarithmicAxis,
311
+ zero: isLogarithmicAxis
285
312
  })
286
313
  }
287
314
 
288
315
  const composeYScale = ({ min, max, yMax, config, leftMax }) => {
289
316
  // Adjust min value if using logarithmic scale
290
- min = config.useLogScale && min >= 0 && min < 1 ? min + 0.1 : min
317
+ const isLogarithmicAxis = config.yAxis.type === 'logarithmic'
318
+ min = isLogarithmicAxis && min >= 0 && min < 1 ? min + 0.1 : min
291
319
  // Select the appropriate scale function
292
- const scaleFunc = config.useLogScale ? scaleLog : scaleLinear
320
+ const scaleFunc = isLogarithmicAxis ? scaleLog : scaleLinear
293
321
 
294
322
  if (config.visualizationType === 'Combo') max = leftMax
323
+
324
+ // If the visualization type is a bump chart then the domain and range need different values
325
+ const domainSet = config.visualizationType === 'Bump Chart' ? [1, max] : [min, max]
326
+ const yRange = config.visualizationType === 'Bump Chart' ? [30, yMax] : [yMax, 0]
295
327
  // Return the configured scale function
296
328
  return scaleFunc({
297
- domain: [min, max],
298
- range: [yMax, 0],
299
- nice: config.useLogScale,
300
- zero: config.useLogScale
329
+ domain: domainSet,
330
+ range: yRange,
331
+ nice: isLogarithmicAxis,
332
+ zero: isLogarithmicAxis
301
333
  })
302
334
  }
303
335
 
@@ -9,9 +9,20 @@ import { localPoint } from '@visx/event'
9
9
  import { bisector } from 'd3-array'
10
10
 
11
11
  export const useTooltip = props => {
12
- const { tableData: data, config, formatNumber, capitalize, formatDate, formatTooltipsDate, parseDate, setSharedFilter } = useContext<ChartContext>(ConfigContext)
12
+ const {
13
+ tableData: data,
14
+ config,
15
+ formatNumber,
16
+ capitalize,
17
+ formatDate,
18
+ formatTooltipsDate,
19
+ parseDate,
20
+ setSharedFilter,
21
+ isDraggingAnnotation
22
+ } = useContext<ChartContext>(ConfigContext)
13
23
  const { xScale, yScale, showTooltip, hideTooltip } = props
14
24
  const { xAxis, visualizationType, orientation, yAxis, runtime } = config
25
+
15
26
  /**
16
27
  * Provides the tooltip information based on the tooltip data array and svg cursor coordinates
17
28
  * @function getTooltipInformation
@@ -19,6 +30,42 @@ export const useTooltip = props => {
19
30
  * @param {Object} eventSvgCoords - The object containing the SVG coordinates of the event.
20
31
  * @return {Object} - The tooltip information with tooltip data.
21
32
  */
33
+
34
+ // function handles only Single series hovred data tooltips
35
+ const findDataKeyByThreshold = (mouseY, datapoint) => {
36
+ let sum = 0
37
+ let threshold = Number(yScale.invert(mouseY))
38
+ let hoveredKey = null
39
+ let hoveredValue = null
40
+
41
+ for (let key of config.runtime?.seriesKeys) {
42
+ if (datapoint.hasOwnProperty(key)) {
43
+ sum += Number(datapoint[key])
44
+ if (sum >= threshold) {
45
+ hoveredValue = datapoint[key]
46
+ hoveredKey = key
47
+ break
48
+ }
49
+ }
50
+ }
51
+
52
+ // Return null if no matching data is found
53
+ return [hoveredKey, hoveredValue]
54
+ }
55
+
56
+ const getFormattedValue = (seriesKey, value, config, getAxisPosition) => {
57
+ // handle case where data is missing
58
+ const showMissingDataValue = config.general.showMissingDataLabel && (!value || value === 'null')
59
+ let formattedValue = seriesKey === config.xAxis.dataKey ? value : formatNumber(value, getAxisPosition(seriesKey))
60
+
61
+ formattedValue =
62
+ showMissingDataValue && (config.visualizationSubType === 'stacked' ? !config.general.hideNullValue : true)
63
+ ? 'N/A'
64
+ : formattedValue
65
+
66
+ return formattedValue
67
+ }
68
+
22
69
  const getTooltipInformation = (tooltipDataArray, eventSvgCoords) => {
23
70
  const { x, y } = eventSvgCoords
24
71
  let initialTooltipData = tooltipDataArray || {}
@@ -45,7 +92,10 @@ export const useTooltip = props => {
45
92
  * @return {void} - The tooltip information is displayed
46
93
  */
47
94
  const handleTooltipMouseOver = (e, additionalChartData) => {
95
+ if (visualizationType === 'Bump Chart') return
48
96
  e.stopPropagation()
97
+ if (isDraggingAnnotation) return
98
+
49
99
  const eventSvgCoords = localPoint(e)
50
100
  const { x, y } = eventSvgCoords
51
101
 
@@ -54,10 +104,13 @@ export const useTooltip = props => {
54
104
 
55
105
  const closestXScaleValue = getXValueFromCoordinate(x - Number(config.yAxis.size || 0))
56
106
 
57
- const includedSeries = visualizationType !== 'Pie' ? config.series.filter(series => series.tooltip === true).map(item => item.dataKey) : config.series.map(item => item.dataKey)
107
+ const includedSeries =
108
+ visualizationType !== 'Pie'
109
+ ? config.runtime.series.filter(series => series.tooltip === true).map(item => item.dataKey)
110
+ : config.runtime.series.map(item => item.dataKey)
58
111
  includedSeries.push(config.xAxis.dataKey)
59
112
  if (config.visualizationType === 'Forecasting') {
60
- config.series.map(s => {
113
+ config.runtime.series.map(s => {
61
114
  s.confidenceIntervals.map(c => {
62
115
  if (c.showInTooltip) {
63
116
  includedSeries.push(c.high)
@@ -84,7 +137,7 @@ export const useTooltip = props => {
84
137
  const resolvedScaleValues = orientation === 'vertical' ? yScaleValues : xScaleValues
85
138
 
86
139
  const getAxisPosition = seriesKey => {
87
- const seriesObj = config.series.filter(s => s.dataKey === seriesKey)[0]
140
+ const seriesObj = config.runtime.series.filter(s => s.dataKey === seriesKey)[0]
88
141
  const position = seriesObj?.axis ? String(seriesObj.axis).toLowerCase() : 'left'
89
142
  return position
90
143
  }
@@ -133,22 +186,34 @@ export const useTooltip = props => {
133
186
  if (visualizationType === 'Forest Plot') {
134
187
  tooltipItems.push([config.xAxis.dataKey, getClosestYValue(y)])
135
188
  }
136
-
137
- if (visualizationType !== 'Pie' && visualizationType !== 'Forest Plot') {
189
+ // handle tooltip for all hovered series
190
+ if (visualizationType !== 'Pie' && visualizationType !== 'Forest Plot' && !config.tooltips.singleSeries) {
138
191
  tooltipItems.push(
139
192
  ...getIncludedTooltipSeries()
140
- ?.filter(seriesKey => config.series?.find(item => item.dataKey === seriesKey && item?.tooltip) || config.xAxis?.dataKey == seriesKey)
193
+ ?.filter(
194
+ seriesKey =>
195
+ config.runtime.series?.find(item => item.dataKey === seriesKey && item?.tooltip) ||
196
+ config.xAxis?.dataKey == seriesKey ||
197
+ visualizationType === 'Forecasting'
198
+ )
141
199
  ?.flatMap(seriesKey => {
142
- let formattedValue = seriesKey === config.xAxis.dataKey ? resolvedScaleValues[0]?.[seriesKey] : formatNumber(resolvedScaleValues[0]?.[seriesKey], getAxisPosition(seriesKey))
143
- const suppressed = config.preliminaryData?.find(pd => pd.label && pd.type === 'suppression' && pd.displayTooltip && resolvedScaleValues[0]?.[seriesKey] === pd.value && (!pd.column || seriesKey === pd.column))
144
- if (suppressed) {
145
- formattedValue = suppressed.label
146
- }
147
- return resolvedScaleValues?.[0]?.[seriesKey] ? [[seriesKey, formattedValue, getAxisPosition(seriesKey)]] : []
200
+ const value = resolvedScaleValues[0]?.[seriesKey]
201
+ const formattedValue = getFormattedValue(seriesKey, value, config, getAxisPosition)
202
+ return [[seriesKey, formattedValue, getAxisPosition(seriesKey)]]
148
203
  })
149
204
  )
150
205
  }
151
206
 
207
+ // handle tooltip for single hovered series
208
+ if (visualizationType !== 'Pie' && visualizationType !== 'Forest Plot' && config.tooltips.singleSeries) {
209
+ const [seriesKey, value] = findDataKeyByThreshold(y, resolvedScaleValues[0])
210
+ if (seriesKey && value) {
211
+ tooltipItems.push([config.xAxis.dataKey, closestXScaleValue])
212
+ const formattedValue = getFormattedValue(seriesKey, value, config, getAxisPosition)
213
+ tooltipItems.push([seriesKey, formattedValue])
214
+ }
215
+ }
216
+
152
217
  return [...tooltipItems, ...additionalTooltipItems]
153
218
  }
154
219
 
@@ -227,7 +292,10 @@ export const useTooltip = props => {
227
292
  return closestX
228
293
  }
229
294
 
230
- if (config.xAxis.type === 'categorical' || (visualizationType === 'Combo' && orientation !== 'horizontal' && visualizationType !== 'Forest Plot')) {
295
+ if (
296
+ config.xAxis.type === 'categorical' ||
297
+ (visualizationType === 'Combo' && orientation !== 'horizontal' && visualizationType !== 'Forest Plot')
298
+ ) {
231
299
  let range = xScale.range()[1] - xScale.range()[0]
232
300
  let eachBand = range / (xScale.domain().length + 1)
233
301
 
@@ -275,6 +343,7 @@ export const useTooltip = props => {
275
343
  // Get the closest x axis value from the pointer.
276
344
  // After getting the closest value, return the data entry with that x scale value.
277
345
  // Pass the config.visual uid (not uuid) along with that data entry to setSharedFilters
346
+ if (config.visualizationType === 'Bump Chart') return
278
347
  const eventSvgCoords = localPoint(e)
279
348
  const { x } = eventSvgCoords
280
349
  if (!x) throw new Error('COVE: no x value in handleTooltipClick.')
@@ -323,7 +392,6 @@ export const useTooltip = props => {
323
392
  const yScaleValues = dataToSearch.map(object => {
324
393
  return Object.fromEntries(Object.entries(object).filter(([key, value]) => includedSeries.includes(key)))
325
394
  })
326
-
327
395
  return yScaleValues
328
396
  } catch (error) {
329
397
  console.error('COVE', error)
@@ -345,7 +413,7 @@ export const useTooltip = props => {
345
413
 
346
414
  // loop through series for items to add to tooltip.
347
415
  // there is probably a better way of doing this.
348
- config.series?.forEach(s => {
416
+ config.runtime.series?.forEach(s => {
349
417
  if (s.type === 'Forecasting') {
350
418
  stageColumns.push(s.stageColumn)
351
419
 
@@ -373,7 +441,10 @@ export const useTooltip = props => {
373
441
  standardLoopItems = [runtime.xAxis.dataKey, ...runtime?.seriesKeys]
374
442
  break
375
443
  case 'Bar':
376
- standardLoopItems = orientation === 'vertical' ? [runtime.xAxis.dataKey, ...runtime?.seriesKeys] : [runtime.yAxis.dataKey, ...runtime?.seriesKeys]
444
+ standardLoopItems =
445
+ orientation === 'vertical'
446
+ ? [runtime.xAxis.dataKey, ...runtime?.seriesKeys]
447
+ : [runtime.yAxis.dataKey, ...runtime?.seriesKeys]
377
448
  break
378
449
  case 'Pie':
379
450
  standardLoopItems = [runtime.xAxis.dataKey, ...runtime?.seriesKeys]
@@ -383,7 +454,13 @@ export const useTooltip = props => {
383
454
  }
384
455
 
385
456
  if (config.dashboard) {
386
- standardLoopItems = [runtime.xAxis.dataKey, ...runtime?.barSeriesKeys, ...runtime?.lineSeriesKeys, ...stageColumns, ...ciItems]
457
+ standardLoopItems = [
458
+ runtime.xAxis.dataKey,
459
+ ...runtime?.barSeriesKeys,
460
+ ...runtime?.lineSeriesKeys,
461
+ ...stageColumns,
462
+ ...ciItems
463
+ ]
387
464
  }
388
465
 
389
466
  return standardLoopItems
@@ -416,7 +493,7 @@ export const useTooltip = props => {
416
493
  * @returns user defined series name.
417
494
  */
418
495
  const getSeriesNameFromLabel = originalColumnName => {
419
- let series = config.series.filter(s => s.dataKey === originalColumnName)
496
+ let series = config.runtime.series.filter(s => s.dataKey === originalColumnName)
420
497
  if (series[0]?.name) return series[0]?.name
421
498
  return originalColumnName
422
499
  }
@@ -426,18 +503,51 @@ export const useTooltip = props => {
426
503
  const [key, value, axisPosition] = additionalData
427
504
 
428
505
  if (visualizationType === 'Forest Plot') {
429
- if (key === config.xAxis.dataKey) return <li className='tooltip-heading'>{`${capitalize(config.xAxis.dataKey ? `${config.xAxis.dataKey}: ` : '')} ${isDateScale(yAxis) ? formatDate(parseDate(key, false)) : value}`}</li>
506
+ if (key === config.xAxis.dataKey)
507
+ return (
508
+ <li className='tooltip-heading'>{`${capitalize(config.xAxis.dataKey ? `${config.xAxis.dataKey}: ` : '')} ${
509
+ isDateScale(yAxis) ? formatDate(parseDate(key, false)) : value
510
+ }`}</li>
511
+ )
430
512
  return <li className='tooltip-body'>{`${getSeriesNameFromLabel(key)}: ${formatNumber(value, 'left')}`}</li>
431
513
  }
432
- const formattedDate = config.tooltips.dateDisplayFormat ? formatTooltipsDate(parseDate(value, false)) : formatDate(parseDate(value, false))
514
+ const formattedDate = config.tooltips.dateDisplayFormat
515
+ ? formatTooltipsDate(parseDate(value, false))
516
+ : formatDate(parseDate(value, false))
433
517
 
434
518
  // TOOLTIP HEADING
435
- if (visualizationType === 'Bar' && orientation === 'horizontal' && key === config.xAxis.dataKey) return <li className='tooltip-heading'>{`${capitalize(config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ` : '')} ${config.xAxis.type === 'date' ? formattedDate : value}`}</li>
436
-
437
- if (key === config.xAxis.dataKey) return <li className='tooltip-heading'>{`${capitalize(config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ` : '')} ${isDateScale(xAxis) ? formattedDate : value}`}</li>
519
+ if (visualizationType === 'Bar' && orientation === 'horizontal' && key === config.xAxis.dataKey)
520
+ return (
521
+ <li className='tooltip-heading'>{`${capitalize(
522
+ config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ` : ''
523
+ )} ${config.xAxis.type === 'date' ? formattedDate : value}`}</li>
524
+ )
525
+
526
+ if (key === config.xAxis.dataKey)
527
+ return (
528
+ <li className='tooltip-heading'>{`${capitalize(
529
+ config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ` : ''
530
+ )} ${isDateScale(xAxis) ? formattedDate : value}`}</li>
531
+ )
438
532
 
439
533
  // TOOLTIP BODY
440
- return <li className='tooltip-body'>{`${getSeriesNameFromLabel(key)}: ${value}`}</li>
534
+ // handle suppressed tooltip items
535
+ const { label, displayGray } =
536
+ (config.visualizationSubType !== 'stacked' &&
537
+ config.general.showSuppressedSymbol &&
538
+ config.preliminaryData?.find(
539
+ pd =>
540
+ pd.label &&
541
+ pd.type === 'suppression' &&
542
+ pd.displayTooltip &&
543
+ value === pd.value &&
544
+ (!pd.column || key === pd.column)
545
+ )) ||
546
+ {}
547
+ const newValue = label || value
548
+ const style = displayGray ? { color: '#8b8b8a' } : {}
549
+
550
+ return <li style={style} className='tooltip-body'>{`${getSeriesNameFromLabel(key)}: ${newValue}`}</li>
441
551
  }
442
552
 
443
553
  return {
@@ -1,6 +1,7 @@
1
1
  @include breakpointClass(md) {
2
2
  .data-table-container {
3
- margin: 5px 1em;
3
+ margin: 5px 0em;
4
+ width: 100%;
4
5
  }
5
6
  }
6
7