@cdc/chart 4.22.10 → 4.22.11

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 (72) hide show
  1. package/README.md +5 -5
  2. package/dist/cdcchart.js +4 -4
  3. package/examples/age-adjusted-rates.json +1486 -1218
  4. package/examples/case-rate-example-config.json +1 -1
  5. package/examples/covid-confidence-example-config.json +33 -33
  6. package/examples/covid-example-config.json +34 -34
  7. package/examples/covid-example-data-confidence.json +30 -30
  8. package/examples/covid-example-data.json +20 -20
  9. package/examples/cutoff-example-config.json +36 -36
  10. package/examples/cutoff-example-data.json +36 -36
  11. package/examples/date-exclusions-config.json +1 -1
  12. package/examples/dynamic-legends.json +124 -124
  13. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json +191 -197
  14. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +230 -240
  15. package/examples/gallery/bar-chart-horizontal/horizontal-stacked.json +239 -247
  16. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +136 -136
  17. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +79 -79
  18. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +80 -80
  19. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +67 -67
  20. package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +110 -110
  21. package/examples/gallery/lollipop/lollipop-style-horizontal.json +215 -219
  22. package/examples/gallery/paired-bar/paired-bar-chart.json +195 -195
  23. package/examples/horizontal-chart.json +35 -35
  24. package/examples/horizontal-stacked-bar-chart.json +34 -34
  25. package/examples/line-chart.json +75 -75
  26. package/examples/paired-bar-data.json +16 -14
  27. package/examples/paired-bar-example.json +48 -48
  28. package/examples/paired-bar-formatted.json +36 -36
  29. package/examples/planet-chart-horizontal-example-config.json +33 -33
  30. package/examples/planet-combo-example-config.json +34 -31
  31. package/examples/planet-example-config.json +35 -33
  32. package/examples/planet-example-data.json +56 -56
  33. package/examples/planet-pie-example-config.json +28 -28
  34. package/examples/private/filters.json +170 -0
  35. package/examples/private/line-test-data.json +21 -21
  36. package/examples/private/line-test-two.json +209 -215
  37. package/examples/private/line-test.json +101 -101
  38. package/examples/private/new.json +48800 -0
  39. package/examples/private/shawn.json +1105 -1295
  40. package/examples/private/test.json +10123 -10123
  41. package/examples/private/yaxis-test.json +4 -3
  42. package/examples/private/yaxis.json +26 -26
  43. package/examples/stacked-vertical-bar-example.json +1 -1
  44. package/examples/temp-example-config.json +61 -54
  45. package/examples/temp-example-data.json +1 -1
  46. package/package.json +2 -2
  47. package/src/CdcChart.tsx +339 -380
  48. package/src/components/BarChart.tsx +425 -469
  49. package/src/components/DataTable.tsx +164 -195
  50. package/src/components/EditorPanel.js +1009 -710
  51. package/src/components/Legend.js +279 -329
  52. package/src/components/LineChart.tsx +90 -79
  53. package/src/components/LinearChart.tsx +376 -434
  54. package/src/components/PairedBarChart.tsx +197 -213
  55. package/src/components/PieChart.tsx +95 -151
  56. package/src/components/SparkLine.js +179 -201
  57. package/src/components/useIntersectionObserver.tsx +17 -20
  58. package/src/context.tsx +3 -3
  59. package/src/data/initial-state.js +37 -16
  60. package/src/hooks/useActiveElement.js +13 -13
  61. package/src/hooks/useChartClasses.js +34 -28
  62. package/src/hooks/useColorPalette.ts +56 -63
  63. package/src/hooks/useLegendClasses.js +18 -10
  64. package/src/hooks/useReduceData.ts +62 -78
  65. package/src/hooks/useRightAxis.js +25 -0
  66. package/src/hooks/useTopAxis.js +6 -0
  67. package/src/index.html +45 -45
  68. package/src/index.tsx +13 -16
  69. package/src/scss/DataTable.scss +5 -4
  70. package/src/scss/editor-panel.scss +71 -69
  71. package/src/scss/main.scss +157 -114
  72. package/src/scss/variables.scss +1 -1
@@ -1,55 +1,51 @@
1
- import React, { useContext, useState, useEffect, useRef } from 'react';
2
- import { animated, useTransition, interpolate } from 'react-spring';
3
- import ReactTooltip from 'react-tooltip';
1
+ import React, { useContext, useState, useEffect, useRef } from 'react'
2
+ import { animated, useTransition, interpolate } from 'react-spring'
3
+ import ReactTooltip from 'react-tooltip'
4
4
 
5
- import Pie, { ProvidedProps, PieArcDatum } from '@visx/shape/lib/shapes/Pie';
6
- import chroma from "chroma-js";
7
- import { Group } from '@visx/group';
8
- import { Text } from '@visx/text';
9
- import useIntersectionObserver from "./useIntersectionObserver";
5
+ import Pie, { ProvidedProps, PieArcDatum } from '@visx/shape/lib/shapes/Pie'
6
+ import chroma from 'chroma-js'
7
+ import { Group } from '@visx/group'
8
+ import { Text } from '@visx/text'
9
+ import useIntersectionObserver from './useIntersectionObserver'
10
10
 
11
- import Context from '../context';
11
+ import Context from '../context'
12
12
 
13
- import ErrorBoundary from '@cdc/core/components/ErrorBoundary';
13
+ import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
14
14
 
15
15
  // react-spring transition definitions
16
- type PieStyles = { startAngle: number; endAngle: number };
16
+ type PieStyles = { startAngle: number; endAngle: number }
17
17
 
18
18
  const enterUpdateTransition = ({ startAngle, endAngle }: PieArcDatum<any>) => ({
19
19
  startAngle,
20
- endAngle,
21
- });
20
+ endAngle
21
+ })
22
22
 
23
23
  export default function PieChart() {
24
- const { transformedData: data, config, dimensions, seriesHighlight, colorScale, formatNumber, currentViewport, handleChartAriaLabels } = useContext<any>(Context);
24
+ const { transformedData: data, config, dimensions, seriesHighlight, colorScale, formatNumber, currentViewport, handleChartAriaLabels } = useContext<any>(Context)
25
25
 
26
- const [filteredData, setFilteredData] = useState<any>(undefined);
27
- const [animatedPie, setAnimatePie] = useState<boolean>(false);
26
+ const [filteredData, setFilteredData] = useState<any>(undefined)
27
+ const [animatedPie, setAnimatePie] = useState<boolean>(false)
28
28
 
29
- const triggerRef = useRef();
29
+ const triggerRef = useRef()
30
30
  const dataRef = useIntersectionObserver(triggerRef, {
31
31
  freezeOnceVisible: false
32
- });
32
+ })
33
33
 
34
- useEffect( () => {
34
+ useEffect(() => {
35
35
  if (dataRef?.isIntersecting && config.animate && !animatedPie) {
36
36
  setTimeout(() => {
37
- setAnimatePie(true);
38
- }, 500);
37
+ setAnimatePie(true)
38
+ }, 500)
39
39
  }
40
40
  }, [dataRef?.isIntersecting, config.animate])
41
41
 
42
42
  type AnimatedPieProps<Datum> = ProvidedProps<Datum> & {
43
- animate?: boolean;
44
- getKey: (d: PieArcDatum<Datum>) => string;
45
- delay?: number;
46
- };
47
-
48
- function AnimatedPie<Datum>({
49
- arcs,
50
- path,
51
- getKey,
52
- }: AnimatedPieProps<Datum>) {
43
+ animate?: boolean
44
+ getKey: (d: PieArcDatum<Datum>) => string
45
+ delay?: number
46
+ }
47
+
48
+ function AnimatedPie<Datum>({ arcs, path, getKey }: AnimatedPieProps<Datum>) {
53
49
  const transitions = useTransition<PieArcDatum<Datum>, PieStyles>(
54
50
  arcs,
55
51
  getKey,
@@ -58,159 +54,107 @@ export default function PieChart() {
58
54
  from: enterUpdateTransition,
59
55
  enter: enterUpdateTransition,
60
56
  update: enterUpdateTransition,
61
- leave: enterUpdateTransition,
62
- },
63
- );
57
+ leave: enterUpdateTransition
58
+ }
59
+ )
64
60
 
65
61
  return (
66
62
  <>
67
- {transitions.map(
68
- ({
69
- item: arc,
70
- props,
71
- key,
72
- }: {
73
- item: PieArcDatum<Datum>;
74
- props: PieStyles;
75
- key: string;
76
- }) => {
77
- let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${formatNumber(arc.data[config.runtime.yAxis.dataKey])}` : formatNumber(arc.data[config.runtime.yAxis.dataKey])
78
- let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${arc.data[config.runtime.xAxis.dataKey]}` : arc.data[config.runtime.xAxis.dataKey]
79
-
80
- const tooltip = `<div>
63
+ {transitions.map(({ item: arc, props, key }: { item: PieArcDatum<Datum>; props: PieStyles; key: string }) => {
64
+ let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${formatNumber(arc.data[config.runtime.yAxis.dataKey])}` : formatNumber(arc.data[config.runtime.yAxis.dataKey])
65
+ let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${arc.data[config.runtime.xAxis.dataKey]}` : arc.data[config.runtime.xAxis.dataKey]
66
+
67
+ const tooltip = `<div>
81
68
  ${yAxisTooltip}<br />
82
69
  ${xAxisTooltip}<br />
83
- Percent: ${Math.round(
84
- (((arc.endAngle - arc.startAngle) * 180) /
85
- Math.PI /
86
- 360) *
87
- 100
88
- ) + "%"}
70
+ Percent: ${Math.round((((arc.endAngle - arc.startAngle) * 180) / Math.PI / 360) * 100) + '%'}
89
71
  `
90
72
 
91
- return (
92
- <Group key={key} style={{ opacity: (config.legend.behavior === "highlight" && seriesHighlight.length > 0 && seriesHighlight.indexOf(arc.data[config.runtime.xAxis.dataKey]) === -1) ? 0.5 : 1 }}>
93
- <animated.path
94
- // compute interpolated path d attribute from intermediate angle values
95
- d={interpolate([props.startAngle, props.endAngle], (startAngle, endAngle) => path({
73
+ return (
74
+ <Group key={key} style={{ opacity: config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(arc.data[config.runtime.xAxis.dataKey]) === -1 ? 0.5 : 1 }}>
75
+ <animated.path
76
+ // compute interpolated path d attribute from intermediate angle values
77
+ d={interpolate([props.startAngle, props.endAngle], (startAngle, endAngle) =>
78
+ path({
96
79
  ...arc,
97
80
  startAngle,
98
- endAngle,
99
- }))}
100
- fill={colorScale(arc.data[config.runtime.xAxis.dataKey])}
101
- data-tip={tooltip}
102
- data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
103
- />
104
- </Group>
105
- );
106
- },
107
- )}
108
- {transitions.map(
109
- ({
110
- item: arc,
111
- key,
112
- }: {
113
- item: PieArcDatum<Datum>;
114
- props: PieStyles;
115
- key: string;
116
- }) => {
117
-
118
- const [centroidX, centroidY] = path.centroid(arc);
119
- const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.1;
120
-
121
- let textColor = "#FFF";
122
- if (colorScale(arc.data[config.runtime.xAxis.dataKey]) && chroma.contrast(textColor, colorScale(arc.data[config.runtime.xAxis.dataKey])) < 3.5) {
123
- textColor = "000";
124
- }
125
-
126
- return (
127
- <animated.g key={key}>
128
- {hasSpaceForLabel && (
129
- <Text
130
- style={{ fill: textColor }}
131
- x={centroidX}
132
- y={centroidY}
133
- dy=".33em"
134
- textAnchor="middle"
135
- pointerEvents="none"
136
- >
137
- {Math.round(
138
- (((arc.endAngle - arc.startAngle) * 180) /
139
- Math.PI /
140
- 360) *
141
- 100
142
- ) + "%"}
143
- </Text>
81
+ endAngle
82
+ })
144
83
  )}
145
- </animated.g>
146
- );
147
- },
148
- )}
84
+ fill={colorScale(arc.data[config.runtime.xAxis.dataKey])}
85
+ data-tip={tooltip}
86
+ data-for={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
87
+ />
88
+ </Group>
89
+ )
90
+ })}
91
+ {transitions.map(({ item: arc, key }: { item: PieArcDatum<Datum>; props: PieStyles; key: string }) => {
92
+ const [centroidX, centroidY] = path.centroid(arc)
93
+ const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.1
94
+
95
+ let textColor = '#FFF'
96
+ if (colorScale(arc.data[config.runtime.xAxis.dataKey]) && chroma.contrast(textColor, colorScale(arc.data[config.runtime.xAxis.dataKey])) < 3.5) {
97
+ textColor = '000'
98
+ }
99
+
100
+ return (
101
+ <animated.g key={key}>
102
+ {hasSpaceForLabel && (
103
+ <Text style={{ fill: textColor }} x={centroidX} y={centroidY} dy='.33em' textAnchor='middle' pointerEvents='none'>
104
+ {Math.round((((arc.endAngle - arc.startAngle) * 180) / Math.PI / 360) * 100) + '%'}
105
+ </Text>
106
+ )}
107
+ </animated.g>
108
+ )
109
+ })}
149
110
  </>
150
- );
111
+ )
151
112
  }
152
113
 
153
- let [ width ] = dimensions;
114
+ let [width] = dimensions
154
115
 
155
- if(config && config.legend && !config.legend.hide && currentViewport === 'lg') {
156
- width = width * 0.73;
116
+ if (config && config.legend && !config.legend.hide && currentViewport === 'lg') {
117
+ width = width * 0.73
157
118
  }
158
119
 
159
- const height = config.aspectRatio ? (width * config.aspectRatio) : config.height;
120
+ const height = config.aspectRatio ? width * config.aspectRatio : config.height
160
121
 
161
- const radius = Math.min(width, height) / 2;
162
- const centerY = height / 2;
163
- const centerX = width / 2;
164
- const donutThickness = (config.pieType === "Donut") ? 75 : radius;
122
+ const radius = Math.min(width, height) / 2
123
+ const centerY = height / 2
124
+ const centerX = width / 2
125
+ const donutThickness = config.pieType === 'Donut' ? 75 : radius
165
126
 
166
127
  useEffect(() => {
167
- if(seriesHighlight.length > 0 && config.legend.behavior !== "highlight"){
168
- let newFilteredData = [];
128
+ if (seriesHighlight.length > 0 && config.legend.behavior !== 'highlight') {
129
+ let newFilteredData = []
169
130
 
170
- data.forEach((d) => {
171
- if(seriesHighlight.indexOf(d[config.runtime.xAxis.dataKey]) !== -1) {
172
- newFilteredData.push(d);
131
+ data.forEach(d => {
132
+ if (seriesHighlight.indexOf(d[config.runtime.xAxis.dataKey]) !== -1) {
133
+ newFilteredData.push(d)
173
134
  }
174
- });
135
+ })
175
136
 
176
- setFilteredData(newFilteredData);
137
+ setFilteredData(newFilteredData)
177
138
  } else {
178
- setFilteredData(undefined);
139
+ setFilteredData(undefined)
179
140
  }
180
- }, [seriesHighlight]);
141
+ }, [seriesHighlight])
181
142
 
182
143
  useEffect(() => {
183
- ReactTooltip.rebuild();
184
- });
144
+ ReactTooltip.rebuild()
145
+ })
185
146
 
186
147
  return (
187
- <ErrorBoundary component="PieChart">
188
- <svg
189
- width={width}
190
- height={height}
191
- className={`group ${animatedPie ? 'animated' : ''}`}
192
- role="img"
193
- aria-label={handleChartAriaLabels(config)}
194
- >
148
+ <ErrorBoundary component='PieChart'>
149
+ <svg width={width} height={height} className={`group ${animatedPie ? 'animated' : ''}`} role='img' aria-label={handleChartAriaLabels(config)}>
195
150
  <Group top={centerY} left={centerX}>
196
- <Pie
197
- data={filteredData || data}
198
- pieValue={d => d[config.runtime.yAxis.dataKey]}
199
- pieSortValues={() => -1}
200
- innerRadius={radius - donutThickness}
201
- outerRadius={radius}
202
- >
203
- {pie => (
204
- <AnimatedPie<any>
205
- {...pie}
206
- getKey={d => d.data[config.runtime.xAxis.dataKey]}
207
- />
208
- )}
151
+ <Pie data={filteredData || data} pieValue={d => d[config.runtime.yAxis.dataKey]} pieSortValues={() => -1} innerRadius={radius - donutThickness} outerRadius={radius}>
152
+ {pie => <AnimatedPie<any> {...pie} getKey={d => d.data[config.runtime.xAxis.dataKey]} />}
209
153
  </Pie>
210
154
  </Group>
211
155
  </svg>
212
156
  <div ref={triggerRef} />
213
- <ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} html={true} type="light" arrowColor="rgba(0,0,0,0)" className="tooltip"/>
157
+ <ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} html={true} type='light' arrowColor='rgba(0,0,0,0)' className='tooltip' />
214
158
  </ErrorBoundary>
215
159
  )
216
160
  }