@cdc/chart 4.23.1 → 4.23.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 (74) hide show
  1. package/dist/cdcchart.js +56289 -702
  2. package/examples/Barchart_with_negative.json +34 -0
  3. package/examples/area-chart.json +187 -0
  4. package/examples/big-small-test-bar.json +328 -0
  5. package/examples/big-small-test-line.json +328 -0
  6. package/examples/big-small-test-negative.json +328 -0
  7. package/examples/box-plot.json +1 -2
  8. package/examples/dynamic-legends.json +1 -1
  9. package/examples/example-bar-chart-nonnumeric.json +36 -0
  10. package/examples/example-bar-chart.json +36 -0
  11. package/examples/example-combo-bar-nonnumeric.json +105 -0
  12. package/examples/example-sparkline.json +76 -0
  13. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +31 -172
  14. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +1 -1
  15. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json +1 -0
  16. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +96 -14
  17. package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +2 -2
  18. package/examples/gallery/line/line.json +1 -0
  19. package/examples/gallery/paired-bar/paired-bar-chart.json +65 -13
  20. package/examples/horizontal-chart-max-increase.json +38 -0
  21. package/examples/line-chart-max-increase.json +32 -0
  22. package/examples/line-chart-nonnumeric.json +32 -0
  23. package/examples/line-chart.json +21 -63
  24. package/examples/newdata.json +1 -1
  25. package/examples/planet-combo-example-config.json +143 -20
  26. package/examples/planet-deviation-config.json +168 -0
  27. package/examples/planet-deviation-data.json +38 -0
  28. package/examples/planet-example-config.json +139 -20
  29. package/examples/planet-example-data-max-increase.json +56 -0
  30. package/examples/planet-example-data-nonnumeric.json +56 -0
  31. package/examples/planet-example-data.json +9 -9
  32. package/examples/planet-pie-example-config-nonnumeric.json +30 -0
  33. package/examples/scatterplot-continuous.csv +17 -0
  34. package/examples/scatterplot.json +136 -0
  35. package/examples/sparkline-chart-nonnumeric.json +76 -0
  36. package/examples/stacked-vertical-bar-example-negative.json +154 -0
  37. package/examples/stacked-vertical-bar-example-nonnumerics.json +154 -0
  38. package/index.html +91 -0
  39. package/package.json +33 -24
  40. package/src/{CdcChart.tsx → CdcChart.jsx} +196 -124
  41. package/src/components/AreaChart.jsx +198 -0
  42. package/src/components/{BarChart.tsx → BarChart.jsx} +154 -122
  43. package/src/components/BoxPlot.jsx +101 -0
  44. package/src/components/{DataTable.tsx → DataTable.jsx} +109 -28
  45. package/src/components/DeviationBar.jsx +191 -0
  46. package/src/components/{EditorPanel.js → EditorPanel.jsx} +676 -157
  47. package/src/components/{Filters.js → Filters.jsx} +6 -11
  48. package/src/components/Legend.jsx +316 -0
  49. package/src/components/{LineChart.tsx → LineChart.jsx} +22 -26
  50. package/src/components/{LinearChart.tsx → LinearChart.jsx} +214 -91
  51. package/src/components/{PairedBarChart.tsx → PairedBarChart.jsx} +44 -78
  52. package/src/components/{PieChart.tsx → PieChart.jsx} +26 -44
  53. package/src/components/ScatterPlot.jsx +51 -0
  54. package/src/components/SparkLine.jsx +218 -0
  55. package/src/components/{useIntersectionObserver.tsx → useIntersectionObserver.jsx} +2 -2
  56. package/src/data/initial-state.js +51 -5
  57. package/src/hooks/useColorPalette.js +68 -0
  58. package/src/hooks/{useReduceData.ts → useReduceData.js} +26 -16
  59. package/src/hooks/useRightAxis.js +3 -1
  60. package/src/index.jsx +16 -0
  61. package/src/scss/DataTable.scss +22 -0
  62. package/src/scss/editor-panel.scss +5 -0
  63. package/src/scss/main.scss +30 -10
  64. package/src/test/CdcChart.test.jsx +6 -0
  65. package/vite.config.js +4 -0
  66. package/dist/495.js +0 -3
  67. package/dist/703.js +0 -1
  68. package/src/components/BoxPlot.js +0 -92
  69. package/src/components/Legend.js +0 -291
  70. package/src/components/SparkLine.js +0 -185
  71. package/src/hooks/useColorPalette.ts +0 -76
  72. package/src/index.html +0 -67
  73. package/src/index.tsx +0 -18
  74. /package/src/{context.tsx → ConfigContext.jsx} +0 -0
@@ -1,46 +1,52 @@
1
- import React, { Fragment, useContext, useEffect, useRef, useState } from 'react'
2
- import ReactTooltip from 'react-tooltip'
1
+ import React, { useContext, useEffect, useRef, useState } from 'react'
2
+ import { Tooltip as ReactTooltip } from 'react-tooltip'
3
3
 
4
4
  import { Group } from '@visx/group'
5
5
  import { Line } from '@visx/shape'
6
6
  import { Text } from '@visx/text'
7
- import { scaleLinear, scalePoint, scaleBand } from '@visx/scale'
7
+ import { scaleLinear, scalePoint, scaleBand, scaleTime } from '@visx/scale'
8
8
  import { AxisLeft, AxisBottom, AxisRight, AxisTop } from '@visx/axis'
9
9
 
10
+ import CoveScatterPlot from './ScatterPlot'
10
11
  import BarChart from './BarChart'
11
12
  import LineChart from './LineChart'
12
- import Context from '../context'
13
+ import ConfigContext from '../ConfigContext'
13
14
  import PairedBarChart from './PairedBarChart'
14
15
  import useIntersectionObserver from './useIntersectionObserver'
15
16
  import CoveBoxPlot from './BoxPlot'
17
+ import CoveAreaChart from './AreaChart'
16
18
 
17
19
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
18
20
  import '../scss/LinearChart.scss'
19
21
  import useReduceData from '../hooks/useReduceData'
20
22
  import useRightAxis from '../hooks/useRightAxis'
21
23
  import useTopAxis from '../hooks/useTopAxis'
24
+ import { DeviationBar } from './DeviationBar'
22
25
 
23
26
  // TODO: Move scaling functions into hooks to manage complexity
24
27
  export default function LinearChart() {
25
- const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig } = useContext<any>(Context)
28
+ const { transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig, stringFormattingOptions } = useContext(ConfigContext)
29
+
26
30
  let [width] = dimensions
27
31
  const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, data)
28
- const [animatedChart, setAnimatedChart] = useState<boolean>(false)
32
+ const [animatedChart, setAnimatedChart] = useState(false)
29
33
 
30
34
  const triggerRef = useRef()
31
35
  const dataRef = useIntersectionObserver(triggerRef, {
32
36
  freezeOnceVisible: false
33
37
  })
38
+
34
39
  // Make sure the chart is visible if in the editor
40
+ /* eslint-disable react-hooks/exhaustive-deps */
35
41
  useEffect(() => {
36
42
  const element = document.querySelector('.isEditor')
37
43
  if (element) {
38
44
  // parent element is visible
39
45
  setAnimatedChart(prevState => true)
40
46
  }
41
- })
47
+ }) /* eslint-disable-line */
42
48
 
43
- // If the chart is in view and set to animate and it has not already played
49
+ // If the chart is in view, set to animate if it has not already played
44
50
  useEffect(() => {
45
51
  if (dataRef?.isIntersecting === true && config.animate) {
46
52
  setTimeout(() => {
@@ -54,14 +60,14 @@ export default function LinearChart() {
54
60
  }
55
61
  const { horizontal: heightHorizontal } = config.heights
56
62
  const height = config.aspectRatio ? width * config.aspectRatio : config.heights[config.orientation]
57
- const xMax = width - config.runtime.yAxis.size - config.yAxis.rightAxisSize
63
+ const xMax = width - config.runtime.yAxis.size - (config.visualizationType === 'Combo' ? config.yAxis.rightAxisSize : 0)
58
64
  const yMax = height - (config.orientation === 'horizontal' ? 0 : config.runtime.xAxis.size)
59
65
 
60
66
  const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data, updateConfig })
61
67
  const { hasTopAxis } = useTopAxis(config)
62
68
 
63
- const getXAxisData = (d: any) => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
64
- const getYAxisData = (d: any, seriesKey: string) => d[seriesKey]
69
+ const getXAxisData = d => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
70
+ const getYAxisData = (d, seriesKey) => d[seriesKey]
65
71
 
66
72
  let xScale
67
73
  let yScale
@@ -71,11 +77,37 @@ export default function LinearChart() {
71
77
  const isMaxValid = existPositiveValue ? enteredMaxValue >= maxValue : enteredMaxValue >= 0
72
78
  const isMinValid = (enteredMinValue <= 0 && minValue >= 0) || (enteredMinValue <= minValue && minValue < 0)
73
79
 
80
+ let max = 0 // need outside the if statement
81
+ let min = 0
74
82
  if (data) {
75
- let min = enteredMinValue && isMinValid ? enteredMinValue : minValue
76
- let max = enteredMaxValue && isMaxValid ? enteredMaxValue : Number.MIN_VALUE
83
+ min = enteredMinValue && isMinValid ? enteredMinValue : minValue
84
+ max = enteredMaxValue && isMaxValid ? enteredMaxValue : Number.MIN_VALUE
85
+
86
+ // DEV-3263 - If Confidence Intervals in data, then need to account for increased height in max for YScale
87
+ if (config.visualizationType === 'Bar' || config.visualizationType === 'Combo' || config.visualizationType === 'Deviation Bar') {
88
+ let ciYMax = 0
89
+ if (config.hasOwnProperty('confidenceKeys')) {
90
+ let upperCIValues = data.map(function (d) {
91
+ return d[config.confidenceKeys.upper]
92
+ })
93
+ ciYMax = Math.max.apply(Math, upperCIValues)
94
+ if (ciYMax > max) max = ciYMax // bump up the max
95
+ }
96
+ }
97
+
98
+ // DEV-3263 - If Confidence Intervals in data, then need to account for increased height in max for YScale
99
+ if (config.visualizationType === 'Bar' || config.visualizationType === 'Combo') {
100
+ let ciYMax = 0
101
+ if (config.hasOwnProperty('confidenceKeys')) {
102
+ let upperCIValues = data.map(function (d) {
103
+ return d[config.confidenceKeys.upper]
104
+ })
105
+ ciYMax = Math.max.apply(Math, upperCIValues)
106
+ if (ciYMax > max) max = ciYMax // bump up the max
107
+ }
108
+ }
77
109
 
78
- if ((config.visualizationType === 'Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && min > 0) {
110
+ if ((config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar' || (config.visualizationType === 'Combo' && !isAllLine)) && min > 0) {
79
111
  min = 0
80
112
  }
81
113
  if (config.visualizationType === 'Combo' && isAllLine) {
@@ -118,23 +150,36 @@ export default function LinearChart() {
118
150
  case maxDataVal > 4 && maxDataVal <= 7:
119
151
  max = max * 1.1
120
152
  break
153
+ default:
154
+ break
155
+ }
156
+ }
157
+
158
+ // DEV-3219 - bc some values are going above YScale - adding 10% or 20% factor onto Max
159
+ // - put the statement up here and it works for both vert and horiz charts of all types
160
+ if (config.yAxis.enablePadding) {
161
+ if (min < 0) {
162
+ // sets with negative data need more padding on the max
163
+ max *= 1.2
164
+ } else {
165
+ max *= 1.1
121
166
  }
122
167
  }
123
168
 
124
169
  if (config.runtime.horizontal) {
125
- xScale = scaleLinear<number>({
170
+ xScale = scaleLinear({
126
171
  domain: [min, max],
127
172
  range: [0, xMax]
128
173
  })
129
174
 
130
175
  yScale =
131
176
  config.runtime.xAxis.type === 'date'
132
- ? scaleLinear<number>({
177
+ ? scaleLinear({
133
178
  domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)]
134
179
  })
135
- : scalePoint<string>({ domain: xAxisDataMapped, padding: 0.5 })
180
+ : scalePoint({ domain: xAxisDataMapped, padding: 0.5 })
136
181
 
137
- seriesScale = scalePoint<string>({
182
+ seriesScale = scalePoint({
138
183
  domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
139
184
  range: [0, yMax]
140
185
  })
@@ -143,24 +188,32 @@ export default function LinearChart() {
143
188
  } else {
144
189
  min = min < 0 ? min * 1.11 : min
145
190
 
146
- yScale = scaleLinear<number>({
191
+ yScale = scaleLinear({
147
192
  domain: [min, max],
148
193
  range: [yMax, 0]
149
194
  })
150
195
 
151
- xScale = scalePoint<string>({
196
+ xScale = scalePoint({
152
197
  domain: xAxisDataMapped,
153
198
  range: [0, xMax],
154
199
  padding: 0.5
155
200
  })
156
201
 
157
- seriesScale = scalePoint<string>({
202
+ seriesScale = scalePoint({
158
203
  domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
159
204
  range: [0, xMax]
160
205
  })
161
206
  }
162
207
 
208
+ if (config.visualizationType === 'Area Chart' && config.xAxis.type === 'date') {
209
+ xScale = scaleTime({
210
+ domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)],
211
+ range: [0, xMax]
212
+ })
213
+ }
214
+
163
215
  if (config.visualizationType === 'Paired Bar') {
216
+ const offset = 1.02 // Offset of the ticks/values from the Axis
164
217
  let groupOneMax = Math.max.apply(
165
218
  Math,
166
219
  data.map(d => d[config.series[0].dataKey])
@@ -171,15 +224,74 @@ export default function LinearChart() {
171
224
  )
172
225
 
173
226
  // group one
174
- var g1xScale = scaleLinear<number>({
175
- domain: [0, Math.max(groupOneMax, groupTwoMax)],
227
+ var g1xScale = scaleLinear({
228
+ domain: [0, Math.max(groupOneMax, groupTwoMax) * offset],
176
229
  range: [xMax / 2, 0]
177
230
  })
178
231
 
179
232
  // group 2
180
- var g2xScale = scaleLinear<number>({
233
+ var g2xScale = scaleLinear({
181
234
  domain: g1xScale.domain(),
182
- range: [xMax / 2, xMax]
235
+ range: [xMax / 2, xMax],
236
+ nice: true
237
+ })
238
+ }
239
+
240
+ if (config.visualizationType === 'Scatter Plot') {
241
+ if (config.xAxis.type === 'continuous') {
242
+ xScale = scaleLinear({
243
+ domain: [0, Math.max.apply(null, xScale.domain())],
244
+ range: [0, xMax]
245
+ })
246
+ }
247
+ }
248
+
249
+ if (config.visualizationType === 'Deviation Bar') {
250
+ const leftOffset = config.isLollipopChart ? 1.05 : 1.03
251
+ yScale = scaleBand({
252
+ domain: xAxisDataMapped,
253
+ range: [0, yMax]
254
+ })
255
+ xScale = scaleLinear({
256
+ domain: [min * leftOffset, Math.max(Number(config.xAxis.target), max)],
257
+ range: [0, xMax],
258
+ round: true
259
+ })
260
+ }
261
+ // Handle Box Plots
262
+ if (config.visualizationType === 'Box Plot') {
263
+ const allOutliers = []
264
+ const hasOutliers = config.boxplot.plots.map(b => b.columnOutliers.map(outlier => allOutliers.push(outlier))) && !config.boxplot.hideOutliers
265
+
266
+ // check if outliers are lower
267
+ if (hasOutliers) {
268
+ let outlierMin = Math.min(...allOutliers)
269
+ let outlierMax = Math.max(...allOutliers)
270
+
271
+ // check if outliers exceed standard bounds
272
+ if (outlierMin < min) min = outlierMin
273
+ if (outlierMax > max) max = outlierMax
274
+ }
275
+
276
+ // check fences for max/min
277
+ let lowestFence = Math.min(...config.boxplot.plots.map(item => item.columnMin))
278
+ let highestFence = Math.max(...config.boxplot.plots.map(item => item.columnMax))
279
+
280
+ if (lowestFence < min) min = lowestFence
281
+ if (highestFence > max) max = highestFence
282
+
283
+ // Set Scales
284
+ yScale = scaleLinear({
285
+ range: [yMax, 0],
286
+ round: true,
287
+ domain: [min, max]
288
+ })
289
+
290
+ xScale = scaleBand({
291
+ range: [0, xMax],
292
+ round: true,
293
+ domain: config.boxplot.categories,
294
+ padding: 0.4
183
295
  })
184
296
  }
185
297
  }
@@ -192,7 +304,8 @@ export default function LinearChart() {
192
304
 
193
305
  const handleBottomTickFormatting = tick => {
194
306
  if (config.runtime.xAxis.type === 'date') return formatDate(tick)
195
- if (config.orientation === 'horizontal') return formatNumber(tick, 'bottom')
307
+ if (config.orientation === 'horizontal') return formatNumber(tick, 'left')
308
+ if (config.xAxis.type === 'continuous') return formatNumber(tick, 'bottom')
196
309
  return tick
197
310
  }
198
311
 
@@ -204,57 +317,36 @@ export default function LinearChart() {
204
317
 
205
318
  if (axis === 'yAxis') {
206
319
  tickCount = isHorizontal && !numTicks ? data.length : isHorizontal && numTicks ? numTicks : !isHorizontal && !numTicks ? undefined : !isHorizontal && numTicks && numTicks
320
+ // to fix edge case of small numbers with decimals
321
+ if (tickCount === undefined && !config.dataFormat.roundTo) {
322
+ // then it is set to Auto
323
+ if (Number(max) <= 3) {
324
+ tickCount = 2
325
+ } else {
326
+ tickCount = 4 // same default as standalone components
327
+ }
328
+ }
329
+ if (Number(tickCount) > Number(max)) {
330
+ // cap it and round it so its an integer
331
+ tickCount = Number(min) < 0 ? Math.round(max) * 2 : Math.round(max)
332
+ }
207
333
  }
208
334
 
209
335
  if (axis === 'xAxis') {
210
336
  tickCount = isHorizontal && !numTicks ? undefined : isHorizontal && numTicks ? numTicks : !isHorizontal && !numTicks ? undefined : !isHorizontal && numTicks && numTicks
337
+ if (isHorizontal && tickCount === undefined && !config.dataFormat.roundTo) {
338
+ // then it is set to Auto
339
+ // - check for small numbers situation
340
+ if (max <= 3) {
341
+ tickCount = 2
342
+ } else {
343
+ tickCount = 4 // same default as standalone components
344
+ }
345
+ }
211
346
  }
212
347
  return tickCount
213
348
  }
214
349
 
215
- // Handle Box Plots
216
- if (config.visualizationType === 'Box Plot') {
217
- let minYValue
218
- let maxYValue
219
- let allOutliers = []
220
- let allLowerBounds = config.boxplot.map(plot => plot.columnMin)
221
- let allUpperBounds = config.boxplot.map(plot => plot.columnMax)
222
-
223
- minYValue = Math.min(...allLowerBounds)
224
- maxYValue = Math.max(...allUpperBounds)
225
-
226
- const hasOutliers = config.boxplot.map(b => b.columnOutliers.map(outlier => allOutliers.push(outlier)))
227
-
228
- if (hasOutliers) {
229
- let outlierMin = Math.min(...allOutliers)
230
- let outlierMax = Math.max(...allOutliers)
231
-
232
- // check if outliers exceed standard bounds
233
- if (outlierMin < minYValue) minYValue = outlierMin
234
- if (outlierMax > maxYValue) maxYValue = outlierMax
235
- }
236
-
237
- const seriesNames = data.map(d => d[config.xAxis.dataKey])
238
-
239
- // Set Scales
240
- yScale = scaleLinear({
241
- range: [yMax, 0],
242
- round: true,
243
- domain: [minYValue, maxYValue]
244
- })
245
-
246
- xScale = scaleBand({
247
- range: [0, xMax],
248
- round: true,
249
- domain: config.boxplot.categories,
250
- padding: 0.4
251
- })
252
- }
253
-
254
- useEffect(() => {
255
- ReactTooltip.rebuild()
256
- })
257
-
258
350
  return isNaN(width) ? (
259
351
  <></>
260
352
  ) : (
@@ -265,9 +357,24 @@ export default function LinearChart() {
265
357
  ? config.regions.map(region => {
266
358
  if (!Object.keys(region).includes('from') || !Object.keys(region).includes('to')) return null
267
359
 
268
- const from = xScale(parseDate(region.from).getTime())
269
- const to = xScale(parseDate(region.to).getTime())
270
- const width = to - from
360
+ let from
361
+ let to
362
+ let width
363
+
364
+ if (config.xAxis.type === 'date') {
365
+ from = xScale(parseDate(region.from).getTime())
366
+ to = xScale(parseDate(region.to).getTime())
367
+ width = to - from
368
+ }
369
+
370
+ if (config.xAxis.type === 'categorical') {
371
+ from = xScale(region.from)
372
+ to = xScale(region.to)
373
+ width = to - from
374
+ }
375
+
376
+ if (!from) return null
377
+ if (!to) return null
271
378
 
272
379
  return (
273
380
  <Group className='regions' left={Number(config.runtime.yAxis.size)} key={region.label}>
@@ -291,7 +398,7 @@ export default function LinearChart() {
291
398
 
292
399
  {/* Y axis */}
293
400
  {config.visualizationType !== 'Spark Line' && (
294
- <AxisLeft scale={yScale} left={Number(config.runtime.yAxis.size)} label={config.runtime.yAxis.label} stroke='#333' tickFormat={tick => handleLeftTickFormatting(tick)} numTicks={countNumOfTicks('yAxis')}>
401
+ <AxisLeft scale={yScale} left={Number(config.runtime.yAxis.size) - config.yAxis.axisPadding} label={config.runtime.yAxis.label} stroke='#333' tickFormat={tick => handleLeftTickFormatting(tick)} numTicks={countNumOfTicks('yAxis')}>
295
402
  {props => {
296
403
  const axisCenter = config.runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
297
404
  const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
@@ -324,15 +431,13 @@ export default function LinearChart() {
324
431
  )}
325
432
 
326
433
  {config.orientation === 'horizontal' && config.visualizationType === 'Paired Bar' && !config.yAxis.hideLabel && (
327
- <Text transform={`translate(${-15}, ${tick.from.y}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} verticalAnchor={config.isLollipopChart ? 'middle' : 'middle'} textAnchor={'end'}>
434
+ <Text transform={`translate(${tick.to.x - 5}, ${tick.to.y - minY + Number(config.barHeight) / 2}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} textAnchor={'end'} verticalAnchor='middle'>
328
435
  {tick.formattedValue}
329
436
  </Text>
330
437
  )}
331
-
332
- {config.orientation === 'horizontal' && config.visualizationType === 'Paired Bar' && !config.yAxis.hideLabel && (
333
- // 17 is a magic number from the offset in barchart.
334
- <Text transform={`translate(${-15}, ${tick.from.y}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} verticalAnchor={config.isLollipopChart ? 'middle' : 'middle'} textAnchor={'end'}>
335
- {formatNumber(tick.formattedValue)}
438
+ {config.orientation === 'horizontal' && config.visualizationType === 'Deviation Bar' && !config.yAxis.hideLabel && (
439
+ <Text transform={`translate(${tick.to.x - 5}, ${config.isLollipopChart ? tick.to.y - minY + 2 : tick.to.y - minY + Number(config.barHeight) / 2}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation : 0})`} textAnchor={'end'} verticalAnchor='middle'>
440
+ {tick.formattedValue}
336
441
  </Text>
337
442
  )}
338
443
 
@@ -409,7 +514,16 @@ export default function LinearChart() {
409
514
 
410
515
  {/* X axis */}
411
516
  {config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Spark Line' && (
412
- <AxisBottom top={yMax} left={Number(config.runtime.yAxis.size)} label={config.runtime.xAxis.label} tickFormat={handleBottomTickFormatting} scale={xScale} stroke='#333' tickStroke='#333' numTicks={countNumOfTicks('xAxis')}>
517
+ <AxisBottom
518
+ top={config.runtime.horizontal ? Number(heightHorizontal) + Number(config.xAxis.axisPadding) : yMax + Number(config.xAxis.axisPadding)}
519
+ left={Number(config.runtime.yAxis.size)}
520
+ label={config.runtime.xAxis.label}
521
+ tickFormat={handleBottomTickFormatting}
522
+ scale={xScale}
523
+ stroke='#333'
524
+ tickStroke='#333'
525
+ numTicks={countNumOfTicks('xAxis')}
526
+ >
413
527
  {props => {
414
528
  const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
415
529
  return (
@@ -447,16 +561,16 @@ export default function LinearChart() {
447
561
  <>
448
562
  <AxisBottom top={yMax} left={Number(config.runtime.yAxis.size)} label={config.runtime.xAxis.label} tickFormat={config.runtime.xAxis.type === 'date' ? formatDate : formatNumber} scale={g1xScale} stroke='#333' tickStroke='#333' numTicks={config.runtime.xAxis.numTicks || undefined}>
449
563
  {props => {
450
- const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
451
564
  return (
452
565
  <Group className='bottom-axis'>
453
566
  {props.ticks.map((tick, i) => {
454
- const tickWidth = xMax / props.ticks.length
567
+ const angle = tick.index !== 0 ? config.yAxis.tickRotation : 0
568
+ const textAnchor = tick.index !== 0 && config.yAxis.tickRotation && config.yAxis.tickRotation > 0 ? 'end' : 'middle'
455
569
  return (
456
570
  <Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
457
571
  {!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
458
572
  {!config.runtime.yAxis.hideLabel && (
459
- <Text transform={`translate(${tick.to.x}, ${tick.to.y}) rotate(-${60})`} verticalAnchor='start' textAnchor={'end'} width={config.runtime.xAxis.tickRotation && config.runtime.xAxis.tickRotation !== '0' ? undefined : tickWidth}>
573
+ <Text x={tick.to.x} y={tick.to.y} angle={-angle} verticalAnchor='start' textAnchor={textAnchor}>
460
574
  {formatNumber(tick.formattedValue)}
461
575
  </Text>
462
576
  )}
@@ -479,17 +593,17 @@ export default function LinearChart() {
479
593
  numTicks={config.runtime.xAxis.numTicks || undefined}
480
594
  >
481
595
  {props => {
482
- const axisCenter = (props.axisToPoint.x - props.axisFromPoint.x) / 2
483
596
  return (
484
597
  <>
485
598
  <Group className='bottom-axis'>
486
599
  {props.ticks.map((tick, i) => {
487
- const tickWidth = xMax / props.ticks.length
600
+ const angle = tick.index !== 0 ? config.yAxis.tickRotation : 0
601
+ const textAnchor = tick.index !== 0 && config.yAxis.tickRotation && config.yAxis.tickRotation > 0 ? 'end' : 'middle'
488
602
  return (
489
603
  <Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
490
604
  {!config.runtime.yAxis.hideTicks && <Line from={tick.from} to={tick.to} stroke='#333' />}
491
605
  {!config.runtime.yAxis.hideLabel && (
492
- <Text transform={`translate(${tick.to.x}, ${tick.to.y}) rotate(-${60})`} verticalAnchor='start' textAnchor={'end'} width={config.runtime.xAxis.tickRotation && config.runtime.xAxis.tickRotation !== '0' ? undefined : tickWidth}>
606
+ <Text x={tick.to.x} y={tick.to.y} angle={-angle} verticalAnchor='start' textAnchor={textAnchor}>
493
607
  {tick.formattedValue}
494
608
  </Text>
495
609
  )}
@@ -499,7 +613,7 @@ export default function LinearChart() {
499
613
  {!config.runtime.yAxis.hideAxis && <Line from={props.axisFromPoint} to={props.axisToPoint} stroke='#333' />}
500
614
  </Group>
501
615
  <Group>
502
- <Text transform={`translate(${xMax / 2}, ${yMax + 20}) rotate(-${0})`} verticalAnchor='start' textAnchor={'middle'} stroke='#333'>
616
+ <Text x={xMax / 2} y={config.xAxis.labelOffset} stroke='#333' textAnchor={'middle'} verticalAnchor='start'>
503
617
  {config.runtime.xAxis.label}
504
618
  </Text>
505
619
  </Group>
@@ -509,25 +623,34 @@ export default function LinearChart() {
509
623
  </AxisBottom>
510
624
  </>
511
625
  )}
512
- {config.visualizationType === 'Paired Bar' && <PairedBarChart width={xMax} height={yMax} />}
626
+
627
+ {config.visualizationType === 'Deviation Bar' && <DeviationBar xScale={xScale} yScale={yScale} width={xMax} height={yMax} />}
628
+
629
+ {/* Paired Bar chart */}
630
+ {config.visualizationType === 'Paired Bar' && <PairedBarChart originalWidth={width} width={xMax} height={yMax} />}
513
631
 
514
632
  {/* Bar chart */}
515
- {config.visualizationType !== 'Line' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && (
633
+ {config.visualizationType !== 'Line' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Area Chart' && config.visualizationType !== 'Scatter Plot' && config.visualizationType !== 'Deviation Bar' && (
516
634
  <>
517
635
  <BarChart xScale={xScale} yScale={yScale} seriesScale={seriesScale} xMax={xMax} yMax={yMax} getXAxisData={getXAxisData} getYAxisData={getYAxisData} animatedChart={animatedChart} visible={animatedChart} />
518
636
  </>
519
637
  )}
520
638
 
521
639
  {/* Line chart */}
522
- {config.visualizationType !== 'Bar' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && (
640
+ {config.visualizationType !== 'Bar' && config.visualizationType !== 'Paired Bar' && config.visualizationType !== 'Box Plot' && config.visualizationType !== 'Area Chart' && config.visualizationType !== 'Scatter Plot' && config.visualizationType !== 'Deviation Bar' && (
523
641
  <>
524
642
  <LineChart xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} xMax={xMax} yMax={yMax} seriesStyle={config.series} />
525
643
  </>
526
644
  )}
527
645
 
646
+ {/* Scatter Plot chart */}
647
+ {config.visualizationType === 'Scatter Plot' && <CoveScatterPlot xScale={xScale} yScale={yScale} getXAxisData={getXAxisData} getYAxisData={getYAxisData} />}
648
+
649
+ {/* Box Plot chart */}
528
650
  {config.visualizationType === 'Box Plot' && <CoveBoxPlot xScale={xScale} yScale={yScale} />}
651
+ {config.visualizationType === 'Area Chart' && <CoveAreaChart xScale={xScale} yScale={yScale} yMax={yMax} xMax={xMax} />}
529
652
  </svg>
530
- <ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} html={true} type='light' arrowColor='rgba(0,0,0,0)' className='tooltip' />
653
+ <ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} variant='light' arrowColor='rgba(0,0,0,0)' className='tooltip' />
531
654
  <div className='animation-trigger' ref={triggerRef} />
532
655
  </ErrorBoundary>
533
656
  )