@cdc/chart 4.23.8 → 4.23.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 (34) hide show
  1. package/dist/cdcchart.js +44114 -44410
  2. package/examples/feature/__data__/area-chart-date-apple.json +1 -5073
  3. package/examples/feature/area/area-chart-date-apple.json +73 -10316
  4. package/examples/feature/area/area-chart-date-city-temperature.json +204 -80
  5. package/examples/{private/confidence_interval_test.json → feature/area/area-chart-stacked.json} +65 -74
  6. package/examples/feature/filters/bar-filter.json +5027 -0
  7. package/examples/feature/legend-highlights/highlights.json +567 -0
  8. package/index.html +28 -7
  9. package/package.json +3 -2
  10. package/src/{CdcChart.jsx → CdcChart.tsx} +77 -71
  11. package/src/components/AreaChart.Stacked.jsx +73 -0
  12. package/src/components/AreaChart.jsx +24 -26
  13. package/src/components/BarChart.StackedVertical.jsx +2 -0
  14. package/src/components/DeviationBar.jsx +67 -13
  15. package/src/components/EditorPanel.jsx +493 -454
  16. package/src/components/Forecasting.jsx +5 -5
  17. package/src/components/Legend.jsx +17 -8
  18. package/src/components/LineChart.Circle.tsx +108 -0
  19. package/src/components/{LineChart.jsx → LineChart.tsx} +10 -42
  20. package/src/components/LinearChart.jsx +460 -443
  21. package/src/components/PieChart.jsx +54 -25
  22. package/src/components/Series.jsx +63 -17
  23. package/src/components/SparkLine.jsx +7 -19
  24. package/src/data/initial-state.js +10 -1
  25. package/src/hooks/useEditorPermissions.js +87 -24
  26. package/src/hooks/useLegendClasses.js +14 -11
  27. package/src/hooks/useReduceData.js +6 -1
  28. package/src/hooks/useScales.js +2 -2
  29. package/src/hooks/useTooltip.jsx +21 -8
  30. package/src/scss/legend.scss +206 -0
  31. package/src/scss/main.scss +25 -24
  32. package/examples/private/tooltip-issue.json +0 -45275
  33. package/src/components/DataTable.jsx +0 -374
  34. /package/src/{components → hooks}/useIntersectionObserver.jsx +0 -0
@@ -48,12 +48,12 @@ const useScales = properties => {
48
48
  }
49
49
 
50
50
  // handle Area chart
51
- if (config.visualizationType === 'Area Chart' && config.xAxis.type === 'date') {
51
+ if (config.xAxis.type === 'date' && config.xAxis.sortDates) {
52
52
  xScale = scaleTime({
53
53
  domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)],
54
54
  range: [0, xMax]
55
55
  })
56
- xScale.type = scaleTypes.TIME
56
+ xScale.type = scaleTypes.LINEAR
57
57
  }
58
58
 
59
59
  // handle Deviation bar
@@ -1,5 +1,6 @@
1
1
  import { useContext } from 'react'
2
2
  import ConfigContext from '../ConfigContext'
3
+ import { defaultStyles } from '@visx/tooltip'
3
4
 
4
5
  // third party
5
6
  import { localPoint } from '@visx/event'
@@ -30,6 +31,8 @@ export const useTooltip = props => {
30
31
  }
31
32
 
32
33
  const tooltipInformation = {
34
+ tooltipLeft: tooltipData.dataXPosition,
35
+ tooltipTop: tooltipData.dataYPosition,
33
36
  tooltipData: tooltipData
34
37
  }
35
38
 
@@ -50,11 +53,22 @@ export const useTooltip = props => {
50
53
  // Additional data for pie charts
51
54
  const { data: pieChartData, arc } = additionalChartData
52
55
 
53
- const closestXScaleValue = getXValueFromCoordinate(x)
56
+ const closestXScaleValue = getXValueFromCoordinate(x - Number(config.yAxis.size || 0))
54
57
 
55
58
  const includedSeries = visualizationType !== 'Pie' ? config.series.filter(series => series.tooltip === true).map(item => item.dataKey) : config.series.map(item => item.dataKey)
56
59
  includedSeries.push(config.xAxis.dataKey)
57
60
 
61
+ if (config.visualizationType === 'Forecasting') {
62
+ config.series.map(s => {
63
+ s.confidenceIntervals.map(c => {
64
+ if (c.showInTooltip) {
65
+ includedSeries.push(c.high)
66
+ includedSeries.push(c.low)
67
+ }
68
+ })
69
+ })
70
+ }
71
+
58
72
  const yScaleValues = getYScaleValues(closestXScaleValue, includedSeries)
59
73
 
60
74
  const xScaleValues = data.filter(d => d[xAxis.dataKey] === getClosestYValue(y))
@@ -103,14 +117,14 @@ export const useTooltip = props => {
103
117
  if (visualizationType === 'Pie') {
104
118
  return [
105
119
  [config.xAxis.dataKey, pieChartData],
106
- [config.runtime.yAxis.dataKey, formatNumber(arc.data[config.runtime.yAxis.dataKey])],
107
- ['Percent', `${Math.round((((arc.endAngle - arc.startAngle) * 180) / Math.PI / 360) * 100) + '%'}`]
120
+ [config.runtime.yAxis.dataKey, formatNumber(arc?.data[config.runtime.yAxis.dataKey])],
121
+ ['Percent', `${Math.round((((arc?.endAngle - arc?.startAngle) * 180) / Math.PI / 360) * 100) + '%'}`]
108
122
  ]
109
123
  }
110
124
 
111
125
  return getIncludedTooltipSeries()
112
126
  .filter(Boolean)
113
- .flatMap(seriesKey => {
127
+ .flatMap((seriesKey, index) => {
114
128
  return resolvedScaleValues[0][seriesKey] ? [[seriesKey, resolvedScaleValues[0][seriesKey], getAxisPosition(seriesKey)]] : []
115
129
  })
116
130
  }
@@ -131,7 +145,6 @@ export const useTooltip = props => {
131
145
  */
132
146
  const handleTooltipMouseOff = () => {
133
147
  if (config.visualizationType === 'Area Chart') {
134
- console.log('HERE IN OFF')
135
148
  setTimeout(() => {
136
149
  hideTooltip()
137
150
  }, 3000)
@@ -170,11 +183,11 @@ export const useTooltip = props => {
170
183
  const getXValueFromCoordinate = x => {
171
184
  if (visualizationType === 'Pie') return
172
185
  if (orientation === 'horizontal') return
173
- if (xScale.type === 'point' || xAxis.type === 'continuous') {
186
+ if (xScale.type === 'point' || xAxis.type === 'continuous' || xAxis.type === 'date') {
174
187
  // Find the closest x value by calculating the minimum distance
175
188
  let closestX = null
176
189
  let minDistance = Number.MAX_VALUE
177
- let offset = x - yAxis.size
190
+ let offset = x
178
191
 
179
192
  data.forEach(d => {
180
193
  const xPosition = xAxis.type === 'date' ? xScale(parseDate(d[xAxis.dataKey])) : xScale(d[xAxis.dataKey])
@@ -315,7 +328,7 @@ export const useTooltip = props => {
315
328
  if (!config.dashboard) {
316
329
  switch (visualizationType) {
317
330
  case 'Combo':
318
- standardLoopItems = [runtime.xAxis.dataKey, ...runtime?.barSeriesKeys, ...runtime?.lineSeriesKeys, ...stageColumns, ...ciItems]
331
+ standardLoopItems = [runtime.xAxis.dataKey, ...runtime?.seriesKeys, ...stageColumns, ...ciItems]
319
332
  break
320
333
  case 'Forecasting':
321
334
  standardLoopItems = [runtime.xAxis.dataKey, ...stageColumns, ...ciItems]
@@ -0,0 +1,206 @@
1
+ // Notes - copied in from map > sidebar.scss
2
+ // should be placed in a more global area eventually.
3
+ // Had to remove/edit some styles to make the legend look proper.
4
+ aside {
5
+ background-color: #fff;
6
+ z-index: 6;
7
+ border-top: $lightGray 1px solid;
8
+ @include breakpointClass(md) {
9
+ &.bottom {
10
+ border: $lightGray 1px solid;
11
+ }
12
+ &.side {
13
+ z-index: 1;
14
+ box-sizing: content-box;
15
+ max-width: 450px;
16
+ margin-top: 2em;
17
+ margin-bottom: 2em;
18
+ align-self: flex-start;
19
+ z-index: 4;
20
+ right: 1em;
21
+ border: $lightGray 1px solid;
22
+ width: 50%;
23
+ top: 2em;
24
+ right: 1em;
25
+
26
+ ul.vertical-sorted {
27
+ @include breakpoint(md) {
28
+ column-count: 2;
29
+ column-fill: balance;
30
+ }
31
+ }
32
+
33
+ ul:not(.vertical-sorted) {
34
+ @include breakpoint(md) {
35
+ column-count: initial;
36
+ column-fill: initial;
37
+ }
38
+ display: flex;
39
+ flex-direction: row;
40
+ flex-wrap: wrap;
41
+ }
42
+ }
43
+
44
+ &.bottom {
45
+ ul.legend-container__ul.vertical-sorted {
46
+ display: block;
47
+ @include breakpoint(md) {
48
+ column-count: 2;
49
+ column-fill: balance;
50
+ }
51
+ }
52
+
53
+ ul.legend-container__ul {
54
+ display: flex;
55
+ flex-direction: row;
56
+ flex-wrap: wrap;
57
+
58
+ li {
59
+ width: 50%;
60
+ }
61
+ }
62
+
63
+ ul.single-row {
64
+ display: block;
65
+ column-count: initial;
66
+ column-fill: auto;
67
+ }
68
+ }
69
+ }
70
+
71
+ &.legend-container {
72
+ padding: 1em;
73
+ position: relative;
74
+ .legend-container__title {
75
+ font-size: 1.3em;
76
+ padding-bottom: 0;
77
+ display: inline-block;
78
+ }
79
+ .legend-container__title + p,
80
+ .legend-container__title + ul,
81
+ p + ul,
82
+ p + p {
83
+ padding-top: 1em;
84
+ }
85
+ .legend-container__reset-button {
86
+ font-size: 0.75em;
87
+ color: rgba(0, 0, 0, 0.6);
88
+ position: absolute;
89
+ right: 1em;
90
+ top: 1em;
91
+ background: rgba(0, 0, 0, 0.1);
92
+ text-transform: uppercase;
93
+ transition: 0.2s all;
94
+ padding: 0.2em 0.5em;
95
+ border: rgba(0, 0, 0, 0.2) 1px solid;
96
+ color: rgba(0, 0, 0, 0.6) !important;
97
+ &:hover {
98
+ text-decoration: none;
99
+ background: rgba(0, 0, 0, 0.15);
100
+ transition: 0.2s all;
101
+ }
102
+ }
103
+ p {
104
+ line-height: 1.4em;
105
+ }
106
+ .legend-container__ul {
107
+ list-style: none;
108
+ padding-top: 1em;
109
+
110
+ &.vertical-sorted {
111
+ flex-direction: column;
112
+ }
113
+ .legend-container__li {
114
+ flex-shrink: 0;
115
+ display: inline-block;
116
+ padding-right: 1em;
117
+ padding-bottom: 1em;
118
+ vertical-align: middle;
119
+ transition: 0.1s opacity;
120
+ display: flex;
121
+ cursor: pointer;
122
+ flex-grow: 1;
123
+
124
+ &.legend-container__li--disabled {
125
+ opacity: 0.4;
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ &.side .legend-container .legend-container__ul--single-column {
132
+ @include breakpointClass(md) {
133
+ width: 25%;
134
+ min-width: 200px;
135
+ .legend-section ul {
136
+ flex-direction: column;
137
+ li {
138
+ width: 100%;
139
+ &:nth-last-of-type(-n + 2) {
140
+ padding-bottom: 1em;
141
+ }
142
+ &:last-child {
143
+ padding-bottom: 0;
144
+ }
145
+ }
146
+ }
147
+ }
148
+ li {
149
+ width: 100%;
150
+ }
151
+ }
152
+
153
+ &.bottom.single-row {
154
+ width: 100%;
155
+ .legend-container ul {
156
+ flex-direction: row;
157
+ align-items: baseline;
158
+ justify-content: flex-start;
159
+ flex-wrap: wrap;
160
+ li {
161
+ justify-items: center;
162
+ line-break: loose;
163
+ align-items: center;
164
+ width: auto;
165
+ padding-right: 1em;
166
+ padding-bottom: 1em;
167
+ display: inline-block;
168
+ & > span {
169
+ margin: 0 !important;
170
+ }
171
+ }
172
+ }
173
+ }
174
+
175
+ @include breakpointClass(sm) {
176
+ .legend-container ul {
177
+ align-items: flex-start;
178
+ justify-content: space-between;
179
+ li {
180
+ flex-grow: 1;
181
+ padding-right: 0.5em;
182
+ }
183
+ }
184
+ }
185
+
186
+ .filters-section {
187
+ padding: 0 1em 1em;
188
+ .heading-3 {
189
+ font-weight: bold;
190
+ margin-bottom: 0.5em;
191
+ }
192
+ form {
193
+ margin-top: 0.5em;
194
+ line-height: 2em;
195
+ display: flex;
196
+ align-items: flex-end;
197
+ section + section {
198
+ margin-left: 0.75em;
199
+ }
200
+ select {
201
+ display: block;
202
+ font-size: 1em;
203
+ }
204
+ }
205
+ }
206
+ }
@@ -126,25 +126,27 @@
126
126
  &__inner {
127
127
  &.bottom {
128
128
  display: grid;
129
- grid-template-columns: auto auto;
129
+ grid-template-columns: 1fr 1fr;
130
+ grid-column-gap: 1.5em;
131
+ }
132
+ &.vertical-sorted {
133
+ display: block;
134
+
135
+ @include breakpoint(md) {
136
+ column-count: 2;
137
+ column-width: 100%;
138
+ }
139
+ column-gap: 1.5em;
140
+ column-fill: balance;
130
141
  }
131
142
 
132
143
  &.single-row {
133
144
  display: flex;
134
145
  flex-direction: row;
135
146
  flex-wrap: wrap;
136
- justify-content: flex-start;
137
-
138
- & > div {
139
- padding: 0 1.2em 1em 0;
140
- }
141
147
 
142
- & div > span {
143
- margin-right: 0 !important;
144
- }
145
-
146
- & > div.legend-item {
147
- margin: 0 !important;
148
+ .legend-item {
149
+ flex-basis: auto;
148
150
  }
149
151
  }
150
152
  }
@@ -177,6 +179,17 @@
177
179
  text-align: left;
178
180
  align-items: flex-start !important;
179
181
  user-select: none;
182
+ white-space: nowrap;
183
+
184
+ .visx-legend-label {
185
+ word-wrap: break-word;
186
+ white-space: pre-wrap;
187
+ word-break: break-word;
188
+ }
189
+ }
190
+
191
+ .vertical-sorted:not(.single-row) .legend-item {
192
+ white-space: nowrap;
180
193
  }
181
194
 
182
195
  .legend-item > .legend-item {
@@ -669,14 +682,6 @@
669
682
  padding: 1em;
670
683
  }
671
684
 
672
- .cove-component__content:not(.no-borders) {
673
- border: 1px solid $lightGray;
674
- }
675
-
676
- .cove-component__header ~ .cove-component__content:not(.no-borders) {
677
- border-top: none !important;
678
- }
679
-
680
685
  .subtext {
681
686
  margin-top: 0px;
682
687
  }
@@ -684,10 +689,6 @@
684
689
  .isEditor {
685
690
  position: relative;
686
691
  }
687
-
688
- .subtext {
689
- margin-bottom: 15px;
690
- }
691
692
  }
692
693
 
693
694
  .cdc-open-viz-module .cove-component__content.sparkline {