@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
@@ -1,5 +1,6 @@
1
1
  @import '@cdc/core/styles/utils/breakpoints';
2
2
  @import '@cdc/core/styles/layout/wrapper-padding';
3
+ @import '@cdc/core/styles/layout/callout';
3
4
 
4
5
  .form-container {
5
6
  overflow-y: auto;
@@ -24,33 +25,17 @@
24
25
  background: transparent;
25
26
 
26
27
  .cdc-callout {
27
- box-shadow: 0 2px 4px rgb(159 159 159 / 10%);
28
- border: 1px solid #dff2f6;
29
- margin: 0;
30
- padding: 1.25rem;
31
- border-radius: 0.25rem;
32
- position: relative;
33
- background: transparent;
34
-
35
- .cdc-callout__flag {
36
- position: absolute;
37
- top: -0.36rem;
38
- right: 1.08rem;
39
- width: 1.84rem;
40
- height: auto;
41
- }
28
+ --cdc-callout-background: transparent;
42
29
 
43
30
  .cove-visualization__title,
44
31
  .cove-visualization__header {
45
32
  background: transparent;
46
33
  border: 0;
47
- color: var(--cool-gray-90, #1f2937);
48
34
  margin: 0 0 1rem;
49
35
  padding: 0;
50
36
  border-radius: 0;
51
37
 
52
38
  h2 {
53
- color: var(--cool-gray-90, #1f2937);
54
39
  font-family: var(--fonts-nunito, var(--app-font-secondary));
55
40
  font-size: 1.1rem;
56
41
  font-weight: 700;
@@ -64,11 +49,17 @@
64
49
  margin-bottom: 0 !important;
65
50
  }
66
51
 
52
+ .y-axis-top-title {
53
+ font-family: var(--fonts-nunito, var(--app-font-secondary));
54
+ font-weight: 700;
55
+ line-height: 1.4;
56
+ margin: 0 0 0.5rem;
57
+ }
58
+
67
59
  .legend-top {
68
60
  .legend-wrapper .tooltip-boundary {
69
61
  display: flex;
70
62
  flex-wrap: wrap;
71
- row-gap: var(--cove-visualization-section-gap, 1.5rem);
72
63
  order: 2;
73
64
 
74
65
  aside {
@@ -188,7 +179,7 @@
188
179
  white-space: nowrap;
189
180
  }
190
181
 
191
- .legend-item>.legend-item {
182
+ .legend-item > .legend-item {
192
183
  display: inline-block;
193
184
  flex: 0 0 auto;
194
185
  }
@@ -222,11 +213,11 @@
222
213
  left: 0%;
223
214
  top: 108%;
224
215
 
225
- &>* {
216
+ & > * {
226
217
  margin: 0;
227
218
  }
228
219
 
229
- &>p,
220
+ & > p,
230
221
  a {
231
222
  margin-left: 5px;
232
223
  }
@@ -235,7 +226,6 @@
235
226
  }
236
227
 
237
228
  .dynamic-legend-list {
238
-
239
229
  // overide traditional legend item that uses !important
240
230
  .legend-item {
241
231
  align-items: flex-end !important;
@@ -268,7 +258,7 @@
268
258
  font-size: 1em;
269
259
  vertical-align: middle;
270
260
 
271
- &>span {
261
+ & > span {
272
262
  display: flex;
273
263
  justify-items: center;
274
264
  align-items: center;
@@ -278,25 +268,25 @@
278
268
  max-height: 1px;
279
269
  }
280
270
 
281
- &>span[class*='Asterisk'] {
271
+ & > span[class*='Asterisk'] {
282
272
  transform: scale(1.8);
283
273
  margin-top: 15px;
284
274
  }
285
275
 
286
- &>span[class*='Dagger'] {
276
+ & > span[class*='Dagger'] {
287
277
  margin-top: 2px;
288
278
  }
289
279
 
290
- &>span[class*='Sign'] {
280
+ & > span[class*='Sign'] {
291
281
  margin-top: 1px;
292
282
  }
293
283
 
294
- &>svg {
284
+ & > svg {
295
285
  width: 50px;
296
286
  height: 23px;
297
287
  }
298
288
 
299
- &>p {
289
+ & > p {
300
290
  margin: 0;
301
291
  }
302
292
  }
@@ -325,8 +315,8 @@
325
315
  min-width: 0;
326
316
  max-width: 100%;
327
317
 
328
- >div,
329
- >aside {
318
+ > div,
319
+ > aside {
330
320
  min-width: 0;
331
321
  max-width: 100%;
332
322
  }
@@ -339,7 +329,7 @@
339
329
 
340
330
  &.legend-top:not(.legend-hidden) {
341
331
  .legend-wrapper {
342
- &>div {
332
+ & > div {
343
333
  order: 2;
344
334
  width: 100%;
345
335
  }
@@ -354,7 +344,7 @@
354
344
 
355
345
  &.legend-left:not(.legend-hidden) {
356
346
  .legend-wrapper {
357
- &>div {
347
+ & > div {
358
348
  order: 2;
359
349
  width: 75%;
360
350
  }
@@ -369,7 +359,7 @@
369
359
 
370
360
  &.legend-right:not(.legend-hidden) {
371
361
  .legend-wrapper {
372
- &>div {
362
+ & > div {
373
363
  order: 1;
374
364
  width: 75%;
375
365
  }
@@ -391,7 +381,7 @@
391
381
  flex-wrap: nowrap;
392
382
  flex-direction: column-reverse;
393
383
 
394
- &>div.tooltip-boundary {
384
+ & > div.tooltip-boundary {
395
385
  margin-top: 1.5em;
396
386
  }
397
387
  }
@@ -401,14 +391,10 @@
401
391
  flex-direction: column;
402
392
  }
403
393
 
404
- &.legend-hidden>svg {
394
+ &.legend-hidden > svg {
405
395
  width: 100% !important;
406
396
  }
407
397
 
408
- &.dashboard-brush {
409
- margin-bottom: 2.5em;
410
- }
411
-
412
398
  // Brush touch support
413
399
  .brush-overlay {
414
400
  touch-action: none;
@@ -434,7 +420,7 @@
434
420
  pointer-events: none;
435
421
  }
436
422
 
437
- >svg {
423
+ > svg {
438
424
  overflow: visible;
439
425
  font-size: 14px;
440
426
  margin: 1rem 0 2rem;
@@ -449,7 +435,7 @@
449
435
  }
450
436
 
451
437
  &.chart-line--hover {
452
- >svg circle {
438
+ > svg circle {
453
439
  opacity: 0;
454
440
 
455
441
  &:hover {
@@ -459,12 +445,12 @@
459
445
  }
460
446
 
461
447
  &.chart-line--always {
462
- >svg circle {
448
+ > svg circle {
463
449
  opacity: 1;
464
450
  }
465
451
 
466
452
  // Animations for line chart and data points
467
- >svg.animated {
453
+ > svg.animated {
468
454
  circle {
469
455
  opacity: 0;
470
456
  animation: revealLolly 0.25s linear forwards;
@@ -525,7 +511,7 @@
525
511
 
526
512
  @include breakpointClass(md) {
527
513
  .visualization-container {
528
- >svg {
514
+ > svg {
529
515
  font-size: 16px;
530
516
  width: 75%;
531
517
  order: 1;
@@ -608,7 +594,6 @@
608
594
  }
609
595
 
610
596
  &.animated {
611
-
612
597
  .vertical path,
613
598
  .vertical rect,
614
599
  .vertical foreignObject div {
@@ -626,7 +611,6 @@
626
611
  }
627
612
 
628
613
  &.animate {
629
-
630
614
  path,
631
615
  rect,
632
616
  foreignObject div {
@@ -685,7 +669,7 @@
685
669
  text-align: center;
686
670
  transform: scale(1);
687
671
 
688
- >.visx-group[style] {
672
+ > .visx-group[style] {
689
673
  transform: scale(1);
690
674
  }
691
675
  }
@@ -707,7 +691,7 @@
707
691
  }
708
692
 
709
693
  .cove-visualization.type-chart.type-sparkline {
710
- &.lg .visualization-container>svg {
694
+ &.lg .visualization-container > svg {
711
695
  width: 100%;
712
696
  }
713
697
 
@@ -738,7 +722,6 @@
738
722
  transform: translate(-20px, 0);
739
723
  }
740
724
  }
741
-
742
725
  }
743
726
 
744
727
  .subtext,
@@ -0,0 +1,122 @@
1
+ import React from 'react'
2
+ import { render, screen, waitFor } from '@testing-library/react'
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
4
+ import CdcChart from '../CdcChartComponent'
5
+
6
+ const dataTableProps = vi.hoisted(() => {
7
+ Object.defineProperty((globalThis as any).HTMLCanvasElement.prototype, 'getContext', {
8
+ configurable: true,
9
+ value: () => ({
10
+ measureText: (text = '') => ({ width: String(text).length * 8 })
11
+ })
12
+ })
13
+
14
+ return [] as any[]
15
+ })
16
+
17
+ vi.mock('@cdc/core/components/DataTable', async () => {
18
+ const React = await vi.importActual<typeof import('react')>('react')
19
+
20
+ return {
21
+ default: props => {
22
+ dataTableProps.push(props)
23
+ return React.createElement('div', { 'data-testid': 'data-table-probe' })
24
+ }
25
+ }
26
+ })
27
+
28
+ vi.mock('@visx/responsive/lib/components/ParentSize', () => ({
29
+ default: ({ children }) => children({ width: 640, height: 360 })
30
+ }))
31
+
32
+ vi.mock('../components/LinearChart', async () => {
33
+ const React = await vi.importActual<typeof import('react')>('react')
34
+
35
+ return {
36
+ default: React.forwardRef(() => React.createElement('div', { 'data-testid': 'mock-linear-chart' }))
37
+ }
38
+ })
39
+
40
+ describe('CdcChart data table dataset wiring', () => {
41
+ beforeEach(() => {
42
+ dataTableProps.length = 0
43
+ })
44
+
45
+ it('passes the selected dashboard dataset metadata to DataTable', async () => {
46
+ const dataset = {
47
+ data: [{ category: 'A', value: 1 }],
48
+ dataFileName: 'stale-chart-source.json',
49
+ dataFileSourceType: 'url',
50
+ dataUrl: '/wcms/vizdata/chart-source.json',
51
+ runtimeDataUrl: '/wcms/vizdata/chart-runtime.json'
52
+ }
53
+
54
+ render(
55
+ <CdcChart
56
+ config={
57
+ {
58
+ type: 'chart',
59
+ visualizationType: 'Bar',
60
+ title: 'Dataset-backed Chart',
61
+ dataKey: 'chartDataset',
62
+ data: dataset.data,
63
+ xAxis: { dataKey: 'category' },
64
+ series: [{ dataKey: 'value' }],
65
+ table: {
66
+ show: true,
67
+ expanded: true,
68
+ download: true,
69
+ label: 'Data Table',
70
+ indexLabel: ''
71
+ }
72
+ } as any
73
+ }
74
+ datasets={{ chartDataset: dataset } as any}
75
+ isDashboard={true}
76
+ interactionLabel='chart-dataset-test'
77
+ />
78
+ )
79
+
80
+ await waitFor(() => expect(dataTableProps.length).toBeGreaterThan(0))
81
+
82
+ expect(dataTableProps.at(-1).dataConfig).toMatchObject({
83
+ runtimeDataUrl: '/wcms/vizdata/chart-runtime.json'
84
+ })
85
+ })
86
+
87
+ it('keeps chart footnotes visible when the data table is collapsed by default', async () => {
88
+ render(
89
+ <CdcChart
90
+ config={
91
+ {
92
+ type: 'chart',
93
+ visualizationType: 'Bar',
94
+ title: 'Footnote-backed Chart',
95
+ data: [{ category: 'A', value: 1 }],
96
+ xAxis: { dataKey: 'category' },
97
+ series: [{ dataKey: 'value' }],
98
+ legacyFootnotes: 'Legacy chart footnote',
99
+ footnotes: {
100
+ staticFootnotes: [{ text: 'Structured chart footnote' }]
101
+ },
102
+ table: {
103
+ show: true,
104
+ expanded: false,
105
+ download: true,
106
+ label: 'Data Table',
107
+ indexLabel: ''
108
+ }
109
+ } as any
110
+ }
111
+ interactionLabel='chart-footnote-collapse-test'
112
+ />
113
+ )
114
+
115
+ await waitFor(() => {
116
+ expect(dataTableProps.at(-1)?.expandDataTable).toBe(false)
117
+ })
118
+
119
+ expect(await screen.findByText('Legacy chart footnote')).toBeInTheDocument()
120
+ expect(await screen.findByText('Structured chart footnote')).toBeInTheDocument()
121
+ })
122
+ })
@@ -1,4 +1,4 @@
1
- import { Axis } from '@cdc/core/types/Axis'
1
+ import { type Axis } from '@cdc/core/types/Axis'
2
2
  import { MarkupConfig } from '@cdc/core/types/MarkupVariable'
3
3
  import { type ForestPlotConfigSettings } from './ForestPlot'
4
4
  import { type HorizonConfigSettings } from './Horizon'
@@ -18,6 +18,8 @@ type General = CoreGeneral & {
18
18
  isReversed?: boolean
19
19
  customColors?: string[]
20
20
  customColorsOrdered?: string[]
21
+ colorAssignmentMode?: 'ordered' | 'by-value'
22
+ colorAssignments?: { key: string; color: string }[]
21
23
  }
22
24
  useIntelligentLineChartLabels?: boolean
23
25
  }
@@ -41,6 +43,7 @@ export type VisualizationType =
41
43
  | 'Box Plot'
42
44
  | 'Deviation Bar'
43
45
  | 'Forest Plot'
46
+ | 'HeatMap'
44
47
  | 'Horizon Chart'
45
48
  | 'Line'
46
49
  | 'Paired Bar'
@@ -53,6 +56,18 @@ export type VisualizationType =
53
56
  | 'Sankey'
54
57
  | 'Bump Chart'
55
58
  | 'Warming Stripes'
59
+
60
+ export type HeatMapXAxisPosition = 'top' | 'bottom'
61
+
62
+ export type HeatMapConfig = {
63
+ cellPadding?: number
64
+ rowLabelGap?: number
65
+ columnLabelGap?: number
66
+ colorBucketCount?: number
67
+ xAxisPosition?: HeatMapXAxisPosition
68
+ showCellValues?: boolean
69
+ }
70
+
56
71
  export interface PreliminaryDataItem {
57
72
  column: string
58
73
  displayLegend: boolean
@@ -70,6 +85,7 @@ export interface PreliminaryDataItem {
70
85
  hideLineStyle: boolean
71
86
  circleSize: number
72
87
  displayGray: boolean
88
+ weight?: number
73
89
  }
74
90
 
75
91
  type DataFormat = {
@@ -143,7 +159,11 @@ type Visual = {
143
159
  maximumShapeAmount: 7
144
160
  }
145
161
 
162
+ import { type AltTextConfig } from '@cdc/core/types/AltText'
163
+ export type { AltTextConfig }
164
+
146
165
  export type AllChartsConfig = {
166
+ altText?: AltTextConfig
147
167
  annotations: Annotation[]
148
168
  animate: boolean
149
169
  general: General
@@ -174,6 +194,9 @@ export type AllChartsConfig = {
174
194
  footnotes: Footnotes
175
195
  forestPlot: ForestPlotConfigSettings
176
196
  formattedData: Object[] & { urlFiltered: boolean }
197
+ originalFormattedData?: Object[]
198
+ yAxisDomainData?: Object[]
199
+ heatmap?: HeatMapConfig
177
200
  heights: {
178
201
  vertical: number
179
202
  horizontal: number
@@ -20,6 +20,8 @@ type SharedChartContext = {
20
20
  currentViewport?: 'lg' | 'md' | 'sm' | 'xs' | 'xxs'
21
21
  vizViewport?: 'lg' | 'md' | 'sm' | 'xs' | 'xxs'
22
22
  dashboardConfig?: DashboardConfig
23
+ excludedData?: Object[]
24
+ filteredData?: Object[]
23
25
  // process top level chart aria label for each chart type
24
26
  handleChartAriaLabels: (config: any) => string
25
27
  handleDragStateChange: (isDragging: any) => void
@@ -37,6 +39,7 @@ type SharedChartContext = {
37
39
  svgRef?: React.RefObject<SVGSVGElement>
38
40
  handleSmallMultipleHover?: (xAxisValue: any, yCoordinate: number) => void
39
41
  visibleAnnotations?: Annotation[]
42
+ yAxisTickValues?: number[]
40
43
  }
41
44
 
42
45
  // Line Chart Specific Context
@@ -56,6 +59,7 @@ type LineChartContext = SharedChartContext & {
56
59
  transformedData: TransformedData[]
57
60
  updateConfig: Function
58
61
  visualizationType: 'Line'
62
+ yAxisDomainData?: Object[]
59
63
  colorPalettes: Record<string, string[]>
60
64
  twoColorPalette: Record<string, string[]>
61
65
  }
@@ -86,4 +90,5 @@ export type ChartContext =
86
90
  transformedData?: TransformedData[]
87
91
  twoColorPalette: any
88
92
  updateConfig?: Function
93
+ yAxisDomainData?: Object[]
89
94
  })
@@ -1,53 +0,0 @@
1
- import { ChartConfig } from '../types/ChartConfig'
2
-
3
- /**
4
- * Calculates the Y-axis auto padding to prevent data labels from overlapping with axis tick labels.
5
- * This is used when inline labels are enabled and there's potential for overlap.
6
- *
7
- * @param yScale - The D3 scale object for the Y-axis (must have .ticks() method)
8
- * @param handleNumTicks - The number of ticks to display on the axis
9
- * @param maxValue - The maximum data value (from useReduceData)
10
- * @param minValue - The minimum data value (from useReduceData)
11
- * @param config - The chart configuration object
12
- * @returns The calculated auto padding percentage (0-100+), or 0 if no padding needed
13
- */
14
- export const getYAxisAutoPadding = (
15
- yScale: any,
16
- handleNumTicks: number,
17
- maxValue: number,
18
- minValue: number,
19
- config: ChartConfig
20
- ): number => {
21
- // Early returns for cases where auto padding is not needed
22
- if (!yScale?.ticks || config.orientation === 'horizontal' || config.yAxis?.max) {
23
- return 0
24
- }
25
-
26
- const ticks = yScale.ticks(handleNumTicks)
27
-
28
- if (!Array.isArray(ticks) || ticks.length === 0) {
29
- return 0
30
- }
31
-
32
- // minimum percentage of the max value that the distance should be from the top grid line
33
- const MINIMUM_DISTANCE_PERCENTAGE = 0.025
34
-
35
- const topGridLine = Math.max(...ticks)
36
- const needsPaddingThreshold = topGridLine - maxValue * MINIMUM_DISTANCE_PERCENTAGE
37
- const maxValueIsGreaterThanThreshold = maxValue > needsPaddingThreshold
38
-
39
- if (!maxValueIsGreaterThanThreshold) return 0
40
-
41
- const tickGap = ticks.length === 1 ? ticks[0] : ticks[1] - ticks[0]
42
- const nextTick = Math.max(...ticks) + tickGap
43
- const divideBy = minValue < 0 ? maxValue / 2 : maxValue
44
- const calculatedPadding = (nextTick - maxValue) / divideBy
45
-
46
- // if auto padding is too close to next tick, add one more ticks worth of padding
47
- const newPadding =
48
- calculatedPadding > MINIMUM_DISTANCE_PERCENTAGE ? calculatedPadding : calculatedPadding + tickGap / divideBy
49
-
50
- /* sometimes even though the padding is getting to the next tick exactly,
51
- d3 still doesn't show the tick. we add 0.1 to ensure to tip it over the edge */
52
- return newPadding * 100 + 0.1
53
- }