@cdc/chart 4.24.5 → 4.24.9-1

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 (86) hide show
  1. package/dist/cdcchart.js +50526 -42181
  2. package/examples/cases-year.json +13379 -0
  3. package/examples/feature/annotations/index.json +542 -0
  4. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +76 -15
  5. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +5 -5
  6. package/examples/xaxis.json +493 -0
  7. package/index.html +20 -10
  8. package/package.json +5 -4
  9. package/src/CdcChart.tsx +461 -172
  10. package/src/_stories/Chart.Legend.Gradient.tsx +19 -0
  11. package/src/_stories/Chart.stories.tsx +18 -171
  12. package/src/_stories/ChartAnnotation.stories.tsx +32 -0
  13. package/src/_stories/_mock/annotation_category_mock.json +473 -0
  14. package/src/_stories/_mock/annotation_date-linear_mock.json +530 -0
  15. package/{examples/feature/line/line-chart.json → src/_stories/_mock/annotation_date-time_mock.json} +150 -69
  16. package/src/_stories/_mock/legend.gradient_mock.json +236 -0
  17. package/src/_stories/_mock/line_chart_two_points_new_chart.json +128 -0
  18. package/src/_stories/_mock/line_chart_two_points_regression_test.json +127 -0
  19. package/src/_stories/_mock/lollipop.json +171 -0
  20. package/src/components/Annotations/components/AnnotationDraggable.styles.css +31 -0
  21. package/src/components/Annotations/components/AnnotationDraggable.tsx +207 -0
  22. package/src/components/Annotations/components/AnnotationDropdown.styles.css +14 -0
  23. package/src/components/Annotations/components/AnnotationDropdown.tsx +72 -0
  24. package/src/components/Annotations/components/AnnotationList.styles.css +45 -0
  25. package/src/components/Annotations/components/AnnotationList.tsx +42 -0
  26. package/src/components/Annotations/components/findNearestDatum.ts +138 -0
  27. package/src/components/Annotations/components/helpers/index.tsx +46 -0
  28. package/src/components/Annotations/index.tsx +13 -0
  29. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +1 -1
  30. package/src/components/AreaChart/components/AreaChart.jsx +1 -1
  31. package/src/components/Axis/Categorical.Axis.tsx +145 -0
  32. package/src/components/BarChart/components/BarChart.Horizontal.tsx +47 -44
  33. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +0 -1
  34. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +11 -14
  35. package/src/components/BarChart/components/BarChart.Vertical.tsx +67 -30
  36. package/src/components/BarChart/helpers/index.ts +91 -0
  37. package/src/components/BrushChart.tsx +205 -0
  38. package/src/components/EditorPanel/EditorPanel.tsx +1794 -403
  39. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +320 -0
  40. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +282 -18
  41. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +43 -8
  42. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +4 -4
  43. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +4 -13
  44. package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
  45. package/src/components/EditorPanel/components/panels.scss +4 -0
  46. package/src/components/EditorPanel/editor-panel.scss +35 -3
  47. package/src/components/EditorPanel/{useEditorPermissions.js → useEditorPermissions.ts} +105 -17
  48. package/src/components/Legend/Legend.Component.tsx +185 -194
  49. package/src/components/Legend/Legend.Suppression.tsx +146 -0
  50. package/src/components/Legend/Legend.tsx +21 -5
  51. package/src/components/Legend/helpers/createFormatLabels.tsx +1 -1
  52. package/src/components/Legend/helpers/index.ts +35 -0
  53. package/src/components/LegendWrapper.tsx +26 -0
  54. package/src/components/LineChart/LineChartProps.ts +1 -15
  55. package/src/components/LineChart/components/LineChart.BumpCircle.tsx +103 -0
  56. package/src/components/LineChart/components/LineChart.Circle.tsx +57 -8
  57. package/src/components/LineChart/helpers.ts +72 -14
  58. package/src/components/LineChart/index.tsx +117 -42
  59. package/src/components/LinearChart.tsx +1366 -0
  60. package/src/components/PairedBarChart.jsx +9 -9
  61. package/src/components/PieChart/PieChart.tsx +75 -18
  62. package/src/components/Sankey/index.tsx +89 -30
  63. package/src/components/ScatterPlot/ScatterPlot.jsx +22 -8
  64. package/src/components/Sparkline/components/SparkLine.tsx +2 -2
  65. package/src/components/ZoomBrush.tsx +90 -44
  66. package/src/data/initial-state.js +25 -7
  67. package/src/helpers/handleChartTabbing.ts +8 -0
  68. package/src/helpers/isConvertLineToBarGraph.ts +4 -0
  69. package/src/hooks/{useBarChart.js → useBarChart.ts} +2 -40
  70. package/src/hooks/useColorScale.ts +1 -1
  71. package/src/hooks/useLegendClasses.ts +68 -0
  72. package/src/hooks/useMinMax.ts +12 -7
  73. package/src/hooks/useScales.ts +58 -26
  74. package/src/hooks/useTooltip.tsx +135 -25
  75. package/src/scss/DataTable.scss +2 -1
  76. package/src/scss/main.scss +128 -28
  77. package/src/types/ChartConfig.ts +83 -10
  78. package/src/types/ChartContext.ts +14 -4
  79. package/tests-examples/helpers/testZeroValue.test.ts +30 -0
  80. package/src/components/BrushHandle.jsx +0 -17
  81. package/src/components/LineChart/index.scss +0 -1
  82. package/src/components/LinearChart.jsx +0 -774
  83. package/src/helpers/filterData.ts +0 -18
  84. package/src/helpers/tests/computeMarginBottom.test.ts +0 -21
  85. package/src/hooks/useLegendClasses.js +0 -31
  86. /package/src/hooks/{useReduceData.js → useReduceData.ts} +0 -0
@@ -24,6 +24,28 @@
24
24
  .cdc-open-viz-module.type-chart {
25
25
  @import 'DataTable';
26
26
 
27
+ .legend-top {
28
+ .legend-wrapper .tooltip-boundary {
29
+ display: flex;
30
+ flex-wrap: wrap;
31
+ order: 2;
32
+ aside {
33
+ width: 100%;
34
+ order: 1;
35
+ }
36
+ }
37
+ }
38
+
39
+ .legend-bottom {
40
+ .legend-wrapper {
41
+ display: flex;
42
+ flex-wrap: wrap;
43
+ aside {
44
+ width: 100%;
45
+ }
46
+ }
47
+ }
48
+
27
49
  &.isEditor .cdc-chart-inner-container {
28
50
  background: white;
29
51
  }
@@ -90,7 +112,15 @@
90
112
  .subtext,
91
113
  .subtext--responsive-ticks,
92
114
  .section-subtext {
93
- padding: 0 1rem;
115
+ &--brush-active {
116
+ margin-top: 2.5em;
117
+ }
118
+ }
119
+
120
+ .type-pie {
121
+ svg.animated-pie {
122
+ width: auto !important;
123
+ }
94
124
  }
95
125
 
96
126
  .legend-container {
@@ -100,15 +130,20 @@
100
130
  vertical-align: top;
101
131
  text-align: left;
102
132
  border: 1px solid $lightGray;
103
- order: 1;
104
133
  position: relative;
105
134
 
135
+ &.no-border {
136
+ border: 1px solid transparent;
137
+ }
138
+
106
139
  &__inner {
107
- &.bottom {
140
+ &.double-column,
141
+ &.single-row {
108
142
  display: grid;
109
143
  grid-template-columns: 1fr 1fr;
110
144
  grid-column-gap: 1.5em;
111
145
  }
146
+
112
147
  &.vertical-sorted {
113
148
  display: block;
114
149
 
@@ -141,9 +176,10 @@
141
176
  word-wrap: break-word;
142
177
  white-space: pre-wrap;
143
178
  word-break: break-word;
144
- @include breakpoint(xs) {
145
- font-size: $font-small;
146
- }
179
+ }
180
+
181
+ & > :first-child {
182
+ margin-top: 3px;
147
183
  }
148
184
  }
149
185
 
@@ -159,20 +195,13 @@
159
195
 
160
196
  h3 {
161
197
  font-size: 1.3rem;
162
- @include breakpoint(xs) {
163
- font-size: $font-small + 0.4em;
164
- }
165
198
  }
166
199
 
167
200
  h3,
168
201
  p {
169
202
  margin-bottom: 0.8em;
170
203
  }
171
- p {
172
- @include breakpoint(xs) {
173
- font-size: $font-small;
174
- }
175
- }
204
+
176
205
  & div.legend-item {
177
206
  margin-bottom: 0.5em !important;
178
207
 
@@ -190,6 +219,23 @@
190
219
  transition: 0.2s all;
191
220
  }
192
221
  }
222
+
223
+ &__outer {
224
+ &.definition-link {
225
+ display: flex;
226
+ flex-direction: row;
227
+ position: absolute;
228
+ left: 0%;
229
+ top: 108%;
230
+ & > * {
231
+ margin: 0;
232
+ }
233
+ & > p,
234
+ a {
235
+ margin-left: 5px;
236
+ }
237
+ }
238
+ }
193
239
  }
194
240
 
195
241
  .dynamic-legend-list {
@@ -226,9 +272,6 @@
226
272
  vertical-align: middle;
227
273
  margin-bottom: 0.5em;
228
274
 
229
- @include breakpoint(xs) {
230
- font-size: $font-small;
231
- }
232
275
  & > span {
233
276
  display: flex;
234
277
  justify-items: center;
@@ -276,7 +319,61 @@
276
319
  display: flex;
277
320
  align-items: flex-start;
278
321
  flex-wrap: wrap;
322
+ justify-content: space-between;
323
+
324
+ &.legend-top:not(.legend-hidden) {
325
+ .legend-wrapper {
326
+ & > div {
327
+ order: 2;
328
+ width: 100%;
329
+ }
330
+ aside {
331
+ width: 100%;
332
+ order: 1;
333
+ height: fit-content;
334
+ }
335
+ }
336
+ }
337
+
338
+ &.legend-left:not(.legend-hidden) {
339
+ .legend-wrapper {
340
+ & > div {
341
+ order: 2;
342
+ width: 75%;
343
+ }
344
+ aside {
345
+ width: 25%;
346
+ order: 1;
347
+ height: fit-content;
348
+ }
349
+ }
350
+ }
351
+
352
+ &.legend-right:not(.legend-hidden) {
353
+ .legend-wrapper {
354
+ & > div {
355
+ order: 1;
356
+ width: 75%;
357
+ }
358
+ aside {
359
+ width: 25%;
360
+ height: fit-content;
361
+ order: 2;
362
+ }
363
+ }
364
+ }
279
365
 
366
+ &.left {
367
+ display: flex;
368
+ flex-direction: row-reverse;
369
+ }
370
+ &.top {
371
+ flex-wrap: nowrap;
372
+ flex-direction: column-reverse;
373
+ & > div.tooltip-boundary {
374
+ margin-top: 1.5em;
375
+ }
376
+ }
280
377
  &.bottom {
281
378
  flex-wrap: nowrap;
282
379
  flex-direction: column;
@@ -284,6 +381,17 @@
284
381
  &.legend-hidden > svg {
285
382
  width: 100% !important;
286
383
  }
384
+ &.dashboard-brush {
385
+ margin-bottom: 2.5em;
386
+ }
387
+
388
+ svg.dragging-annotation * {
389
+ user-select: none;
390
+ }
391
+
392
+ svg.dragging-annotation path {
393
+ pointer-events: none;
394
+ }
287
395
 
288
396
  > svg {
289
397
  overflow: visible;
@@ -415,15 +523,7 @@
415
523
  }
416
524
 
417
525
  @include breakpointClass(md) {
418
- .filters-section,
419
- .chart-container:not(.sparkline) {
420
- margin-left: 1em;
421
- margin-right: 1em;
422
- }
423
-
424
526
  .chart-container {
425
- flex-wrap: nowrap;
426
-
427
527
  .no-wrap {
428
528
  flex-wrap: nowrap;
429
529
  }
@@ -431,14 +531,15 @@
431
531
  .legend-container {
432
532
  width: 25%;
433
533
  margin-left: 1em;
434
- order: 2;
534
+ height: fit-content;
435
535
 
436
536
  &.left {
437
537
  margin-left: 0;
438
538
  margin-right: 1em;
439
539
  order: 0;
440
540
  }
441
- &.bottom {
541
+ &.bottom,
542
+ &.top {
442
543
  width: 100%;
443
544
  margin-left: 0;
444
545
  }
@@ -702,7 +803,6 @@
702
803
  .subtext,
703
804
  .subtext--responsive-ticks {
704
805
  margin-top: 0px;
705
- padding: 0 1rem;
706
806
  }
707
807
 
708
808
  .isEditor {
@@ -8,14 +8,34 @@ import { Table } from '@cdc/core/types/Table'
8
8
  import { BoxPlot } from '@cdc/core/types/BoxPlot'
9
9
  import { General } from '@cdc/core/types/General'
10
10
  import { type Link } from './../components/Sankey/types'
11
- import { Legend } from '@cdc/core/types/Legend'
12
11
  import { ConfidenceInterval } from '@cdc/core/types/ConfidenceInterval'
13
12
  import { Region } from '@cdc/core/types/Region'
14
- import { type PreliminaryDataItem } from '../components/LineChart/LineChartProps'
13
+
15
14
  import { VizFilter } from '@cdc/core/types/VizFilter'
15
+ import { type Annotation } from '@cdc/core/types/Annotation'
16
16
 
17
+ export type ViewportSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg'
17
18
  export type ChartColumns = Record<string, Column>
18
19
 
20
+ export interface PreliminaryDataItem {
21
+ column: string
22
+ displayLegend: boolean
23
+ displayTable: boolean
24
+ displayTooltip: boolean
25
+ iconCode: string
26
+ label: string
27
+ lineCode: string
28
+ seriesKey: string
29
+ style: string
30
+ symbol: string
31
+ type: 'effect' | 'suppression'
32
+ value: string
33
+ hideBarSymbol: boolean
34
+ hideLineStyle: boolean
35
+ circleSize: number
36
+ displayGray: boolean
37
+ }
38
+
19
39
  type DataFormat = {
20
40
  abbreviated: boolean
21
41
  bottomAbbreviated: boolean
@@ -52,12 +72,20 @@ export type Legend = {
52
72
  hide: boolean
53
73
  highlightOnHover: boolean
54
74
  label: string
55
- lineMode: boolean
56
- position: string
75
+ position: 'left' | 'bottom' | 'top' | 'right'
57
76
  reverseLabelOrder: boolean
58
77
  singleRow: boolean
59
78
  type: string
60
79
  verticalSorted: boolean
80
+ hideSuppressionLink:boolean
81
+ style:'circles'|'boxes'|'gradient'|'lines'
82
+ subStyle:'linear blocks'|'smooth'
83
+ hideSuppressedLabels:boolean
84
+ tickRotation:string
85
+ hideBorder:{
86
+ side:boolean
87
+ topBottom:boolean
88
+ }
61
89
  }
62
90
 
63
91
  type Visual = {
@@ -70,13 +98,14 @@ type Visual = {
70
98
  horizontalHoverLine?: boolean
71
99
  }
72
100
 
73
- type AllChartsConfig = {
101
+ export type AllChartsConfig = {
102
+ annotations: Annotation[]
74
103
  animate: boolean
75
104
  general: General
76
105
  barHasBorder: 'true' | 'false'
77
106
  barHeight: number
78
107
  barSpace: number
79
- barStyle: string
108
+ barStyle: 'lollipop'|'rounded'|'flat'
80
109
  barThickness: number
81
110
  boxplot: BoxPlot
82
111
  brush: {
@@ -106,6 +135,7 @@ type AllChartsConfig = {
106
135
  formattedData: Object[] & { urlFiltered: boolean }
107
136
  heights: {
108
137
  vertical: number
138
+ mobileVertical: number
109
139
  }
110
140
  highlightedBarValues: { value: any; color: string; borderWidth: number; legendLabel: string }[]
111
141
  introText: string
@@ -149,10 +179,9 @@ type AllChartsConfig = {
149
179
  topAxis: { hasLine: boolean }
150
180
  twoColor: { palette: string }
151
181
  type: 'chart' | 'dashboard'
152
- useLogScale: boolean
153
182
  uid: string | number
154
183
  visual: Visual
155
- visualizationType: 'Area Chart' | 'Bar' | 'Box Plot' | 'Deviation Bar' | 'Forest Plot' | 'Line' | 'Paired Bar' | 'Pie' | 'Scatter Plot' | 'Spark Line' | 'Combo' | 'Forecasting' | 'Sankey'
184
+ visualizationType: 'Area Chart' | 'Bar' | 'Box Plot' | 'Deviation Bar' | 'Forest Plot' | 'Line' | 'Paired Bar' | 'Pie' | 'Scatter Plot' | 'Spark Line' | 'Combo' | 'Forecasting' | 'Sankey' | 'Bump Chart'
156
185
  visualizationSubType: string
157
186
  xAxis: Axis
158
187
  yAxis: Axis
@@ -188,8 +217,52 @@ export type ForestPlotConfig = {
188
217
  } & AllChartsConfig
189
218
 
190
219
  export type LineChartConfig = {
191
- visualizationType: 'Line'
220
+ allowLineToBarGraph: boolean
221
+ convertLineToBarGraph: boolean
192
222
  lineDatapointStyle: 'hidden' | 'always show' | 'hover'
223
+ visualizationType: 'Line'
224
+ } & AllChartsConfig
225
+
226
+ export type SankeyLink = {
227
+ depth: number
228
+ height: number
229
+ id: string
230
+ index: number
231
+ layer: number
232
+ sourceLinks: SankeyLink[]
233
+ targetLinks: SankeyLink[]
234
+ value: number
235
+ x0: number
236
+ x1: number
237
+ y0: number
238
+ y1: number
239
+ }
240
+
241
+ type StoryNode = {
242
+ StoryNode: string
243
+ segmentTextAfter: string
244
+ segmentTextBefore: string
245
+ }
246
+
247
+ export type SankeyChartConfig = {
248
+ enableTooltips: boolean
249
+ data: [
250
+ {
251
+ tooltips: Object[]
252
+ // data to display in the sankey chart tooltips
253
+ tooltipData: Object[]
254
+ // data to display in the data table, bypasses the default data table output
255
+ tableData: Object[]
256
+ links: {
257
+ source: SankeyLink
258
+ target: SankeyLink
259
+ value: number
260
+ }[],
261
+ storyNodeText: StoryNode[]
262
+ :
263
+ }
264
+ ]
265
+ visualizationType: 'Sankey'
193
266
  } & AllChartsConfig
194
267
 
195
- export type ChartConfig = LineChartConfig | ForestPlotConfig | AllChartsConfig
268
+ export type ChartConfig = SankeyChartConfig | LineChartConfig | ForestPlotConfig | AllChartsConfig
@@ -1,6 +1,8 @@
1
1
  import { type ChartConfig } from './ChartConfig'
2
2
  import { PickD3Scale } from '@visx/scale'
3
3
  import { type SharedFilter } from '@cdc/dashboard/src/types/SharedFilter'
4
+ import { type Annotation } from '@cdc/core/types/Annotation'
5
+ import { DimensionsType } from '@cdc/core/types/Dimensions'
4
6
 
5
7
  export type ColorScale = PickD3Scale<'ordinal', any, any>
6
8
 
@@ -15,21 +17,28 @@ type SharedChartContext = {
15
17
  handleChartAriaLabels: (config: any) => string
16
18
  colorScale?: ColorScale
17
19
  config: ChartConfig
18
- currentViewport?: string
20
+ currentViewport?: 'lg' | 'md' | 'sm' | 'xs' | 'xxs'
19
21
  highlight?: Function
20
22
  highlightReset?: Function
21
23
  legendIsolateValues?: string[]
22
24
  setLegendIsolateValues?: Function
23
- getTextWidth?: () => string | number
25
+ getTextWidth?: (a: string, b: string) => string
24
26
  brushConfig: { data: []; isBrushing: boolean; isActive: boolean }
25
27
  setBrushConfig: Function
26
28
  clean: Function
27
29
  capitalize: (value: string) => string
30
+ // whether or not the legend is appearing below the chart
31
+ isLegendBottom?: boolean
32
+ // whether or not the chart is viewed within the editor screen
33
+ isEditor?: boolean
34
+ // whether or not the user is dragging an annotation
35
+ isDraggingAnnotation?: boolean
28
36
  }
29
37
 
30
38
  // Line Chart Specific Context
31
39
  type LineChartContext = SharedChartContext & {
32
- dimensions: [screenWidth: number, screenHeight: number]
40
+ convertLineToBarGraph: boolean
41
+ dimensions: DimensionsType
33
42
  formatDate: Function
34
43
  formatTooltipsDate: Function
35
44
  formatNumber: Function
@@ -50,7 +59,8 @@ type LineChartContext = SharedChartContext & {
50
59
  export type ChartContext =
51
60
  | LineChartContext
52
61
  | (SharedChartContext & {
53
- dimensions: [screenWidth: number, screenHeight: number]
62
+ annotations: Annotation[]
63
+ dimensions: DimensionsType
54
64
  formatDate?: Function
55
65
  formatTooltipsDate: Function
56
66
  formatNumber?: Function
@@ -0,0 +1,30 @@
1
+ import { testZeroValue } from '../../src/components/BarChart/helpers'
2
+
3
+ describe('testZeroValue', () => {
4
+ test('returns true for "0" as string', () => {
5
+ expect(testZeroValue('0')).toBe(true)
6
+ })
7
+
8
+ test('returns true for "0" as number', () => {
9
+ expect(testZeroValue(0)).toBe(true)
10
+ })
11
+
12
+ test('returns true for 0.0 as number', () => {
13
+ expect(testZeroValue(0.0)).toBe(true)
14
+ })
15
+
16
+ // check false case
17
+ test('returns false for "ABC" as string', () => {
18
+ expect(testZeroValue('ABC')).toBe(false)
19
+ })
20
+ test('returns false for 999 as number', () => {
21
+ expect(testZeroValue(999)).toBe(false)
22
+ })
23
+ // test for null & undefined cases
24
+ test('returns undefined for a null', () => {
25
+ expect(testZeroValue(null)).toBe(undefined)
26
+ })
27
+ test('returns undefined for a undefined', () => {
28
+ expect(testZeroValue(undefined)).toBe(undefined)
29
+ })
30
+ })
@@ -1,17 +0,0 @@
1
- import { Group } from '@visx/group'
2
-
3
- const BrushHandle = props => {
4
- const { x, height, isBrushActive } = props
5
- const pathWidth = 8
6
- const pathHeight = 15
7
- if (!isBrushActive) {
8
- return null
9
- }
10
- return (
11
- <Group left={x + pathWidth / 2} top={(height - pathHeight) / 2}>
12
- <path fill='#f2f2f2' d='M -4.5 0.5 L 3.5 0.5 L 3.5 15.5 L -4.5 15.5 L -4.5 0.5 M -1.5 4 L -1.5 12 M 0.5 4 L 0.5 12' stroke='#999999' strokeWidth='1' style={{ cursor: 'ew-resize' }} />
13
- </Group>
14
- )
15
- }
16
-
17
- export default BrushHandle
@@ -1 +0,0 @@
1
- // Line Chart Styles...