@cdc/chart 4.23.9 → 4.23.10
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/LICENSE +201 -0
- package/dist/cdcchart.js +44099 -44436
- 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/feature/area/area-chart-stacked.json +239 -0
- package/examples/feature/filters/bar-filter.json +5027 -0
- package/examples/feature/legend-highlights/highlights.json +567 -0
- package/index.html +9 -6
- package/package.json +3 -2
- package/src/{CdcChart.jsx → CdcChart.tsx} +77 -71
- package/src/components/AreaChart.Stacked.jsx +73 -0
- package/src/components/AreaChart.jsx +24 -26
- package/src/components/DeviationBar.jsx +67 -13
- package/src/components/EditorPanel.jsx +483 -452
- package/src/components/Forecasting.jsx +5 -5
- package/src/components/Legend.jsx +6 -5
- package/src/components/LineChart.Circle.tsx +108 -0
- package/src/components/{LineChart.jsx → LineChart.tsx} +10 -42
- 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 +6 -0
- package/src/hooks/useEditorPermissions.js +87 -24
- package/src/hooks/useReduceData.js +5 -0
- package/src/hooks/useScales.js +1 -1
- package/src/hooks/useTooltip.jsx +19 -6
- package/src/scss/main.scss +6 -12
- package/src/components/DataTable.jsx +0 -494
- /package/src/{components → hooks}/useIntersectionObserver.jsx +0 -0
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import React, { useContext, useState, useEffect, useRef } from 'react'
|
|
2
2
|
import { animated, useTransition, interpolate } from 'react-spring'
|
|
3
|
-
import { Tooltip as ReactTooltip } from 'react-tooltip'
|
|
4
|
-
|
|
5
|
-
import Pie from '@visx/shape/lib/shapes/Pie'
|
|
6
3
|
import chroma from 'chroma-js'
|
|
4
|
+
|
|
5
|
+
// visx
|
|
6
|
+
import { Pie } from '@visx/shape'
|
|
7
7
|
import { Group } from '@visx/group'
|
|
8
8
|
import { Text } from '@visx/text'
|
|
9
|
-
import
|
|
9
|
+
import { useTooltip, TooltipWithBounds } from '@visx/tooltip'
|
|
10
10
|
|
|
11
|
+
// cove
|
|
11
12
|
import ConfigContext from '../ConfigContext'
|
|
12
|
-
|
|
13
|
+
import { useTooltip as useCoveTooltip } from '../hooks/useTooltip'
|
|
14
|
+
import useIntersectionObserver from '../hooks/useIntersectionObserver'
|
|
13
15
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
14
16
|
|
|
15
17
|
const enterUpdateTransition = ({ startAngle, endAngle }) => ({
|
|
@@ -17,9 +19,15 @@ const enterUpdateTransition = ({ startAngle, endAngle }) => ({
|
|
|
17
19
|
endAngle
|
|
18
20
|
})
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
const { transformedData: data, config, dimensions, seriesHighlight, colorScale, formatNumber, currentViewport, handleChartAriaLabels } = useContext(ConfigContext)
|
|
22
|
-
|
|
22
|
+
const PieChart = props => {
|
|
23
|
+
const { transformedData: data, config, dimensions, seriesHighlight, colorScale, formatNumber, currentViewport, handleChartAriaLabels, isEditor } = useContext(ConfigContext)
|
|
24
|
+
const { tooltipData, showTooltip, hideTooltip, tooltipOpen, tooltipLeft, tooltipTop } = useTooltip()
|
|
25
|
+
const { handleTooltipMouseOver, handleTooltipMouseOff, TooltipListItem } = useCoveTooltip({
|
|
26
|
+
xScale: false,
|
|
27
|
+
yScale: false,
|
|
28
|
+
showTooltip,
|
|
29
|
+
hideTooltip
|
|
30
|
+
})
|
|
23
31
|
const [filteredData, setFilteredData] = useState(undefined)
|
|
24
32
|
const [animatedPie, setAnimatePie] = useState(false)
|
|
25
33
|
|
|
@@ -29,7 +37,6 @@ export default function PieChart() {
|
|
|
29
37
|
})
|
|
30
38
|
|
|
31
39
|
// Make sure the chart is visible if in the editor
|
|
32
|
-
/* eslint-disable react-hooks/exhaustive-deps */
|
|
33
40
|
useEffect(() => {
|
|
34
41
|
const element = document.querySelector('.isEditor')
|
|
35
42
|
if (element) {
|
|
@@ -46,7 +53,7 @@ export default function PieChart() {
|
|
|
46
53
|
}
|
|
47
54
|
}, [dataRef?.isIntersecting, config.animate]) // eslint-disable-line
|
|
48
55
|
|
|
49
|
-
|
|
56
|
+
const AnimatedPie = ({ arcs, path, getKey }) => {
|
|
50
57
|
const transitions = useTransition(arcs, getKey, {
|
|
51
58
|
from: enterUpdateTransition,
|
|
52
59
|
enter: enterUpdateTransition,
|
|
@@ -54,19 +61,24 @@ export default function PieChart() {
|
|
|
54
61
|
leave: enterUpdateTransition
|
|
55
62
|
})
|
|
56
63
|
|
|
64
|
+
// DEV-5053
|
|
65
|
+
// onMouseLeave function doesn't work on animated.path for some reason.
|
|
66
|
+
// As a workaround, we continue to fire the tooltipData while hovered,
|
|
67
|
+
// and use this useEffect to hide the tooltip so it doesn't persist when users scroll.
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
const timeout = setTimeout(() => {
|
|
70
|
+
hideTooltip()
|
|
71
|
+
}, 500)
|
|
72
|
+
return () => {
|
|
73
|
+
clearTimeout(timeout)
|
|
74
|
+
}
|
|
75
|
+
}, [tooltipData])
|
|
76
|
+
|
|
57
77
|
return (
|
|
58
78
|
<>
|
|
59
|
-
{transitions.map(({ item: arc, props, key }) => {
|
|
60
|
-
let yAxisTooltip = config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ${formatNumber(arc.data[config.runtime.yAxis.dataKey])}` : formatNumber(arc.data[config.runtime.yAxis.dataKey])
|
|
61
|
-
let xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${arc.data[config.runtime.xAxis.dataKey]}` : arc.data[config.runtime.xAxis.dataKey]
|
|
62
|
-
|
|
63
|
-
const tooltip = `<div>
|
|
64
|
-
${yAxisTooltip}<br />
|
|
65
|
-
${xAxisTooltip}<br />
|
|
66
|
-
Percent: ${Math.round((((arc.endAngle - arc.startAngle) * 180) / Math.PI / 360) * 100) + '%'}
|
|
67
|
-
`
|
|
79
|
+
{transitions.map(({ item: arc, props, key }, animatedPieIndex) => {
|
|
68
80
|
return (
|
|
69
|
-
<Group key={key} style={{ opacity: config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(arc.data[config.runtime.xAxis.dataKey]) === -1 ? 0.5 : 1 }}>
|
|
81
|
+
<Group className={arc.data[config.xAxis.dataKey]} key={`${key}-${animatedPieIndex}`} style={{ opacity: config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(arc.data[config.runtime.xAxis.dataKey]) === -1 ? 0.5 : 1 }}>
|
|
70
82
|
<animated.path
|
|
71
83
|
d={interpolate([props.startAngle, props.endAngle], (startAngle, endAngle) =>
|
|
72
84
|
path({
|
|
@@ -76,8 +88,8 @@ export default function PieChart() {
|
|
|
76
88
|
})
|
|
77
89
|
)}
|
|
78
90
|
fill={colorScale(arc.data[config.runtime.xAxis.dataKey])}
|
|
79
|
-
|
|
80
|
-
|
|
91
|
+
onMouseEnter={e => handleTooltipMouseOver(e, { data: arc.data[config.runtime.xAxis.dataKey], arc })}
|
|
92
|
+
onMouseLeave={e => handleTooltipMouseOff()}
|
|
81
93
|
/>
|
|
82
94
|
</Group>
|
|
83
95
|
)
|
|
@@ -138,13 +150,30 @@ export default function PieChart() {
|
|
|
138
150
|
<ErrorBoundary component='PieChart'>
|
|
139
151
|
<svg width={width} height={height} className={`animated-pie group ${config.animate === false || animatedPie ? 'animated' : ''}`} role='img' aria-label={handleChartAriaLabels(config)}>
|
|
140
152
|
<Group top={centerY} left={centerX}>
|
|
141
|
-
|
|
142
|
-
|
|
153
|
+
{/* prettier-ignore */}
|
|
154
|
+
<Pie
|
|
155
|
+
data={filteredData || data}
|
|
156
|
+
pieValue={d => d[config.runtime.yAxis.dataKey]}
|
|
157
|
+
pieSortValues={() => -1}
|
|
158
|
+
innerRadius={radius - donutThickness}
|
|
159
|
+
outerRadius={radius}
|
|
160
|
+
>
|
|
161
|
+
{pie => <AnimatedPie {...pie} getKey={d => d.data[config.runtime.xAxis.dataKey]}/>}
|
|
143
162
|
</Pie>
|
|
144
163
|
</Group>
|
|
145
164
|
</svg>
|
|
146
165
|
<div ref={triggerRef} />
|
|
147
|
-
|
|
166
|
+
{tooltipData && Object.entries(tooltipData.data).length > 0 && tooltipOpen && showTooltip && tooltipData.dataYPosition && tooltipData.dataXPosition && (
|
|
167
|
+
<>
|
|
168
|
+
<style>{`.tooltip {background-color: rgba(255,255,255, ${config.tooltips.opacity / 100}) !important`}</style>
|
|
169
|
+
<TooltipWithBounds key={Math.random()} className={'tooltip cdc-open-viz-module'} left={tooltipLeft} top={tooltipTop}>
|
|
170
|
+
<ul>{typeof tooltipData === 'object' && Object.entries(tooltipData.data).map((item, index) => <TooltipListItem item={item} key={index} />)}</ul>
|
|
171
|
+
</TooltipWithBounds>
|
|
172
|
+
</>
|
|
173
|
+
)}
|
|
174
|
+
{/* <ReactTooltip id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`} variant='light' arrowColor='rgba(0,0,0,0)' className='tooltip' /> */}
|
|
148
175
|
</ErrorBoundary>
|
|
149
176
|
)
|
|
150
177
|
}
|
|
178
|
+
|
|
179
|
+
export default PieChart
|
|
@@ -4,13 +4,14 @@ import ConfigContext from '../ConfigContext'
|
|
|
4
4
|
// Core
|
|
5
5
|
import InputSelect from '@cdc/core/components/inputs/InputSelect'
|
|
6
6
|
import Check from '@cdc/core/assets/icon-check.svg'
|
|
7
|
+
import { approvedCurveTypes } from '@cdc/core/helpers/lineChartHelpers'
|
|
7
8
|
|
|
8
9
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
9
10
|
|
|
10
11
|
// Third Party
|
|
11
12
|
import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemPanel, AccordionItemButton } from 'react-accessible-accordion'
|
|
12
13
|
import { Draggable } from '@hello-pangea/dnd'
|
|
13
|
-
import { colorPalettesChart } from '@cdc/core/data/colorPalettes'
|
|
14
|
+
import { colorPalettesChart, sequentialPalettes } from '@cdc/core/data/colorPalettes'
|
|
14
15
|
|
|
15
16
|
const SeriesContext = React.createContext()
|
|
16
17
|
|
|
@@ -36,9 +37,17 @@ const SeriesDropdownLineType = props => {
|
|
|
36
37
|
const { series, index } = props
|
|
37
38
|
|
|
38
39
|
// Run a quick test to determine if we should even show this.
|
|
39
|
-
const supportsLineType =
|
|
40
|
+
const supportsLineType = () => {
|
|
41
|
+
let supported = false
|
|
42
|
+
if (config.visualizationSubType === 'stacked') return supported
|
|
43
|
+
const supportedCharts = ['Line', 'dashed-sm', 'dashed-md', 'dashed-lg', 'Area Chart']
|
|
44
|
+
if (supportedCharts.some(item => item.includes(series.type))) {
|
|
45
|
+
supported = true
|
|
46
|
+
}
|
|
47
|
+
return supported
|
|
48
|
+
}
|
|
40
49
|
|
|
41
|
-
if (!supportsLineType) return
|
|
50
|
+
if (!supportsLineType()) return
|
|
42
51
|
|
|
43
52
|
const changeLineType = (i, value) => {
|
|
44
53
|
let series = [...config.series]
|
|
@@ -46,14 +55,6 @@ const SeriesDropdownLineType = props => {
|
|
|
46
55
|
updateConfig({ ...config, series })
|
|
47
56
|
}
|
|
48
57
|
|
|
49
|
-
const approvedCurveTypes = {
|
|
50
|
-
Linear: 'curveLinear',
|
|
51
|
-
Cardinal: 'curveCardinal',
|
|
52
|
-
Natural: 'curveNatural',
|
|
53
|
-
'Monotone X': 'curveMonotoneX',
|
|
54
|
-
Step: 'curveStep'
|
|
55
|
-
}
|
|
56
|
-
|
|
57
58
|
let options = []
|
|
58
59
|
|
|
59
60
|
Object.keys(approvedCurveTypes).map(curveName => {
|
|
@@ -218,6 +219,10 @@ const SeriesDropdownForecastColor = props => {
|
|
|
218
219
|
// Hide AxisPositionDropdown in certain cases.
|
|
219
220
|
if (!series) return
|
|
220
221
|
|
|
222
|
+
const allowedForecastingColors = () => {
|
|
223
|
+
return Object.keys(sequentialPalettes)
|
|
224
|
+
}
|
|
225
|
+
|
|
221
226
|
return series?.stages?.map((stage, stageIndex) => (
|
|
222
227
|
<InputSelect
|
|
223
228
|
key={`${stage}--${stageIndex}`}
|
|
@@ -235,7 +240,7 @@ const SeriesDropdownForecastColor = props => {
|
|
|
235
240
|
series: copyOfSeries
|
|
236
241
|
})
|
|
237
242
|
}}
|
|
238
|
-
options={Object.keys(
|
|
243
|
+
options={Object.keys(sequentialPalettes)}
|
|
239
244
|
/>
|
|
240
245
|
))
|
|
241
246
|
}
|
|
@@ -290,7 +295,7 @@ const SeriesDropdownConfidenceInterval = props => {
|
|
|
290
295
|
</>
|
|
291
296
|
</AccordionItemHeading>
|
|
292
297
|
<AccordionItemPanel>
|
|
293
|
-
|
|
298
|
+
<div className='input-group'>
|
|
294
299
|
<label htmlFor='showInTooltip'>Show In Tooltip</label>
|
|
295
300
|
<div className={'cove-input__checkbox--small'} onClick={e => updateShowInTooltip(e, index, ciIndex)}>
|
|
296
301
|
<div className={`cove-input__checkbox-box${'blue' ? ' custom-color' : ''}`} style={{ backgroundColor: '' }}>
|
|
@@ -298,7 +303,45 @@ const SeriesDropdownConfidenceInterval = props => {
|
|
|
298
303
|
</div>
|
|
299
304
|
<input className='cove-input--hidden' type='checkbox' name={'showInTooltip'} checked={showInTooltip ? showInTooltip : false} readOnly />
|
|
300
305
|
</div>
|
|
301
|
-
</div>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
{/* <label>
|
|
309
|
+
High Label
|
|
310
|
+
<input
|
|
311
|
+
type='text'
|
|
312
|
+
key={`series-ci-high-label-${index}`}
|
|
313
|
+
value={series.confidenceIntervals[index]?.highLabel ? series.confidenceIntervals[index]?.highLabel : ''}
|
|
314
|
+
onChange={e => {
|
|
315
|
+
const copiedConfidenceArray = [...config.series[index].confidenceIntervals]
|
|
316
|
+
copiedConfidenceArray[ciIndex].highLabel = e.target.value
|
|
317
|
+
const copyOfSeries = [...config.series] // copy the entire series array
|
|
318
|
+
copyOfSeries[index] = { ...copyOfSeries[index], confidenceIntervals: copiedConfidenceArray }
|
|
319
|
+
updateConfig({
|
|
320
|
+
...config,
|
|
321
|
+
series: copyOfSeries
|
|
322
|
+
})
|
|
323
|
+
}}
|
|
324
|
+
/>
|
|
325
|
+
</label> */}
|
|
326
|
+
|
|
327
|
+
{/* <label>
|
|
328
|
+
Low label
|
|
329
|
+
<input
|
|
330
|
+
type='text'
|
|
331
|
+
key={`series-ci-high-label-${index}`}
|
|
332
|
+
value={series.confidenceIntervals[index]?.lowLabel ? series.confidenceIntervals[index]?.lowLabel : ''}
|
|
333
|
+
onChange={e => {
|
|
334
|
+
const copiedConfidenceArray = [...config.series[index].confidenceIntervals]
|
|
335
|
+
copiedConfidenceArray[ciIndex].lowLabel = e.target.value
|
|
336
|
+
const copyOfSeries = [...config.series] // copy the entire series array
|
|
337
|
+
copyOfSeries[index] = { ...copyOfSeries[index], confidenceIntervals: copiedConfidenceArray }
|
|
338
|
+
updateConfig({
|
|
339
|
+
...config,
|
|
340
|
+
series: copyOfSeries
|
|
341
|
+
})
|
|
342
|
+
}}
|
|
343
|
+
/>
|
|
344
|
+
</label> */}
|
|
302
345
|
|
|
303
346
|
<InputSelect
|
|
304
347
|
initial='Select an option'
|
|
@@ -375,11 +418,15 @@ const SeriesInputName = props => {
|
|
|
375
418
|
let series = [...config.series]
|
|
376
419
|
let seriesLabelsCopy = { ...config.runtime.seriesLabels }
|
|
377
420
|
series[i].name = value
|
|
378
|
-
seriesLabelsCopy[series[i].dataKey] = series[i].name
|
|
421
|
+
seriesLabelsCopy[series[i].dataKey] = series[i].name ? series[i].name : series[i].dataKey
|
|
379
422
|
|
|
380
423
|
let newConfig = {
|
|
381
424
|
...config,
|
|
382
|
-
series
|
|
425
|
+
series,
|
|
426
|
+
runtime: {
|
|
427
|
+
...config.runtime,
|
|
428
|
+
seriesLabels: seriesLabelsCopy
|
|
429
|
+
}
|
|
383
430
|
}
|
|
384
431
|
|
|
385
432
|
updateConfig(newConfig)
|
|
@@ -506,7 +553,6 @@ const SeriesItem = props => {
|
|
|
506
553
|
<Series.Dropdown.SeriesType series={series} index={i} />
|
|
507
554
|
<Series.Dropdown.AxisPosition series={series} index={i} />
|
|
508
555
|
<Series.Dropdown.LineType series={series} index={i} />
|
|
509
|
-
{/* <Series.Dropdown.ForecastingStage series={series} index={i} /> */}
|
|
510
556
|
<Series.Dropdown.ForecastingColor series={series} index={i} />
|
|
511
557
|
<Series.Dropdown.ConfidenceInterval series={series} index={i} />
|
|
512
558
|
<Series.Checkbox.DisplayInTooltip series={series} index={i} />
|
|
@@ -6,6 +6,7 @@ import { LinePath } from '@visx/shape'
|
|
|
6
6
|
import { Text } from '@visx/text'
|
|
7
7
|
import { scaleLinear, scalePoint } from '@visx/scale'
|
|
8
8
|
import { AxisBottom } from '@visx/axis'
|
|
9
|
+
|
|
9
10
|
import { MarkerArrow } from '@visx/marker'
|
|
10
11
|
|
|
11
12
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
@@ -14,7 +15,8 @@ import useReduceData from '../hooks/useReduceData'
|
|
|
14
15
|
|
|
15
16
|
import ConfigContext from '../ConfigContext'
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
const SparkLine = props => {
|
|
19
|
+
const { width: parentWidth, height: parentHeight } = props
|
|
18
20
|
const { transformedData: data, config, parseDate, formatDate, seriesHighlight, formatNumber, colorScale, handleChartAriaLabels } = useContext(ConfigContext)
|
|
19
21
|
let width = parentWidth
|
|
20
22
|
const { minValue, maxValue } = useReduceData(config, data, ConfigContext)
|
|
@@ -91,16 +93,14 @@ export default function SparkLine({ width: parentWidth, height: parentHeight })
|
|
|
91
93
|
|
|
92
94
|
return (
|
|
93
95
|
<ErrorBoundary component='SparkLine'>
|
|
94
|
-
<svg role='img' aria-label={handleChartAriaLabels(config)} width={
|
|
96
|
+
<svg role='img' aria-label={handleChartAriaLabels(config)} width={parentWidth} height={100} className={'sparkline'} tabIndex={0}>
|
|
95
97
|
{config.runtime.lineSeriesKeys?.length > 0
|
|
96
98
|
? config.runtime.lineSeriesKeys
|
|
97
99
|
: config.runtime.seriesKeys.map((seriesKey, index) => (
|
|
98
100
|
<>
|
|
99
101
|
<Group
|
|
102
|
+
style={{ width }}
|
|
100
103
|
className='sparkline-group'
|
|
101
|
-
height={parentHeight}
|
|
102
|
-
style={{ height: parentHeight }}
|
|
103
|
-
top={margin.top}
|
|
104
104
|
key={`series-${seriesKey}`}
|
|
105
105
|
opacity={config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(seriesKey) === -1 ? 0.5 : 1}
|
|
106
106
|
display={config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(seriesKey) !== -1 ? 'block' : 'none'}
|
|
@@ -115,25 +115,11 @@ export default function SparkLine({ width: parentWidth, height: parentHeight })
|
|
|
115
115
|
${config.seriesLabel ? `${config.seriesLabel}: ${seriesKey}` : ''}
|
|
116
116
|
</div>`
|
|
117
117
|
|
|
118
|
-
let circleRadii = 4.5
|
|
119
118
|
return (
|
|
120
119
|
<Group key={`series-${seriesKey}-point-${dataIndex}`}>
|
|
121
120
|
<Text display={config.labels ? 'block' : 'none'} x={xScale(getXAxisData(d))} y={yScale(getYAxisData(d, seriesKey))} fill={colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[seriesKey] : seriesKey) : '#000'} textAnchor='middle'>
|
|
122
121
|
{formatNumber(d[seriesKey])}
|
|
123
122
|
</Text>
|
|
124
|
-
{/* hide data point circles */}
|
|
125
|
-
{/* dataIndex + 1 !== data.length && (config.lineDatapointStyle === 'always show' || config.lineDatapointStyle === 'hover') && (
|
|
126
|
-
<circle
|
|
127
|
-
key={`${seriesKey}-${dataIndex}`}
|
|
128
|
-
r={circleRadii}
|
|
129
|
-
cx={xScale(getXAxisData(d))}
|
|
130
|
-
cy={yScale(getYAxisData(d, seriesKey))}
|
|
131
|
-
fill={colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[seriesKey] : seriesKey) : '#000'}
|
|
132
|
-
style={{ fill: colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[seriesKey] : seriesKey) : '#000' }}
|
|
133
|
-
data-tooltip-html={tooltip}
|
|
134
|
-
data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
|
|
135
|
-
/>
|
|
136
|
-
)*/}
|
|
137
123
|
</Group>
|
|
138
124
|
)
|
|
139
125
|
})}
|
|
@@ -180,3 +166,5 @@ export default function SparkLine({ width: parentWidth, height: parentHeight })
|
|
|
180
166
|
</ErrorBoundary>
|
|
181
167
|
)
|
|
182
168
|
}
|
|
169
|
+
|
|
170
|
+
export default SparkLine
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
type: 'chart',
|
|
3
3
|
debugSvg: false,
|
|
4
|
+
chartMessage: {
|
|
5
|
+
noData: 'No Data Available'
|
|
6
|
+
},
|
|
4
7
|
title: '',
|
|
5
8
|
showTitle: true,
|
|
6
9
|
showDownloadMediaButton: false,
|
|
@@ -219,5 +222,8 @@ export default {
|
|
|
219
222
|
brush: {
|
|
220
223
|
pattern_id: 'brush_pattern',
|
|
221
224
|
accent_color: '#ddd'
|
|
225
|
+
},
|
|
226
|
+
area: {
|
|
227
|
+
isStacked: false
|
|
222
228
|
}
|
|
223
229
|
}
|
|
@@ -14,7 +14,7 @@ export const useEditorPermissions = () => {
|
|
|
14
14
|
'Combo',
|
|
15
15
|
'Deviation Bar',
|
|
16
16
|
'Forecasting',
|
|
17
|
-
|
|
17
|
+
'Forest Plot',
|
|
18
18
|
'Line',
|
|
19
19
|
'Paired Bar',
|
|
20
20
|
'Pie',
|
|
@@ -22,14 +22,28 @@ export const useEditorPermissions = () => {
|
|
|
22
22
|
'Spark Line'
|
|
23
23
|
]
|
|
24
24
|
|
|
25
|
+
const headerColors = ['theme-blue', 'theme-purple', 'theme-brown', 'theme-teal', 'theme-pink', 'theme-orange', 'theme-slate', 'theme-indigo', 'theme-cyan', 'theme-green', 'theme-amber']
|
|
26
|
+
|
|
27
|
+
const visSupportsSuperTitle = () => {
|
|
28
|
+
const disabledCharts = ['Spark Line']
|
|
29
|
+
if (disabledCharts.includes(visualizationType)) return false
|
|
30
|
+
return true
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const visSupportsFootnotes = () => {
|
|
34
|
+
const disabledCharts = ['Spark Line']
|
|
35
|
+
if (disabledCharts.includes(visualizationType)) return false
|
|
36
|
+
return true
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
const visHasLabelOnData = () => {
|
|
26
|
-
const disabledCharts = ['Area Chart', 'Box Plot', 'Pie', 'Scatter Plot', 'Forest Plot']
|
|
40
|
+
const disabledCharts = ['Area Chart', 'Box Plot', 'Pie', 'Scatter Plot', 'Forest Plot', 'Spark Line']
|
|
27
41
|
if (disabledCharts.includes(visualizationType)) return false
|
|
28
42
|
return true
|
|
29
43
|
}
|
|
30
44
|
|
|
31
45
|
const visCanAnimate = () => {
|
|
32
|
-
const disabledCharts = ['Area Chart', 'Scatter Plot', 'Box Plot', 'Forest Plot']
|
|
46
|
+
const disabledCharts = ['Area Chart', 'Scatter Plot', 'Box Plot', 'Forest Plot', 'Spark Line']
|
|
33
47
|
if (disabledCharts.includes(visualizationType)) return false
|
|
34
48
|
return true
|
|
35
49
|
}
|
|
@@ -40,6 +54,8 @@ export const useEditorPermissions = () => {
|
|
|
40
54
|
return false
|
|
41
55
|
case 'Forest Plot':
|
|
42
56
|
return false
|
|
57
|
+
case 'Spark Line':
|
|
58
|
+
return false
|
|
43
59
|
default:
|
|
44
60
|
return true
|
|
45
61
|
}
|
|
@@ -82,11 +98,19 @@ export const useEditorPermissions = () => {
|
|
|
82
98
|
return false
|
|
83
99
|
case 'Pie':
|
|
84
100
|
return false
|
|
101
|
+
case 'Spark Line':
|
|
102
|
+
return false
|
|
85
103
|
default:
|
|
86
104
|
return true
|
|
87
105
|
}
|
|
88
106
|
}
|
|
89
107
|
|
|
108
|
+
const visSupportsTooltipOpacity = () => {
|
|
109
|
+
const disabledCharts = ['Spark Line']
|
|
110
|
+
if (disabledCharts.includes(visualizationType)) return false
|
|
111
|
+
return true
|
|
112
|
+
}
|
|
113
|
+
|
|
90
114
|
const visSupportsTooltipLines = () => {
|
|
91
115
|
const enabledCharts = ['Combo', 'Forecasting', 'Area Chart', 'Line', 'Bar']
|
|
92
116
|
if (enabledCharts.includes(visualizationType)) return true
|
|
@@ -94,13 +118,13 @@ export const useEditorPermissions = () => {
|
|
|
94
118
|
}
|
|
95
119
|
|
|
96
120
|
const visSupportsSequentialPallete = () => {
|
|
97
|
-
const disabledCharts = ['Paired Bar', 'Deviation Bar', 'Forest Plot']
|
|
121
|
+
const disabledCharts = ['Paired Bar', 'Deviation Bar', 'Forest Plot', 'Forecasting']
|
|
98
122
|
if (disabledCharts.includes(visualizationType)) return false
|
|
99
123
|
return true
|
|
100
124
|
}
|
|
101
125
|
|
|
102
126
|
const visSupportsNonSequentialPallete = () => {
|
|
103
|
-
const disabledCharts = ['Paired Bar', 'Deviation Bar', 'Forest Plot']
|
|
127
|
+
const disabledCharts = ['Paired Bar', 'Deviation Bar', 'Forest Plot', 'Forecasting']
|
|
104
128
|
if (disabledCharts.includes(visualizationType)) return false
|
|
105
129
|
return true
|
|
106
130
|
}
|
|
@@ -112,37 +136,43 @@ export const useEditorPermissions = () => {
|
|
|
112
136
|
}
|
|
113
137
|
|
|
114
138
|
const visSupportsDateCategoryAxisLabel = () => {
|
|
115
|
-
const disabledCharts = ['Forest Plot']
|
|
139
|
+
const disabledCharts = ['Forest Plot', 'Spark Line']
|
|
116
140
|
if (disabledCharts.includes(visualizationType)) return false
|
|
117
141
|
return true
|
|
118
142
|
}
|
|
119
143
|
|
|
120
144
|
const visSupportsDateCategoryAxisLine = () => {
|
|
121
|
-
const disabledCharts = ['Forest Plot']
|
|
145
|
+
const disabledCharts = ['Forest Plot', 'Spark Line']
|
|
122
146
|
if (disabledCharts.includes(visualizationType)) return false
|
|
123
147
|
return true
|
|
124
148
|
}
|
|
125
149
|
|
|
126
150
|
const visSupportsDateCategoryAxisTicks = () => {
|
|
127
|
-
const disabledCharts = ['Forest Plot']
|
|
151
|
+
const disabledCharts = ['Forest Plot', 'Spark Line']
|
|
128
152
|
if (disabledCharts.includes(visualizationType)) return false
|
|
129
153
|
return true
|
|
130
154
|
}
|
|
131
155
|
|
|
132
156
|
const visSupportsDateCategoryTickRotation = () => {
|
|
133
|
-
const disabledCharts = ['Forest Plot']
|
|
157
|
+
const disabledCharts = ['Forest Plot', 'Spark Line']
|
|
134
158
|
if (disabledCharts.includes(visualizationType)) return false
|
|
135
159
|
return true
|
|
136
160
|
}
|
|
137
161
|
|
|
138
162
|
const visSupportsDateCategoryNumTicks = () => {
|
|
139
|
-
const disabledCharts = ['Forest Plot']
|
|
163
|
+
const disabledCharts = ['Forest Plot', 'Spark Line']
|
|
164
|
+
if (disabledCharts.includes(visualizationType)) return false
|
|
165
|
+
return true
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const visSupportsResponsiveTicks = () => {
|
|
169
|
+
const disabledCharts = ['Spark Line']
|
|
140
170
|
if (disabledCharts.includes(visualizationType)) return false
|
|
141
171
|
return true
|
|
142
172
|
}
|
|
143
173
|
|
|
144
174
|
const visSupportsRegions = () => {
|
|
145
|
-
const disabledCharts = ['Forest Plot', 'Pie', 'Paired Bar']
|
|
175
|
+
const disabledCharts = ['Forest Plot', 'Pie', 'Paired Bar', 'Spark Line']
|
|
146
176
|
if (disabledCharts.includes(visualizationType)) return false
|
|
147
177
|
return true
|
|
148
178
|
}
|
|
@@ -188,31 +218,64 @@ export const useEditorPermissions = () => {
|
|
|
188
218
|
return true
|
|
189
219
|
}
|
|
190
220
|
|
|
221
|
+
const visSupportsChartHeight = () => {
|
|
222
|
+
const disabledCharts = ['Spark Line']
|
|
223
|
+
if (disabledCharts.includes(visualizationType)) return false
|
|
224
|
+
return true
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const visSupportsLeftValueAxis = () => {
|
|
228
|
+
const disabledCharts = ['Spark Line']
|
|
229
|
+
if (disabledCharts.includes(visualizationType)) return false
|
|
230
|
+
return true
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const visSupportsRankByValue = () => {
|
|
234
|
+
const disabledCharts = ['Spark Line']
|
|
235
|
+
if (disabledCharts.includes(visualizationType)) return false
|
|
236
|
+
return true
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const visSupportsDateCategoryHeight = () => {
|
|
240
|
+
const disabledCharts = ['Spark Line']
|
|
241
|
+
if (disabledCharts.includes(visualizationType)) return false
|
|
242
|
+
return true
|
|
243
|
+
}
|
|
244
|
+
|
|
191
245
|
return {
|
|
192
246
|
enabledChartTypes,
|
|
193
|
-
|
|
194
|
-
|
|
247
|
+
headerColors,
|
|
248
|
+
visCanAnimate,
|
|
195
249
|
visHasAnchors,
|
|
196
250
|
visHasBarBorders,
|
|
197
251
|
visHasDataCutoff,
|
|
198
|
-
|
|
252
|
+
visHasLabelOnData,
|
|
199
253
|
visHasLegend,
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
254
|
+
visHasNumbersOnBars,
|
|
255
|
+
visSupportsBarSpace,
|
|
256
|
+
visSupportsBarThickness,
|
|
257
|
+
visSupportsChartHeight,
|
|
204
258
|
visSupportsDateCategoryAxisLabel,
|
|
205
259
|
visSupportsDateCategoryAxisLine,
|
|
206
260
|
visSupportsDateCategoryAxisTicks,
|
|
207
|
-
|
|
261
|
+
visSupportsDateCategoryHeight,
|
|
208
262
|
visSupportsDateCategoryNumTicks,
|
|
209
|
-
|
|
263
|
+
visSupportsDateCategoryTickRotation,
|
|
210
264
|
visSupportsFilters,
|
|
265
|
+
visSupportsFootnotes,
|
|
266
|
+
visSupportsLeftValueAxis,
|
|
267
|
+
visSupportsNonSequentialPallete,
|
|
268
|
+
visSupportsRankByValue,
|
|
269
|
+
visSupportsRegions,
|
|
270
|
+
visSupportsResponsiveTicks,
|
|
271
|
+
visSupportsReverseColorPalette,
|
|
272
|
+
visSupportsSequentialPallete,
|
|
273
|
+
visSupportsSuperTitle,
|
|
274
|
+
visSupportsTooltipLines,
|
|
275
|
+
visSupportsTooltipOpacity,
|
|
211
276
|
visSupportsValueAxisGridLines,
|
|
212
|
-
visSupportsValueAxisTicks,
|
|
213
|
-
visSupportsValueAxisLine,
|
|
214
277
|
visSupportsValueAxisLabels,
|
|
215
|
-
|
|
216
|
-
|
|
278
|
+
visSupportsValueAxisLine,
|
|
279
|
+
visSupportsValueAxisTicks
|
|
217
280
|
}
|
|
218
281
|
}
|
|
@@ -13,6 +13,11 @@ function useReduceData(config, data) {
|
|
|
13
13
|
max = Math.max(...yTotals)
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
if (config.visualizationSubType === 'stacked' && config.visualizationType === 'Area Chart') {
|
|
17
|
+
const yTotals = data.map(sumYValues(config.runtime.seriesKeys))
|
|
18
|
+
max = Math.max(...yTotals)
|
|
19
|
+
}
|
|
20
|
+
|
|
16
21
|
if ((config.visualizationType === 'Bar' || config.visualizationType === 'Deviation Bar') && config.series && config.series.dataKey) {
|
|
17
22
|
max = Math.max(...data.map(d => (isNumber(d[config.series.dataKey]) ? Number(cleanChars(d[config.series.dataKey])) : 0)))
|
|
18
23
|
}
|
package/src/hooks/useScales.js
CHANGED