@cdc/chart 4.23.8 → 4.23.10-alpha
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.
- package/dist/cdcchart.js +43990 -44283
- package/examples/feature/__data__/area-chart-date-apple.json +1 -5073
- package/examples/feature/area/area-chart-date-apple.json +73 -10316
- package/examples/feature/area/area-chart-date-city-temperature.json +204 -80
- package/examples/{private/confidence_interval_test.json → feature/area/area-chart-stacked.json} +65 -74
- package/examples/feature/bar/lollipop.json +156 -0
- package/examples/feature/combo/planet-combo-example-config.json +99 -9
- package/examples/feature/filters/bar-filter.json +5027 -0
- package/examples/feature/legend-highlights/highlights.json +567 -0
- package/examples/private/TESTING.json +0 -0
- package/examples/private/forest-plot.json +356 -0
- package/examples/private/{tooltip-issue.json → full.json} +25288 -25239
- package/examples/private/missing-color.json +333 -0
- package/index.html +30 -8
- package/package.json +3 -2
- package/src/{CdcChart.jsx → CdcChart.tsx} +81 -74
- package/src/_stories/Chart.stories.tsx +188 -0
- package/src/components/AreaChart.Stacked.jsx +73 -0
- package/src/components/AreaChart.jsx +24 -26
- package/src/components/BarChart.StackedVertical.jsx +2 -0
- package/src/components/DeviationBar.jsx +67 -13
- package/src/components/EditorPanel.jsx +493 -454
- package/src/components/Forecasting.jsx +5 -5
- package/src/components/ForestPlotSettings.jsx +5 -6
- package/src/components/Legend.jsx +18 -9
- package/src/components/LineChart.Circle.tsx +102 -0
- package/src/components/{LineChart.jsx → LineChart.tsx} +9 -48
- package/src/components/LinearChart.jsx +460 -443
- package/src/components/PieChart.jsx +54 -25
- package/src/components/Series.jsx +63 -17
- package/src/components/SparkLine.jsx +7 -19
- package/src/data/initial-state.js +10 -1
- package/src/hooks/useBarChart.js +1 -1
- package/src/hooks/useEditorPermissions.js +87 -24
- package/src/hooks/useLegendClasses.js +14 -11
- package/src/hooks/useReduceData.js +6 -1
- package/src/hooks/useScales.js +4 -4
- package/src/hooks/useTooltip.jsx +21 -8
- package/src/scss/legend.scss +206 -0
- package/src/scss/main.scss +25 -24
- package/src/components/DataTable.jsx +0 -374
- /package/src/{components → hooks}/useIntersectionObserver.jsx +0 -0
|
@@ -10,10 +10,8 @@ import { AreaClosed, LinePath, Bar } from '@visx/shape'
|
|
|
10
10
|
import { Group } from '@visx/group'
|
|
11
11
|
import { bisector } from 'd3-array'
|
|
12
12
|
|
|
13
|
-
const AreaChart =
|
|
14
|
-
|
|
15
|
-
const DEBUG = isDebug
|
|
16
|
-
|
|
13
|
+
const AreaChart = props => {
|
|
14
|
+
const { xScale, yScale, yMax, xMax, handleTooltipMouseOver, handleTooltipMouseOff, isDebug, isBrush, brushData, children } = props
|
|
17
15
|
// import data from context
|
|
18
16
|
let { transformedData: data, config, handleLineType, parseDate, formatDate, formatNumber, seriesHighlight, colorScale, rawData } = useContext(ConfigContext)
|
|
19
17
|
|
|
@@ -23,7 +21,7 @@ const AreaChart = ({ xScale, yScale, yMax, xMax, getXAxisData, getYAxisData, cha
|
|
|
23
21
|
if (isBrush && isDebug) console.log('###AREAchart BRUSH data, xScale, yScale, yMax, xMax', data, xScale, yScale, yMax, xMax)
|
|
24
22
|
|
|
25
23
|
// Draw transparent bars over the chart to get tooltip data
|
|
26
|
-
// Turn
|
|
24
|
+
// Turn isDebug on for additional context.
|
|
27
25
|
if (!data) return
|
|
28
26
|
|
|
29
27
|
// Tooltip helper for getting data to the closest date/category hovered.
|
|
@@ -98,29 +96,29 @@ const AreaChart = ({ xScale, yScale, yMax, xMax, getXAxisData, getYAxisData, cha
|
|
|
98
96
|
<React.Fragment key={index}>
|
|
99
97
|
{/* prettier-ignore */}
|
|
100
98
|
<LinePath
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
99
|
+
data={seriesData}
|
|
100
|
+
x={d => handleX(d)}
|
|
101
|
+
y={d => handleY(d, index, s)}
|
|
102
|
+
stroke={displayArea ? colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[s.dataKey] : s.dataKey) : '#000' : 'transparent'}
|
|
103
|
+
strokeWidth={2}
|
|
104
|
+
strokeOpacity={1}
|
|
105
|
+
shapeRendering='geometricPrecision'
|
|
106
|
+
curve={curveType}
|
|
107
|
+
strokeDasharray={s.type ? handleLineType(s.type) : 0}
|
|
108
|
+
/>
|
|
111
109
|
|
|
112
110
|
{/* prettier-ignore */}
|
|
113
111
|
<AreaClosed
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
112
|
+
key={'area-chart'}
|
|
113
|
+
fill={displayArea ? colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[s.dataKey] : s.dataKey) : '#000' : 'transparent'}
|
|
114
|
+
fillOpacity={transparentArea ? 0.25 : 0.5}
|
|
115
|
+
data={seriesData}
|
|
116
|
+
x={d => handleX(d)}
|
|
117
|
+
y={d => handleY(d, index, s)}
|
|
118
|
+
yScale={yScale}
|
|
119
|
+
curve={curveType}
|
|
120
|
+
strokeDasharray={s.type ? handleLineType(s.type) : 0}
|
|
121
|
+
/>
|
|
124
122
|
{getFirstBrushHandleOnly(children, index)}
|
|
125
123
|
</React.Fragment>
|
|
126
124
|
)
|
|
@@ -128,7 +126,7 @@ const AreaChart = ({ xScale, yScale, yMax, xMax, getXAxisData, getYAxisData, cha
|
|
|
128
126
|
|
|
129
127
|
{/* Transparent bar for tooltips - disable if AreaChart is a brush */}
|
|
130
128
|
{/* prettier-ignore */}
|
|
131
|
-
{!isBrush && <Bar width={Number(xMax)} height={Number(yMax)} fill={
|
|
129
|
+
{!isBrush && <Bar width={Number(xMax)} height={Number(yMax)} fill={isDebug ? 'red' : 'transparent'} fillOpacity={0.05} style={isDebug ? { stroke: 'black', strokeWidth: 2 } : {}} onMouseMove={e => handleTooltipMouseOver(e, rawData)} onMouseLeave={handleTooltipMouseOff} />}
|
|
132
130
|
</Group>
|
|
133
131
|
</ErrorBoundary>
|
|
134
132
|
</svg>
|
|
@@ -27,6 +27,8 @@ const BarChartStackedVertical = props => {
|
|
|
27
27
|
const xAxisValue = config.runtime.xAxis.type === 'date' ? formatDate(parseDate(data[bar.index][config.runtime.xAxis.dataKey])) : data[bar.index][config.runtime.xAxis.dataKey]
|
|
28
28
|
const yAxisValue = formatNumber(bar.bar ? bar.bar.data[bar.key] : 0, 'left')
|
|
29
29
|
|
|
30
|
+
if(!yAxisValue) return <></>
|
|
31
|
+
|
|
30
32
|
const style = applyRadius(barStack.index)
|
|
31
33
|
let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${yAxisValue}` : yAxisValue
|
|
32
34
|
const xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { Line } from '@visx/shape'
|
|
2
2
|
import { Group } from '@visx/group'
|
|
3
|
-
import { useContext, useEffect } from 'react'
|
|
3
|
+
import { useContext, useEffect, useRef, useState } from 'react'
|
|
4
4
|
import ConfigContext from '../ConfigContext'
|
|
5
5
|
import { Text } from '@visx/text'
|
|
6
6
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
7
7
|
import chroma from 'chroma-js'
|
|
8
|
+
import useIntersectionObserver from '../hooks/useIntersectionObserver'
|
|
8
9
|
|
|
9
10
|
export default function DeviationBar({ height, xScale }) {
|
|
10
|
-
const { transformedData: data, config, formatNumber, twoColorPalette, getTextWidth, updateConfig, parseDate, formatDate } = useContext(ConfigContext)
|
|
11
|
-
|
|
12
|
-
if (!config || config?.series?.length !== 1 || config.orientation !== 'horizontal') return
|
|
13
|
-
|
|
11
|
+
const { transformedData: data, config, formatNumber, twoColorPalette, getTextWidth, updateConfig, parseDate, formatDate, currentViewport } = useContext(ConfigContext)
|
|
14
12
|
const { barStyle, tipRounding, roundingStyle, twoColor } = config
|
|
15
|
-
|
|
13
|
+
const barRefs = useRef([])
|
|
14
|
+
const [windowWidth, setWindowWidth] = useState(window.innerWidth)
|
|
16
15
|
const radius = roundingStyle === 'standard' ? '8px' : roundingStyle === 'shallow' ? '5px' : roundingStyle === 'finger' ? '15px' : '0px'
|
|
17
16
|
const fontSize = { small: 16, medium: 18, large: 20 }
|
|
18
17
|
const isRounded = config.barStyle === 'rounded'
|
|
@@ -76,14 +75,57 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
76
75
|
}
|
|
77
76
|
targetLabel.calculate()
|
|
78
77
|
|
|
78
|
+
const targetRef = useRef(null)
|
|
79
|
+
|
|
80
|
+
const entry = useIntersectionObserver(targetRef, {})
|
|
81
|
+
|
|
79
82
|
useEffect(() => {
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
const handleResize = () => {
|
|
84
|
+
setWindowWidth(window.innerWidth)
|
|
85
|
+
barRefs.current.forEach(bar => {
|
|
86
|
+
bar.style.transition = 'none'
|
|
87
|
+
bar.style.transform = 'translate(0) scale(1)'
|
|
88
|
+
})
|
|
82
89
|
}
|
|
83
|
-
|
|
84
|
-
|
|
90
|
+
window.addEventListener('resize', handleResize)
|
|
91
|
+
|
|
92
|
+
return () => {
|
|
93
|
+
window.removeEventListener('resize', handleResize)
|
|
85
94
|
}
|
|
86
|
-
}, [
|
|
95
|
+
}, [])
|
|
96
|
+
const [animatedChart, setAnimatedChart] = useState(false)
|
|
97
|
+
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (entry?.isIntersecting) {
|
|
100
|
+
setTimeout(() => {
|
|
101
|
+
setAnimatedChart(true)
|
|
102
|
+
}, 100)
|
|
103
|
+
}
|
|
104
|
+
}, [entry?.isIntersecting, config.animate]) // eslint-disable-line
|
|
105
|
+
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
barRefs.current.forEach((bar, i) => {
|
|
108
|
+
if (config.animate) {
|
|
109
|
+
const normalizedTarget = (target / maxVal) * 100
|
|
110
|
+
bar.style.opacity = '0'
|
|
111
|
+
bar.style.transform = `translate(${normalizedTarget / 1.07}%) scale(0, 1)`
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
bar.style.opacity = '1'
|
|
114
|
+
bar.style.transform = 'translate(0) scale(1)'
|
|
115
|
+
bar.style.transition = 'transform 0.5s ease'
|
|
116
|
+
}, 100)
|
|
117
|
+
} else {
|
|
118
|
+
bar.style.transition = 'none'
|
|
119
|
+
bar.style.opacity = '0'
|
|
120
|
+
}
|
|
121
|
+
if (!config.animate) {
|
|
122
|
+
bar.style.transition = 'none'
|
|
123
|
+
bar.style.opacity = '1'
|
|
124
|
+
}
|
|
125
|
+
})
|
|
126
|
+
}, [config.animate, config, animatedChart])
|
|
127
|
+
|
|
128
|
+
if (!config || config?.series?.length !== 1) return <></>
|
|
87
129
|
|
|
88
130
|
return (
|
|
89
131
|
<ErrorBoundary component='Deviation Bar'>
|
|
@@ -122,7 +164,6 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
122
164
|
const fill = isBarColorDark ? '#FFFFFF' : '#000000'
|
|
123
165
|
|
|
124
166
|
let textProps = getTextProps(config.isLollipopChart, textFits, lollipopShapeSize, fill)
|
|
125
|
-
|
|
126
167
|
// tooltips
|
|
127
168
|
const xAxisValue = formatNumber(barValue, 'left')
|
|
128
169
|
const yAxisValue = config.runtime.yAxis.type === 'date' ? formatDate(parseDate(data[index][config.runtime.originalXAxis.dataKey])) : data[index][config.runtime.originalXAxis.dataKey]
|
|
@@ -135,7 +176,19 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
135
176
|
|
|
136
177
|
return (
|
|
137
178
|
<Group key={`deviation-bar-${config.orientation}-${seriesKey}-${index}`}>
|
|
138
|
-
<foreignObject
|
|
179
|
+
<foreignObject
|
|
180
|
+
ref={el => {
|
|
181
|
+
// targetRef.current = el
|
|
182
|
+
barRefs.current[index] = el
|
|
183
|
+
}}
|
|
184
|
+
x={barX}
|
|
185
|
+
y={barY}
|
|
186
|
+
width={barWidth}
|
|
187
|
+
height={barHeight}
|
|
188
|
+
style={{ border: `${borderWidth}px solid #333`, backgroundColor: barColor[barPosition], ...borderRadius }}
|
|
189
|
+
data-tooltip-html={tooltip}
|
|
190
|
+
data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
191
|
+
/>
|
|
139
192
|
{config.yAxis.displayNumbersOnBar && (
|
|
140
193
|
<Text verticalAnchor='middle' x={textX} y={textY} {...textProps[barPosition]}>
|
|
141
194
|
{formatNumber(d[seriesKey], 'left')}
|
|
@@ -155,6 +208,7 @@ export default function DeviationBar({ height, xScale }) {
|
|
|
155
208
|
|
|
156
209
|
{shouldShowTargetLine && <Line from={{ x: targetX, y: 0 }} to={{ x: targetX, y: height }} stroke='#333' strokeWidth={2} />}
|
|
157
210
|
</Group>
|
|
211
|
+
<foreignObject y={height / 2} ref={targetRef}></foreignObject>
|
|
158
212
|
</ErrorBoundary>
|
|
159
213
|
)
|
|
160
214
|
}
|