@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
@@ -0,0 +1,70 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { getBoxPlotConfig } from '../getBoxPlotConfig'
4
+ import { ChartConfig } from '../../types/ChartConfig'
5
+
6
+ const createBoxPlotConfig = (): ChartConfig =>
7
+ ({
8
+ xAxis: {
9
+ dataKey: 'Group'
10
+ },
11
+ series: [
12
+ {
13
+ dataKey: 'Score'
14
+ }
15
+ ],
16
+ dataFormat: {
17
+ roundTo: 0
18
+ }
19
+ } as ChartConfig)
20
+
21
+ describe('getBoxPlotConfig', () => {
22
+ it('sorts generated value arrays numerically for numeric strings', () => {
23
+ const data = [
24
+ { Group: 'Group A', Score: '1' },
25
+ { Group: 'Group A', Score: '2' },
26
+ { Group: 'Group A', Score: '3' },
27
+ { Group: 'Group A', Score: '10' },
28
+ { Group: 'Group A', Score: '20' },
29
+ { Group: 'Group A', Score: '100' }
30
+ ]
31
+
32
+ const [plots] = getBoxPlotConfig(createBoxPlotConfig(), data)
33
+
34
+ expect(plots[0].values).toEqual([1, 2, 3, 10, 20, 100])
35
+ expect(plots[0].columnNonOutliers).toEqual([1, 2, 3, 10, 20])
36
+ expect(plots[0].columnOutliers).toEqual([100])
37
+ })
38
+
39
+ it('parses formatted numeric strings before sorting', () => {
40
+ const data = [
41
+ { Group: 'Group A', Score: '1,234.5' },
42
+ { Group: 'Group A', Score: '20' },
43
+ { Group: 'Group A', Score: '3' }
44
+ ]
45
+
46
+ const [plots] = getBoxPlotConfig(createBoxPlotConfig(), data)
47
+
48
+ expect(plots[0].values).toEqual([3, 20, 1234.5])
49
+ expect(plots[0].columnCount).toBe(3)
50
+ })
51
+
52
+ it('ignores blank, null, and nonnumeric values when generating box plot stats', () => {
53
+ const data = [
54
+ { Group: 'Group A', Score: '1' },
55
+ { Group: 'Group A', Score: '' },
56
+ { Group: 'Group A', Score: null },
57
+ { Group: 'Group A', Score: undefined },
58
+ { Group: 'Group A', Score: 'n/a' },
59
+ { Group: 'Group A', Score: '2' },
60
+ { Group: 'Group A', Score: '3' }
61
+ ]
62
+
63
+ const [plots] = getBoxPlotConfig(createBoxPlotConfig(), data)
64
+
65
+ expect(plots[0].values).toEqual([1, 2, 3])
66
+ expect(plots[0].columnCount).toBe(3)
67
+ expect(plots[0].columnNonOutliers).toEqual([1, 2, 3])
68
+ expect(plots[0].columnOutliers).toEqual([])
69
+ })
70
+ })
@@ -0,0 +1,113 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { ChartConfig } from '../../types/ChartConfig'
3
+ import { getColorCodeCategoryColorMap } from '../getColorCodeCategoryColorMap'
4
+
5
+ const buildConfig = (
6
+ colorCode = 'Group',
7
+ paletteOverrides: Partial<ChartConfig['general']['palette']> = {}
8
+ ): ChartConfig =>
9
+ ({
10
+ visualizationType: 'Bar',
11
+ general: {
12
+ palette: {
13
+ name: 'sequential_blue',
14
+ version: '2.0',
15
+ ...paletteOverrides
16
+ }
17
+ },
18
+ legend: { colorCode }
19
+ } as ChartConfig)
20
+
21
+ const colorPalettes = {
22
+ sequential_blue: Array.from({ length: 9 }, (_, index) => `#00000${index}`),
23
+ sequential_bluereverse: Array.from({ length: 9 }, (_, index) => `#00000${8 - index}`),
24
+ qualitative_standard: Array.from({ length: 9 }, (_, index) => `qualitative-${index}`)
25
+ }
26
+
27
+ describe('getColorCodeCategoryColorMap', () => {
28
+ it('assigns colors to unique categories in encounter order', () => {
29
+ const result = getColorCodeCategoryColorMap(
30
+ buildConfig(),
31
+ [{ Group: 'Group A' }, { Group: 'Group B' }, { Group: 'Group A' }],
32
+ colorPalettes
33
+ )
34
+
35
+ expect(Array.from(result.entries())).toEqual([
36
+ ['Group A', '#000000'],
37
+ ['Group B', '#000001']
38
+ ])
39
+ })
40
+
41
+ it('uses the 2.1 chart distribution for two categories in a sequential palette', () => {
42
+ const result = getColorCodeCategoryColorMap(
43
+ buildConfig('Group', { version: '2.1' }),
44
+ [{ Group: 'Group A' }, { Group: 'Group B' }, { Group: 'Group A' }],
45
+ colorPalettes
46
+ )
47
+
48
+ expect(Array.from(result.entries())).toEqual([
49
+ ['Group A', '#000004'],
50
+ ['Group B', '#000008']
51
+ ])
52
+ })
53
+
54
+ it('uses the full V2 chart distribution for three categories in a sequential palette', () => {
55
+ const result = getColorCodeCategoryColorMap(
56
+ buildConfig('Group', { version: '2.1' }),
57
+ [{ Group: 'Group A' }, { Group: 'Group B' }, { Group: 'Group C' }],
58
+ colorPalettes
59
+ )
60
+
61
+ expect(Array.from(result.values())).toEqual(['#000000', '#000004', '#000008'])
62
+ })
63
+
64
+ it('uses the V2 qualitative distribution for color-coded categories', () => {
65
+ const result = getColorCodeCategoryColorMap(
66
+ buildConfig('Group', { name: 'qualitative_standard', version: '2.1' }),
67
+ [{ Group: 'Group A' }, { Group: 'Group B' }, { Group: 'Group C' }],
68
+ colorPalettes
69
+ )
70
+
71
+ expect(Array.from(result.values())).toEqual(['qualitative-0', 'qualitative-4', 'qualitative-6'])
72
+ })
73
+
74
+ it('uses the V2 sequential colors in reverse order for a reversed palette', () => {
75
+ const rows = [{ Group: 'Group A' }, { Group: 'Group B' }]
76
+ const reversed = getColorCodeCategoryColorMap(
77
+ buildConfig('Group', {
78
+ name: 'sequential_bluereverse',
79
+ version: '2.1',
80
+ isReversed: true
81
+ }),
82
+ rows,
83
+ colorPalettes
84
+ )
85
+
86
+ expect(Array.from(reversed.values())).toEqual(['#000008', '#000004'])
87
+ })
88
+
89
+ it('preserves raw palette order for custom palettes', () => {
90
+ const rows = [{ Group: 'Group A' }, { Group: 'Group B' }]
91
+ const custom = getColorCodeCategoryColorMap(
92
+ buildConfig('Group', { version: '2.1', customColors: ['#111111', '#222222'] }),
93
+ rows,
94
+ colorPalettes
95
+ )
96
+
97
+ expect(Array.from(custom.values())).toEqual(['#111111', '#222222'])
98
+ })
99
+
100
+ it('repeats the palette when there are more categories than colors', () => {
101
+ const result = getColorCodeCategoryColorMap(
102
+ buildConfig(),
103
+ [{ Group: 'Group A' }, { Group: 'Group B' }, { Group: 'Group C' }],
104
+ colorPalettes
105
+ )
106
+
107
+ expect(Array.from(result.values())).toEqual(['#000000', '#000001', '#000002'])
108
+ })
109
+
110
+ it('returns an empty map without a color-code column', () => {
111
+ expect(getColorCodeCategoryColorMap(buildConfig(''), [{ Group: 'Group A' }], colorPalettes).size).toBe(0)
112
+ })
113
+ })
@@ -1,6 +1,14 @@
1
- import { describe, expect, it } from 'vitest'
1
+ import { describe, expect, it, vi } from 'vitest'
2
2
  import { getColorScale } from '../getColorScale'
3
3
  import { ChartConfig } from '../../types/ChartConfig'
4
+ import { colorPalettesChartV2 } from '@cdc/core/data/colorPalettes'
5
+ import {
6
+ colorblindColorDistribution,
7
+ chartV21ColorDistribution,
8
+ divergentColorDistribution,
9
+ qualitativeStandardColorDistribution,
10
+ v2ColorDistribution
11
+ } from '@cdc/core/helpers/palettes/colorDistributions'
4
12
 
5
13
  const buildConfig = (overrides: Partial<ChartConfig> = {}): ChartConfig =>
6
14
  ({
@@ -177,6 +185,63 @@ describe('getColorScale series color assignments', () => {
177
185
  expect(colorScale('Series C')).toBe('#303030')
178
186
  })
179
187
 
188
+ it('fills invalid customColorsOrdered entries with black', () => {
189
+ const colorScale = getColorScale(
190
+ buildConfig({
191
+ general: {
192
+ palette: {
193
+ name: 'qualitative_standard',
194
+ version: '2.0',
195
+ customColorsOrdered: ['', '#222222', 'whyte']
196
+ }
197
+ } as any
198
+ })
199
+ )
200
+
201
+ expect(colorScale('Series A')).toBe('#000000')
202
+ expect(colorScale('Series B')).toBe('#222222')
203
+ expect(colorScale('Series C')).toBe('#000000')
204
+ })
205
+
206
+ it('uses black when saved customColors are all invalid', () => {
207
+ const colorScale = getColorScale(
208
+ buildConfig({
209
+ general: {
210
+ palette: {
211
+ name: 'qualitative_standard',
212
+ version: '2.0',
213
+ customColors: ['', 'whyte']
214
+ }
215
+ } as any
216
+ })
217
+ )
218
+
219
+ expect(colorScale('Series A')).toBe('#000000')
220
+ expect(colorScale('Series B')).toBe('#000000')
221
+ expect(colorScale('Series C')).toBe('#000000')
222
+ })
223
+
224
+ it('uses black when the named palette cannot be resolved', () => {
225
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
226
+ const colorScale = getColorScale(
227
+ buildConfig({
228
+ general: {
229
+ palette: {
230
+ name: 'unknown_palette',
231
+ version: '2.0'
232
+ }
233
+ } as any
234
+ })
235
+ )
236
+
237
+ expect(warn).toHaveBeenCalledWith('Palette "unknown_palette" not found, falling back to black')
238
+ expect(colorScale('Series A')).toBe('#000000')
239
+ expect(colorScale('Series B')).toBe('#000000')
240
+ expect(colorScale('Series C')).toBe('#000000')
241
+
242
+ warn.mockRestore()
243
+ })
244
+
180
245
  it('falls back to the named palette when customColors is empty', () => {
181
246
  const colorScale = getColorScale(
182
247
  buildConfig({
@@ -195,3 +260,163 @@ describe('getColorScale series color assignments', () => {
195
260
  expect(colorScale('Series C')).toBe('#5A8E3F')
196
261
  })
197
262
  })
263
+
264
+ const buildDistributionConfig = (
265
+ numberOfSeries: number,
266
+ paletteName = 'qualitative_standard',
267
+ paletteVersion: '2.0' | '2.1' = '2.0',
268
+ overrides: Partial<ChartConfig> = {}
269
+ ) => {
270
+ const seriesKeys = Array.from({ length: numberOfSeries }, (_, index) => `series_${index + 1}`)
271
+ const seriesLabelsAll = seriesKeys.map((_, index) => `Series ${index + 1}`)
272
+
273
+ return buildConfig({
274
+ general: {
275
+ palette: {
276
+ name: paletteName,
277
+ version: paletteVersion
278
+ }
279
+ } as any,
280
+ series: seriesKeys.map((dataKey, index) => ({ dataKey, name: seriesLabelsAll[index], type: 'Line' })) as any,
281
+ runtime: {
282
+ seriesKeys,
283
+ seriesLabels: Object.fromEntries(seriesKeys.map((key, index) => [key, seriesLabelsAll[index]])),
284
+ seriesLabelsAll
285
+ } as any,
286
+ ...overrides
287
+ })
288
+ }
289
+
290
+ const getScaleColors = (config: ChartConfig) => {
291
+ const scale = getColorScale(config)
292
+ return config.runtime.seriesLabelsAll.map(label => scale(label))
293
+ }
294
+
295
+ describe('getColorScale distribution profiles', () => {
296
+ it.each(Object.keys(qualitativeStandardColorDistribution).map(Number))(
297
+ 'uses released colorblind colors for %i series with palette version 2.0',
298
+ count => {
299
+ const expected = colorblindColorDistribution[count].map(index => colorPalettesChartV2.qualitative_standard[index])
300
+
301
+ expect(getScaleColors(buildDistributionConfig(count))).toEqual(expected)
302
+ }
303
+ )
304
+
305
+ it.each(Object.keys(qualitativeStandardColorDistribution).map(Number))(
306
+ 'uses improved colorblind colors for %i series with palette version 2.1',
307
+ count => {
308
+ const expected = qualitativeStandardColorDistribution[count].map(
309
+ index => colorPalettesChartV2.qualitative_standard[index]
310
+ )
311
+
312
+ expect(getScaleColors(buildDistributionConfig(count, 'qualitative_standard', '2.1'))).toEqual(expected)
313
+ }
314
+ )
315
+
316
+ it('uses the V2 forward colors in reverse order for a reversed palette', () => {
317
+ const count = 5
318
+ const expected = qualitativeStandardColorDistribution[count]
319
+ .map(index => colorPalettesChartV2.qualitative_standard[index])
320
+ .reverse()
321
+
322
+ expect(getScaleColors(buildDistributionConfig(count, 'qualitative_standardreverse', '2.1'))).toEqual(expected)
323
+ })
324
+
325
+ it('uses the chart 2.1 distribution for a two-series sequential palette', () => {
326
+ const expected = chartV21ColorDistribution[2].map(index => colorPalettesChartV2.sequential_blue[index])
327
+
328
+ expect(getScaleColors(buildDistributionConfig(2, 'sequential_blue', '2.1'))).toEqual(expected)
329
+ })
330
+
331
+ it('preserves the released sequential distribution for palette version 2.0', () => {
332
+ const expected = v2ColorDistribution[2].map(index => colorPalettesChartV2.sequential_blue[index])
333
+
334
+ expect(getScaleColors(buildDistributionConfig(2, 'sequential_blue', '2.0'))).toEqual(expected)
335
+ })
336
+
337
+ it('uses the 2.1 sequential colors in reverse order for a reversed palette', () => {
338
+ const expected = chartV21ColorDistribution[2].map(index => colorPalettesChartV2.sequential_blue[index]).reverse()
339
+
340
+ expect(
341
+ getScaleColors(
342
+ buildDistributionConfig(2, 'sequential_bluereverse', '2.1', {
343
+ general: {
344
+ palette: {
345
+ name: 'sequential_bluereverse',
346
+ version: '2.1',
347
+ isReversed: true
348
+ }
349
+ } as any
350
+ })
351
+ )
352
+ ).toEqual(expected)
353
+ })
354
+
355
+ it('does not change divergent colors between palette versions', () => {
356
+ const count = 5
357
+ const expected = divergentColorDistribution[count].map(index => colorPalettesChartV2.divergent_blue_orange[index])
358
+
359
+ expect(getScaleColors(buildDistributionConfig(count, 'divergent_blue_orange', '2.0'))).toEqual(expected)
360
+ expect(getScaleColors(buildDistributionConfig(count, 'divergent_blue_orange', '2.1'))).toEqual(expected)
361
+ })
362
+
363
+ it('bypasses distribution profiles for non-empty custom colors', () => {
364
+ const customColors = Array.from({ length: 9 }, (_, index) => `#00000${index}`)
365
+ const config = buildDistributionConfig(5, 'qualitative_standard', '2.1', {
366
+ general: {
367
+ palette: {
368
+ name: 'qualitative_standard',
369
+ version: '2.1',
370
+ customColors
371
+ }
372
+ } as any
373
+ })
374
+
375
+ expect(getScaleColors(config)).toEqual(customColors.slice(0, 5))
376
+ })
377
+
378
+ it('treats empty custom color arrays as inactive', () => {
379
+ const config = buildDistributionConfig(3, 'qualitative_standard', '2.1', {
380
+ general: {
381
+ palette: {
382
+ name: 'qualitative_standard',
383
+ version: '2.1',
384
+ customColors: [],
385
+ customColorsOrdered: []
386
+ }
387
+ } as any
388
+ })
389
+ const expected = qualitativeStandardColorDistribution[3].map(
390
+ index => colorPalettesChartV2.qualitative_standard[index]
391
+ )
392
+
393
+ expect(getScaleColors(config)).toEqual(expected)
394
+ })
395
+
396
+ it('retains slice and repeat behavior outside the supported item range', () => {
397
+ const expected = [...colorPalettesChartV2.qualitative_standard, colorPalettesChartV2.qualitative_standard[0]]
398
+
399
+ expect(getScaleColors(buildDistributionConfig(10, 'qualitative_standard', '2.1'))).toEqual(expected)
400
+ })
401
+
402
+ it('does not apply the 2.1 distribution to an unsupported chart type', () => {
403
+ const config = buildDistributionConfig(3, 'qualitative_standard', '2.1', {
404
+ visualizationType: 'Horizon Chart'
405
+ })
406
+ const expected = colorblindColorDistribution[3].map(index => colorPalettesChartV2.qualitative_standard[index])
407
+
408
+ expect(getScaleColors(config)).toEqual(expected)
409
+ })
410
+
411
+ it('applies the 2.1 distribution to a color-coded bar chart', () => {
412
+ const config = buildDistributionConfig(3, 'qualitative_standard', '2.1', {
413
+ visualizationType: 'Bar',
414
+ legend: { colorCode: 'category' } as any
415
+ })
416
+ const expected = qualitativeStandardColorDistribution[3].map(
417
+ index => colorPalettesChartV2.qualitative_standard[index]
418
+ )
419
+
420
+ expect(getScaleColors(config)).toEqual(expected)
421
+ })
422
+ })
@@ -0,0 +1,61 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { getDynamicYAxisCategories } from '../getDynamicYAxisCategories'
3
+
4
+ const config = {
5
+ categories: [
6
+ { label: 'Very Low', upperBoundKey: 'very_low_max' },
7
+ { label: 'Low', upperBoundKey: 'low_max' },
8
+ { label: 'Moderate', upperBoundKey: 'moderate_max' },
9
+ { label: 'High', upperBoundKey: 'high_max' },
10
+ { label: 'Very High', upperBoundKey: 'very_high_max' }
11
+ ]
12
+ }
13
+
14
+ describe('getDynamicYAxisCategories', () => {
15
+ it('converts cumulative upper bounds into category heights and uses configured colors', () => {
16
+ config.categories = config.categories.map((category, index) => ({ ...category, color: `color-${index}` }))
17
+ const result = getDynamicYAxisCategories({
18
+ config,
19
+ data: [{ very_low_max: 12.5, low_max: 16, moderate_max: 18, high_max: 21, very_high_max: 35 }]
20
+ })
21
+
22
+ expect(result).toEqual({
23
+ axisMax: 35,
24
+ categories: [
25
+ { label: 'Very Low', height: '12.5', color: 'color-0' },
26
+ { label: 'Low', height: '3.5', color: 'color-1' },
27
+ { label: 'Moderate', height: '2', color: 'color-2' },
28
+ { label: 'High', height: '3', color: 'color-3' },
29
+ { label: 'Very High', height: '14', color: 'color-4' }
30
+ ]
31
+ })
32
+ })
33
+
34
+ it('returns null for missing, invalid, or non-increasing current-row data', () => {
35
+ expect(getDynamicYAxisCategories({ config, data: [{ very_low_max: 12 }] })).toBeNull()
36
+ expect(
37
+ getDynamicYAxisCategories({
38
+ config,
39
+ data: [{ very_low_max: 12, low_max: 10, moderate_max: 18, high_max: 21, very_high_max: 35 }]
40
+ })
41
+ ).toBeNull()
42
+ })
43
+
44
+ it('returns null while filtered chart data is temporarily empty', () => {
45
+ expect(getDynamicYAxisCategories({ config, data: [] })).toBeNull()
46
+ })
47
+
48
+ it('leaves the final category open-ended when it has no upper-bound key', () => {
49
+ const categories = config.categories.map((category, index) =>
50
+ index === config.categories.length - 1 ? { ...category, upperBoundKey: undefined } : category
51
+ )
52
+
53
+ const result = getDynamicYAxisCategories({
54
+ config: { categories },
55
+ data: [{ very_low_max: 12.5, low_max: 16, moderate_max: 18, high_max: 21 }]
56
+ })
57
+
58
+ expect(result?.axisMax).toBeNull()
59
+ expect(result?.categories.at(-1)).toEqual({ label: 'Very High', height: '', color: 'color-4' })
60
+ })
61
+ })
@@ -155,6 +155,47 @@ describe('getMinMax automatic max strategy', () => {
155
155
  expect(result.rightMax).toBe(89)
156
156
  })
157
157
 
158
+ it('uses stacked row totals for combo left-axis bar series and keeps right-axis line max independent', () => {
159
+ const barSeriesA = { dataKey: 'DoseOne', type: 'Bar', axis: 'Left', tooltip: true }
160
+ const barSeriesB = { dataKey: 'DoseTwo', type: 'Bar', axis: 'Left', tooltip: true }
161
+ const rightLineSeries = { dataKey: 'Rate', type: 'Line', axis: 'Right', tooltip: true }
162
+ const data = [
163
+ { DoseOne: 520, DoseTwo: 80, Rate: 900 },
164
+ { DoseOne: 0, DoseTwo: 600, Rate: 725 }
165
+ ]
166
+ const config = createConfig({
167
+ visualizationType: 'Combo',
168
+ visualizationSubType: 'stacked',
169
+ series: [barSeriesA, barSeriesB, rightLineSeries],
170
+ runtime: {
171
+ ...createConfig().runtime,
172
+ yAxis: {
173
+ ...createConfig().runtime.yAxis,
174
+ min: '',
175
+ max: ''
176
+ },
177
+ series: [barSeriesA, barSeriesB, rightLineSeries],
178
+ seriesKeys: ['DoseOne', 'DoseTwo', 'Rate'],
179
+ barSeriesKeys: ['DoseOne', 'DoseTwo'],
180
+ lineSeriesKeys: ['Rate']
181
+ } as any
182
+ })
183
+
184
+ const result = getMinMax({
185
+ config,
186
+ minValue: 0,
187
+ maxValue: 900,
188
+ existPositiveValue: true,
189
+ data,
190
+ tableData: data,
191
+ isAllLine: false
192
+ })
193
+
194
+ expect(result.leftMax).toBe(600)
195
+ expect(result.leftMax).not.toBe(1120)
196
+ expect(result.rightMax).toBe(900)
197
+ })
198
+
158
199
  it('forces a zero min for line charts when boundary suppression is present', () => {
159
200
  const config = createConfig({
160
201
  visualizationType: 'Line',
@@ -0,0 +1,26 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import getStackedSeriesMax from '../getStackedSeriesMax'
3
+
4
+ describe('getStackedSeriesMax', () => {
5
+ it('uses the tallest row sum instead of summing independent series maxima', () => {
6
+ const data = [
7
+ { apples: 400, oranges: 10 },
8
+ { apples: 50, oranges: 300 }
9
+ ]
10
+
11
+ expect(getStackedSeriesMax(data, ['apples', 'oranges'])).toBe(410)
12
+ })
13
+
14
+ it('accepts series objects and dynamic category original data keys', () => {
15
+ const data = [
16
+ { apples: 125, oranges: 75, dynamicFruit: 999 },
17
+ { apples: 10, oranges: 50, dynamicFruit: 999 }
18
+ ]
19
+ const series = [
20
+ { dataKey: 'apples' },
21
+ { dataKey: 'dynamicFruit', originalDataKey: 'oranges', dynamicCategory: true }
22
+ ]
23
+
24
+ expect(getStackedSeriesMax(data, series)).toBe(200)
25
+ })
26
+ })
@@ -1,37 +1,55 @@
1
- import { handleRankByValue } from '../handleRankByValue'
2
- import { ChartConfig } from '../../types/ChartConfig'
3
-
4
- describe('handleRankByValue', () => {
5
- it('should sort the data in ascending order when rankByValue is "asc"', () => {
6
- const data = [{ value: 3 }, { value: 1 }, { value: 2 }]
7
- const config: ChartConfig = {
8
- rankByValue: 'asc',
9
- series: [{ dataKey: 'value' }]
10
- }
11
-
12
- const result = handleRankByValue(data, config)
13
- expect(result).toEqual([{ value: 1 }, { value: 2 }, { value: 3 }])
14
- })
15
-
16
- it('should sort the data in descending order when rankByValue is "desc"', () => {
17
- const data = [{ value: 3 }, { value: 1 }, { value: 2 }]
18
- const config: ChartConfig = {
19
- rankByValue: 'desc',
20
- series: [{ dataKey: 'value' }]
21
- }
22
-
23
- const result = handleRankByValue(data, config)
24
- expect(result).toEqual([{ value: 3 }, { value: 2 }, { value: 1 }])
25
- })
26
-
27
- it('should handle numeric strings correctly', () => {
28
- const data = [{ value: '3' }, { value: '1' }, { value: '2' }]
29
- const config: ChartConfig = {
30
- rankByValue: 'asc',
31
- series: [{ dataKey: 'value' }]
32
- }
33
-
34
- const result = handleRankByValue(data, config)
35
- expect(result).toEqual([{ value: '1' }, { value: '2' }, { value: '3' }])
36
- })
37
- })
1
+ import { handleRankByValue } from '../handleRankByValue'
2
+ import { ChartConfig } from '../../types/ChartConfig'
3
+
4
+ describe('handleRankByValue', () => {
5
+ it('should sort the data in ascending order when rankByValue is "asc"', () => {
6
+ const data = [{ value: 3 }, { value: 1 }, { value: 2 }]
7
+ const originalData = [...data]
8
+ const config: ChartConfig = {
9
+ rankByValue: 'asc',
10
+ series: [{ dataKey: 'value' }]
11
+ }
12
+
13
+ const result = handleRankByValue(data, config)
14
+ expect(result).toEqual([{ value: 1 }, { value: 2 }, { value: 3 }])
15
+ expect(result).not.toBe(data)
16
+ expect(data).toEqual(originalData)
17
+ })
18
+
19
+ it('should sort the data in descending order when rankByValue is "desc"', () => {
20
+ const data = [{ value: 3 }, { value: 1 }, { value: 2 }]
21
+ const originalData = [...data]
22
+ const config: ChartConfig = {
23
+ rankByValue: 'desc',
24
+ series: [{ dataKey: 'value' }]
25
+ }
26
+
27
+ const result = handleRankByValue(data, config)
28
+ expect(result).toEqual([{ value: 3 }, { value: 2 }, { value: 1 }])
29
+ expect(result).not.toBe(data)
30
+ expect(data).toEqual(originalData)
31
+ })
32
+
33
+ it('should handle numeric strings correctly', () => {
34
+ const data = [{ value: '3' }, { value: '1' }, { value: '2' }]
35
+ const config: ChartConfig = {
36
+ rankByValue: 'asc',
37
+ series: [{ dataKey: 'value' }]
38
+ }
39
+
40
+ const result = handleRankByValue(data, config)
41
+ expect(result).toEqual([{ value: '1' }, { value: '2' }, { value: '3' }])
42
+ })
43
+
44
+ it('should return the original data reference when rankByValue is not set', () => {
45
+ const data = [{ value: 3 }, { value: 1 }, { value: 2 }]
46
+ const config: ChartConfig = {
47
+ rankByValue: undefined,
48
+ series: [{ dataKey: 'value' }]
49
+ }
50
+
51
+ const result = handleRankByValue(data, config)
52
+ expect(result).toBe(data)
53
+ expect(result).toEqual([{ value: 3 }, { value: 1 }, { value: 2 }])
54
+ })
55
+ })