@cdc/chart 4.23.11 → 4.24.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 (103) hide show
  1. package/dist/cdcchart.js +30220 -29764
  2. package/examples/feature/bar/additional-column-tooltip.json +446 -0
  3. package/examples/feature/bar/tall-data.json +98 -0
  4. package/examples/feature/forest-plot/forest-plot.json +63 -19
  5. package/examples/feature/forest-plot/linear.json +52 -3
  6. package/examples/feature/forest-plot/log.json +26 -0
  7. package/examples/feature/forest-plot/logarithmic.json +0 -35
  8. package/examples/feature/line/line-chart-preliminary.json +346 -0
  9. package/examples/feature/scatterplot/scatterplot.json +272 -33
  10. package/examples/private/chart-t.json +3740 -0
  11. package/examples/private/combo.json +369 -0
  12. package/examples/private/epi-data.csv +13 -0
  13. package/examples/private/epi-data.json +62 -0
  14. package/examples/private/epi.json +403 -0
  15. package/examples/private/occupancy.json +109283 -0
  16. package/examples/private/prod-line-config.json +401 -0
  17. package/examples/private/region-data.json +822 -0
  18. package/examples/private/region-testing.json +312 -0
  19. package/examples/private/scaling.json +45325 -0
  20. package/examples/private/testing-data.json +1739 -0
  21. package/examples/private/testing.json +816 -0
  22. package/index.html +7 -7
  23. package/package.json +2 -2
  24. package/src/CdcChart.tsx +29 -210
  25. package/src/ConfigContext.tsx +6 -0
  26. package/src/_stories/ChartEditor.stories.tsx +22 -0
  27. package/src/_stories/ChartLine.preliminary.tsx +19 -0
  28. package/src/_stories/_mock/pie_config.json +191 -0
  29. package/src/_stories/_mock/pie_data.json +218 -0
  30. package/src/_stories/_mock/preliminary_mock.json +346 -0
  31. package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +2 -2
  32. package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +1 -1
  33. package/src/components/AreaChart/index.tsx +4 -0
  34. package/src/components/{BarChart.Horizontal.tsx → BarChart/components/BarChart.Horizontal.tsx} +8 -8
  35. package/src/components/{BarChart.StackedHorizontal.tsx → BarChart/components/BarChart.StackedHorizontal.tsx} +37 -7
  36. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +106 -0
  37. package/src/components/{BarChart.Vertical.tsx → BarChart/components/BarChart.Vertical.tsx} +41 -57
  38. package/src/components/BarChart/components/BarChart.jsx +39 -0
  39. package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
  40. package/src/components/BarChart/components/context.tsx +13 -0
  41. package/src/components/BarChart/index.tsx +3 -0
  42. package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +1 -1
  43. package/src/components/BoxPlot/index.tsx +3 -0
  44. package/src/components/{EditorPanel.jsx → EditorPanel/EditorPanel.tsx} +667 -851
  45. package/src/components/EditorPanel/components/Panel.DateHighlighting.tsx +109 -0
  46. package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panel.ForestPlotSettings.tsx} +87 -166
  47. package/src/components/EditorPanel/components/Panel.Regions.tsx +168 -0
  48. package/src/components/{Series.jsx → EditorPanel/components/Panel.Series.tsx} +1 -1
  49. package/src/components/EditorPanel/components/PanelProps.ts +3 -0
  50. package/src/components/EditorPanel/components/Panels.tsx +13 -0
  51. package/src/components/EditorPanel/components/panels.scss +72 -0
  52. package/src/components/EditorPanel/editor-panel.scss +751 -0
  53. package/src/components/EditorPanel/index.tsx +3 -0
  54. package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +29 -2
  55. package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
  56. package/src/components/Forecasting/index.tsx +3 -0
  57. package/src/components/ForestPlot/ForestPlot.tsx +254 -0
  58. package/src/components/ForestPlot/ForestPlotProps.ts +7 -0
  59. package/src/components/ForestPlot/index.tsx +1 -209
  60. package/src/components/{Legend.jsx → Legend/Legend.tsx} +150 -113
  61. package/src/components/Legend/index.tsx +3 -0
  62. package/src/components/LineChart/LineChartProps.ts +29 -0
  63. package/src/components/LineChart/{LineChart.Circle.tsx → components/LineChart.Circle.tsx} +12 -3
  64. package/src/components/LineChart/helpers.ts +45 -0
  65. package/src/components/LineChart/index.tsx +20 -8
  66. package/src/components/LinearChart.jsx +52 -69
  67. package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +16 -7
  68. package/src/components/PieChart/index.tsx +3 -0
  69. package/src/components/Regions/components/Regions.tsx +135 -0
  70. package/src/components/Regions/index.tsx +3 -0
  71. package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
  72. package/src/components/ScatterPlot/index.tsx +3 -0
  73. package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
  74. package/src/components/Sparkline/index.tsx +3 -0
  75. package/src/data/initial-state.js +5 -6
  76. package/src/helpers/abbreviateNumber.ts +17 -0
  77. package/src/helpers/computeMarginBottom.ts +55 -0
  78. package/src/helpers/filterData.ts +18 -0
  79. package/src/helpers/generateColorsArray.ts +8 -0
  80. package/src/helpers/getQuartiles.ts +30 -0
  81. package/src/helpers/handleChartAriaLabels.ts +19 -0
  82. package/src/helpers/handleLineType.ts +18 -0
  83. package/src/helpers/lineOptions.ts +18 -0
  84. package/src/helpers/sort.ts +7 -0
  85. package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
  86. package/src/hooks/useBarChart.js +7 -6
  87. package/src/hooks/useScales.ts +1 -1
  88. package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +23 -21
  89. package/src/scss/main.scss +67 -3
  90. package/src/types/ChartConfig.ts +158 -23
  91. package/src/types/ChartContext.ts +26 -10
  92. package/src/types/ForestPlot.ts +7 -14
  93. package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
  94. package/src/ConfigContext.jsx +0 -5
  95. package/src/components/BarChart.StackedVertical.tsx +0 -91
  96. package/src/components/BarChart.jsx +0 -30
  97. package/src/components/ForestPlot/Readme.md +0 -0
  98. package/src/scss/LinearChart.scss +0 -0
  99. package/src/scss/editor-panel.scss +0 -745
  100. package/src/scss/legend.scss +0 -206
  101. package/src/scss/mixins.scss +0 -0
  102. package/src/scss/variables.scss +0 -1
  103. package/src/types/ChartProps.ts +0 -7
@@ -0,0 +1,106 @@
1
+ import React, { useContext, useState } from 'react'
2
+ import ConfigContext from '../../../ConfigContext'
3
+ import { useBarChart } from '../../../hooks/useBarChart'
4
+ import { BarStack } from '@visx/shape'
5
+ import { Group } from '@visx/group'
6
+ import { Text } from '@visx/text'
7
+ import BarChartContext from './context'
8
+ import Regions from '../../Regions'
9
+
10
+ const BarChartStackedVertical = () => {
11
+ const [barWidth, setBarWidth] = useState(0)
12
+ const { xScale, yScale, xMax, yMax } = useContext(BarChartContext)
13
+ const { transformedData, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter } = useContext(ConfigContext)
14
+ const { isHorizontal, barBorderWidth, applyRadius, hoveredBar, getAdditionalColumn, onMouseLeaveBar, onMouseOverBar } = useBarChart()
15
+ const { orientation } = config
16
+ const data = config.brush.active && config.brush.data?.length ? config.brush.data : transformedData
17
+
18
+ return (
19
+ config.visualizationSubType === 'stacked' &&
20
+ !isHorizontal && (
21
+ <>
22
+ <BarStack data={data} keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys} x={d => d[config.runtime.xAxis.dataKey]} xScale={xScale} yScale={yScale} color={colorScale}>
23
+ {barStacks =>
24
+ barStacks.reverse().map(barStack =>
25
+ barStack.bars.map(bar => {
26
+ let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
27
+ let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
28
+ let barThickness = xMax / barStack.bars.length
29
+ let barThicknessAdjusted = barThickness * (config.barThickness || 0.8)
30
+ let offset = (barThickness * (1 - (config.barThickness || 0.8))) / 2
31
+ // tooltips
32
+ const xAxisValue = config.runtime.xAxis.type === 'date' ? formatDate(parseDate(data[bar.index][config.runtime.xAxis.dataKey])) : data[bar.index][config.runtime.xAxis.dataKey]
33
+ const yAxisValue = formatNumber(bar.bar ? bar.bar.data[bar.key] : 0, 'left')
34
+ if (!yAxisValue) return
35
+ const style = applyRadius(barStack.index)
36
+ const xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
37
+ const additionalColTooltip = getAdditionalColumn(hoveredBar)
38
+ const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${yAxisValue}`
39
+ const tooltip = `<ul>
40
+ <li class="tooltip-heading"">${xAxisTooltip}</li>
41
+ <li class="tooltip-body ">${tooltipBody}</li>
42
+ <li class="tooltip-body ">${additionalColTooltip}</li>
43
+ </li></ul>`
44
+
45
+ setBarWidth(barThicknessAdjusted)
46
+
47
+ return (
48
+ <Group key={`${barStack.index}--${bar.index}--${orientation}`}>
49
+ <style>
50
+ {`
51
+ #barStack${barStack.index}-${bar.index} rect,
52
+ #barStack${barStack.index}-${bar.index} foreignObject div{
53
+ animation-delay: ${barStack.index * 0.5}s;
54
+ transform-origin: ${barThicknessAdjusted / 2}px ${bar.y + bar.height}px
55
+ }
56
+ `}
57
+ </style>
58
+ <Group key={`bar-stack-${barStack.index}-${bar.index}`} id={`barStack${barStack.index}-${bar.index}`} className='stack vertical'>
59
+ <Text display={config.labels && displayBar ? 'block' : 'none'} opacity={transparentBar ? 0.5 : 1} x={barThickness * bar.index + offset} y={bar.y - 5} fill={'#000'} textAnchor='middle'>
60
+ {yAxisValue}
61
+ </Text>
62
+ <foreignObject
63
+ onMouseOver={() => onMouseOverBar(xAxisValue, bar.key)}
64
+ onMouseLeave={onMouseLeaveBar}
65
+ key={`bar-stack-${barStack.index}-${bar.index}`}
66
+ x={barThickness * bar.index + offset}
67
+ y={bar.y}
68
+ width={barThicknessAdjusted}
69
+ height={bar.height}
70
+ display={displayBar ? 'block' : 'none'}
71
+ data-tooltip-html={tooltip}
72
+ data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
73
+ onClick={e => {
74
+ e.preventDefault()
75
+ if (setSharedFilter) {
76
+ bar[config.xAxis.dataKey] = xAxisValue
77
+ setSharedFilter(config.uid, bar)
78
+ }
79
+ }}
80
+ >
81
+ <div
82
+ style={{
83
+ transition: 'all 0.2s linear',
84
+ opacity: transparentBar ? 0.2 : 1,
85
+ width: barThicknessAdjusted,
86
+ height: bar.height,
87
+ background: colorScale(config.runtime.seriesLabels[bar.key]),
88
+ border: `${config.barHasBorder === 'true' ? barBorderWidth : 0}px solid #333`,
89
+ ...style
90
+ }}
91
+ ></div>
92
+ </foreignObject>
93
+ </Group>
94
+ </Group>
95
+ )
96
+ })
97
+ )
98
+ }
99
+ </BarStack>
100
+ <Regions xScale={xScale} yMax={yMax} barWidth={barWidth} totalBarsInGroup={1} />
101
+ </>
102
+ )
103
+ )
104
+ }
105
+
106
+ export default BarChartStackedVertical
@@ -1,30 +1,55 @@
1
1
  import React, { useContext, useState } from 'react'
2
- import ConfigContext from '../ConfigContext'
3
- import { useBarChart } from '../hooks/useBarChart'
2
+ import ConfigContext from '../../../ConfigContext'
3
+ import { type ChartContext } from '../../../types/ChartContext'
4
+ import { useBarChart } from '../../../hooks/useBarChart'
4
5
  import { Group } from '@visx/group'
5
6
  import { Text } from '@visx/text'
6
7
  import { BarGroup } from '@visx/shape'
7
- import { useHighlightedBars } from '../hooks/useHighlightedBars'
8
+ import { useHighlightedBars } from '../../../hooks/useHighlightedBars'
8
9
  import { FaStar } from 'react-icons/fa'
10
+ import Regions from './../../Regions'
9
11
 
10
12
  // third party
11
13
  import chroma from 'chroma-js'
14
+ import BarChartContext, { type BarChartContextValues } from './context'
12
15
 
13
- import { type BarChartProps } from '../types/ChartProps'
14
-
15
- export const BarChartVertical = (props: BarChartProps) => {
16
- const { xScale, yScale, xMax, yMax, seriesScale } = props
16
+ export const BarChartVertical = () => {
17
+ const { xScale, yScale, xMax, yMax, seriesScale } = useContext<BarChartContextValues>(BarChartContext)
17
18
 
18
19
  const [barWidth, setBarWidth] = useState(0)
19
20
  const [totalBarsInGroup, setTotalBarsInGroup] = useState(0)
20
21
 
21
- const { barBorderWidth, hasMultipleSeries, applyRadius, updateBars, assignColorsToValues, section, lollipopBarWidth, lollipopShapeSize, getHighlightedBarColorByValue, getHighlightedBarByValue, generateIconSize, getAdditionalColumn, hoveredBar, onMouseOverBar, onMouseLeaveBar } = useBarChart()
22
-
23
- // CONTEXT VALUES
24
22
  // prettier-ignore
25
- const { colorScale, config, formatDate, formatNumber, getXAxisData, getYAxisData, isNumber, parseDate, seriesHighlight, setSharedFilter, transformedData, dashboardConfig, setSeriesHighlight } = useContext(ConfigContext)
23
+ const {
24
+ applyRadius,
25
+ assignColorsToValues,
26
+ barBorderWidth,
27
+ generateIconSize,
28
+ getAdditionalColumn,
29
+ getHighlightedBarByValue,
30
+ getHighlightedBarColorByValue,
31
+ lollipopBarWidth,
32
+ lollipopShapeSize,
33
+ onMouseLeaveBar,
34
+ onMouseOverBar,
35
+ section
36
+ } = useBarChart()
26
37
 
27
- const { runtime } = config
38
+ // prettier-ignore
39
+ const {
40
+ colorScale,
41
+ config,
42
+ dashboardConfig,
43
+ formatDate,
44
+ formatNumber,
45
+ getXAxisData,
46
+ getYAxisData,
47
+ isNumber,
48
+ parseDate,
49
+ seriesHighlight,
50
+ setSharedFilter,
51
+ transformedData,
52
+ } = useContext<ChartContext>(ConfigContext)
28
53
 
29
54
  const { HighLightedBarUtils } = useHighlightedBars(config)
30
55
  const data = config.brush.active && config.brush.data?.length ? config.brush.data : transformedData
@@ -89,14 +114,15 @@ export const BarChartVertical = (props: BarChartProps) => {
89
114
  const newIndex = bar.value < 0 ? -1 : index
90
115
  const borderRadius = applyRadius(newIndex)
91
116
  // tooltips
92
- const additionalColTooltip = getAdditionalColumn(hoveredBar)
117
+
118
+ const additionalColTooltip = getAdditionalColumn(bar.key, data[barGroup.index][config.runtime.originalXAxis.dataKey])
93
119
  let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
94
120
  const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${yAxisValue}`
95
121
 
96
122
  const tooltip = `<ul>
97
123
  <li class="tooltip-heading">${xAxisTooltip}</li>
98
124
  <li class="tooltip-body ">${tooltipBody}</li>
99
- <li class="tooltip-body ">${additionalColTooltip}</li>
125
+ ${additionalColTooltip ? '<li class="tooltip-body ">' + additionalColTooltip + '</li>' : ''}
100
126
  </li></ul>`
101
127
 
102
128
  // configure colors
@@ -298,49 +324,7 @@ export const BarChartVertical = (props: BarChartProps) => {
298
324
  })
299
325
  : ''}
300
326
 
301
- {config.regions && config.visualizationType !== 'Combo'
302
- ? config.regions.map(region => {
303
- if (!Object.keys(region).includes('from') || !Object.keys(region).includes('to')) return null
304
-
305
- let from
306
- let to
307
- let width
308
-
309
- if (config.xAxis.type === 'date') {
310
- from = xScale(parseDate(region.from).getTime()) - (barWidth * totalBarsInGroup) / 2
311
- to = xScale(parseDate(region.to).getTime()) + (barWidth * totalBarsInGroup) / 2
312
-
313
- width = to - from
314
- }
315
-
316
- if (config.xAxis.type === 'categorical') {
317
- from = xScale(region.from)
318
- to = xScale(region.to)
319
- width = to - from
320
- }
321
-
322
- if (!from) return null
323
- if (!to) return null
324
-
325
- return (
326
- <Group className='regions' left={0} key={region.label}>
327
- <path
328
- stroke='#333'
329
- d={`M${from} -5
330
- L${from} 5
331
- M${from} 0
332
- L${to} 0
333
- M${to} -5
334
- L${to} 5`}
335
- />
336
- <rect x={from} y={0} width={width} height={yMax} fill={region.background} opacity={0.3} />
337
- <Text x={from + width / 2} y={5} fill={region.color} verticalAnchor='start' textAnchor='middle'>
338
- {region.label}
339
- </Text>
340
- </Group>
341
- )
342
- })
343
- : ''}
327
+ <Regions xScale={xScale} yMax={yMax} barWidth={barWidth} totalBarsInGroup={totalBarsInGroup} />
344
328
  </Group>
345
329
  )
346
330
  )
@@ -0,0 +1,39 @@
1
+ import React, { useContext } from 'react'
2
+
3
+ // visx
4
+ import { Group } from '@visx/group'
5
+ import { Bar } from '@visx/shape'
6
+
7
+ // cdc
8
+ import BarChartType from './BarChartType'
9
+ import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
10
+ import ConfigContext from '../../../ConfigContext'
11
+ import BarChartContext from './context'
12
+
13
+ const BarChart = ({ xScale, yScale, seriesScale, xMax, yMax, handleTooltipMouseOver, handleTooltipMouseOff, handleTooltipClick }) => {
14
+ const { transformedData: data, config } = useContext(ConfigContext)
15
+
16
+ const contextValues = {
17
+ xScale,
18
+ yScale,
19
+ xMax,
20
+ yMax,
21
+ seriesScale
22
+ }
23
+
24
+ return (
25
+ <ErrorBoundary component='BarChart'>
26
+ <BarChartContext.Provider value={contextValues}>
27
+ <Group left={parseFloat(config.runtime.yAxis.size)}>
28
+ <BarChartType.StackedVertical />
29
+ <BarChartType.StackedHorizontal />
30
+ <BarChartType.Vertical />
31
+ <BarChartType.Horizontal />
32
+ <Bar key={'bars'} display={config.tooltips.singleSeries ? 'none' : 'block'} width={Number(xMax)} height={Number(yMax)} fill={'transparent'} fillOpacity={0.05} onMouseMove={e => handleTooltipMouseOver(e, data)} onMouseOut={handleTooltipMouseOff} onClick={e => handleTooltipClick(e, data)} />
33
+ </Group>
34
+ </BarChartContext.Provider>
35
+ </ErrorBoundary>
36
+ )
37
+ }
38
+
39
+ export default BarChart
@@ -1,5 +1,3 @@
1
- import React from 'react'
2
-
3
1
  import BarChartStackedVertical from './BarChart.StackedVertical'
4
2
  import BarChartStackedHorizontal from './BarChart.StackedHorizontal'
5
3
  import BarChartVertical from './BarChart.Vertical'
@@ -0,0 +1,13 @@
1
+ import { createContext } from 'react'
2
+
3
+ const BarChartContext = createContext(null)
4
+
5
+ export type BarChartContextValues = {
6
+ xMax: number
7
+ yMax: number
8
+ xScale: Function
9
+ yScale: Function
10
+ seriesScale: Function
11
+ }
12
+
13
+ export default BarChartContext
@@ -0,0 +1,3 @@
1
+ import BarChart from './components/BarChart'
2
+
3
+ export default BarChart
@@ -1,7 +1,7 @@
1
1
  import React, { useContext, useEffect } from 'react'
2
2
  import { BoxPlot } from '@visx/stats'
3
3
  import { Group } from '@visx/group'
4
- import ConfigContext from '../ConfigContext'
4
+ import ConfigContext from '../../ConfigContext'
5
5
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
6
6
  import { colorPalettesChart } from '@cdc/core/data/colorPalettes'
7
7
 
@@ -0,0 +1,3 @@
1
+ import BoxPlot from './BoxPlot'
2
+
3
+ export default BoxPlot