@cdc/chart 4.26.6 → 4.26.10

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 (276) hide show
  1. package/CONFIG.md +504 -368
  2. package/dist/cdcchart-CYc-Kayd.es.js +22488 -0
  3. package/dist/cdcchart-DCKn8NmI.es.js +20695 -0
  4. package/dist/cdcchart-Dyui9nk_.es.js +45828 -0
  5. package/dist/cdcchart.js +4 -96498
  6. package/examples/__data__/vega-remote-data.json +6 -0
  7. package/examples/dendrogram.json +18 -0
  8. package/examples/feature/bar/bar-chart-race-annual-change.json +68 -0
  9. package/examples/feature/heatmap/average-age-categorical.json +2 -2
  10. package/examples/feature/heatmap/calendar-heatmap.json +2 -2
  11. package/examples/feature/heatmap/cell-values-bottom-axis.json +2 -2
  12. package/examples/feature/heatmap/sparse-aggregation.json +2 -2
  13. package/examples/feature/line/line-chart-race.json +50 -0
  14. package/examples/feature/sankey/sankey-example-data.json +40 -1441
  15. package/examples/feature/sankey/sankey_chart_data.csv +9 -20
  16. package/examples/network.json +31 -0
  17. package/examples/private/box-plot.json +573 -0
  18. package/examples/private/custom-color-issue.json +625 -0
  19. package/examples/private/custom-colors.json +522 -0
  20. package/examples/private/cutoff.json +10750 -0
  21. package/examples/private/flueview.json +22051 -0
  22. package/examples/private/overlay-legend.json +485 -0
  23. package/examples/private/pie-test.json +469 -0
  24. package/examples/vega-remote.json +22 -0
  25. package/package.json +11 -13
  26. package/src/CdcChart.tsx +2 -2
  27. package/src/CdcChartComponent.tsx +444 -217
  28. package/src/_stories/Chart.BarRace.stories.tsx +443 -0
  29. package/src/_stories/Chart.BoxPlotNumericSort.stories.tsx +189 -0
  30. package/src/_stories/Chart.BoxPlotStatsParity.stories.tsx +207 -0
  31. package/src/_stories/Chart.ColorDistribution.stories.tsx +299 -0
  32. package/src/_stories/Chart.DataCutoff.stories.tsx +147 -0
  33. package/src/_stories/Chart.DataTableDownloadFilename.stories.tsx +60 -0
  34. package/src/_stories/Chart.Dendrogram.stories.tsx +373 -0
  35. package/src/_stories/Chart.Forecast.CILegend.stories.tsx +236 -0
  36. package/src/_stories/Chart.HeatMap.stories.tsx +170 -4
  37. package/src/_stories/Chart.Legend.AxisAlign.stories.tsx +119 -0
  38. package/src/_stories/Chart.LineRace.stories.tsx +149 -0
  39. package/src/_stories/Chart.Network.stories.tsx +432 -0
  40. package/src/_stories/Chart.PaletteConversion.Editor.stories.tsx +208 -0
  41. package/src/_stories/Chart.Patterns.smoke.stories.tsx +31 -0
  42. package/src/_stories/Chart.PercentageValue.stories.tsx +311 -0
  43. package/src/_stories/Chart.PieLabels.stories.tsx +49 -0
  44. package/src/_stories/Chart.RankByValueMutation.stories.tsx +206 -0
  45. package/src/_stories/Chart.RequiredFields.stories.tsx +681 -0
  46. package/src/_stories/Chart.Sankey.stories.tsx +417 -0
  47. package/src/_stories/Chart.SeriesColorAssignments.stories.tsx +47 -0
  48. package/src/_stories/Chart.SmallMultiplesNumericTileOrder.stories.tsx +137 -0
  49. package/src/_stories/Chart.TooltipSeriesLabels.stories.tsx +43 -0
  50. package/src/_stories/Chart.VegaRemoteData.stories.tsx +31 -0
  51. package/src/_stories/Chart.smoke.stories.tsx +14 -1
  52. package/src/_stories/ChartAnnotation.Editor.stories.tsx +78 -0
  53. package/src/_stories/ChartAxisTitles.smoke.stories.tsx +48 -0
  54. package/src/_stories/ChartBar.Editor.stories.tsx +499 -57
  55. package/src/_stories/ChartBrush.Editor.stories.tsx +46 -67
  56. package/src/_stories/ChartBrush.Regression.stories.tsx +135 -0
  57. package/src/_stories/ChartEditor.Editor.stories.tsx +33 -3
  58. package/src/_stories/ChartLine.EffectCompatibility.stories.tsx +120 -0
  59. package/src/_stories/ChartPrefixSuffix.smoke.stories.tsx +28 -1
  60. package/src/_stories/_mock/annotation_event-line_mock.json +2 -2
  61. package/src/_stories/_mock/editor-test-configs.json +20 -10
  62. package/src/_stories/_mock/editor-test-datasets.json +38 -42
  63. package/src/_stories/_mock/heatmap-average-age-categorical.json +2 -2
  64. package/src/_stories/_mock/heatmap.json +2 -2
  65. package/src/_stories/_mock/legend-axis-align-stacked-bar.json +125 -0
  66. package/src/_stories/_mock/sankey_mock.json +23 -27
  67. package/src/components/Annotations/components/AnnotationDraggable.styles.css +52 -0
  68. package/src/components/Annotations/components/AnnotationDraggable.tsx +639 -139
  69. package/src/components/Annotations/components/AnnotationDropdown.styles.css +44 -4
  70. package/src/components/Annotations/components/AnnotationDropdown.tsx +10 -32
  71. package/src/components/Annotations/helpers/resolveAnnotationLayout.ts +212 -0
  72. package/src/components/Annotations/tests/AnnotationDraggable.test.tsx +612 -19
  73. package/src/components/Annotations/tests/AnnotationDropdown.test.tsx +50 -0
  74. package/src/components/Annotations/tests/resolveAnnotationLayout.test.ts +203 -0
  75. package/src/components/Axis/BottomAxis.tsx +1 -1
  76. package/src/components/Axis/Categorical.Axis.tsx +3 -3
  77. package/src/components/Axis/RightAxis.tsx +21 -13
  78. package/src/components/BarChart/components/BarChart.Horizontal.tsx +39 -8
  79. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +13 -4
  80. package/src/components/BarChart/components/BarChart.StackedVertical.test.ts +28 -0
  81. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +30 -26
  82. package/src/components/BarChart/components/BarChart.Vertical.tsx +38 -28
  83. package/src/components/BarChart/components/PortionPatternOverlay.tsx +61 -0
  84. package/src/components/BarChart/components/context.tsx +6 -0
  85. package/src/components/BarChart/helpers/getBarData.ts +28 -28
  86. package/src/components/BarChart/helpers/getBarHeights.ts +2 -2
  87. package/src/components/BarChart/helpers/getPatternUrl.ts +2 -5
  88. package/src/components/BarChart/helpers/index.ts +8 -0
  89. package/src/components/BarChart/helpers/portionPattern.ts +243 -0
  90. package/src/components/BarChart/helpers/tests/addMinimumBarHeights.test.ts +42 -0
  91. package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +13 -0
  92. package/src/components/BarChart/helpers/tests/portionPattern.test.ts +280 -0
  93. package/src/components/BarChart/helpers/tests/useBarChart.test.tsx +202 -0
  94. package/src/components/BarChart/helpers/useBarChart.ts +60 -60
  95. package/src/components/BarChartRace/BarChartRace.test.tsx +199 -0
  96. package/src/components/BarChartRace/BarChartRace.tsx +230 -0
  97. package/src/components/BarChartRace/BarChartRaceFallback.test.tsx +61 -0
  98. package/src/components/BarChartRace/BarChartRaceFallback.tsx +48 -0
  99. package/src/components/BarChartRace/bar-chart-race.css +160 -0
  100. package/src/components/BarChartRace/helpers.test.ts +114 -0
  101. package/src/components/BarChartRace/helpers.ts +185 -0
  102. package/src/components/BarChartRace/index.ts +3 -0
  103. package/src/components/BoxPlot/BoxPlot.Horizontal.tsx +7 -6
  104. package/src/components/BoxPlot/BoxPlot.Vertical.tsx +9 -7
  105. package/src/components/BoxPlot/helpers/index.ts +13 -83
  106. package/src/components/Brush/BrushSelector.tsx +10 -24
  107. package/src/components/Brush/MiniChartPreview.tsx +33 -1
  108. package/src/components/Dendrogram/components/Dendrogram.tsx +374 -0
  109. package/src/components/Dendrogram/dendrogram.css +113 -0
  110. package/src/components/Dendrogram/helpers/layoutDendrogram.test.ts +95 -0
  111. package/src/components/Dendrogram/helpers/layoutDendrogram.ts +56 -0
  112. package/src/components/Dendrogram/helpers/prepareDendrogramData.test.ts +135 -0
  113. package/src/components/Dendrogram/helpers/prepareDendrogramData.ts +166 -0
  114. package/src/components/Dendrogram/helpers/resolveDendrogramLabels.test.ts +196 -0
  115. package/src/components/Dendrogram/helpers/resolveDendrogramLabels.ts +418 -0
  116. package/src/components/Dendrogram/index.tsx +1 -0
  117. package/src/components/Dendrogram/types/index.ts +66 -0
  118. package/src/components/EditorPanel/EditorPanel.tsx +1111 -805
  119. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +50 -5
  120. package/src/components/EditorPanel/components/Panels/Panel.Dendrogram.css +10 -0
  121. package/src/components/EditorPanel/components/Panels/Panel.Dendrogram.tsx +211 -0
  122. package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +19 -8
  123. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +104 -61
  124. package/src/components/EditorPanel/components/Panels/Panel.Network.css +9 -0
  125. package/src/components/EditorPanel/components/Panels/Panel.Network.tsx +202 -0
  126. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +236 -36
  127. package/src/components/EditorPanel/components/Panels/Panel.Radar.tsx +6 -1
  128. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +89 -105
  129. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +21 -6
  130. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +1 -1
  131. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +8 -66
  132. package/src/components/EditorPanel/components/Panels/RacingControls.test.tsx +131 -0
  133. package/src/components/EditorPanel/components/Panels/RacingControls.tsx +185 -0
  134. package/src/components/EditorPanel/components/Panels/SeriesColorAssignments.tsx +2 -2
  135. package/src/components/EditorPanel/components/Panels/index.tsx +4 -0
  136. package/src/components/EditorPanel/helpers/getVisualizationTypeConfigUpdate.ts +20 -7
  137. package/src/components/EditorPanel/helpers/tests/getVisualizationTypeConfigUpdate.test.ts +25 -2
  138. package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +5 -4
  139. package/src/components/EditorPanel/useEditorPermissions.test.tsx +94 -0
  140. package/src/components/EditorPanel/useEditorPermissions.ts +75 -25
  141. package/src/components/Forecasting/Forecasting.tsx +16 -7
  142. package/src/components/HeatMap/components/HeatMap.tsx +511 -178
  143. package/src/components/HeatMap/heatmap.constants.ts +7 -3
  144. package/src/components/HeatMap/heatmap.css +101 -2
  145. package/src/components/HeatMap/helpers/layout.ts +80 -0
  146. package/src/components/HeatMap/tests/HeatMap.test.tsx +339 -16
  147. package/src/components/HeatMap/tests/helpers.test.ts +79 -0
  148. package/src/components/Legend/Legend.Component.tsx +163 -148
  149. package/src/components/Legend/Legend.Suppression.tsx +3 -3
  150. package/src/components/Legend/LegendGroup/LegendGroup.styles.css +7 -0
  151. package/src/components/Legend/LegendGroup/LegendGroup.tsx +47 -35
  152. package/src/components/Legend/helpers/createFormatLabels.test.ts +226 -0
  153. package/src/components/Legend/helpers/createFormatLabels.tsx +45 -51
  154. package/src/components/LineChart/components/LineChart.Circle.tsx +3 -3
  155. package/src/components/LineChart/helpers.test.ts +126 -38
  156. package/src/components/LineChart/helpers.ts +9 -6
  157. package/src/components/LineChart/index.tsx +71 -27
  158. package/src/components/LineChart/tests/LineChart.test.tsx +630 -0
  159. package/src/components/LineChartRace/LineChartRace.test.tsx +275 -0
  160. package/src/components/LineChartRace/LineChartRace.tsx +134 -0
  161. package/src/components/LineChartRace/LineChartRaceFallback.tsx +28 -0
  162. package/src/components/LineChartRace/helpers.test.ts +88 -0
  163. package/src/components/LineChartRace/helpers.ts +157 -0
  164. package/src/components/LineChartRace/index.ts +3 -0
  165. package/src/components/LineChartRace/line-chart-race.css +16 -0
  166. package/src/components/LinearChart/ValueAxisAnchors.tsx +58 -0
  167. package/src/components/LinearChart/VisualizationRenderer.tsx +18 -23
  168. package/src/components/LinearChart/tests/LinearChart.test.tsx +412 -13
  169. package/src/components/LinearChart/tests/VisualizationRenderer.test.tsx +141 -0
  170. package/src/components/LinearChart/tests/mockConfigContext.ts +2 -1
  171. package/src/components/LinearChart.tsx +85 -54
  172. package/src/components/Network/components/Network.tsx +372 -0
  173. package/src/components/Network/helpers/layoutNetwork.test.ts +68 -0
  174. package/src/components/Network/helpers/layoutNetwork.ts +87 -0
  175. package/src/components/Network/helpers/prepareNetworkData.test.ts +116 -0
  176. package/src/components/Network/helpers/prepareNetworkData.ts +101 -0
  177. package/src/components/Network/helpers/resolveNetworkLabels.test.ts +112 -0
  178. package/src/components/Network/helpers/resolveNetworkLabels.ts +206 -0
  179. package/src/components/Network/index.tsx +3 -0
  180. package/src/components/Network/network.css +107 -0
  181. package/src/components/Network/types/index.ts +56 -0
  182. package/src/components/PairedBarChart.jsx +5 -10
  183. package/src/components/PairedBarChart.test.tsx +71 -0
  184. package/src/components/PieChart/PieChart.tsx +121 -13
  185. package/src/components/PieChart/helpers/labelPlacement.test.ts +88 -0
  186. package/src/components/PieChart/helpers/labelPlacement.ts +95 -0
  187. package/src/components/RacingChartRenderer.tsx +44 -0
  188. package/src/components/Regions/components/Regions.test.tsx +179 -0
  189. package/src/components/Regions/components/Regions.tsx +104 -69
  190. package/src/components/Regions/index.tsx +2 -3
  191. package/src/components/Sankey/components/Sankey.tsx +264 -437
  192. package/src/components/Sankey/helpers/getSankeyTooltip.ts +12 -0
  193. package/src/components/Sankey/helpers/prepareSankeyData.test.ts +71 -0
  194. package/src/components/Sankey/helpers/prepareSankeyData.ts +90 -0
  195. package/src/components/Sankey/sankey.scss +57 -116
  196. package/src/components/Sankey/types/index.ts +41 -4
  197. package/src/components/ScatterPlot/ScatterPlot.jsx +28 -12
  198. package/src/components/ScatterPlot/ScatterPlot.test.tsx +60 -0
  199. package/src/components/SmallMultiples/SmallMultiples.tsx +12 -12
  200. package/src/components/SmallMultiples/tests/SmallMultipleTile.test.tsx +7 -5
  201. package/src/components/raceTiming.ts +18 -0
  202. package/src/data/initial-state.js +79 -31
  203. package/src/helpers/applyChartTypeContract.ts +71 -0
  204. package/src/helpers/axisLabelFontSize.ts +2 -2
  205. package/src/helpers/boxPlotStats.ts +60 -0
  206. package/src/helpers/bumpChartTooltip.ts +2 -1
  207. package/src/helpers/calculateHorizontalBarCategoryLabelWidth.test.ts +37 -0
  208. package/src/helpers/calculateHorizontalBarCategoryLabelWidth.ts +3 -2
  209. package/src/helpers/calculateRightYAxisWidth.ts +60 -0
  210. package/src/helpers/categoryOrder.ts +60 -0
  211. package/src/helpers/colorAssignmentHelpers.ts +2 -2
  212. package/src/helpers/createNewChartConfig.ts +56 -0
  213. package/src/helpers/dataDrivenYAxisCategories.ts +18 -0
  214. package/src/helpers/forecastLegend.ts +88 -0
  215. package/src/helpers/getBoxPlotConfig.ts +26 -38
  216. package/src/helpers/getChartTypeDefaultPalette.ts +29 -0
  217. package/src/helpers/getColorCodeCategoryColorMap.ts +26 -0
  218. package/src/helpers/getColorScale.ts +31 -22
  219. package/src/helpers/getComboChartConfig.ts +0 -1
  220. package/src/helpers/getDynamicYAxisCategories.ts +69 -0
  221. package/src/helpers/getExcludedData.ts +0 -1
  222. package/src/helpers/getHasBoundarySuppression.ts +4 -3
  223. package/src/helpers/getMinMax.ts +11 -8
  224. package/src/helpers/getNewRuntime.ts +4 -3
  225. package/src/helpers/getPiePercent.ts +3 -3
  226. package/src/helpers/getStackedSeriesMax.ts +51 -0
  227. package/src/helpers/getV21ChartDistributionColors.ts +57 -0
  228. package/src/helpers/handleRankByValue.ts +15 -15
  229. package/src/helpers/isConvertLineToBarGraph.ts +2 -2
  230. package/src/helpers/seriesColumnSettings.ts +31 -3
  231. package/src/helpers/sizeHelpers.ts +4 -5
  232. package/src/helpers/smallMultiplesHelpers.ts +10 -13
  233. package/src/helpers/tests/applyChartTypeContract.test.ts +37 -0
  234. package/src/helpers/tests/boxPlotStats.test.ts +31 -0
  235. package/src/helpers/tests/bumpChartTooltip.test.ts +29 -0
  236. package/src/helpers/tests/calculateRightYAxisWidth.test.ts +105 -0
  237. package/src/helpers/tests/categoryOrder.test.ts +57 -0
  238. package/src/helpers/tests/countNumOfTicks.test.ts +11 -0
  239. package/src/helpers/tests/createNewChartConfig.test.ts +182 -0
  240. package/src/helpers/tests/getBoxPlotConfig.test.ts +70 -0
  241. package/src/helpers/tests/getColorCodeCategoryColorMap.test.ts +113 -0
  242. package/src/helpers/tests/getColorScale.test.ts +226 -1
  243. package/src/helpers/tests/getDynamicYAxisCategories.test.ts +61 -0
  244. package/src/helpers/tests/getMinMax.test.ts +41 -0
  245. package/src/helpers/tests/getStackedSeriesMax.test.ts +26 -0
  246. package/src/helpers/tests/handleRankByValue.test.ts +55 -37
  247. package/src/helpers/tests/seriesColumnSettings.test.ts +83 -0
  248. package/src/helpers/tests/smallMultiplesHelpers.test.ts +37 -1
  249. package/src/helpers/tests/tooltipHelpers.test.ts +80 -0
  250. package/src/helpers/tooltipHelpers.ts +16 -0
  251. package/src/hooks/tests/useRightAxis.test.tsx +143 -2
  252. package/src/hooks/tests/useScales.test.tsx +3 -6
  253. package/src/hooks/tests/useTooltip.test.tsx +484 -0
  254. package/src/hooks/usePrefersReducedMotion.ts +22 -0
  255. package/src/hooks/useReduceData.ts +4 -36
  256. package/src/hooks/useRightAxis.ts +19 -26
  257. package/src/hooks/useScales.ts +15 -0
  258. package/src/hooks/useTooltip.tsx +106 -71
  259. package/src/scss/main.scss +74 -2
  260. package/src/store/chart.reducer.ts +4 -4
  261. package/src/test/CdcChart.dataTable.test.tsx +582 -14
  262. package/src/test/CdcChart.dendrogram.test.tsx +277 -0
  263. package/src/test/CdcChart.finalization.test.tsx +143 -0
  264. package/src/test/CdcChart.network.test.tsx +271 -0
  265. package/src/types/ChartConfig.ts +91 -54
  266. package/src/types/ChartContext.ts +5 -0
  267. package/src/types/Horizon.ts +1 -1
  268. package/LICENSE +0 -201
  269. package/dist/cdcchart-BWVIUcAF.es.js +0 -4802
  270. package/src/_stories/Chart.Sankey.smoke.stories.tsx +0 -62
  271. package/src/components/Sankey/components/ColumnList.tsx +0 -19
  272. package/src/components/Sankey/helpers/getSankeyTooltip.tsx +0 -34
  273. package/src/components/Sankey/useSankeyAlert.tsx +0 -60
  274. package/src/data/legacy-defaults.ts +0 -18
  275. package/src/helpers/ensureSpecialChartAxisTypes.ts +0 -11
  276. package/src/helpers/tests/ensureSpecialChartAxisTypes.test.ts +0 -30
@@ -5,25 +5,62 @@ import ConfigContext from '../ConfigContext'
5
5
  import { type ChartContext } from '../types/ChartContext'
6
6
  import { formatNumber as formatColNumber } from '@cdc/core/helpers/cove/number'
7
7
  import { isDateScale } from '@cdc/core/helpers/cove/date'
8
+ import { getSeriesValueLabel } from '@cdc/core/helpers/getSeriesName'
8
9
  // Third-party library imports
9
10
  import { localPoint } from '@visx/event'
10
11
  import { bisector } from 'd3-array'
11
- import _ from 'lodash'
12
+ import find from 'lodash/find'
13
+ import omit from 'lodash/omit'
14
+ import pick from 'lodash/pick'
15
+ import round from 'lodash/round'
16
+ import uniq from 'lodash/uniq'
12
17
  import { getHorizontalBarHeights } from '../components/BarChart/helpers/getBarHeights'
13
18
  import {
14
19
  findColumnConfigByName,
20
+ getAdditionalColumnFormattingParams,
15
21
  getSeriesColumnFormattingParams,
16
22
  getSeriesOwnedColumnNames
17
23
  } from '../helpers/seriesColumnSettings'
18
24
  import {
19
25
  buildTooltipRow,
20
26
  getTooltipSeriesMarker,
27
+ shouldShowTooltipSeriesRow,
21
28
  tooltipHasMarkerColumn,
22
29
  type TooltipRow
23
30
  } from '../helpers/tooltipHelpers'
24
31
  import { publishAnalyticsEvent } from '@cdc/core/helpers/metrics/helpers'
25
32
  import { getVizSubType, getVizTitle } from '@cdc/core/helpers/metrics/utils'
26
33
 
34
+ type TooltipListItemProps = {
35
+ row: TooltipRow
36
+ index: number
37
+ useMarkerColumn?: boolean
38
+ }
39
+
40
+ type TooltipBodyProps = Omit<TooltipListItemProps, 'useMarkerColumn'> & {
41
+ activeLabel: string
42
+ useMarkerColumn: boolean
43
+ }
44
+
45
+ const renderTooltipMarker = (
46
+ shouldRenderMarkerSlot: boolean,
47
+ markerColor: TooltipRow['markerColor'],
48
+ markerShape: NonNullable<TooltipRow['markerShape']>
49
+ ) => {
50
+ if (!shouldRenderMarkerSlot) return null
51
+
52
+ return (
53
+ <span className='tooltip-marker-slot' aria-hidden='true'>
54
+ {markerColor ? (
55
+ <span
56
+ className={`tooltip-marker-swatch tooltip-marker-swatch--${markerShape}`}
57
+ style={{ backgroundColor: markerColor }}
58
+ />
59
+ ) : null}
60
+ </span>
61
+ )
62
+ }
63
+
27
64
  export const useTooltip = props => {
28
65
  // Track the last X-axis value to prevent duplicate analytics events
29
66
  const lastAnalyticsXValue = useRef<string | number | null>(null)
@@ -37,7 +74,8 @@ export const useTooltip = props => {
37
74
  formatTooltipsDate,
38
75
  parseDate,
39
76
  setSharedFilter,
40
- isDraggingAnnotation
77
+ isDraggingAnnotation,
78
+ seriesHighlight
41
79
  } = useContext<ChartContext>(ConfigContext)
42
80
  const { xScale, yScale, seriesScale, showTooltip, hideTooltip, interactionLabel = '' } = props
43
81
  const { xAxis, visualizationType, orientation, yAxis, runtime } = config
@@ -148,12 +186,8 @@ export const useTooltip = props => {
148
186
  const columnName = column.name || colKey
149
187
  if (seriesOwnedColumnNames.includes(columnName)) continue
150
188
 
151
- const formattingParams = {
152
- addColPrefix: column.prefix,
153
- addColSuffix: column.suffix,
154
- addColRoundTo: column.roundToPlace || '',
155
- addColCommas: column.commas
156
- }
189
+ // Extra columns own their affixes; explicit blanks prevent fallback to the value-axis units.
190
+ const formattingParams = getAdditionalColumnFormattingParams(column)
157
191
 
158
192
  const pieColumnData = additionalChartData?.data?.[column.name]
159
193
  const columnData =
@@ -264,29 +298,36 @@ export const useTooltip = props => {
264
298
  const seriesObjWithName = config.runtime.series.find(
265
299
  series => series.dataKey === seriesKey && series.name !== undefined
266
300
  )
301
+ const showTooltipSeriesRow = shouldShowTooltipSeriesRow({
302
+ legendBehavior: config.legend?.behavior,
303
+ seriesHighlight,
304
+ seriesKey
305
+ })
267
306
 
268
307
  if (
269
308
  (value === null || value === undefined || value === '' || formattedValue === 'N/A') &&
270
309
  config.general.hideNullValue
271
310
  ) {
272
311
  return []
273
- } else if (seriesObjWithName && seriesObjWithName.name === '') {
312
+ } else if (config.xAxis?.dataKey == seriesKey) {
274
313
  return [
275
314
  createTooltipRow({
276
- key: '',
315
+ key: seriesKey,
277
316
  value: formattedValue,
278
317
  axisPosition: getAxisPosition(seriesKey),
279
- kind: 'series',
280
- seriesKey
318
+ kind: 'heading'
281
319
  })
282
320
  ]
283
- } else if (config.xAxis?.dataKey == seriesKey) {
321
+ } else if (!showTooltipSeriesRow) {
322
+ return []
323
+ } else if (seriesObjWithName && seriesObjWithName.name === '') {
284
324
  return [
285
325
  createTooltipRow({
286
- key: seriesKey,
326
+ key: '',
287
327
  value: formattedValue,
288
328
  axisPosition: getAxisPosition(seriesKey),
289
- kind: 'heading'
329
+ kind: 'series',
330
+ seriesKey
290
331
  })
291
332
  ]
292
333
  } else {
@@ -328,7 +369,7 @@ export const useTooltip = props => {
328
369
 
329
370
  const runtimeSeries =
330
371
  config.tooltips.singleSeries && visualizationType === 'Line'
331
- ? [_.find(config.runtime.series, d => d.dataKey === singleSeriesValue)]
372
+ ? [find(config.runtime.series, d => d.dataKey === singleSeriesValue)]
332
373
  : config.runtime.series
333
374
 
334
375
  runtimeSeries?.forEach(series => {
@@ -569,7 +610,7 @@ export const useTooltip = props => {
569
610
  const barsWithHeights = getHorizontalBarHeights<{ group }>(config, barGroups)
570
611
 
571
612
  const barGroup = findClosest(
572
- barsWithHeights.map(d => [d, _.round(d.y)]),
613
+ barsWithHeights.map(d => [d, round(d.y)]),
573
614
  mouseY
574
615
  )
575
616
 
@@ -580,7 +621,7 @@ export const useTooltip = props => {
580
621
  const seriesWithY = config.series.map((c, i) => [c, config.barHeight * i]) as [Object, number][]
581
622
  const hoveredSeries = findClosest(seriesWithY, subGroupMouseY)
582
623
  const exludeColumns = config.series.filter(s => s.dataKey !== hoveredSeries.dataKey).map(s => s.dataKey)
583
- const dataColumn = _.omit(columns[0], exludeColumns)
624
+ const dataColumn = omit(columns[0], exludeColumns)
584
625
  return dataColumn
585
626
  } else {
586
627
  const columnsWithY = columns.map((c, i) => [c, config.barHeight * i]) as [Object, number][]
@@ -661,7 +702,7 @@ export const useTooltip = props => {
661
702
  const includedSeries = runtimeSeries.map(item => item.dataKey)
662
703
  includedSeries.push(config.xAxis.dataKey)
663
704
  // get dynamic category series
664
- const dynamicDataCategories = _.uniq(
705
+ const dynamicDataCategories = uniq(
665
706
  config.runtime.series.flatMap(series => {
666
707
  if (series.dynamicCategory) {
667
708
  return [series.dynamicCategory, series.originalDataKey]
@@ -701,7 +742,7 @@ export const useTooltip = props => {
701
742
  }
702
743
  }
703
744
 
704
- return dataToSearch.map(d => _.pick(d, includedSeries))
745
+ return dataToSearch.map(d => pick(d, includedSeries))
705
746
  }
706
747
 
707
748
  /**
@@ -754,37 +795,23 @@ export const useTooltip = props => {
754
795
  }
755
796
  }
756
797
 
757
- /**
758
- * find the original series and use the name property if available
759
- * otherwise default back to the original column name.
760
- * @param {String} input - original columnName
761
- * @returns user defined series name.
762
- */
763
- const getSeriesNameFromLabel = originalColumnName => {
764
- let series = config.runtime.series.filter(s => s.dataKey === originalColumnName)
765
- if (series[0] && series[0].name !== undefined) return series[0]?.name
766
- const columnConfig = findColumnConfigByName(config.columns || {}, originalColumnName)?.columnConfig
767
- if (columnConfig?.label !== undefined) return columnConfig.label
768
- return originalColumnName
769
- }
798
+ const renderForestPlotTooltipItem = (row: TooltipRow, activeLabel: string) => {
799
+ if (row.key === config.xAxis.dataKey)
800
+ return (
801
+ <li className='tooltip-heading'>{`${capitalize(config.xAxis.dataKey ? `${config.xAxis.dataKey}: ` : '')} ${
802
+ isDateScale(yAxis) ? formatDate(parseDate(row.key, false)) : row.value
803
+ }`}</li>
804
+ )
770
805
 
771
- const TooltipListItem = ({ row, index, useMarkerColumn = false }) => {
772
- const { key, value, axisPosition, kind, markerColor, markerShape = 'circle' } = row
806
+ return <li className='tooltip-body'>{`${activeLabel}: ${formatNumber(row.value, 'left')}`}</li>
807
+ }
773
808
 
774
- if (visualizationType === 'Forest Plot') {
775
- if (key === config.xAxis.dataKey)
776
- return (
777
- <li className='tooltip-heading'>{`${capitalize(config.xAxis.dataKey ? `${config.xAxis.dataKey}: ` : '')} ${
778
- isDateScale(yAxis) ? formatDate(parseDate(key, false)) : value
779
- }`}</li>
780
- )
781
- return <li className='tooltip-body'>{`${getSeriesNameFromLabel(key)}: ${formatNumber(value, 'left')}`}</li>
782
- }
809
+ const renderTooltipHeading = (row: TooltipRow) => {
810
+ const { key, value } = row
783
811
  const formattedDate = config.tooltips.dateDisplayFormat
784
812
  ? formatTooltipsDate(parseDate(value, false))
785
813
  : formatDate(parseDate(value, false))
786
814
 
787
- // TOOLTIP HEADING
788
815
  if (visualizationType === 'Bar' && orientation === 'horizontal' && key === config.xAxis.dataKey)
789
816
  return (
790
817
  <li className='tooltip-heading'>{`${capitalize(
@@ -801,20 +828,25 @@ export const useTooltip = props => {
801
828
  )} ${isDateScale(xAxis) ? formattedDate : value}`}</li>
802
829
  )
803
830
 
804
- // TOOLTIP BODY
805
- // handle suppressed tooltip items
806
- const shouldCheckSuppression = config.visualizationSubType !== 'stacked'
807
- let suppressionEntry
808
- if (shouldCheckSuppression && config.preliminaryData) {
809
- suppressionEntry = config.preliminaryData.find(
810
- pd =>
811
- pd.label &&
812
- pd.type === 'suppression' &&
813
- pd.displayTooltip &&
814
- value === pd.value &&
815
- (!pd.column || key === pd.column)
816
- )
817
- }
831
+ return null
832
+ }
833
+
834
+ const getSuppressionEntry = (row: TooltipRow) => {
835
+ if (config.visualizationSubType === 'stacked' || !config.preliminaryData) return undefined
836
+
837
+ return config.preliminaryData.find(
838
+ pd =>
839
+ pd.label &&
840
+ pd.type === 'suppression' &&
841
+ pd.displayTooltip &&
842
+ row.value === pd.value &&
843
+ (!pd.column || row.key === pd.column)
844
+ )
845
+ }
846
+
847
+ const renderTooltipBody = ({ row, index, useMarkerColumn, activeLabel }: TooltipBodyProps) => {
848
+ const { value, kind, markerColor, markerShape = 'circle' } = row
849
+ const suppressionEntry = getSuppressionEntry(row)
818
850
 
819
851
  // Remove suppressed items entirely if not showing symbols
820
852
  if (suppressionEntry && !config.general.showSuppressedSymbol) {
@@ -826,22 +858,12 @@ export const useTooltip = props => {
826
858
  let newValue = label || value
827
859
  const style = displayGray ? { color: '#8b8b8a' } : {}
828
860
 
829
- if (index == 1 && config.yAxis?.inlineLabel) {
861
+ if (index === 1 && config.yAxis?.inlineLabel) {
830
862
  newValue = `${config.dataFormat.prefix}${newValue}${config.dataFormat.suffix}`
831
863
  }
832
- const activeLabel = getSeriesNameFromLabel(key)
833
864
  const displayText = activeLabel ? `${activeLabel}: ${newValue}` : newValue
834
865
  const shouldRenderMarkerSlot = useMarkerColumn && kind !== 'heading'
835
- const markerSlot = shouldRenderMarkerSlot ? (
836
- <span className='tooltip-marker-slot' aria-hidden='true'>
837
- {markerColor ? (
838
- <span
839
- className={`tooltip-marker-swatch tooltip-marker-swatch--${markerShape}`}
840
- style={{ backgroundColor: markerColor }}
841
- />
842
- ) : null}
843
- </span>
844
- ) : null
866
+ const markerSlot = renderTooltipMarker(shouldRenderMarkerSlot, markerColor, markerShape)
845
867
  const content = displayText !== undefined ? parse(String(displayText)) : displayText
846
868
 
847
869
  return (
@@ -857,6 +879,19 @@ export const useTooltip = props => {
857
879
  )
858
880
  }
859
881
 
882
+ const TooltipListItem = ({ row, index, useMarkerColumn = false }: TooltipListItemProps) => {
883
+ const activeLabel = row.kind === 'series' ? getSeriesValueLabel(row.key, config) : row.key
884
+
885
+ if (visualizationType === 'Forest Plot') {
886
+ return renderForestPlotTooltipItem(row, activeLabel)
887
+ }
888
+
889
+ const heading = renderTooltipHeading(row)
890
+ if (heading) return heading
891
+
892
+ return renderTooltipBody({ row, index, useMarkerColumn, activeLabel })
893
+ }
894
+
860
895
  return {
861
896
  getIncludedTooltipSeries,
862
897
  getXValueFromCoordinate,
@@ -49,11 +49,61 @@
49
49
  margin-bottom: 0 !important;
50
50
  }
51
51
 
52
+ .chart-required-fields-alerts {
53
+ display: grid;
54
+ gap: 0.75rem;
55
+
56
+ > .alert {
57
+ justify-content: flex-start;
58
+ margin: 0;
59
+ width: 100%;
60
+
61
+ .alert-message,
62
+ > .d-flex {
63
+ align-items: center;
64
+ display: flex;
65
+ }
66
+ }
67
+
68
+ &__link {
69
+ background: transparent;
70
+ border: 0;
71
+ color: inherit;
72
+ cursor: pointer;
73
+ font: inherit;
74
+ font-weight: 700;
75
+ padding: 0;
76
+ text-decoration: underline;
77
+
78
+ &:hover,
79
+ &:focus-visible {
80
+ text-decoration-thickness: 2px;
81
+ }
82
+ }
83
+ }
84
+
85
+ .y-axis-top-title-row {
86
+ display: flex;
87
+ gap: 1rem;
88
+ margin: 0 0 0.5rem;
89
+ width: 100%;
90
+ }
91
+
52
92
  .y-axis-top-title {
53
93
  font-family: var(--fonts-nunito, var(--app-font-secondary));
54
94
  font-weight: 700;
55
95
  line-height: 1.4;
56
- margin: 0 0 0.5rem;
96
+ min-width: 0;
97
+ width: 100%;
98
+ }
99
+
100
+ .y-axis-top-title-row--split .y-axis-top-title {
101
+ flex: 1 1 0;
102
+ }
103
+
104
+ .y-axis-top-title--right {
105
+ margin-left: auto;
106
+ text-align: right;
57
107
  }
58
108
 
59
109
  .legend-top {
@@ -203,6 +253,24 @@
203
253
  outline-offset: 5px;
204
254
  border-radius: 1px;
205
255
  }
256
+
257
+ &--interactive {
258
+ border-radius: 1px;
259
+ isolation: isolate;
260
+ position: relative;
261
+
262
+ &:hover,
263
+ &:focus-visible {
264
+ &::before {
265
+ background-color: var(--colors-cyan-10, #eff9fa);
266
+ border-radius: 6px;
267
+ content: '';
268
+ inset: -6px;
269
+ position: absolute;
270
+ z-index: -1;
271
+ }
272
+ }
273
+ }
206
274
  }
207
275
 
208
276
  &__outer {
@@ -255,7 +323,7 @@
255
323
  display: flex;
256
324
  flex-direction: row;
257
325
  align-items: center;
258
- font-size: 1em;
326
+ font-size: var(--legend-item-font-size);
259
327
  vertical-align: middle;
260
328
 
261
329
  & > span {
@@ -268,6 +336,10 @@
268
336
  max-height: 1px;
269
337
  }
270
338
 
339
+ & > p {
340
+ font-size: var(--legend-item-font-size);
341
+ }
342
+
271
343
  & > span[class*='Asterisk'] {
272
344
  transform: scale(1.8);
273
345
  margin-top: 15px;
@@ -1,8 +1,8 @@
1
1
  import ChartActions from './chart.actions'
2
2
  import defaults from '../data/initial-state.js'
3
- import { ChartConfig, type ViewportSize } from '../types/ChartConfig'
3
+ import { ChartConfig } from '../types/ChartConfig'
4
4
  import { DimensionsType } from '@cdc/core/types/Dimensions'
5
- import _ from 'lodash'
5
+ import type { ViewPort } from '@cdc/core/types/ViewPort'
6
6
 
7
7
  type ChartState = {
8
8
  isLoading: boolean
@@ -12,8 +12,8 @@ type ChartState = {
12
12
  excludedData: object[]
13
13
  filteredData: object[]
14
14
  seriesHighlight: string[]
15
- currentViewport: ViewportSize
16
- vizViewport: ViewportSize
15
+ currentViewport: ViewPort
16
+ vizViewport: ViewPort
17
17
  dimensions: DimensionsType
18
18
  container: HTMLElement | null
19
19
  coveLoadedEventRan: boolean