@cdc/chart 4.26.4 → 4.26.6

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 (141) hide show
  1. package/CONFIG.md +353 -29
  2. package/LICENSE +201 -0
  3. package/dist/{cdcchart-DQ00cQCm.es.js → cdcchart-BWVIUcAF.es.js} +5 -55
  4. package/dist/cdcchart.js +37885 -35117
  5. package/examples/feature/heatmap/average-age-categorical.json +313 -0
  6. package/examples/feature/heatmap/calendar-heatmap.json +134 -0
  7. package/examples/feature/heatmap/cell-values-bottom-axis.json +181 -0
  8. package/examples/feature/heatmap/sparse-aggregation.json +158 -0
  9. package/examples/private/bad-y-axis.json +543 -0
  10. package/examples/private/bar-chart-negative-value.json +455 -0
  11. package/examples/private/bump-chart.json +1116 -0
  12. package/examples/private/test-123.json +624 -0
  13. package/package.json +4 -3
  14. package/src/CdcChart.tsx +5 -4
  15. package/src/CdcChartComponent.tsx +166 -62
  16. package/src/_stories/Chart.AltText.stories.tsx +136 -0
  17. package/src/_stories/Chart.HeatMap.stories.tsx +187 -0
  18. package/src/_stories/Chart.Sankey.smoke.stories.tsx +62 -0
  19. package/src/_stories/Chart.SeriesColorAssignments.stories.tsx +183 -0
  20. package/src/_stories/Chart.SmallMultiples.smoke.stories.tsx +29 -0
  21. package/src/_stories/Chart.YAxisAutoMaxStrategy.stories.tsx +52 -0
  22. package/src/_stories/Chart.YAxisFilterDomain.stories.tsx +90 -0
  23. package/src/_stories/ChartAnnotation.smoke.stories.tsx +10 -0
  24. package/src/_stories/ChartAxisTitles.smoke.stories.tsx +13 -0
  25. package/src/_stories/ChartBar.Editor.stories.tsx +63 -0
  26. package/src/_stories/ChartBrush.Interaction.stories.tsx +112 -0
  27. package/src/_stories/ChartBrush.smoke.stories.tsx +13 -4
  28. package/src/_stories/_mock/alt_text_metadata.json +38 -0
  29. package/src/_stories/_mock/annotation_event-line_mock.json +1064 -0
  30. package/src/_stories/_mock/heatmap-average-age-categorical.json +315 -0
  31. package/src/_stories/_mock/heatmap.json +156 -0
  32. package/src/_stories/_mock/reported_pertussis_cases.json +1643 -0
  33. package/src/_stories/_mock/sankey_mock.json +78 -0
  34. package/src/_stories/_mock/small_multiples/small_multiples_lines.json +1 -1
  35. package/src/components/Annotations/components/AnnotationDraggable.styles.css +22 -1
  36. package/src/components/Annotations/components/AnnotationDraggable.tsx +220 -120
  37. package/src/components/Annotations/components/AnnotationDropdown.tsx +5 -2
  38. package/src/components/Annotations/tests/AnnotationDraggable.test.tsx +198 -0
  39. package/src/components/Axis/LeftAxis.tsx +17 -11
  40. package/src/components/Axis/LeftAxisGridlines.tsx +22 -12
  41. package/src/components/Axis/RightAxis.tsx +3 -0
  42. package/src/components/Axis/tests/AxisTickValues.test.tsx +86 -0
  43. package/src/components/Brush/BrushSelector.tsx +88 -187
  44. package/src/components/Brush/brushInteraction.ts +22 -0
  45. package/src/components/Brush/tests/brushInteraction.test.ts +38 -0
  46. package/src/components/EditorPanel/EditorPanel.tsx +677 -185
  47. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +114 -52
  48. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +105 -13
  49. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +1 -0
  50. package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +5 -0
  51. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +2 -2
  52. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.test.tsx +98 -0
  53. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +10 -0
  54. package/src/components/EditorPanel/components/Panels/Panel.Visual.test.tsx +484 -0
  55. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +4 -1
  56. package/src/components/EditorPanel/components/Panels/SeriesColorAssignments.tsx +262 -0
  57. package/src/components/EditorPanel/components/Panels/panelVisual.styles.css +32 -0
  58. package/src/components/EditorPanel/components/panels.scss +10 -0
  59. package/src/components/EditorPanel/editor-panel.scss +47 -0
  60. package/src/components/EditorPanel/helpers/getVisualizationTypeConfigUpdate.ts +61 -0
  61. package/src/components/EditorPanel/helpers/tests/getVisualizationTypeConfigUpdate.test.ts +74 -0
  62. package/src/components/EditorPanel/useEditorPermissions.test.tsx +315 -0
  63. package/src/components/EditorPanel/useEditorPermissions.ts +77 -21
  64. package/src/components/HeatMap/components/HeatMap.tsx +767 -0
  65. package/src/components/HeatMap/components/HeatMapGradientLegend.tsx +128 -0
  66. package/src/components/HeatMap/heatmap.constants.ts +13 -0
  67. package/src/components/HeatMap/heatmap.css +85 -0
  68. package/src/components/HeatMap/helpers/index.ts +261 -0
  69. package/src/components/HeatMap/index.tsx +5 -0
  70. package/src/components/HeatMap/tests/HeatMap.test.tsx +1072 -0
  71. package/src/components/HeatMap/tests/helpers.test.ts +167 -0
  72. package/src/components/Legend/Legend.Component.tsx +2 -2
  73. package/src/components/Legend/helpers/createFormatLabels.test.ts +88 -0
  74. package/src/components/Legend/helpers/createFormatLabels.tsx +6 -1
  75. package/src/components/LineChart/components/LineChart.BumpCircle.tsx +19 -22
  76. package/src/components/LineChart/helpers.test.ts +574 -0
  77. package/src/components/LineChart/helpers.ts +39 -16
  78. package/src/components/LineChart/index.tsx +28 -5
  79. package/src/components/LinearChart/tests/LinearChart.test.tsx +137 -33
  80. package/src/components/LinearChart/tests/mockConfigContext.ts +1 -0
  81. package/src/components/LinearChart.tsx +103 -47
  82. package/src/components/PieChart/PieChart.tsx +4 -1
  83. package/src/components/RadarChart/RadarChart.tsx +3 -1
  84. package/src/components/Regions/components/Regions.tsx +195 -41
  85. package/src/components/Sankey/components/Sankey.tsx +7 -3
  86. package/src/components/Sankey/helpers/getSankeyTooltip.tsx +7 -6
  87. package/src/components/ScatterPlot/ScatterPlot.jsx +3 -3
  88. package/src/components/SmallMultiples/SmallMultipleTile.tsx +33 -3
  89. package/src/components/SmallMultiples/SmallMultiples.css +12 -0
  90. package/src/components/SmallMultiples/SmallMultiples.tsx +50 -15
  91. package/src/components/SmallMultiples/tests/SmallMultipleTile.test.tsx +152 -0
  92. package/src/components/SmallMultiples/tests/SmallMultiples.test.tsx +170 -0
  93. package/src/components/Sparkline/components/SparkLine.tsx +4 -9
  94. package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +1 -1
  95. package/src/components/WarmingStripes/WarmingStripesGradientLegend.tsx +2 -2
  96. package/src/data/initial-state.js +12 -0
  97. package/src/helpers/axisLabelFontSize.ts +8 -0
  98. package/src/helpers/bumpChartTooltip.ts +54 -0
  99. package/src/helpers/calculateLeftYAxisWidth.ts +13 -3
  100. package/src/helpers/colorAssignmentHelpers.ts +102 -0
  101. package/src/helpers/dataHelpers.ts +11 -1
  102. package/src/helpers/ensureSpecialChartAxisTypes.ts +11 -0
  103. package/src/helpers/getAxisMaxOverride.ts +16 -0
  104. package/src/helpers/getCleanTopTickMax.ts +64 -0
  105. package/src/helpers/getColorScale.ts +18 -9
  106. package/src/helpers/getHasBoundarySuppression.ts +26 -0
  107. package/src/helpers/getMinMax.ts +26 -25
  108. package/src/helpers/getYAxisDomainData.ts +38 -0
  109. package/src/helpers/getYAxisFinalizationEligibility.ts +40 -0
  110. package/src/helpers/handleChartAriaLabels.ts +23 -10
  111. package/src/helpers/hasSpacedInlineLabel.ts +10 -0
  112. package/src/helpers/seriesColumnSettings.ts +5 -4
  113. package/src/helpers/seriesHighlight.ts +26 -0
  114. package/src/helpers/smallMultiplesHelpers.ts +5 -0
  115. package/src/helpers/tests/axisLabelFontSize.test.ts +15 -0
  116. package/src/helpers/tests/bumpChartTooltip.test.ts +75 -0
  117. package/src/helpers/tests/calculateLeftYAxisWidth.test.ts +38 -0
  118. package/src/helpers/tests/dataHelpers.test.ts +135 -0
  119. package/src/helpers/tests/ensureSpecialChartAxisTypes.test.ts +30 -0
  120. package/src/helpers/tests/getAxisMaxOverride.test.ts +36 -0
  121. package/src/helpers/tests/getCleanTopTickMax.test.ts +165 -0
  122. package/src/helpers/tests/getColorScale.test.ts +197 -0
  123. package/src/helpers/tests/getMinMax.test.ts +211 -0
  124. package/src/helpers/tests/getYAxisDomainData.test.ts +119 -0
  125. package/src/helpers/tests/getYAxisFinalizationEligibility.test.ts +185 -0
  126. package/src/helpers/tests/handleChartAriaLabels.test.ts +71 -0
  127. package/src/helpers/tests/hasSpacedInlineLabel.test.ts +75 -0
  128. package/src/helpers/tests/seriesColumnSettings.test.ts +16 -2
  129. package/src/helpers/tests/seriesHighlight.test.ts +61 -0
  130. package/src/helpers/tests/smallMultiplesHelpers.test.ts +99 -0
  131. package/src/hooks/tests/useRightAxis.test.tsx +127 -0
  132. package/src/hooks/tests/useScales.test.tsx +383 -0
  133. package/src/hooks/useRightAxis.ts +30 -13
  134. package/src/hooks/useScales.ts +48 -21
  135. package/src/hooks/useTooltip.tsx +3 -1
  136. package/src/index.jsx +5 -2
  137. package/src/scss/main.scss +32 -49
  138. package/src/test/CdcChart.dataTable.test.tsx +122 -0
  139. package/src/types/ChartConfig.ts +24 -1
  140. package/src/types/ChartContext.ts +5 -0
  141. package/src/helpers/getYAxisAutoPadding.ts +0 -53
@@ -0,0 +1,167 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ buildHeatMapData,
4
+ getHeatMapBucketPalette,
5
+ getHeatMapColorBucketCount,
6
+ getHeatMapColorScale,
7
+ getHeatMapDataGroupRanges
8
+ } from '../helpers'
9
+ import { type ChartConfig } from '../../../types/ChartConfig'
10
+
11
+ describe('buildHeatMapData', () => {
12
+ it('aggregates duplicate x/series cells using numeric sum', () => {
13
+ const { columns, minValue, maxValue } = buildHeatMapData({
14
+ data: [
15
+ { month: 'Jan', Austin: 2, Boston: 4 },
16
+ { month: 'Jan', Austin: 3, Boston: 0 }
17
+ ],
18
+ xDataKey: 'month',
19
+ series: [
20
+ { dataKey: 'Austin', name: 'Austin' },
21
+ { dataKey: 'Boston', name: 'Boston' }
22
+ ],
23
+ xAxisType: 'categorical'
24
+ })
25
+
26
+ expect(columns).toHaveLength(1)
27
+ expect(columns[0].bins[0].value).toBe(5)
28
+ expect(columns[0].bins[0].sourceRows).toHaveLength(2)
29
+ expect(columns[0].bins[1].value).toBe(4)
30
+ expect(minValue).toBe(4)
31
+ expect(maxValue).toBe(5)
32
+ })
33
+
34
+ it('orders date-based x values in ascending order', () => {
35
+ const { columns } = buildHeatMapData({
36
+ data: [
37
+ { date: '2024-03-01', Austin: 1 },
38
+ { date: '2024-01-01', Austin: 2 },
39
+ { date: '2024-02-01', Austin: 3 }
40
+ ],
41
+ xDataKey: 'date',
42
+ series: [{ dataKey: 'Austin', name: 'Austin' }],
43
+ xAxisType: 'date'
44
+ })
45
+
46
+ expect(columns.map(column => column.key)).toEqual(['2024-01-01', '2024-02-01', '2024-03-01'])
47
+ })
48
+
49
+ it('creates empty cells for missing x/series combinations', () => {
50
+ const { columns, rowLabels } = buildHeatMapData({
51
+ data: [
52
+ { month: 'Jan', Austin: 5 },
53
+ { month: 'Feb', Boston: 4 }
54
+ ],
55
+ xDataKey: 'month',
56
+ series: [
57
+ { dataKey: 'Austin', name: 'Austin' },
58
+ { dataKey: 'Boston', name: 'Boston' }
59
+ ],
60
+ xAxisType: 'categorical'
61
+ })
62
+
63
+ expect(rowLabels).toEqual(['Austin', 'Boston'])
64
+ expect(columns).toHaveLength(2)
65
+ expect(columns[0].bins[1].value).toBeNull()
66
+ expect(columns[1].bins[0].value).toBeNull()
67
+ })
68
+
69
+ it('builds series-driven rows when data series are provided', () => {
70
+ const { columns, rowLabels, minValue, maxValue } = buildHeatMapData({
71
+ data: [
72
+ { month: 'Jan', Austin: 12, Boston: 30 },
73
+ { month: 'Feb', Austin: 18, Boston: 40 }
74
+ ],
75
+ xDataKey: 'month',
76
+ series: [
77
+ { dataKey: 'Austin', name: 'Austin' },
78
+ { dataKey: 'Boston', name: 'Boston' }
79
+ ],
80
+ seriesLabels: { Austin: 'Austin', Boston: 'Boston' },
81
+ xAxisType: 'categorical'
82
+ })
83
+
84
+ expect(rowLabels).toEqual(['Austin', 'Boston'])
85
+ expect(columns).toHaveLength(2)
86
+ expect(columns[0].bins[0].value).toBe(12)
87
+ expect(columns[0].bins[1].value).toBe(30)
88
+ expect(columns[1].bins[0].value).toBe(18)
89
+ expect(columns[1].bins[1].value).toBe(40)
90
+ expect(minValue).toBe(12)
91
+ expect(maxValue).toBe(40)
92
+ })
93
+
94
+ it('keeps non-calendar categories in source order for average age by city', () => {
95
+ const { columns, rowLabels, minValue, maxValue } = buildHeatMapData({
96
+ data: [
97
+ { communityType: 'Urban Core', Atlanta: 34, Chicago: 36, Phoenix: 38 },
98
+ { communityType: 'Suburban', Atlanta: 41, Chicago: 39, Phoenix: 42 },
99
+ { communityType: 'Rural', Atlanta: 46, Chicago: 44, Phoenix: 49 }
100
+ ],
101
+ xDataKey: 'communityType',
102
+ series: [
103
+ { dataKey: 'Atlanta', name: 'Atlanta' },
104
+ { dataKey: 'Chicago', name: 'Chicago' },
105
+ { dataKey: 'Phoenix', name: 'Phoenix' }
106
+ ],
107
+ xAxisType: 'categorical'
108
+ })
109
+
110
+ expect(columns.map(column => column.key)).toEqual(['Urban Core', 'Suburban', 'Rural'])
111
+ expect(rowLabels).toEqual(['Atlanta', 'Chicago', 'Phoenix'])
112
+ expect(columns[0].bins.map(bin => bin.value)).toEqual([34, 36, 38])
113
+ expect(columns[2].bins[2].value).toBe(49)
114
+ expect(minValue).toBe(34)
115
+ expect(maxValue).toBe(49)
116
+ })
117
+ })
118
+
119
+ describe('HeatMap data grouping', () => {
120
+ const buildPaletteConfig = (colorBucketCount?: unknown) =>
121
+ ({
122
+ general: {
123
+ palette: {
124
+ customColors: ['#000000', '#ffffff']
125
+ }
126
+ },
127
+ heatmap: {
128
+ colorBucketCount
129
+ }
130
+ } as ChartConfig)
131
+
132
+ it('clamps HeatMap data grouping to the supported range', () => {
133
+ expect(getHeatMapColorBucketCount(buildPaletteConfig(undefined))).toBe(9)
134
+ expect(getHeatMapColorBucketCount(buildPaletteConfig(0))).toBe(1)
135
+ expect(getHeatMapColorBucketCount(buildPaletteConfig(-4))).toBe(1)
136
+ expect(getHeatMapColorBucketCount(buildPaletteConfig(12))).toBe(9)
137
+ })
138
+
139
+ it('supports one bucket as the minimum heatmap color count', () => {
140
+ const colorScale = getHeatMapColorScale(buildPaletteConfig(1), 0, 100)
141
+
142
+ expect(getHeatMapBucketPalette(buildPaletteConfig(1))).toHaveLength(1)
143
+ expect(colorScale(1)).toBe(colorScale(99))
144
+ })
145
+
146
+ it('uses the configured number of data groups for heatmap cell colors', () => {
147
+ const colorScale = getHeatMapColorScale(buildPaletteConfig(5), 0, 100)
148
+ const bucketColors = [0, 20, 40, 60, 80].map(value => colorScale(value))
149
+
150
+ expect(getHeatMapColorBucketCount(buildPaletteConfig(5))).toBe(5)
151
+ expect(getHeatMapBucketPalette(buildPaletteConfig(5))).toHaveLength(5)
152
+ expect(new Set(bucketColors)).toHaveLength(5)
153
+ expect(colorScale(1)).toBe(colorScale(19))
154
+ })
155
+
156
+ it('builds data group legend ranges from the heatmap grouping domain', () => {
157
+ const ranges = getHeatMapDataGroupRanges(buildPaletteConfig(5), 0, 1, value => value.toFixed(1))
158
+
159
+ expect(ranges.map(range => range.label)).toEqual([
160
+ '0.0\u20130.2',
161
+ '0.2\u20130.4',
162
+ '0.4\u20130.6',
163
+ '0.6\u20130.8',
164
+ '0.8\u20131.0'
165
+ ])
166
+ })
167
+ })
@@ -242,7 +242,7 @@ const Legend: React.FC<LegendProps> = forwardRef(
242
242
  </>
243
243
  )}
244
244
  </>
245
- <LegendLabel align='left' className='m-0 cove-prose'>
245
+ <LegendLabel align='left' className='m-0'>
246
246
  {parse(label.text)}
247
247
  </LegendLabel>
248
248
  </LegendItem>
@@ -361,7 +361,7 @@ const Legend: React.FC<LegendProps> = forwardRef(
361
361
  />
362
362
  </svg>
363
363
  </span>
364
- <LegendLabel align='left' className='m-0 cove-prose'>
364
+ <LegendLabel align='left' className='m-0'>
365
365
  {parse(String((pattern as any)?.label || key))}
366
366
  </LegendLabel>
367
367
  </LegendItem>
@@ -0,0 +1,88 @@
1
+ import { scaleOrdinal } from '@visx/scale'
2
+ import { describe, expect, it, vi } from 'vitest'
3
+ import { createFormatLabels } from './createFormatLabels'
4
+ import { ChartConfig } from '../../../types/ChartConfig'
5
+ import { Label } from '../../../types/Label'
6
+
7
+ const defaultLabels: Label[] = [
8
+ { datum: 'Series A', index: 0, text: 'Series A', value: '#aa0000' },
9
+ { datum: 'Series B', index: 1, text: 'Series B', value: '#00bb00' }
10
+ ]
11
+
12
+ const buildConfig = (overrides: Partial<ChartConfig> = {}): ChartConfig =>
13
+ ({
14
+ visualizationType: 'Line',
15
+ visualizationSubType: 'regular',
16
+ general: {
17
+ palette: {
18
+ colorAssignmentMode: 'ordered'
19
+ }
20
+ },
21
+ legend: {},
22
+ smallMultiples: {
23
+ mode: 'by-series',
24
+ colorMode: 'same'
25
+ },
26
+ series: [
27
+ { dataKey: 'series_a', name: 'Series A', type: 'Line' },
28
+ { dataKey: 'series_b', name: 'Series B', type: 'Line' }
29
+ ],
30
+ runtime: {
31
+ seriesKeys: ['series_a', 'series_b'],
32
+ seriesLabels: {
33
+ series_a: 'Series A',
34
+ series_b: 'Series B'
35
+ },
36
+ seriesLabelsAll: ['Series A', 'Series B']
37
+ },
38
+ ...overrides
39
+ } as ChartConfig)
40
+
41
+ const colorScale = scaleOrdinal({
42
+ domain: ['Series A', 'Series B'],
43
+ range: ['#aa0000', '#00bb00'],
44
+ unknown: null
45
+ })
46
+
47
+ const formatLabels = (config: ChartConfig) => createFormatLabels(config, [], [], colorScale, vi.fn())(defaultLabels)
48
+
49
+ describe('createFormatLabels small multiples legend colors', () => {
50
+ it('uses the first color for by-series same-color legends by default', () => {
51
+ const labels = formatLabels(buildConfig())
52
+
53
+ expect(labels.map(label => label.value)).toEqual(['#aa0000', '#aa0000'])
54
+ })
55
+
56
+ it('preserves assigned series colors for by-series same-color legends', () => {
57
+ const labels = formatLabels(
58
+ buildConfig({
59
+ general: {
60
+ palette: {
61
+ colorAssignmentMode: 'by-value',
62
+ colorAssignments: [
63
+ { key: 'series_a', color: '#aa0000' },
64
+ { key: 'series_b', color: '#00bb00' }
65
+ ]
66
+ }
67
+ } as any
68
+ })
69
+ )
70
+
71
+ expect(labels.map(label => label.value)).toEqual(['#aa0000', '#00bb00'])
72
+ })
73
+
74
+ it('ignores stale assignments for by-series same-color legends', () => {
75
+ const labels = formatLabels(
76
+ buildConfig({
77
+ general: {
78
+ palette: {
79
+ colorAssignmentMode: 'by-value',
80
+ colorAssignments: [{ key: 'removed_series', color: '#00bb00' }]
81
+ }
82
+ } as any
83
+ })
84
+ )
85
+
86
+ expect(labels.map(label => label.value)).toEqual(['#aa0000', '#aa0000'])
87
+ })
88
+ })
@@ -13,6 +13,7 @@ import { v2ColorDistribution } from '@cdc/core/helpers/palettes/colorDistributio
13
13
  import { updatePaletteNames } from '@cdc/core/helpers/updatePaletteNames'
14
14
  import { buildForecastPaletteMappings } from '../../../helpers/buildForecastPaletteMappings'
15
15
  import { getFullColorPalette } from '../../../helpers/smallMultiplesHelpers'
16
+ import { hasSeriesColorAssignmentOverrides } from '../../../helpers/colorAssignmentHelpers'
16
17
  import { FaStar } from 'react-icons/fa'
17
18
  import { Label } from '../../../types/Label'
18
19
  import { ColorScale, TransformedData } from '../../../types/ChartContext'
@@ -36,7 +37,11 @@ export const createFormatLabels =
36
37
 
37
38
  // Handle small multiples legend adjustments
38
39
  // by-series + same: all tiles use same color, legend should show one color
39
- if (config.smallMultiples?.mode === 'by-series' && config.smallMultiples?.colorMode === 'same') {
40
+ if (
41
+ config.smallMultiples?.mode === 'by-series' &&
42
+ config.smallMultiples?.colorMode === 'same' &&
43
+ !hasSeriesColorAssignmentOverrides(config)
44
+ ) {
40
45
  const baseColor = colorScale?.range()?.[0]
41
46
  return defaultLabels.map((label, i) => ({
42
47
  ...label,
@@ -1,9 +1,11 @@
1
- import { useState } from 'react'
1
+ import { useContext } from 'react'
2
2
  import { Group } from '@visx/group'
3
- import { type Column } from '@cdc/core/types/Column'
4
3
  import React from 'react'
5
4
  import { type ChartConfig } from '../../../types/ChartConfig'
6
5
  import { APP_FONT_COLOR } from '@cdc/core/helpers/constants'
6
+ import ConfigContext from '../../../ConfigContext'
7
+ import { isDateScale } from '@cdc/core/helpers/cove/date'
8
+ import { buildBumpChartTooltipHtml } from '../../../helpers/bumpChartTooltip'
7
9
 
8
10
  type LineChartBumpCircleProp = {
9
11
  config: ChartConfig
@@ -15,17 +17,15 @@ type LineChartBumpCircleProp = {
15
17
 
16
18
  const LineChartBumpCircle = (props: LineChartBumpCircleProp) => {
17
19
  const { config, xScale, yScale, parseDate, yAxisWidth } = props
20
+ const { colorScale, formatDate, formatTooltipsDate } = useContext(ConfigContext)
18
21
 
19
22
  // get xScale and yScale...
20
23
  if (!config?.runtime?.series) return
21
24
 
22
25
  const handleX = xValue => {
23
- if (config.xAxis.type === 'date') {
26
+ if (isDateScale(config.xAxis)) {
24
27
  return parseDate(xValue).getTime()
25
28
  }
26
- if (config.xAxis.type === 'date-time') {
27
- return new Date(xValue)
28
- }
29
29
  if (config.xAxis.type === 'categorical') {
30
30
  return xValue
31
31
  }
@@ -35,20 +35,7 @@ const LineChartBumpCircle = (props: LineChartBumpCircleProp) => {
35
35
  return xScale.bandwidth ? xScale.bandwidth() / 2 + Number(xValue) : Number(xValue)
36
36
  }
37
37
 
38
- const getListItems = dataRow => {
39
- return Object.values(config.columns)
40
- ?.filter(column => column.tooltips)
41
- .map(column => {
42
- const label = column.label || column.name
43
- return `
44
- <li className='tooltip-body'>
45
- <strong>${label}</strong>: ${dataRow[column.name]}
46
- </li>`
47
- })
48
- .join(' ')
49
- }
50
-
51
- const getTooltip = dataRow => `<ul> ${getListItems(dataRow)} </ul>`
38
+ const tooltipId = `cdc-open-viz-tooltip-${config.runtime.uniqueId}-bump`
52
39
 
53
40
  const circles = config.runtime?.series.map(series => {
54
41
  return config.data.map((d, dataIndex) => {
@@ -61,8 +48,18 @@ const LineChartBumpCircle = (props: LineChartBumpCircleProp) => {
61
48
  <>
62
49
  <circle
63
50
  key={`bump-circle-${series_dataKey}-${dataIndex}`}
64
- data-tooltip-html={getTooltip(d)}
65
- data-tooltip-id={`bump-chart`}
51
+ data-tooltip-html={buildBumpChartTooltipHtml({
52
+ config,
53
+ colorScale,
54
+ dataRow: d,
55
+ series,
56
+ helpers: {
57
+ formatDate,
58
+ formatTooltipsDate,
59
+ parseDate
60
+ }
61
+ })}
62
+ data-tooltip-id={tooltipId}
66
63
  r={10}
67
64
  cx={Number(checkBandScale(xScale(handleX(axis_dataKey))))}
68
65
  cy={Number(yScale(series_dataKey))}