@cdc/chart 4.26.7 → 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 (255) hide show
  1. package/CONFIG.md +502 -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 -97406
  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/overlay-legend.json +485 -0
  22. package/examples/private/pie-test.json +469 -0
  23. package/examples/vega-remote.json +22 -0
  24. package/package.json +11 -5
  25. package/src/CdcChartComponent.tsx +405 -208
  26. package/src/_stories/Chart.BarRace.stories.tsx +443 -0
  27. package/src/_stories/Chart.BoxPlotNumericSort.stories.tsx +189 -0
  28. package/src/_stories/Chart.BoxPlotStatsParity.stories.tsx +207 -0
  29. package/src/_stories/Chart.ColorDistribution.stories.tsx +299 -0
  30. package/src/_stories/Chart.DataCutoff.stories.tsx +147 -0
  31. package/src/_stories/Chart.DataTableDownloadFilename.stories.tsx +60 -0
  32. package/src/_stories/Chart.Dendrogram.stories.tsx +373 -0
  33. package/src/_stories/Chart.Forecast.CILegend.stories.tsx +236 -0
  34. package/src/_stories/Chart.HeatMap.stories.tsx +170 -4
  35. package/src/_stories/Chart.Legend.AxisAlign.stories.tsx +119 -0
  36. package/src/_stories/Chart.LineRace.stories.tsx +149 -0
  37. package/src/_stories/Chart.Network.stories.tsx +432 -0
  38. package/src/_stories/Chart.PaletteConversion.Editor.stories.tsx +208 -0
  39. package/src/_stories/Chart.Patterns.smoke.stories.tsx +31 -0
  40. package/src/_stories/Chart.PercentageValue.stories.tsx +311 -0
  41. package/src/_stories/Chart.PieLabels.stories.tsx +4 -2
  42. package/src/_stories/Chart.RankByValueMutation.stories.tsx +206 -0
  43. package/src/_stories/Chart.RequiredFields.stories.tsx +681 -0
  44. package/src/_stories/Chart.Sankey.stories.tsx +417 -0
  45. package/src/_stories/Chart.SeriesColorAssignments.stories.tsx +47 -0
  46. package/src/_stories/Chart.SmallMultiplesNumericTileOrder.stories.tsx +137 -0
  47. package/src/_stories/Chart.TooltipSeriesLabels.stories.tsx +43 -0
  48. package/src/_stories/Chart.VegaRemoteData.stories.tsx +31 -0
  49. package/src/_stories/ChartAnnotation.Editor.stories.tsx +78 -0
  50. package/src/_stories/ChartAxisTitles.smoke.stories.tsx +48 -0
  51. package/src/_stories/ChartBar.Editor.stories.tsx +499 -57
  52. package/src/_stories/ChartBrush.Editor.stories.tsx +46 -67
  53. package/src/_stories/ChartBrush.Regression.stories.tsx +135 -0
  54. package/src/_stories/ChartEditor.Editor.stories.tsx +33 -3
  55. package/src/_stories/ChartLine.EffectCompatibility.stories.tsx +120 -0
  56. package/src/_stories/_mock/annotation_event-line_mock.json +2 -2
  57. package/src/_stories/_mock/editor-test-configs.json +20 -10
  58. package/src/_stories/_mock/editor-test-datasets.json +38 -42
  59. package/src/_stories/_mock/heatmap-average-age-categorical.json +2 -2
  60. package/src/_stories/_mock/heatmap.json +2 -2
  61. package/src/_stories/_mock/legend-axis-align-stacked-bar.json +125 -0
  62. package/src/_stories/_mock/sankey_mock.json +23 -27
  63. package/src/components/Annotations/components/AnnotationDraggable.styles.css +52 -0
  64. package/src/components/Annotations/components/AnnotationDraggable.tsx +639 -139
  65. package/src/components/Annotations/components/AnnotationDropdown.styles.css +44 -4
  66. package/src/components/Annotations/components/AnnotationDropdown.tsx +10 -32
  67. package/src/components/Annotations/helpers/resolveAnnotationLayout.ts +212 -0
  68. package/src/components/Annotations/tests/AnnotationDraggable.test.tsx +612 -19
  69. package/src/components/Annotations/tests/AnnotationDropdown.test.tsx +50 -0
  70. package/src/components/Annotations/tests/resolveAnnotationLayout.test.ts +203 -0
  71. package/src/components/Axis/BottomAxis.tsx +1 -1
  72. package/src/components/Axis/Categorical.Axis.tsx +3 -3
  73. package/src/components/Axis/RightAxis.tsx +21 -13
  74. package/src/components/BarChart/components/BarChart.Horizontal.tsx +38 -6
  75. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +12 -3
  76. package/src/components/BarChart/components/BarChart.StackedVertical.test.ts +28 -0
  77. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +29 -25
  78. package/src/components/BarChart/components/BarChart.Vertical.tsx +37 -26
  79. package/src/components/BarChart/components/PortionPatternOverlay.tsx +61 -0
  80. package/src/components/BarChart/components/context.tsx +6 -0
  81. package/src/components/BarChart/helpers/getPatternUrl.ts +2 -5
  82. package/src/components/BarChart/helpers/index.ts +8 -0
  83. package/src/components/BarChart/helpers/portionPattern.ts +243 -0
  84. package/src/components/BarChart/helpers/tests/addMinimumBarHeights.test.ts +42 -0
  85. package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +13 -0
  86. package/src/components/BarChart/helpers/tests/portionPattern.test.ts +280 -0
  87. package/src/components/BarChart/helpers/tests/useBarChart.test.tsx +104 -0
  88. package/src/components/BarChart/helpers/useBarChart.ts +60 -59
  89. package/src/components/BarChartRace/BarChartRace.test.tsx +199 -0
  90. package/src/components/BarChartRace/BarChartRace.tsx +230 -0
  91. package/src/components/BarChartRace/BarChartRaceFallback.test.tsx +61 -0
  92. package/src/components/BarChartRace/BarChartRaceFallback.tsx +48 -0
  93. package/src/components/BarChartRace/bar-chart-race.css +160 -0
  94. package/src/components/BarChartRace/helpers.test.ts +114 -0
  95. package/src/components/BarChartRace/helpers.ts +185 -0
  96. package/src/components/BarChartRace/index.ts +3 -0
  97. package/src/components/BoxPlot/helpers/index.ts +11 -82
  98. package/src/components/Brush/BrushSelector.tsx +9 -23
  99. package/src/components/Brush/MiniChartPreview.tsx +33 -1
  100. package/src/components/Dendrogram/components/Dendrogram.tsx +374 -0
  101. package/src/components/Dendrogram/dendrogram.css +113 -0
  102. package/src/components/Dendrogram/helpers/layoutDendrogram.test.ts +95 -0
  103. package/src/components/Dendrogram/helpers/layoutDendrogram.ts +56 -0
  104. package/src/components/Dendrogram/helpers/prepareDendrogramData.test.ts +135 -0
  105. package/src/components/Dendrogram/helpers/prepareDendrogramData.ts +166 -0
  106. package/src/components/Dendrogram/helpers/resolveDendrogramLabels.test.ts +196 -0
  107. package/src/components/Dendrogram/helpers/resolveDendrogramLabels.ts +418 -0
  108. package/src/components/Dendrogram/index.tsx +1 -0
  109. package/src/components/Dendrogram/types/index.ts +66 -0
  110. package/src/components/EditorPanel/EditorPanel.tsx +1005 -760
  111. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +50 -5
  112. package/src/components/EditorPanel/components/Panels/Panel.Dendrogram.css +10 -0
  113. package/src/components/EditorPanel/components/Panels/Panel.Dendrogram.tsx +211 -0
  114. package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +19 -8
  115. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +88 -54
  116. package/src/components/EditorPanel/components/Panels/Panel.Network.css +9 -0
  117. package/src/components/EditorPanel/components/Panels/Panel.Network.tsx +202 -0
  118. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +233 -33
  119. package/src/components/EditorPanel/components/Panels/Panel.Radar.tsx +6 -1
  120. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +89 -105
  121. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +2 -2
  122. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +1 -1
  123. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +8 -66
  124. package/src/components/EditorPanel/components/Panels/RacingControls.test.tsx +131 -0
  125. package/src/components/EditorPanel/components/Panels/RacingControls.tsx +185 -0
  126. package/src/components/EditorPanel/components/Panels/SeriesColorAssignments.tsx +2 -2
  127. package/src/components/EditorPanel/components/Panels/index.tsx +4 -0
  128. package/src/components/EditorPanel/helpers/getVisualizationTypeConfigUpdate.ts +20 -7
  129. package/src/components/EditorPanel/helpers/tests/getVisualizationTypeConfigUpdate.test.ts +25 -2
  130. package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +2 -1
  131. package/src/components/EditorPanel/useEditorPermissions.test.tsx +62 -0
  132. package/src/components/EditorPanel/useEditorPermissions.ts +70 -24
  133. package/src/components/Forecasting/Forecasting.tsx +15 -6
  134. package/src/components/HeatMap/components/HeatMap.tsx +511 -178
  135. package/src/components/HeatMap/heatmap.constants.ts +7 -3
  136. package/src/components/HeatMap/heatmap.css +101 -2
  137. package/src/components/HeatMap/helpers/layout.ts +80 -0
  138. package/src/components/HeatMap/tests/HeatMap.test.tsx +339 -16
  139. package/src/components/HeatMap/tests/helpers.test.ts +79 -0
  140. package/src/components/Legend/Legend.Component.tsx +110 -90
  141. package/src/components/Legend/LegendGroup/LegendGroup.styles.css +7 -0
  142. package/src/components/Legend/LegendGroup/LegendGroup.tsx +47 -34
  143. package/src/components/Legend/helpers/createFormatLabels.test.ts +226 -0
  144. package/src/components/Legend/helpers/createFormatLabels.tsx +45 -51
  145. package/src/components/LineChart/components/LineChart.Circle.tsx +3 -3
  146. package/src/components/LineChart/helpers.test.ts +126 -38
  147. package/src/components/LineChart/helpers.ts +9 -4
  148. package/src/components/LineChart/index.tsx +69 -24
  149. package/src/components/LineChart/tests/LineChart.test.tsx +630 -0
  150. package/src/components/LineChartRace/LineChartRace.test.tsx +275 -0
  151. package/src/components/LineChartRace/LineChartRace.tsx +134 -0
  152. package/src/components/LineChartRace/LineChartRaceFallback.tsx +28 -0
  153. package/src/components/LineChartRace/helpers.test.ts +88 -0
  154. package/src/components/LineChartRace/helpers.ts +157 -0
  155. package/src/components/LineChartRace/index.ts +3 -0
  156. package/src/components/LineChartRace/line-chart-race.css +16 -0
  157. package/src/components/LinearChart/ValueAxisAnchors.tsx +58 -0
  158. package/src/components/LinearChart/VisualizationRenderer.tsx +18 -23
  159. package/src/components/LinearChart/tests/LinearChart.test.tsx +412 -13
  160. package/src/components/LinearChart/tests/VisualizationRenderer.test.tsx +141 -0
  161. package/src/components/LinearChart/tests/mockConfigContext.ts +2 -1
  162. package/src/components/LinearChart.tsx +81 -51
  163. package/src/components/Network/components/Network.tsx +372 -0
  164. package/src/components/Network/helpers/layoutNetwork.test.ts +68 -0
  165. package/src/components/Network/helpers/layoutNetwork.ts +87 -0
  166. package/src/components/Network/helpers/prepareNetworkData.test.ts +116 -0
  167. package/src/components/Network/helpers/prepareNetworkData.ts +101 -0
  168. package/src/components/Network/helpers/resolveNetworkLabels.test.ts +112 -0
  169. package/src/components/Network/helpers/resolveNetworkLabels.ts +206 -0
  170. package/src/components/Network/index.tsx +3 -0
  171. package/src/components/Network/network.css +107 -0
  172. package/src/components/Network/types/index.ts +56 -0
  173. package/src/components/PairedBarChart.jsx +5 -10
  174. package/src/components/PairedBarChart.test.tsx +71 -0
  175. package/src/components/PieChart/PieChart.tsx +9 -8
  176. package/src/components/RacingChartRenderer.tsx +44 -0
  177. package/src/components/Regions/components/Regions.test.tsx +179 -0
  178. package/src/components/Regions/components/Regions.tsx +104 -69
  179. package/src/components/Regions/index.tsx +2 -3
  180. package/src/components/Sankey/components/Sankey.tsx +264 -437
  181. package/src/components/Sankey/helpers/getSankeyTooltip.ts +12 -0
  182. package/src/components/Sankey/helpers/prepareSankeyData.test.ts +71 -0
  183. package/src/components/Sankey/helpers/prepareSankeyData.ts +90 -0
  184. package/src/components/Sankey/sankey.scss +57 -116
  185. package/src/components/Sankey/types/index.ts +41 -4
  186. package/src/components/ScatterPlot/ScatterPlot.jsx +28 -4
  187. package/src/components/ScatterPlot/ScatterPlot.test.tsx +60 -0
  188. package/src/components/SmallMultiples/SmallMultiples.tsx +12 -12
  189. package/src/components/SmallMultiples/tests/SmallMultipleTile.test.tsx +7 -5
  190. package/src/components/raceTiming.ts +18 -0
  191. package/src/data/initial-state.js +77 -31
  192. package/src/helpers/applyChartTypeContract.ts +71 -0
  193. package/src/helpers/axisLabelFontSize.ts +2 -2
  194. package/src/helpers/boxPlotStats.ts +60 -0
  195. package/src/helpers/bumpChartTooltip.ts +2 -1
  196. package/src/helpers/calculateHorizontalBarCategoryLabelWidth.test.ts +37 -0
  197. package/src/helpers/calculateHorizontalBarCategoryLabelWidth.ts +3 -2
  198. package/src/helpers/calculateRightYAxisWidth.ts +60 -0
  199. package/src/helpers/colorAssignmentHelpers.ts +2 -2
  200. package/src/helpers/createNewChartConfig.ts +56 -0
  201. package/src/helpers/dataDrivenYAxisCategories.ts +18 -0
  202. package/src/helpers/forecastLegend.ts +88 -0
  203. package/src/helpers/getBoxPlotConfig.ts +18 -37
  204. package/src/helpers/getChartTypeDefaultPalette.ts +29 -0
  205. package/src/helpers/getColorCodeCategoryColorMap.ts +26 -0
  206. package/src/helpers/getColorScale.ts +31 -22
  207. package/src/helpers/getDynamicYAxisCategories.ts +69 -0
  208. package/src/helpers/getMinMax.ts +9 -7
  209. package/src/helpers/getNewRuntime.ts +5 -2
  210. package/src/helpers/getStackedSeriesMax.ts +51 -0
  211. package/src/helpers/getV21ChartDistributionColors.ts +57 -0
  212. package/src/helpers/handleRankByValue.ts +15 -15
  213. package/src/helpers/seriesColumnSettings.ts +10 -0
  214. package/src/helpers/sizeHelpers.ts +4 -3
  215. package/src/helpers/smallMultiplesHelpers.ts +10 -13
  216. package/src/helpers/tests/applyChartTypeContract.test.ts +37 -0
  217. package/src/helpers/tests/boxPlotStats.test.ts +31 -0
  218. package/src/helpers/tests/bumpChartTooltip.test.ts +29 -0
  219. package/src/helpers/tests/calculateRightYAxisWidth.test.ts +105 -0
  220. package/src/helpers/tests/countNumOfTicks.test.ts +11 -0
  221. package/src/helpers/tests/createNewChartConfig.test.ts +182 -0
  222. package/src/helpers/tests/getBoxPlotConfig.test.ts +70 -0
  223. package/src/helpers/tests/getColorCodeCategoryColorMap.test.ts +113 -0
  224. package/src/helpers/tests/getColorScale.test.ts +226 -1
  225. package/src/helpers/tests/getDynamicYAxisCategories.test.ts +61 -0
  226. package/src/helpers/tests/getMinMax.test.ts +41 -0
  227. package/src/helpers/tests/getStackedSeriesMax.test.ts +26 -0
  228. package/src/helpers/tests/handleRankByValue.test.ts +55 -37
  229. package/src/helpers/tests/seriesColumnSettings.test.ts +23 -0
  230. package/src/helpers/tests/smallMultiplesHelpers.test.ts +37 -1
  231. package/src/helpers/tests/tooltipHelpers.test.ts +80 -0
  232. package/src/helpers/tooltipHelpers.ts +16 -0
  233. package/src/hooks/tests/useTooltip.test.tsx +353 -1
  234. package/src/hooks/usePrefersReducedMotion.ts +22 -0
  235. package/src/hooks/useReduceData.ts +4 -36
  236. package/src/hooks/useScales.ts +15 -0
  237. package/src/hooks/useTooltip.tsx +95 -64
  238. package/src/scss/main.scss +74 -2
  239. package/src/store/chart.reducer.ts +4 -3
  240. package/src/test/CdcChart.dataTable.test.tsx +490 -16
  241. package/src/test/CdcChart.dendrogram.test.tsx +277 -0
  242. package/src/test/CdcChart.finalization.test.tsx +143 -0
  243. package/src/test/CdcChart.network.test.tsx +271 -0
  244. package/src/types/ChartConfig.ts +91 -54
  245. package/src/types/ChartContext.ts +5 -0
  246. package/src/types/Horizon.ts +1 -1
  247. package/LICENSE +0 -201
  248. package/dist/cdcchart-BWVIUcAF.es.js +0 -4802
  249. package/src/_stories/Chart.Sankey.smoke.stories.tsx +0 -62
  250. package/src/components/Sankey/components/ColumnList.tsx +0 -19
  251. package/src/components/Sankey/helpers/getSankeyTooltip.tsx +0 -34
  252. package/src/components/Sankey/useSankeyAlert.tsx +0 -60
  253. package/src/data/legacy-defaults.ts +0 -18
  254. package/src/helpers/ensureSpecialChartAxisTypes.ts +0 -11
  255. package/src/helpers/tests/ensureSpecialChartAxisTypes.test.ts +0 -30
@@ -0,0 +1,50 @@
1
+ import React from 'react'
2
+ import { fireEvent, render, screen } from '@testing-library/react'
3
+ import { describe, expect, it } from 'vitest'
4
+ import ConfigContext from '../../../ConfigContext'
5
+ import AnnotationDropdown from '../components/AnnotationDropdown'
6
+
7
+ vi.mock('@cdc/core/components/ui/Icon', () => ({
8
+ default: ({ display }: { display: string }) => <span data-icon={display} />
9
+ }))
10
+
11
+ describe('AnnotationDropdown', () => {
12
+ it('uses the shared toggle treatment and joins the expanded panel to its header', () => {
13
+ const annotation = { text: 'Important annotation' }
14
+ const context = {
15
+ config: {
16
+ annotations: [annotation],
17
+ general: {
18
+ annotationDropdownText: '',
19
+ mobileAnnotationDisplay: 'symbol',
20
+ showAnnotationDropdown: true
21
+ },
22
+ table: { height: 120, limitHeight: true }
23
+ },
24
+ currentViewport: 'lg',
25
+ visibleAnnotations: [annotation]
26
+ }
27
+
28
+ render(
29
+ <ConfigContext.Provider value={context as any}>
30
+ <AnnotationDropdown />
31
+ </ConfigContext.Provider>
32
+ )
33
+
34
+ const toggle = screen.getByRole('button', { name: 'Annotations' })
35
+ const section = toggle.closest('section')
36
+
37
+ expect(toggle).toHaveClass('data-table-heading', 'data-table-heading--toggle', 'annotation__dropdown-list')
38
+ expect(toggle).toHaveAttribute('aria-expanded', 'false')
39
+ expect(section).not.toHaveClass('my-4')
40
+ expect(section).not.toHaveClass('mt-4')
41
+ expect(section).not.toHaveClass('mb-4')
42
+
43
+ fireEvent.click(toggle)
44
+
45
+ const panel = section?.querySelector('.annotation-dropdown__panel') as HTMLElement
46
+ expect(toggle).toHaveAttribute('aria-expanded', 'true')
47
+ expect(toggle.nextElementSibling).toBe(panel)
48
+ expect(panel).toHaveStyle({ maxHeight: '120px', overflowY: 'auto' })
49
+ })
50
+ })
@@ -0,0 +1,203 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ getAnnotationAttachment,
4
+ getAnnotationLabelRect,
5
+ getFacingAnnotationSide,
6
+ getPreferredAnnotationSide,
7
+ MIN_ANNOTATION_LABEL_WIDTH_EM,
8
+ MIN_EVENT_LINE_LABEL_WIDTH_EM,
9
+ resolveAnnotationLayout,
10
+ resolveAnnotationRectangleDrag
11
+ } from '../helpers/resolveAnnotationLayout'
12
+
13
+ const base = {
14
+ endpointX: 200,
15
+ endpointY: 150,
16
+ dx: 100,
17
+ dy: 10,
18
+ labelWidth: 120,
19
+ labelHeight: 40,
20
+ plotWidth: 400,
21
+ plotHeight: 300,
22
+ fontSize: 16,
23
+ labelPosition: 'auto' as const
24
+ }
25
+
26
+ describe('resolveAnnotationLayout', () => {
27
+ it.each([
28
+ [100, 10, 'right'],
29
+ [-100, 10, 'left'],
30
+ [10, -100, 'above'],
31
+ [10, 100, 'below']
32
+ ] as const)('derives %s/%s as the %s preferred side', (dx, dy, side) => {
33
+ expect(getPreferredAnnotationSide(dx, dy)).toBe(side)
34
+ expect(resolveAnnotationLayout({ ...base, dx, dy }).side).toBe(side)
35
+ })
36
+
37
+ it('slides parallel to the preferred side without changing sides', () => {
38
+ const result = resolveAnnotationLayout({ ...base, endpointY: 5 })
39
+
40
+ expect(result.side).toBe('right')
41
+ expect(result.y).toBe(20)
42
+ expect(result.x).toBe(200)
43
+ })
44
+
45
+ it('keeps a short label on its preferred side near an edge when its measured width fits', () => {
46
+ const result = resolveAnnotationLayout({ ...base, endpointX: 320, labelWidth: 70 })
47
+
48
+ expect(result.side).toBe('right')
49
+ expect(result.constrainedWidth).toBeUndefined()
50
+ })
51
+
52
+ it('constrains a long label to the 6em minimum without changing sides', () => {
53
+ const result = resolveAnnotationLayout({ ...base, endpointX: 100, labelWidth: 180 })
54
+
55
+ expect(result.side).toBe('right')
56
+ expect(result.width).toBe(180)
57
+
58
+ const constrained = resolveAnnotationLayout({ ...base, endpointX: 304, labelWidth: 180 })
59
+ expect(constrained.side).toBe('right')
60
+ expect(constrained.width).toBe(96)
61
+ expect(constrained.constrainedWidth).toBe(96)
62
+ })
63
+
64
+ it('accepts the 4em event-line minimum', () => {
65
+ const result = resolveAnnotationLayout({
66
+ ...base,
67
+ endpointX: 336,
68
+ labelWidth: 180,
69
+ minWidthEm: MIN_EVENT_LINE_LABEL_WIDTH_EM,
70
+ labelPosition: 'right'
71
+ })
72
+
73
+ expect(result.width).toBe(64)
74
+ expect(result.constrainedWidth).toBe(64)
75
+ })
76
+
77
+ it('keeps a persisted automatic side even when the scaled offsets favor another side', () => {
78
+ const result = resolveAnnotationLayout({
79
+ ...base,
80
+ endpointX: 350,
81
+ endpointY: 30,
82
+ dx: 10,
83
+ dy: -200,
84
+ autoSide: 'right',
85
+ labelWidth: 140,
86
+ labelHeight: 60
87
+ })
88
+
89
+ expect(result.side).toBe('right')
90
+ })
91
+
92
+ it('keeps the preferred side for unavoidable overflow', () => {
93
+ const result = resolveAnnotationLayout({
94
+ ...base,
95
+ endpointX: 390,
96
+ endpointY: 150,
97
+ labelWidth: 240,
98
+ labelHeight: 310
99
+ })
100
+
101
+ expect(result.side).toBe('right')
102
+ expect(result.width).toBe(MIN_ANNOTATION_LABEL_WIDTH_EM * base.fontSize)
103
+ expect(result.constrainedWidth).toBe(MIN_ANNOTATION_LABEL_WIDTH_EM * base.fontSize)
104
+ })
105
+
106
+ it.each([
107
+ ['left', -100, 150, 96, 150],
108
+ ['right', 500, 150, 304, 150],
109
+ ['above', 200, -100, 200, 40],
110
+ ['below', 200, 500, 200, 260]
111
+ ] as const)('clamps %s placement to the same-side boundary', (autoSide, endpointX, endpointY, x, y) => {
112
+ const result = resolveAnnotationLayout({ ...base, endpointX, endpointY, autoSide })
113
+
114
+ expect(result.side).toBe(autoSide)
115
+ expect(result.x).toBe(x)
116
+ expect(result.y).toBe(y)
117
+ })
118
+
119
+ it.each(['left', 'right', 'above', 'below'] as const)(
120
+ 'keeps explicit %s placement even when it cannot fit',
121
+ labelPosition => {
122
+ const result = resolveAnnotationLayout({
123
+ ...base,
124
+ endpointX: 5,
125
+ endpointY: 5,
126
+ labelWidth: 300,
127
+ labelHeight: 200,
128
+ labelPosition
129
+ })
130
+
131
+ expect(result.side).toBe(labelPosition)
132
+ }
133
+ )
134
+ })
135
+
136
+ describe('rectangle-based annotation dragging', () => {
137
+ const rect = { left: 100, top: 60, width: 120, height: 40 }
138
+
139
+ it.each(['left', 'right', 'above', 'below'] as const)(
140
+ 'reconstructs the same rectangle from its %s attachment',
141
+ side => {
142
+ const attachment = getAnnotationAttachment(rect, side)
143
+
144
+ expect(getAnnotationLabelRect(attachment.x, attachment.y, rect.width, rect.height, side)).toEqual(rect)
145
+ }
146
+ )
147
+
148
+ it.each([
149
+ [20, 80, 'right'],
150
+ [300, 80, 'left'],
151
+ [160, 0, 'below'],
152
+ [160, 150, 'above']
153
+ ] as const)('chooses the edge facing a subject at %s/%s', (subjectX, subjectY, side) => {
154
+ expect(getFacingAnnotationSide(subjectX, subjectY, rect)).toBe(side)
155
+ })
156
+
157
+ it('normalizes distance by the rectangle dimensions when choosing the facing edge', () => {
158
+ const wideRect = { left: 0, top: 80, width: 200, height: 40 }
159
+
160
+ expect(getFacingAnnotationSide(160, 140, wideRect)).toBe('above')
161
+ })
162
+
163
+ it('changes only the attachment when the selected side changes', () => {
164
+ const right = resolveAnnotationRectangleDrag({
165
+ rect,
166
+ subjectX: 20,
167
+ subjectY: 80,
168
+ plotWidth: 400,
169
+ plotHeight: 300,
170
+ side: 'right'
171
+ })
172
+ const below = resolveAnnotationRectangleDrag({
173
+ rect,
174
+ subjectX: 160,
175
+ subjectY: 0,
176
+ plotWidth: 400,
177
+ plotHeight: 300,
178
+ side: 'below'
179
+ })
180
+
181
+ expect(right.rect).toEqual(rect)
182
+ expect(below.rect).toEqual(rect)
183
+ expect({ x: right.layout.x, y: right.layout.y }).toEqual({ x: 100, y: 80 })
184
+ expect({ x: below.layout.x, y: below.layout.y }).toEqual({ x: 160, y: 60 })
185
+ })
186
+
187
+ it('clamps the rectangle before deriving the persisted attachment', () => {
188
+ const result = resolveAnnotationRectangleDrag({
189
+ rect: { ...rect, left: 350, top: -20 },
190
+ subjectX: 200,
191
+ subjectY: 150,
192
+ plotWidth: 400,
193
+ plotHeight: 300,
194
+ side: 'left'
195
+ })
196
+
197
+ expect(result.rect).toEqual({ ...rect, left: 280, top: 0 })
198
+ expect(result.layout.x).toBe(400)
199
+ expect(result.layout.y).toBe(20)
200
+ expect(result.dx).toBe(200)
201
+ expect(result.dy).toBe(-130)
202
+ })
203
+ })
@@ -98,7 +98,7 @@ const BottomAxis: React.FC<BottomAxisProps> = ({
98
98
  config.runtime.xAxis.manual
99
99
  ? getTickValues(xAxisDataMapped, xScale, isDateTime ? xTickCount : getManualStep(), config)
100
100
  : config.runtime.xAxis.type === 'date'
101
- ? xAxisDataMapped
101
+ ? sortedUniqueXAxisData
102
102
  : // For date-time with small datasets (e.g., brush-filtered), use explicit tick values
103
103
  // to ensure each data point can have a tick. Otherwise, visx may generate too few.
104
104
  // Use uniqueXAxisDataMapped to handle cases where multiple series share x-axis values
@@ -9,7 +9,7 @@ import createBarElement from '@cdc/core/components/createBarElement'
9
9
  import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
10
10
  import { APP_FONT_SIZE } from '@cdc/core/helpers/constants'
11
11
 
12
- const CategoricalYAxis = ({ yScale, yMax, leftSize, xMax }) => {
12
+ const CategoricalYAxis = ({ yScale, yMax, leftSize, xMax, categories }) => {
13
13
  const { config } = useContext(ConfigContext)
14
14
 
15
15
  const { orientation } = config
@@ -22,7 +22,7 @@ const CategoricalYAxis = ({ yScale, yMax, leftSize, xMax }) => {
22
22
  }
23
23
  }
24
24
 
25
- const categories = config.yAxis?.categories
25
+ if (!categories?.length) return null
26
26
 
27
27
  // Get max from the yScale domain
28
28
  const max = yScale.domain()[1]
@@ -146,7 +146,7 @@ const CategoricalYAxis = ({ yScale, yMax, leftSize, xMax }) => {
146
146
  {/* White background spacing between stackes */}
147
147
  {!isLastIndex && <rect x={bar.x} y={bar.y} width={bar.width} height={1} fill={'#fff'}></rect>}
148
148
  {/* Right side Axis line */}
149
- <rect x={bar.x + bar.width} y={0} width={1} height={yMax} fill={'#000'}></rect>
149
+ {!config.yAxis.hideAxis && <rect x={bar.x + bar.width} y={0} width={1} height={yMax} fill='#000' />}
150
150
  </Group>
151
151
  </Group>
152
152
  )
@@ -6,6 +6,7 @@ import { Text } from '@visx/text'
6
6
  import { ScaleLinear } from 'd3-scale'
7
7
 
8
8
  import ConfigContext from '../../ConfigContext'
9
+ import { DEFAULT_TICK_LENGTH, TICK_LABEL_MARGIN_RIGHT } from './axis.constants'
9
10
 
10
11
  // Constants
11
12
  const HORIZONTAL_TICK_OFFSET_ADJUSTMENT = 5
@@ -15,6 +16,7 @@ type RightAxisProps = {
15
16
  yMax: number
16
17
  xMax: number
17
18
  yAxisWidth: number
19
+ rightAxisWidth: number
18
20
  tickValues?: number[]
19
21
  tickLabelFontSize: number
20
22
  axisLabelFontSize: number
@@ -30,12 +32,14 @@ export const RightAxis: React.FC<RightAxisProps> = ({
30
32
  yMax,
31
33
  xMax,
32
34
  yAxisWidth,
35
+ rightAxisWidth,
33
36
  tickValues,
34
37
  tickLabelFontSize,
35
38
  axisLabelFontSize
36
39
  }) => {
37
40
  const { config, formatNumber } = useContext(ConfigContext)
38
41
  const { runtime } = config
42
+ const showSideTitle = config.yAxis.rightTitlePlacement !== 'top'
39
43
 
40
44
  const horizontalTickOffset = (ticks: any[]) =>
41
45
  yMax / ticks.length / 2 - (yMax / ticks.length) * (1 - config.barThickness) + HORIZONTAL_TICK_OFFSET_ADJUSTMENT
@@ -44,8 +48,9 @@ export const RightAxis: React.FC<RightAxisProps> = ({
44
48
  <VisxAxisRight
45
49
  scale={yScaleRight}
46
50
  left={yAxisWidth + xMax}
47
- label={config.yAxis.rightLabel}
51
+ label={runtime.yAxis.rightLabel ?? config.yAxis.rightLabel}
48
52
  tickFormat={tick => formatNumber(tick, 'right')}
53
+ tickLength={DEFAULT_TICK_LENGTH}
49
54
  numTicks={runtime.yAxis.rightNumTicks || undefined}
50
55
  {...(tickValues ? { tickValues } : {})}
51
56
  labelOffset={45}
@@ -55,6 +60,7 @@ export const RightAxis: React.FC<RightAxisProps> = ({
55
60
  config.orientation === 'horizontal'
56
61
  ? (props.axisToPoint.y - props.axisFromPoint.y) / 2
57
62
  : (props.axisFromPoint.y - props.axisToPoint.y) / 2
63
+ const sideTitleX = Math.max(0, rightAxisWidth - axisLabelFontSize)
58
64
 
59
65
  return (
60
66
  <Group className='right-axis'>
@@ -75,7 +81,7 @@ export const RightAxis: React.FC<RightAxisProps> = ({
75
81
 
76
82
  {!config.yAxis.rightHideLabel && (
77
83
  <Text
78
- x={tick.to.x}
84
+ x={tick.to.x + TICK_LABEL_MARGIN_RIGHT}
79
85
  y={tick.to.y + (runtime.horizontal ? horizontalTickOffset(props.ticks) : 0)}
80
86
  verticalAnchor={runtime.horizontal ? 'start' : 'middle'}
81
87
  textAnchor='start'
@@ -90,17 +96,19 @@ export const RightAxis: React.FC<RightAxisProps> = ({
90
96
 
91
97
  {!config.yAxis.rightHideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
92
98
 
93
- <Text
94
- className='y-label'
95
- textAnchor='middle'
96
- verticalAnchor='start'
97
- transform={`translate(${config.yAxis.rightLabelOffsetSize || 0}, ${axisCenter}) rotate(-90)`}
98
- fontWeight='bold'
99
- fill={config.yAxis.rightAxisLabelColor}
100
- fontSize={axisLabelFontSize}
101
- >
102
- {props.label}
103
- </Text>
99
+ {showSideTitle && (
100
+ <Text
101
+ className='y-label'
102
+ textAnchor='middle'
103
+ verticalAnchor='start'
104
+ transform={`translate(${sideTitleX}, ${axisCenter}) rotate(-90)`}
105
+ fontWeight='bold'
106
+ fill={config.yAxis.rightAxisLabelColor}
107
+ fontSize={axisLabelFontSize}
108
+ >
109
+ {props.label}
110
+ </Text>
111
+ )}
104
112
  </Group>
105
113
  )
106
114
  }}
@@ -17,6 +17,7 @@ import createBarElement from '@cdc/core/components/createBarElement'
17
17
  import { getBarConfig, testZeroValue, getLollipopStemColor, getLollipopHeadColor } from '../helpers'
18
18
  import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
19
19
  import isNumber from '@cdc/core/helpers/isNumber'
20
+ import { getSeriesValueLabel } from '@cdc/core/helpers/getSeriesName'
20
21
 
21
22
  // Local context and types
22
23
  import BarChartContext, { BarChartContextValues } from './context'
@@ -24,8 +25,10 @@ import { ChartContext } from '../../../types/ChartContext'
24
25
  import { getBarData } from '../helpers/getBarData'
25
26
  import { getHorizontalBarHeights } from '../helpers/getBarHeights'
26
27
  import { getPatternUrl as getPatternUrlForBar } from '../helpers/getPatternUrl'
28
+ import { getPortionPatternRenderData } from '../helpers/portionPattern'
27
29
  import { getChartPatternId } from '../../../helpers/getChartPatternId'
28
30
  import { buildSeriesTooltipListHtml } from '../../../helpers/tooltipHelpers'
31
+ import { BarPortionPatternOverlay } from './PortionPatternOverlay'
29
32
 
30
33
  const BarChartHorizontal = () => {
31
34
  const { xScale, yScale, yMax, seriesScale, barChart } = useContext<BarChartContextValues>(BarChartContext)
@@ -41,6 +44,7 @@ const BarChartHorizontal = () => {
41
44
  getHighlightedBarColorByValue,
42
45
  getHighlightedBarByValue,
43
46
  getAdditionalColumn,
47
+ formatTooltipValue,
44
48
  hoveredBar,
45
49
  onMouseLeaveBar,
46
50
  onMouseOverBar
@@ -48,7 +52,6 @@ const BarChartHorizontal = () => {
48
52
 
49
53
  const {
50
54
  transformedData: data,
51
- tableData,
52
55
  colorScale,
53
56
  seriesHighlight,
54
57
  config,
@@ -120,8 +123,9 @@ const BarChartHorizontal = () => {
120
123
  id={patternId}
121
124
  height={size}
122
125
  width={size}
123
- fill={pattern.color}
124
- strokeWidth={0.25}
126
+ fill='transparent'
127
+ stroke={pattern.color}
128
+ strokeWidth={0.75}
125
129
  />
126
130
  )
127
131
  default:
@@ -141,7 +145,7 @@ const BarChartHorizontal = () => {
141
145
  <Group>
142
146
  {renderPatternDefs()}
143
147
  <BarGroup
144
- data={config.preliminaryData?.some(pd => pd.value && pd.type === 'suppression') ? tableData : _data}
148
+ data={_data}
145
149
  keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys}
146
150
  height={yMax}
147
151
  x0={d => d[config.runtime.originalXAxis.dataKey]}
@@ -242,7 +246,8 @@ const BarChartHorizontal = () => {
242
246
  ? `${config.runtime.yAxis.label}: ${xAxisValue}`
243
247
  : xAxisValue
244
248
  const additionalColTooltip = getAdditionalColumn(bar.key, hoveredBar)
245
- const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${yAxisValue}`
249
+ const tooltipValue = formatTooltipValue(bar.key, dataValue, yAxisValue, barGroup.index)
250
+ const tooltipBody = `${getSeriesValueLabel(bar.key, config)}: ${tooltipValue}`
246
251
  const tooltip = buildSeriesTooltipListHtml({
247
252
  config,
248
253
  colorScale,
@@ -261,7 +266,7 @@ const BarChartHorizontal = () => {
261
266
  : colorScale(bar.key)
262
267
  const hasDynamicCategory = config.series.find(s => s.dynamicCategory)
263
268
  if (!hasDynamicCategory && config.legend.colorCode) {
264
- barColor = assignColorsToValues(barGroups.length, barGroup.index, barColor) // Color code by category
269
+ barColor = assignColorsToValues(barGroup.index, barColor) // Color code by category
265
270
  }
266
271
  const isRegularLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'regular'
267
272
  const isTwoToneLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'two-tone'
@@ -339,6 +344,20 @@ const BarChartHorizontal = () => {
339
344
  allowNonSeriesFieldMatch: !config.series || config.series.length <= 1
340
345
  })
341
346
  const baseBackground = getBarBackgroundColor()
347
+ const portionPatternRenderData = getPortionPatternRenderData({
348
+ config,
349
+ orientation: 'horizontal',
350
+ bounds: {
351
+ x: barX,
352
+ y: barHeight * bar.index,
353
+ width: barWidth,
354
+ height: numbericBarHeight
355
+ },
356
+ patterns: config.legend?.patterns,
357
+ datum,
358
+ seriesKey: bar.key,
359
+ totalValue: bar.value
360
+ })
342
361
 
343
362
  return (
344
363
  <Group display={hideGroup} key={`${barGroup.index}--${index}`}>
@@ -400,6 +419,19 @@ const BarChartHorizontal = () => {
400
419
  }
401
420
  })}
402
421
 
422
+ {portionPatternRenderData && (
423
+ <BarPortionPatternOverlay
424
+ config={config}
425
+ index={newIndex}
426
+ renderData={portionPatternRenderData}
427
+ transformOrigin={`0 ${barY + barHeight}px`}
428
+ style={{
429
+ opacity: transparentBar ? 0.2 : 1,
430
+ display: displayBar ? 'block' : 'none'
431
+ }}
432
+ />
433
+ )}
434
+
403
435
  {(absentDataLabel || isSuppressed) && (
404
436
  <rect
405
437
  x={barX}
@@ -13,6 +13,7 @@ import BarChartContext, { type BarChartContextValues } from './context'
13
13
  import { type ChartContext } from '../../../types/ChartContext'
14
14
 
15
15
  import createBarElement from '@cdc/core/components/createBarElement'
16
+ import { getSeriesValueLabel } from '@cdc/core/helpers/getSeriesName'
16
17
  import { getHorizontalBarHeights } from '../helpers/getBarHeights'
17
18
  import { getPatternUrl as getPatternUrlForBar } from '../helpers/getPatternUrl'
18
19
  import { getChartPatternId } from '../../../helpers/getChartPatternId'
@@ -38,6 +39,7 @@ const BarChartStackedHorizontal = () => {
38
39
  barBorderWidth,
39
40
  displayNumbersOnBar,
40
41
  getAdditionalColumn,
42
+ formatTooltipValue,
41
43
  hoveredBar,
42
44
  isHorizontal,
43
45
  isLabelBelowBar,
@@ -104,8 +106,9 @@ const BarChartStackedHorizontal = () => {
104
106
  id={patternId}
105
107
  height={size}
106
108
  width={size}
107
- fill={pattern.color}
108
- strokeWidth={0.25}
109
+ fill='transparent'
110
+ stroke={pattern.color}
111
+ strokeWidth={0.75}
109
112
  />
110
113
  )
111
114
  default:
@@ -161,7 +164,13 @@ const BarChartStackedHorizontal = () => {
161
164
  : yAxisValue
162
165
  const textWidth = getTextWidth(xAxisValue, `normal ${labelFontSize}px sans-serif`)
163
166
  const additionalColTooltip = getAdditionalColumn(bar.key, hoveredBar)
164
- const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${xAxisValue}`
167
+ const tooltipValue = formatTooltipValue(
168
+ bar.key,
169
+ data[bar.index][config.runtime.originalXAxis.dataKey],
170
+ xAxisValue,
171
+ bar.index
172
+ )
173
+ const tooltipBody = `${getSeriesValueLabel(bar.key, config)}: ${tooltipValue}`
165
174
  const tooltip = buildSeriesTooltipListHtml({
166
175
  config,
167
176
  colorScale,
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { getStackedVerticalBarThickness } from './BarChart.StackedVertical'
3
+
4
+ describe('getStackedVerticalBarThickness', () => {
5
+ it.each(['date', 'date-time'])('does not apply bar thickness twice for a %s axis', () => {
6
+ expect(
7
+ getStackedVerticalBarThickness({
8
+ isDateAxisType: true,
9
+ dateScaleWidth: 40,
10
+ xMax: 400,
11
+ barCount: 4,
12
+ barThickness: 0.8
13
+ })
14
+ ).toBe(40)
15
+ })
16
+
17
+ it('applies bar thickness to categorical bars', () => {
18
+ expect(
19
+ getStackedVerticalBarThickness({
20
+ isDateAxisType: false,
21
+ dateScaleWidth: 40,
22
+ xMax: 400,
23
+ barCount: 4,
24
+ barThickness: 0.8
25
+ })
26
+ ).toBe(80)
27
+ })
28
+ })
@@ -1,25 +1,39 @@
1
- import React, { useContext, useState } from 'react'
1
+ import React, { useContext } from 'react'
2
2
  import ConfigContext from '../../../ConfigContext'
3
3
  import { BarStack } from '@visx/shape'
4
4
  import { Group } from '@visx/group'
5
5
  import { PatternLines, PatternCircles, PatternWaves } from '@visx/pattern'
6
6
  import BarChartContext from './context'
7
- import Regions from '../../Regions'
8
7
  import { addMinimumBarHeights } from '../helpers'
9
8
 
10
9
  import createBarElement from '@cdc/core/components/createBarElement'
10
+ import { getSeriesValueLabel } from '@cdc/core/helpers/getSeriesName'
11
11
  import { getPatternUrl as getPatternUrlForBar } from '../helpers/getPatternUrl'
12
12
  import { getChartPatternId } from '../../../helpers/getChartPatternId'
13
13
  import { buildSeriesTooltipListHtml } from '../../../helpers/tooltipHelpers'
14
14
 
15
+ export const getStackedVerticalBarThickness = ({
16
+ isDateAxisType,
17
+ dateScaleWidth,
18
+ xMax,
19
+ barCount,
20
+ barThickness
21
+ }: {
22
+ isDateAxisType: boolean
23
+ dateScaleWidth: number
24
+ xMax: number
25
+ barCount: number
26
+ barThickness: number
27
+ }) => (isDateAxisType ? dateScaleWidth : barThickness * (xMax / barCount))
28
+
15
29
  const BarChartStackedVertical = () => {
16
- const [barWidth, setBarWidth] = useState(0)
17
30
  const { xScale, yScale, seriesScale, xMax, yMax, barChart } = useContext(BarChartContext)
18
31
  const {
19
32
  isHorizontal,
20
33
  barBorderWidth,
21
34
  hoveredBar,
22
35
  getAdditionalColumn,
36
+ formatTooltipValue,
23
37
  onMouseLeaveBar,
24
38
  onMouseOverBar,
25
39
  barStackedSeriesKeys
@@ -89,8 +103,9 @@ const BarChartStackedVertical = () => {
89
103
  id={patternId}
90
104
  height={size}
91
105
  width={size}
92
- fill={pattern.color}
93
- strokeWidth={0.25}
106
+ fill='transparent'
107
+ stroke={pattern.color}
108
+ strokeWidth={0.75}
94
109
  />
95
110
  )
96
111
  default:
@@ -127,15 +142,19 @@ const BarChartStackedVertical = () => {
127
142
  config.legend.behavior === 'highlight' ||
128
143
  seriesHighlight.length === 0 ||
129
144
  seriesHighlight.indexOf(bar.key) !== -1
130
- let barThickness = isDateAxisType
131
- ? seriesScale.range()[1] - seriesScale.range()[0]
132
- : xMax / barStack.bars.length
133
- if (config.runtime.xAxis.type !== 'date') barThickness = config.barThickness * barThickness
145
+ const barThickness = getStackedVerticalBarThickness({
146
+ isDateAxisType,
147
+ dateScaleWidth: seriesScale.range()[1] - seriesScale.range()[0],
148
+ xMax,
149
+ barCount: barStack.bars.length,
150
+ barThickness: config.barThickness
151
+ })
134
152
  // tooltips
135
153
  const rawXValue = bar.bar.data[config.runtime.xAxis.dataKey]
136
154
  const xAxisValue = isDateAxisType ? formatDate(parseDate(rawXValue)) : rawXValue
137
155
  const yAxisValue = formatNumber(bar.bar ? bar.bar.data[bar.key] : 0, 'left')
138
156
  if (!yAxisValue) return
157
+ const tooltipValue = formatTooltipValue(bar.key, rawXValue, yAxisValue, bar.index)
139
158
  const barX =
140
159
  xScale(isDateAxisType ? parseDate(rawXValue) : rawXValue) -
141
160
  (isDateTimeScaleAxisType ? barThickness / 2 : 0)
@@ -143,7 +162,7 @@ const BarChartStackedVertical = () => {
143
162
  ? `${config.runtime.xAxis.label}: ${xAxisValue}`
144
163
  : xAxisValue
145
164
  const additionalColTooltip = getAdditionalColumn(bar.key, hoveredBar)
146
- const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${yAxisValue}`
165
+ const tooltipBody = `${getSeriesValueLabel(bar.key, config)}: ${tooltipValue}`
147
166
  const tooltip = buildSeriesTooltipListHtml({
148
167
  config,
149
168
  colorScale,
@@ -153,8 +172,6 @@ const BarChartStackedVertical = () => {
153
172
  extraRows: additionalColTooltip ? [additionalColTooltip] : []
154
173
  })
155
174
 
156
- setBarWidth(barThickness)
157
-
158
175
  // Check if this bar should use a pattern
159
176
  const patternUrl = getPatternUrlForBar({
160
177
  patterns: config.legend?.patterns,
@@ -239,19 +256,6 @@ const BarChartStackedVertical = () => {
239
256
  })
240
257
  }}
241
258
  </BarStack>
242
- <Regions
243
- xScale={xScale}
244
- yMax={yMax}
245
- barWidth={barWidth}
246
- totalBarsInGroup={1}
247
- xMax={xMax}
248
- handleTooltipMouseOff={() => {}}
249
- handleTooltipMouseOver={() => {}}
250
- handleTooltipClick={() => {}}
251
- tooltipData={null}
252
- showTooltip={() => {}}
253
- hideTooltip={() => {}}
254
- />
255
259
  </>
256
260
  )
257
261
  )