@cdc/chart 4.26.2 → 4.26.3

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 (70) hide show
  1. package/LICENSE +201 -0
  2. package/dist/cdcchart.js +35674 -32430
  3. package/examples/data/data-with-metadata.json +10 -0
  4. package/examples/feature/pie/planet-pie-example-config.json +2 -1
  5. package/examples/metadata-variables.json +58 -0
  6. package/package.json +3 -3
  7. package/src/CdcChart.tsx +8 -4
  8. package/src/CdcChartComponent.tsx +321 -288
  9. package/src/_stories/Chart.CustomColors.stories.tsx +74 -0
  10. package/src/_stories/Chart.Defaults.stories.tsx +95 -0
  11. package/src/_stories/Chart.SmallestLeftAxisMax.stories.tsx +64 -0
  12. package/src/_stories/Chart.stories.tsx +36 -2
  13. package/src/_stories/ChartBar.Editor.stories.tsx +97 -38
  14. package/src/_stories/ChartBrush.Editor.stories.tsx +11 -25
  15. package/src/_stories/ChartEditor.Editor.stories.tsx +1 -1
  16. package/src/_stories/_mock/paired-bar-abbr.json +421 -0
  17. package/src/_stories/_mock/pie_custom_colors.json +268 -0
  18. package/src/_stories/_mock/smallest_left_axis_max.json +104 -0
  19. package/src/components/Annotations/components/AnnotationDraggable.styles.css +10 -10
  20. package/src/components/Annotations/components/AnnotationDropdown.styles.css +1 -1
  21. package/src/components/Annotations/components/AnnotationList.styles.css +11 -11
  22. package/src/components/Axis/BottomAxis.tsx +10 -3
  23. package/src/components/Axis/PairedBarAxis.tsx +10 -4
  24. package/src/components/BarChart/components/BarChart.Horizontal.tsx +12 -28
  25. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +12 -30
  26. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +12 -31
  27. package/src/components/BarChart/components/BarChart.Vertical.tsx +12 -28
  28. package/src/components/BarChart/helpers/getPatternUrl.ts +94 -0
  29. package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +134 -0
  30. package/src/components/BarChart/helpers/useBarChart.ts +3 -0
  31. package/src/components/Brush/BrushSelector.tsx +2 -1
  32. package/src/components/Brush/MiniChartPreview.tsx +21 -26
  33. package/src/components/EditorPanel/EditorPanel.tsx +56 -43
  34. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +9 -9
  35. package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +0 -78
  36. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +39 -1
  37. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +24 -42
  38. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +83 -2
  39. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +45 -42
  40. package/src/components/EditorPanel/editor-panel.scss +1 -1
  41. package/src/components/ForestPlot/ForestPlot.tsx +26 -22
  42. package/src/components/Legend/LegendGroup/LegendGroup.styles.css +4 -4
  43. package/src/components/Legend/helpers/createFormatLabels.tsx +3 -2
  44. package/src/components/LinearChart/tests/LinearChart.test.tsx +77 -0
  45. package/src/components/LinearChart/tests/mockConfigContext.ts +2 -0
  46. package/src/components/LinearChart.tsx +26 -6
  47. package/src/components/PieChart/PieChart.tsx +19 -4
  48. package/src/components/RadarChart/RadarChart.tsx +1 -1
  49. package/src/components/Regions/components/Regions.tsx +6 -6
  50. package/src/components/Sankey/components/Sankey.tsx +3 -3
  51. package/src/components/Sankey/sankey.scss +1 -1
  52. package/src/components/SmallMultiples/SmallMultiples.css +5 -5
  53. package/src/components/Sparkline/index.scss +4 -2
  54. package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +8 -8
  55. package/src/data/initial-state.js +23 -14
  56. package/src/data/legacy-defaults.ts +18 -0
  57. package/src/helpers/abbreviateNumber.ts +24 -17
  58. package/src/helpers/getChartPatternId.ts +17 -0
  59. package/src/helpers/getMinMax.ts +16 -2
  60. package/src/helpers/seriesColumnSettings.ts +114 -0
  61. package/src/helpers/tests/countNumOfTicks.test.ts +77 -0
  62. package/src/helpers/tests/seriesColumnSettings.test.ts +84 -0
  63. package/src/hooks/useRightAxis.ts +14 -0
  64. package/src/hooks/useScales.ts +92 -56
  65. package/src/hooks/useTooltip.tsx +20 -3
  66. package/src/scss/main.scss +152 -79
  67. package/src/test/CdcChart.test.jsx +2 -2
  68. package/src/types/ChartConfig.ts +4 -0
  69. package/tests/fixtures/chart-config-with-metadata.json +29 -0
  70. package/tests/fixtures/data-with-metadata.json +10 -0
@@ -1,25 +1,76 @@
1
- @import '@cdc/core/styles/v2/utils/breakpoints';
1
+ @import '@cdc/core/styles/utils/breakpoints';
2
+ @import '@cdc/core/styles/layout/wrapper-padding';
2
3
 
3
4
  .form-container {
4
5
  overflow-y: auto;
5
6
  }
6
7
 
7
- .cdc-open-viz-module.type-dashboard {
8
- .cdc-open-viz-module.type-chart.isEditor {
9
- .cdc-chart-inner-container {
8
+ .cove-visualization.type-dashboard {
9
+ .cove-visualization.type-chart.is-editor {
10
+ .cove-visualization__body {
10
11
  background: white;
11
12
  }
12
13
  }
13
14
  }
14
15
 
15
- .cdc-open-viz-module.type-chart {
16
+ .cove-visualization.type-chart {
16
17
  @import 'DataTable';
17
18
 
19
+ .cove-visualization__body {
20
+ @include cove-visualization-body-padding;
21
+ }
22
+
23
+ .cove-visualization__body.component--tp5-treatment {
24
+ background: transparent;
25
+
26
+ .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
+ }
42
+
43
+ .cove-visualization__title,
44
+ .cove-visualization__header {
45
+ background: transparent;
46
+ border: 0;
47
+ color: var(--cool-gray-90, #1f2937);
48
+ margin: 0 0 1rem;
49
+ padding: 0;
50
+ border-radius: 0;
51
+
52
+ h2 {
53
+ color: var(--cool-gray-90, #1f2937);
54
+ font-family: var(--fonts-nunito, var(--app-font-secondary));
55
+ font-size: 1.1rem;
56
+ font-weight: 700;
57
+ }
58
+ }
59
+ }
60
+ }
61
+
62
+ .cove-visualization__title,
63
+ .cove-visualization__header {
64
+ margin-bottom: 0 !important;
65
+ }
66
+
18
67
  .legend-top {
19
68
  .legend-wrapper .tooltip-boundary {
20
69
  display: flex;
21
70
  flex-wrap: wrap;
71
+ row-gap: var(--cove-visualization-section-gap, 1.5rem);
22
72
  order: 2;
73
+
23
74
  aside {
24
75
  width: 100%;
25
76
  order: 1;
@@ -31,13 +82,16 @@
31
82
  .legend-wrapper {
32
83
  display: flex;
33
84
  flex-wrap: wrap;
85
+ row-gap: var(--cove-visualization-section-gap, 1.5rem);
86
+
34
87
  aside {
35
88
  width: 100%;
89
+ margin-top: var(--cove-visualization-section-gap, 1.5rem) !important;
36
90
  }
37
91
  }
38
92
  }
39
93
 
40
- &.isEditor .cdc-chart-inner-container {
94
+ &.is-editor .cove-visualization__body {
41
95
  background: white;
42
96
  }
43
97
 
@@ -47,11 +101,6 @@
47
101
  margin-bottom: 20px;
48
102
  }
49
103
 
50
- .subtext,
51
- .subtext--responsive-ticks,
52
- .section-subtext {
53
- }
54
-
55
104
  .type-pie {
56
105
  svg.animated-pie {
57
106
  width: auto !important;
@@ -60,7 +109,6 @@
60
109
 
61
110
  .legend-container {
62
111
  #supression-tooltip {
63
- font-family: 'Nunito', sans-serif;
64
112
  font-size: 0.8337rem;
65
113
  font-weight: 400;
66
114
  max-width: 16.7rem;
@@ -70,6 +118,7 @@
70
118
  white-space: normal;
71
119
  line-height: 1.4;
72
120
  }
121
+
73
122
  background: #fff;
74
123
  width: 100%;
75
124
  vertical-align: top;
@@ -101,6 +150,7 @@
101
150
  flex-direction: column;
102
151
  row-gap: var(--space-between-legend-item-rows);
103
152
  column-gap: var(--space-between-legend-item-columns);
153
+
104
154
  &.double-column,
105
155
  &.single-row {
106
156
  display: grid;
@@ -126,6 +176,7 @@
126
176
  text-align: left;
127
177
  user-select: none;
128
178
  line-height: var(--legend-item-font-size);
179
+
129
180
  .visx-legend-label {
130
181
  word-wrap: break-word;
131
182
  white-space: pre-wrap;
@@ -137,7 +188,7 @@
137
188
  white-space: nowrap;
138
189
  }
139
190
 
140
- .legend-item > .legend-item {
191
+ .legend-item>.legend-item {
141
192
  display: inline-block;
142
193
  flex: 0 0 auto;
143
194
  }
@@ -155,6 +206,7 @@
155
206
  opacity: 0.5;
156
207
  transition: 0.2s all;
157
208
  }
209
+
158
210
  &.highlighted {
159
211
  outline: 1px solid #005ea2;
160
212
  outline-offset: 5px;
@@ -170,10 +222,11 @@
170
222
  left: 0%;
171
223
  top: 108%;
172
224
 
173
- & > * {
225
+ &>* {
174
226
  margin: 0;
175
227
  }
176
- & > p,
228
+
229
+ &>p,
177
230
  a {
178
231
  margin-left: 5px;
179
232
  }
@@ -182,6 +235,7 @@
182
235
  }
183
236
 
184
237
  .dynamic-legend-list {
238
+
185
239
  // overide traditional legend item that uses !important
186
240
  .legend-item {
187
241
  align-items: flex-end !important;
@@ -214,7 +268,7 @@
214
268
  font-size: 1em;
215
269
  vertical-align: middle;
216
270
 
217
- & > span {
271
+ &>span {
218
272
  display: flex;
219
273
  justify-items: center;
220
274
  align-items: center;
@@ -224,23 +278,25 @@
224
278
  max-height: 1px;
225
279
  }
226
280
 
227
- & > span[class*='Asterisk'] {
281
+ &>span[class*='Asterisk'] {
228
282
  transform: scale(1.8);
229
283
  margin-top: 15px;
230
284
  }
231
- & > span[class*='Dagger'] {
285
+
286
+ &>span[class*='Dagger'] {
232
287
  margin-top: 2px;
233
288
  }
234
- & > span[class*='Sign'] {
289
+
290
+ &>span[class*='Sign'] {
235
291
  margin-top: 1px;
236
292
  }
237
293
 
238
- & > svg {
294
+ &>svg {
239
295
  width: 50px;
240
296
  height: 23px;
241
297
  }
242
298
 
243
- & > p {
299
+ &>p {
244
300
  margin: 0;
245
301
  }
246
302
  }
@@ -257,18 +313,37 @@
257
313
  position: relative;
258
314
  }
259
315
 
260
- .chart-container {
316
+ .visualization-container {
261
317
  display: flex;
262
318
  align-items: flex-start;
263
319
  flex-wrap: wrap;
264
320
  justify-content: space-between;
321
+ min-width: 0;
322
+ max-width: 100%;
323
+
324
+ .legend-wrapper {
325
+ min-width: 0;
326
+ max-width: 100%;
327
+
328
+ >div,
329
+ >aside {
330
+ min-width: 0;
331
+ max-width: 100%;
332
+ }
333
+ }
334
+
335
+ .tooltip-boundary {
336
+ min-width: 0;
337
+ max-width: 100%;
338
+ }
265
339
 
266
340
  &.legend-top:not(.legend-hidden) {
267
341
  .legend-wrapper {
268
- & > div {
342
+ &>div {
269
343
  order: 2;
270
344
  width: 100%;
271
345
  }
346
+
272
347
  aside {
273
348
  width: 100%;
274
349
  order: 1;
@@ -279,10 +354,11 @@
279
354
 
280
355
  &.legend-left:not(.legend-hidden) {
281
356
  .legend-wrapper {
282
- & > div {
357
+ &>div {
283
358
  order: 2;
284
359
  width: 75%;
285
360
  }
361
+
286
362
  aside {
287
363
  width: 25%;
288
364
  order: 1;
@@ -293,10 +369,11 @@
293
369
 
294
370
  &.legend-right:not(.legend-hidden) {
295
371
  .legend-wrapper {
296
- & > div {
372
+ &>div {
297
373
  order: 1;
298
374
  width: 75%;
299
375
  }
376
+
300
377
  aside {
301
378
  width: 25%;
302
379
  height: fit-content;
@@ -309,20 +386,25 @@
309
386
  display: flex;
310
387
  flex-direction: row-reverse;
311
388
  }
389
+
312
390
  &.top {
313
391
  flex-wrap: nowrap;
314
392
  flex-direction: column-reverse;
315
- & > div.tooltip-boundary {
393
+
394
+ &>div.tooltip-boundary {
316
395
  margin-top: 1.5em;
317
396
  }
318
397
  }
398
+
319
399
  &.bottom {
320
400
  flex-wrap: nowrap;
321
401
  flex-direction: column;
322
402
  }
323
- &.legend-hidden > svg {
403
+
404
+ &.legend-hidden>svg {
324
405
  width: 100% !important;
325
406
  }
407
+
326
408
  &.dashboard-brush {
327
409
  margin-bottom: 2.5em;
328
410
  }
@@ -352,7 +434,7 @@
352
434
  pointer-events: none;
353
435
  }
354
436
 
355
- > svg {
437
+ >svg {
356
438
  overflow: visible;
357
439
  font-size: 14px;
358
440
  margin: 1rem 0 2rem;
@@ -367,7 +449,7 @@
367
449
  }
368
450
 
369
451
  &.chart-line--hover {
370
- > svg circle {
452
+ >svg circle {
371
453
  opacity: 0;
372
454
 
373
455
  &:hover {
@@ -377,12 +459,12 @@
377
459
  }
378
460
 
379
461
  &.chart-line--always {
380
- > svg circle {
462
+ >svg circle {
381
463
  opacity: 1;
382
464
  }
383
465
 
384
466
  // Animations for line chart and data points
385
- > svg.animated {
467
+ >svg.animated {
386
468
  circle {
387
469
  opacity: 0;
388
470
  animation: revealLolly 0.25s linear forwards;
@@ -416,7 +498,7 @@
416
498
  }
417
499
 
418
500
  @include breakpointClass(sm) {
419
- .chart-container {
501
+ .visualization-container {
420
502
  .no-wrap {
421
503
  flex-wrap: nowrap;
422
504
  }
@@ -431,6 +513,7 @@
431
513
  margin-right: 1em;
432
514
  order: 0;
433
515
  }
516
+
434
517
  &.bottom,
435
518
  &.top {
436
519
  width: 100%;
@@ -441,8 +524,8 @@
441
524
  }
442
525
 
443
526
  @include breakpointClass(md) {
444
- .chart-container {
445
- > svg {
527
+ .visualization-container {
528
+ >svg {
446
529
  font-size: 16px;
447
530
  width: 75%;
448
531
  order: 1;
@@ -458,7 +541,6 @@
458
541
  // ANIMATIONS
459
542
  // Pie Chart Animations
460
543
  .animated-pie {
461
- margin: auto !important;
462
544
  transition: all 0.4s ease-in-out;
463
545
  opacity: 0;
464
546
  transform-origin: center;
@@ -499,6 +581,7 @@
499
581
  &.animated path.animation {
500
582
  opacity: 0;
501
583
  }
584
+
502
585
  &.animate {
503
586
  path.animation {
504
587
  opacity: 1;
@@ -506,6 +589,7 @@
506
589
  stroke-dashoffset: 4000;
507
590
  animation: dash 2s ease-in-out forwards;
508
591
  }
592
+
509
593
  @keyframes dash {
510
594
  to {
511
595
  stroke-dashoffset: 0;
@@ -524,6 +608,7 @@
524
608
  }
525
609
 
526
610
  &.animated {
611
+
527
612
  .vertical path,
528
613
  .vertical rect,
529
614
  .vertical foreignObject div {
@@ -541,6 +626,7 @@
541
626
  }
542
627
 
543
628
  &.animate {
629
+
544
630
  path,
545
631
  rect,
546
632
  foreignObject div {
@@ -598,7 +684,8 @@
598
684
  .cdc-visualization__paired-bar-chart {
599
685
  text-align: center;
600
686
  transform: scale(1);
601
- > .visx-group[style] {
687
+
688
+ >.visx-group[style] {
602
689
  transform: scale(1);
603
690
  }
604
691
  }
@@ -619,36 +706,39 @@
619
706
  }
620
707
  }
621
708
 
622
- .cdc-open-viz-module .is-editor .cdc-chart-inner-container {
623
- overflow: hidden;
624
- background-color: var(--white);
625
- }
709
+ .cove-visualization.type-chart.type-sparkline {
710
+ &.lg .visualization-container>svg {
711
+ width: 100%;
712
+ }
626
713
 
627
- .isEditor.type-sparkline .cdc-chart-inner-container {
628
- margin: 3em auto 0;
629
- max-width: 60%;
630
- }
714
+ .visualization-container.sparkline {
715
+ display: flex !important;
716
+ flex-wrap: wrap !important;
717
+ }
631
718
 
632
- .cdc-open-viz-module.type-chart.lg.type-sparkline .chart-container > svg {
633
- width: 100%;
634
- }
719
+ .cove-visualization__body {
720
+ &:not(.component--has-background):not(.component--hide-background-color) {
721
+ background: #f2f2f2;
722
+ }
635
723
 
636
- .chart-container.sparkline {
637
- display: flex !important;
638
- flex-wrap: wrap !important;
639
- }
724
+ &.component--hide-background-color {
725
+ background: transparent;
726
+ }
640
727
 
641
- .cdc-open-viz-module.type-chart.type-sparkline {
642
- .cove-component__content {
643
- background: #f2f2f2;
644
- }
728
+ &.sparkline {
729
+ padding: 1em;
730
+ border-bottom-left-radius: 3px;
731
+ border-bottom-right-radius: 3px;
645
732
 
646
- .cove-component__content.component--hideBackgroundColor {
647
- background: transparent;
648
- }
733
+ .visx-axis-tick:first-of-type {
734
+ transform: translate(20px, 0);
735
+ }
736
+
737
+ .visx-axis-tick:last-of-type {
738
+ transform: translate(-20px, 0);
739
+ }
740
+ }
649
741
 
650
- .cove-component__content .chart-container {
651
- padding: 1em;
652
742
  }
653
743
 
654
744
  .subtext,
@@ -656,29 +746,12 @@
656
746
  margin-top: 0px;
657
747
  }
658
748
 
659
- .isEditor {
749
+ .is-editor {
660
750
  position: relative;
661
751
  }
662
752
  }
663
753
 
664
- .cdc-open-viz-module .cove-component__content.sparkline {
665
- padding: 1em;
666
- }
667
-
668
- .cove-component__content.sparkline {
669
- border-bottom-left-radius: 3px;
670
- border-bottom-right-radius: 3px;
671
-
672
- .visx-axis-tick:first-of-type {
673
- transform: translate(20px, 0);
674
- }
675
-
676
- .visx-axis-tick:last-of-type {
677
- transform: translate(-20px, 0);
678
- }
679
- }
680
-
681
- .cdc-open-viz-module .debug {
754
+ .cove-visualization .debug {
682
755
  border: 2px solid red;
683
756
  }
684
757
 
@@ -1,11 +1,11 @@
1
- import path from 'path'
1
+ import path from 'node:path'
2
2
  import { testStandaloneBuild } from '@cdc/core/helpers/tests/testStandaloneBuild.ts'
3
3
  import { describe, it, expect } from 'vitest'
4
4
 
5
5
  describe('Chart', () => {
6
6
  it('Can be built in isolation', async () => {
7
7
  const pkgDir = path.join(__dirname, '..')
8
- const result = testStandaloneBuild(pkgDir)
8
+ const result = await testStandaloneBuild(pkgDir)
9
9
  expect(result).toBe(true)
10
10
  }, 300000)
11
11
  })
@@ -134,6 +134,8 @@ type Visual = {
134
134
  accent?: boolean
135
135
  background?: boolean
136
136
  hideBackgroundColor?: boolean
137
+ tp5Treatment?: boolean
138
+ tp5Background?: boolean
137
139
  verticalHoverLine?: boolean
138
140
  horizontalHoverLine?: boolean
139
141
  lineDatapointSymbol: 'none' | 'standard'
@@ -156,6 +158,7 @@ export type AllChartsConfig = {
156
158
  columns: ChartColumns
157
159
  confidenceKeys: ConfidenceInterval
158
160
  data: Object[]
161
+ dataMetadata?: Record<string, string>
159
162
  dataUrl: string
160
163
  dataCutoff: number
161
164
  dataDescription: Partial<DataDescription>
@@ -184,6 +187,7 @@ export type AllChartsConfig = {
184
187
  isPaletteReversed: boolean
185
188
  labels: boolean
186
189
  legend: Legend
190
+ locale: string
187
191
  lineDatapointColor: 'Same as Line' | 'Lighter than Line'
188
192
  lineDatapointStyle: 'hidden' | 'always show' | 'hover'
189
193
  lollipopColorStyle: 'regular' | 'two-tone'
@@ -0,0 +1,29 @@
1
+ {
2
+ "type": "chart",
3
+ "visualizationType": "Bar",
4
+ "dataUrl": "/packages/chart/tests/fixtures/data-with-metadata.json",
5
+ "enableMarkupVariables": true,
6
+ "markupVariables": [
7
+ {
8
+ "name": "Last Updated",
9
+ "tag": "{{lastUpdated}}",
10
+ "metadataKey": "lastUpdated",
11
+ "conditions": []
12
+ },
13
+ {
14
+ "name": "State",
15
+ "tag": "{{state}}",
16
+ "columnName": "STATE",
17
+ "conditions": []
18
+ }
19
+ ],
20
+ "description": "Data last updated {{lastUpdated}}",
21
+ "xAxis": {
22
+ "dataKey": "STATE"
23
+ },
24
+ "series": [
25
+ {
26
+ "dataKey": "Rate"
27
+ }
28
+ ]
29
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "lastUpdated": "January 15, 2026",
3
+ "source": "CDC NREVSS",
4
+ "data": [
5
+ { "STATE": "AL", "Rate": "10", "Location": "Home" },
6
+ { "STATE": "AK", "Rate": "12", "Location": "Home" },
7
+ { "STATE": "FL", "Rate": "10", "Location": "Work" },
8
+ { "STATE": "GA", "Rate": "12", "Location": "Work" }
9
+ ]
10
+ }