@cdc/chart 4.25.6 → 4.25.7

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 (36) hide show
  1. package/dist/cdcchart.js +52667 -32246
  2. package/package.json +3 -2
  3. package/src/CdcChartComponent.tsx +13 -9
  4. package/src/_stories/Chart.BoxPlot.stories.tsx +35 -0
  5. package/src/_stories/Chart.stories.tsx +0 -7
  6. package/src/_stories/Chart.tooltip.stories.tsx +35 -275
  7. package/src/_stories/_mock/bar-chart-suppressed.json +2 -80
  8. package/src/_stories/_mock/boxplot_multiseries.json +252 -166
  9. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +1 -1
  10. package/src/components/AreaChart/components/AreaChart.jsx +4 -8
  11. package/src/components/BarChart/components/BarChart.Horizontal.tsx +34 -2
  12. package/src/components/BarChart/components/BarChart.Vertical.tsx +15 -0
  13. package/src/components/BoxPlot/BoxPlot.Horizontal.tsx +131 -0
  14. package/src/components/BoxPlot/{BoxPlot.tsx → BoxPlot.Vertical.tsx} +4 -4
  15. package/src/components/BoxPlot/helpers/index.ts +32 -12
  16. package/src/components/BrushChart.tsx +1 -1
  17. package/src/components/EditorPanel/EditorPanel.tsx +19 -14
  18. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +2 -2
  19. package/src/components/Forecasting/{Forecasting.jsx → Forecasting.tsx} +32 -12
  20. package/src/components/Legend/LegendGroup/LegendGroup.tsx +1 -0
  21. package/src/components/Legend/helpers/index.ts +2 -2
  22. package/src/components/LineChart/helpers.ts +7 -7
  23. package/src/components/LinearChart.tsx +127 -72
  24. package/src/data/initial-state.js +1 -5
  25. package/src/helpers/countNumOfTicks.ts +4 -19
  26. package/src/helpers/filterAndShiftLinearDateTicks.ts +58 -0
  27. package/src/helpers/getBridgedData.ts +13 -0
  28. package/src/helpers/tests/getBridgedData.test.ts +64 -0
  29. package/src/hooks/useScales.ts +42 -42
  30. package/src/hooks/useTooltip.tsx +3 -2
  31. package/src/scss/main.scss +2 -4
  32. package/src/store/chart.actions.ts +2 -2
  33. package/src/store/chart.reducer.ts +4 -12
  34. package/src/types/ChartConfig.ts +1 -6
  35. package/src/components/BoxPlot/index.tsx +0 -3
  36. /package/src/components/Brush/{BrushController..tsx → BrushController.tsx} +0 -0
@@ -44,7 +44,7 @@ const useScales = (properties: useScaleProps) => {
44
44
  const xAxisType = config.runtime.xAxis.type
45
45
  const isHorizontal = config.orientation === 'horizontal'
46
46
  const { visualizationType, xAxis, forestPlot } = config
47
-
47
+ const paddingRange = ['Area Chart', 'Forecasting'].includes(config.visualizationType) ? 1 : 1 - config.barThickness
48
48
  // define scales
49
49
  let xScale = null
50
50
  let yScale = null
@@ -68,22 +68,16 @@ const useScales = (properties: useScaleProps) => {
68
68
 
69
69
  // handle Vertical bars
70
70
  if (!isHorizontal) {
71
- xScale = composeScaleBand(xAxisDataMapped, [0, xMax], 1 - config.barThickness)
71
+ xScale = composeScaleBand(xAxisDataMapped, [0, xMax], paddingRange)
72
72
  yScale = composeYScale(properties)
73
73
  seriesScale = composeScaleBand(seriesDomain, [0, xScale.bandwidth()], 0)
74
74
  }
75
75
 
76
- // handle Linear scaled viz
77
- if (config.xAxis.type === 'date' && !isHorizontal) {
78
- const xAxisDataMappedSorted = sortXAxisData(xAxisDataMapped, config.xAxis.sortByRecentDate)
79
- xScale = composeScaleBand(xAxisDataMappedSorted, [0, xMax], 1 - config.barThickness)
80
- }
81
-
82
76
  // handle Linear scaled viz
83
77
  if (config.xAxis.type === 'date' && !isHorizontal) {
84
78
  const sorted = sortXAxisData(xAxisDataMapped, config.xAxis.sortByRecentDate)
85
79
 
86
- xScale = composeScaleBand(sorted, [0, xMax], 1 - config.barThickness)
80
+ xScale = composeScaleBand(sorted, [0, xMax], paddingRange)
87
81
  xScale.type = scaleTypes.BAND
88
82
  }
89
83
 
@@ -153,44 +147,50 @@ const useScales = (properties: useScaleProps) => {
153
147
 
154
148
  // handle Box plot
155
149
  if (visualizationType === 'Box Plot') {
156
- const allOutliers = []
157
- const hasOutliers =
158
- config.boxplot.plots.map(b => b.columnOutliers.map(outlier => allOutliers.push(outlier))) &&
159
- !config.boxplot.hideOutliers
160
-
161
- // check if outliers are lower
162
- if (hasOutliers) {
163
- let outlierMin = Math.min(...allOutliers)
164
- let outlierMax = Math.max(...allOutliers)
165
-
166
- // check if outliers exceed standard bounds
167
- if (outlierMin < min) min = outlierMin
168
- if (outlierMax > max) max = outlierMax
150
+ const {
151
+ boxplot: { plots, hideOutliers },
152
+ xAxis: { dataKey },
153
+ orientation,
154
+ runtime: { seriesKeys },
155
+ series,
156
+ barThickness
157
+ } = config
158
+
159
+ // 1) merge outliers + fences
160
+ let lo = min,
161
+ hi = max
162
+ for (const { columnOutliers = [], columnLowerBounds: lb, columnUpperBounds: ub } of plots) {
163
+ if (!hideOutliers && columnOutliers.length) {
164
+ lo = Math.min(lo, ...columnOutliers)
165
+ hi = Math.max(hi, ...columnOutliers)
166
+ }
167
+ lo = Math.min(lo, lb)
168
+ hi = Math.max(hi, ub)
169
169
  }
170
+ ;[min, max] = [lo, hi]
170
171
 
171
- // check fences for max/min
172
- let lowestFence = Math.min(...config.boxplot.plots.map(item => item.columnLowerBounds))
173
- let highestFence = Math.max(...config.boxplot.plots.map(item => item.columnUpperBounds))
172
+ // 2) unique categories
173
+ const cats = Array.from(new Set(data.map(d => d[dataKey])))
174
174
 
175
- if (lowestFence < min) min = lowestFence
176
- if (highestFence > max) max = highestFence
175
+ if (orientation === 'horizontal') {
176
+ xScale = composeXScale({ min, max, xMax, config })
177
+ xScale.type = scaleTypes.LINEAR
177
178
 
178
- // Set Scales
179
+ yScale = composeScaleBand(cats, [0, yMax], 0.4)
180
+ seriesScale = composeScaleBand(seriesKeys, [0, yScale.bandwidth()], 0.3)
181
+ } else {
182
+ xScale = composeScaleBand(cats, [0, xMax], 1 - barThickness)
183
+ xScale.type = scaleTypes.BAND
179
184
 
180
- const categories = _.uniq(data.map(d => d[config.xAxis.dataKey]))
181
- const range = [0, config.barThickness * 100 || 1]
182
- const domain = _.map(config.series, 'dataKey')
183
- yScale = scaleLinear({
184
- range: [yMax, 0],
185
- round: true,
186
- domain: [min, max]
187
- })
188
- xScale = scaleBand({
189
- range: [0, xMax],
190
- domain: categories
191
- })
192
- xScale.type = scaleTypes.BAND
193
- seriesScale = composeScaleBand(domain, range)
185
+ // numeric Y
186
+ yScale = composeYScale({ min, max, yMax, config, leftMax: 0 })
187
+
188
+ seriesScale = composeScaleBand(
189
+ series.map(s => s.dataKey),
190
+ [0, xScale.bandwidth()],
191
+ 0
192
+ )
193
+ }
194
194
  }
195
195
 
196
196
  // handle Paired bar
@@ -286,10 +286,11 @@ export const useTooltip = props => {
286
286
  let minDistance = Number.MAX_VALUE
287
287
  let offset = x
288
288
 
289
+ const barThicknessOffset = config.xAxis.type === 'date' ? xScale.bandwidth() / 2 : 0
289
290
  data.forEach(d => {
290
291
  const xPosition = isDateScale(xAxis) ? xScale(parseDate(d[xAxis.dataKey])) : xScale(d[xAxis.dataKey])
291
292
  let bwOffset = config.barHeight
292
- const distance = Math.abs(Number(xPosition - offset + (isClick ? bwOffset * 2 : 0)))
293
+ const distance = Math.abs(Number(xPosition + barThicknessOffset - offset + (isClick ? bwOffset * 2 : 0)))
293
294
 
294
295
  if (distance <= minDistance) {
295
296
  minDistance = distance
@@ -593,7 +594,7 @@ export const useTooltip = props => {
593
594
 
594
595
  return (
595
596
  <li style={style} className='tooltip-body mb-1'>
596
- {displayText}
597
+ {parse(displayText)}
597
598
  </li>
598
599
  )
599
600
  }
@@ -1,3 +1,5 @@
1
+ @import '@cdc/core/styles/accessibility';
2
+
1
3
  @mixin breakpoint($class) {
2
4
  @if $class == xs {
3
5
  @media (max-width: 767px) {
@@ -513,10 +515,6 @@
513
515
  }
514
516
  }
515
517
 
516
- [tabindex]:focus-visible {
517
- outline: 2px solid rgb(0, 95, 204) !important;
518
- }
519
-
520
518
  // ANIMATIONS
521
519
  // Pie Chart Animations
522
520
  .animated-pie {
@@ -16,7 +16,7 @@ type SET_DIMENSIONS = Action<'SET_DIMENSIONS', DimensionsType>
16
16
  type SET_CONTAINER = Action<'SET_CONTAINER', object>
17
17
  type SET_LOADED_EVENT = Action<'SET_LOADED_EVENT', boolean>
18
18
  type SET_DRAG_ANNOTATIONS = Action<'SET_DRAG_ANNOTATIONS', boolean>
19
- type SET_BRUSH_CONFIG = Action<'SET_BRUSH_CONFIG', object>
19
+ type SET_BRUSH_DATA = Action<'SET_BRUSH_DATA', object[]>
20
20
  type ChartActions =
21
21
  | SET_CONFIG
22
22
  | UPDATE_CONFIG
@@ -31,6 +31,6 @@ type ChartActions =
31
31
  | SET_LOADED_EVENT
32
32
  | SET_DRAG_ANNOTATIONS
33
33
  | SET_LOADING
34
- | SET_BRUSH_CONFIG
34
+ | SET_BRUSH_DATA
35
35
 
36
36
  export default ChartActions
@@ -18,11 +18,7 @@ type ChartState = {
18
18
  coveLoadedEventRan: boolean
19
19
  isDraggingAnnotation: boolean
20
20
  imageId: string
21
- brushConfig: {
22
- data: object[]
23
- isActive: boolean
24
- isBrushing: boolean
25
- }
21
+ brushData: object[] | []
26
22
  }
27
23
 
28
24
  export const getInitialState = (configObj: ChartConfig): ChartState => {
@@ -41,11 +37,7 @@ export const getInitialState = (configObj: ChartConfig): ChartState => {
41
37
  coveLoadedEventRan: false,
42
38
  isDraggingAnnotation: false,
43
39
  imageId: `cove-${Math.random().toString(16).slice(-4)}`,
44
- brushConfig: {
45
- data: [],
46
- isActive: false,
47
- isBrushing: false
48
- }
40
+ brushData: []
49
41
  }
50
42
  }
51
43
 
@@ -77,7 +69,7 @@ export const reducer = (state: ChartState, action: ChartActions): ChartState =>
77
69
  return { ...state, coveLoadedEventRan: action.payload }
78
70
  case 'SET_DRAG_ANNOTATIONS':
79
71
  return { ...state, isDraggingAnnotation: action.payload }
80
- case 'SET_BRUSH_CONFIG':
81
- return { ...state, brushConfig: action.payload }
72
+ case 'SET_BRUSH_DATA':
73
+ return { ...state, brushData: action.payload }
82
74
  }
83
75
  }
@@ -44,7 +44,7 @@ export interface PreliminaryDataItem {
44
44
  iconCode: string
45
45
  label: string
46
46
  lineCode: string
47
- seriesKey: string
47
+ seriesKeys: string[]
48
48
  style: string
49
49
  symbol: string
50
50
  type: 'effect' | 'suppression'
@@ -120,11 +120,6 @@ export type AllChartsConfig = {
120
120
  barStyle: 'lollipop' | 'rounded' | 'flat'
121
121
  barThickness: number
122
122
  boxplot: BoxPlot
123
- brush: {
124
- active: boolean
125
- data: object[]
126
- isBrushing: boolean
127
- }
128
123
  chartMessage: { noData?: string }
129
124
  color: string
130
125
  colorMatchLineSeriesLabels: boolean
@@ -1,3 +0,0 @@
1
- import BoxPlot from './BoxPlot'
2
-
3
- export default BoxPlot