@cdc/chart 4.25.3 → 4.25.6-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.
- package/dist/cdcchart.js +50009 -46835
- package/index.html +130 -129
- package/package.json +22 -27
- package/src/CdcChartComponent.tsx +75 -35
- package/src/_stories/Chart.CI.stories.tsx +10 -0
- package/src/_stories/Chart.DynamicSeries.stories.tsx +68 -49
- package/src/_stories/Chart.stories.tsx +99 -86
- package/src/_stories/ChartPrefixSuffix.stories.tsx +29 -32
- package/{examples/private/line-issue.json → src/_stories/_mock/barchart_labels.mock.json} +150 -35
- package/src/_stories/_mock/dynamic_series_bar_config.json +1 -1
- package/src/_stories/_mock/dynamic_series_suppression_mock.json +610 -0
- package/{examples/private/not-loading.json → src/_stories/_mock/pie_calculated_area.json} +152 -95
- package/src/components/Annotations/components/AnnotationDropdown.tsx +2 -2
- package/src/components/AreaChart/components/AreaChart.jsx +33 -5
- package/src/components/Axis/Categorical.Axis.tsx +2 -2
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +38 -37
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +18 -8
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +8 -8
- package/src/components/BarChart/components/BarChart.Vertical.tsx +47 -36
- package/src/components/BarChart/components/{BarChart.jsx → BarChart.tsx} +23 -5
- package/src/components/BarChart/components/context.tsx +20 -2
- package/src/components/BarChart/helpers/getBarHeights.ts +47 -0
- package/src/components/BarChart/helpers/index.ts +5 -2
- package/src/components/BarChart/helpers/tests/getBarHeights.test.ts +83 -0
- package/src/{hooks → components/BarChart/helpers}/useBarChart.ts +9 -46
- package/src/components/BoxPlot/BoxPlot.tsx +2 -1
- package/src/components/Brush/BrushChart.tsx +73 -0
- package/src/components/Brush/BrushController..tsx +39 -0
- package/src/components/DeviationBar.jsx +2 -2
- package/src/components/EditorPanel/EditorPanel.tsx +246 -156
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +36 -36
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +52 -25
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +12 -4
- package/src/components/EditorPanel/components/Panels/panelVisual.styles.css +8 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +5 -5
- package/src/components/ForestPlot/ForestPlot.tsx +2 -2
- package/src/components/HoverLine/HoverLine.tsx +74 -0
- package/src/components/Legend/Legend.Component.tsx +1 -1
- package/src/components/Legend/Legend.Suppression.tsx +59 -25
- package/src/components/Legend/helpers/createFormatLabels.tsx +28 -0
- package/src/components/Legend/helpers/index.ts +1 -1
- package/src/components/LineChart/LineChartProps.ts +3 -1
- package/src/components/LineChart/components/LineChart.Circle.tsx +72 -119
- package/src/components/LineChart/helpers.ts +139 -62
- package/src/components/LineChart/index.tsx +106 -55
- package/src/components/LinearChart.tsx +125 -138
- package/src/components/PairedBarChart.jsx +3 -2
- package/src/components/PieChart/PieChart.tsx +127 -102
- package/src/components/ScatterPlot/ScatterPlot.jsx +5 -0
- package/src/components/Sparkline/components/SparkLine.tsx +80 -18
- package/src/data/initial-state.js +11 -6
- package/src/helpers/countNumOfTicks.ts +4 -19
- package/src/helpers/dataHelpers.ts +23 -2
- package/src/helpers/getNewRuntime.ts +35 -0
- package/src/helpers/getPiePercent.ts +22 -0
- package/src/helpers/getTransformedData.ts +22 -0
- package/src/helpers/sizeHelpers.ts +1 -1
- package/src/helpers/tests/getNewRuntime.test.ts +82 -0
- package/src/helpers/tests/getPiePercent.test.ts +38 -0
- package/src/hooks/useMinMax.ts +21 -28
- package/src/hooks/useRightAxis.ts +5 -3
- package/src/hooks/useScales.ts +15 -6
- package/src/hooks/useTooltip.tsx +218 -203
- package/src/index.jsx +2 -2
- package/src/scss/main.scss +21 -10
- package/src/store/chart.actions.ts +2 -6
- package/src/store/chart.reducer.ts +23 -23
- package/src/types/ChartConfig.ts +12 -4
- package/src/types/ChartContext.ts +0 -2
- package/examples/private/DEV-8850-2.json +0 -493
- package/examples/private/DEV-9822.json +0 -574
- package/examples/private/DEV-9840.json +0 -553
- package/examples/private/DEV-9850-3.json +0 -461
- package/examples/private/chart.json +0 -1084
- package/examples/private/ci_formatted.json +0 -202
- package/examples/private/ci_issue.json +0 -3016
- package/examples/private/completed.json +0 -634
- package/examples/private/dem-data-long.csv +0 -20
- package/examples/private/dem-data-long.json +0 -36
- package/examples/private/demographic_data.csv +0 -157
- package/examples/private/demographic_data.json +0 -2654
- package/examples/private/demographic_dynamic.json +0 -443
- package/examples/private/demographic_standard.json +0 -560
- package/examples/private/ehdi.json +0 -29939
- package/examples/private/test.json +0 -493
- package/src/components/ZoomBrush.tsx +0 -251
|
@@ -4,15 +4,14 @@ import React, { forwardRef, useContext, useEffect, useMemo, useRef, useState } f
|
|
|
4
4
|
import { AxisLeft, AxisBottom, AxisRight, AxisTop } from '@visx/axis'
|
|
5
5
|
import { Group } from '@visx/group'
|
|
6
6
|
import { Line, Bar } from '@visx/shape'
|
|
7
|
-
import { Text } from '@visx/text'
|
|
8
7
|
import { Tooltip as ReactTooltip } from 'react-tooltip'
|
|
8
|
+
import { Text } from '@visx/text'
|
|
9
9
|
import { useTooltip, TooltipWithBounds } from '@visx/tooltip'
|
|
10
10
|
import _ from 'lodash'
|
|
11
11
|
|
|
12
12
|
// CDC Components
|
|
13
13
|
import { isDateScale } from '@cdc/core/helpers/cove/date'
|
|
14
|
-
import
|
|
15
|
-
import { AreaChart, AreaChartStacked } from './AreaChart'
|
|
14
|
+
import { AreaChartStacked } from './AreaChart'
|
|
16
15
|
import BarChart from './BarChart'
|
|
17
16
|
import ConfigContext from '../ConfigContext'
|
|
18
17
|
import BoxPlot from './BoxPlot'
|
|
@@ -43,6 +42,8 @@ import { useEditorPermissions } from './EditorPanel/useEditorPermissions'
|
|
|
43
42
|
import Annotation from './Annotations'
|
|
44
43
|
import { BlurStrokeText } from '@cdc/core/components/BlurStrokeText'
|
|
45
44
|
import { countNumOfTicks } from '../helpers/countNumOfTicks'
|
|
45
|
+
import HoverLine from './HoverLine/HoverLine'
|
|
46
|
+
import BrushChart from './BrushChart'
|
|
46
47
|
|
|
47
48
|
type LinearChartProps = {
|
|
48
49
|
parentWidth: number
|
|
@@ -59,10 +60,23 @@ const AXIS_LABEL_FONT_SIZE = 18
|
|
|
59
60
|
const AXIS_LABEL_FONT_SIZE_SMALL = 14
|
|
60
61
|
const TICK_LABEL_MARGIN_RIGHT = 4.5
|
|
61
62
|
|
|
63
|
+
type TooltipData = {
|
|
64
|
+
dataXPosition?: number
|
|
65
|
+
dataYPosition?: number
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type UseTooltipReturn<T = TooltipData> = {
|
|
69
|
+
tooltipData: T | null
|
|
70
|
+
showTooltip: (tooltipData: T) => void
|
|
71
|
+
hideTooltip: () => void
|
|
72
|
+
tooltipOpen: boolean
|
|
73
|
+
tooltipLeft: number | null
|
|
74
|
+
tooltipTop: number | null
|
|
75
|
+
}
|
|
76
|
+
|
|
62
77
|
const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, parentWidth }, svgRef) => {
|
|
63
78
|
// prettier-ignore
|
|
64
79
|
const {
|
|
65
|
-
brushConfig,
|
|
66
80
|
colorScale,
|
|
67
81
|
config,
|
|
68
82
|
convertLineToBarGraph,
|
|
@@ -79,8 +93,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
79
93
|
parentRef,
|
|
80
94
|
tableData,
|
|
81
95
|
transformedData: data,
|
|
82
|
-
updateConfig,
|
|
83
96
|
seriesHighlight,
|
|
97
|
+
brushConfig
|
|
84
98
|
} = useContext(ConfigContext)
|
|
85
99
|
|
|
86
100
|
// CONFIG
|
|
@@ -99,14 +113,14 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
99
113
|
dataFormat,
|
|
100
114
|
debugSvg
|
|
101
115
|
} = config
|
|
102
|
-
const {
|
|
103
|
-
const { labelsAboveGridlines, hideAxis } = config.yAxis
|
|
116
|
+
const { labelsAboveGridlines, hideAxis, inlineLabel } = config.yAxis
|
|
104
117
|
|
|
105
118
|
// HOOKS % STATES
|
|
106
119
|
const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, data)
|
|
107
120
|
const { visSupportsReactTooltip } = useEditorPermissions()
|
|
108
121
|
const { hasTopAxis } = getTopAxis(config)
|
|
109
122
|
const [animatedChart, setAnimatedChart] = useState(false)
|
|
123
|
+
const [showHoverLine, setShowHoverLine] = useState(false)
|
|
110
124
|
const [point, setPoint] = useState({ x: 0, y: 0 })
|
|
111
125
|
const [suffixWidth, setSuffixWidth] = useState(0)
|
|
112
126
|
const [yAxisAutoPadding, setYAxisAutoPadding] = useState(0)
|
|
@@ -121,6 +135,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
121
135
|
const xAxisTitleRef = useRef(null)
|
|
122
136
|
const lastMaxValue = useRef(maxValue)
|
|
123
137
|
const gridLineRefs = useRef([])
|
|
138
|
+
const tooltipRef = useRef(null)
|
|
124
139
|
|
|
125
140
|
const dataRef = useIntersectionObserver(triggerRef, {
|
|
126
141
|
freezeOnceVisible: false
|
|
@@ -132,8 +147,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
132
147
|
const isLogarithmicAxis = config.yAxis.type === 'logarithmic'
|
|
133
148
|
const isForestPlot = visualizationType === 'Forest Plot'
|
|
134
149
|
const isDateTime = config.xAxis.type === 'date-time'
|
|
135
|
-
const
|
|
136
|
-
const labelsOverflow =
|
|
150
|
+
const inlineLabelHasNoSpace = !inlineLabel?.includes(' ')
|
|
151
|
+
const labelsOverflow = inlineLabel && !inlineLabelHasNoSpace
|
|
137
152
|
const padding = orientation === 'horizontal' ? Number(config.xAxis.size) : Number(config.yAxis.size)
|
|
138
153
|
const yLabelOffset = isNaN(parseInt(`${runtime.yAxis.labelOffset}`)) ? 0 : parseInt(`${runtime.yAxis.labelOffset}`)
|
|
139
154
|
const tickLabelFontSize = isMobileHeightViewport(currentViewport) ? TICK_LABEL_FONT_SIZE_SMALL : TICK_LABEL_FONT_SIZE
|
|
@@ -218,7 +233,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
218
233
|
yMax
|
|
219
234
|
}
|
|
220
235
|
const { min, max, leftMax, rightMax } = useMinMax(properties)
|
|
221
|
-
const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data
|
|
236
|
+
const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data })
|
|
222
237
|
const { xScale, yScale, seriesScale, g1xScale, g2xScale, xScaleNoPadding, xScaleAnnotation } = useScales({
|
|
223
238
|
...properties,
|
|
224
239
|
min,
|
|
@@ -226,7 +241,10 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
226
241
|
leftMax,
|
|
227
242
|
rightMax,
|
|
228
243
|
dimensions,
|
|
229
|
-
xMax:
|
|
244
|
+
xMax:
|
|
245
|
+
parentWidth -
|
|
246
|
+
Number(config.orientation === 'horizontal' ? config.xAxis.size : config.yAxis.size) -
|
|
247
|
+
(hasRightAxis ? config.yAxis.rightAxisSize : 0)
|
|
230
248
|
})
|
|
231
249
|
|
|
232
250
|
const [yTickCount, xTickCount] = ['yAxis', 'xAxis'].map(axis =>
|
|
@@ -235,7 +253,9 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
235
253
|
const handleNumTicks = isForestPlot ? config.data.length : yTickCount
|
|
236
254
|
|
|
237
255
|
// Tooltip Helpers
|
|
238
|
-
|
|
256
|
+
|
|
257
|
+
const { tooltipData, showTooltip, hideTooltip, tooltipOpen, tooltipLeft, tooltipTop } =
|
|
258
|
+
useTooltip<UseTooltipReturn<TooltipData>>()
|
|
239
259
|
|
|
240
260
|
// prettier-ignore
|
|
241
261
|
const {
|
|
@@ -243,12 +263,12 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
243
263
|
handleTooltipClick,
|
|
244
264
|
handleTooltipMouseOff,
|
|
245
265
|
TooltipListItem,
|
|
246
|
-
getXValueFromCoordinate
|
|
247
266
|
} = useCoveTooltip({
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
267
|
+
xScale,
|
|
268
|
+
yScale,
|
|
269
|
+
seriesScale,
|
|
270
|
+
showTooltip,
|
|
271
|
+
hideTooltip
|
|
252
272
|
})
|
|
253
273
|
// get the number of months between the first and last date
|
|
254
274
|
const { dataKey } = runtime.xAxis
|
|
@@ -256,7 +276,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
256
276
|
data.length && isDateTime
|
|
257
277
|
? [0, data.length - 1].map(i => parseDate(data[i][dataKey])).reduce((a, b) => Math.abs(a - b)) / MONTH_AS_MS
|
|
258
278
|
: 0
|
|
259
|
-
const useDateSpanMonths = isDateTime && dateSpanMonths > xTickCount
|
|
279
|
+
const useDateSpanMonths = isDateTime && dateSpanMonths > xTickCount && !config.runtime.xAxis.manual
|
|
260
280
|
|
|
261
281
|
// GETTERS & FUNCTIONS
|
|
262
282
|
const handleLeftTickFormatting = (tick, index, ticks) => {
|
|
@@ -268,7 +288,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
268
288
|
if (config.data && !config.data[index] && visualizationType === 'Forest Plot') return
|
|
269
289
|
if (config.visualizationType === 'Forest Plot') return config.data[index][config.xAxis.dataKey]
|
|
270
290
|
if (isDateScale(runtime.yAxis)) return formatDate(parseDate(tick))
|
|
271
|
-
if (orientation === 'vertical' && max - min < 3)
|
|
291
|
+
if (orientation === 'vertical' && max - min < 3 && !config.dataFormat?.roundTo)
|
|
272
292
|
return formatNumber(tick, 'left', shouldAbbreviate, false, false, '1', { index, length: ticks.length })
|
|
273
293
|
if (orientation === 'vertical') {
|
|
274
294
|
// TODO suggestion: pass all options as object key/values to allow for more flexibility
|
|
@@ -372,7 +392,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
372
392
|
if (!suffixEl) return setSuffixWidth(0)
|
|
373
393
|
const suffixElWidth = suffixEl.getBBox().width
|
|
374
394
|
setSuffixWidth(suffixElWidth)
|
|
375
|
-
}, [config.dataFormat.suffix,
|
|
395
|
+
}, [config.dataFormat.suffix, inlineLabel])
|
|
376
396
|
|
|
377
397
|
// forest plot x-axis label positioning
|
|
378
398
|
useEffect(() => {
|
|
@@ -398,11 +418,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
398
418
|
const topLabelOnGridline = topYLabelRef.current && yAxis.labelsAboveGridlines
|
|
399
419
|
|
|
400
420
|
// Heights to add
|
|
401
|
-
|
|
402
421
|
const brushHeight = brush?.active ? brush?.height + brush?.height : 0
|
|
422
|
+
const brushHeightWithMargin = config.brush?.active ? brushHeight + brushHeight : 0
|
|
403
423
|
const forestRowsHeight = isForestPlot ? config.data.length * forestPlot.rowHeight : 0
|
|
404
424
|
const topLabelOnGridlineHeight = topLabelOnGridline ? topYLabelRef.current.getBBox().height : 0
|
|
405
|
-
const additionalHeight = axisBottomHeight +
|
|
425
|
+
const additionalHeight = axisBottomHeight + brushHeightWithMargin + forestRowsHeight + topLabelOnGridlineHeight
|
|
406
426
|
const newHeight = initialHeight + additionalHeight
|
|
407
427
|
if (!parentRef.current) return
|
|
408
428
|
|
|
@@ -438,7 +458,9 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
438
458
|
}, [maxValue])
|
|
439
459
|
|
|
440
460
|
useEffect(() => {
|
|
441
|
-
if (
|
|
461
|
+
if (!yScale?.ticks) return
|
|
462
|
+
const ticks = yScale.ticks(handleNumTicks)
|
|
463
|
+
if (orientation === 'horizontal' || !labelsOverflow || config.yAxis?.max || ticks.length === 0) {
|
|
442
464
|
setYAxisAutoPadding(0)
|
|
443
465
|
return
|
|
444
466
|
}
|
|
@@ -446,13 +468,12 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
446
468
|
// minimum percentage of the max value that the distance should be from the top grid line
|
|
447
469
|
const MINIMUM_DISTANCE_PERCENTAGE = 0.025
|
|
448
470
|
|
|
449
|
-
const topGridLine = Math.max(...
|
|
471
|
+
const topGridLine = Math.max(...ticks)
|
|
450
472
|
const needsPaddingThreshold = topGridLine - maxValue * MINIMUM_DISTANCE_PERCENTAGE
|
|
451
473
|
const maxValueIsGreaterThanThreshold = maxValue > needsPaddingThreshold
|
|
452
474
|
|
|
453
475
|
if (!maxValueIsGreaterThanThreshold) return
|
|
454
476
|
|
|
455
|
-
const ticks = yScale.ticks(handleNumTicks)
|
|
456
477
|
const tickGap = ticks.length === 1 ? ticks[0] : ticks[1] - ticks[0]
|
|
457
478
|
const nextTick = Math.max(...yScale.ticks(handleNumTicks)) + tickGap
|
|
458
479
|
const divideBy = minValue < 0 ? maxValue / 2 : maxValue
|
|
@@ -467,6 +488,23 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
467
488
|
setYAxisAutoPadding(newPadding * 100 + 0.1)
|
|
468
489
|
}, [maxValue, labelsOverflow, yScale, handleNumTicks])
|
|
469
490
|
|
|
491
|
+
useEffect(() => {
|
|
492
|
+
if (!tooltipOpen) return
|
|
493
|
+
if (!tooltipRef.current) return
|
|
494
|
+
|
|
495
|
+
const { dataXPosition } = tooltipData as { [key: string]: number }
|
|
496
|
+
|
|
497
|
+
if (!dataXPosition) return
|
|
498
|
+
|
|
499
|
+
const { width: tooltipWidth } = tooltipRef.current.node.getBoundingClientRect()
|
|
500
|
+
|
|
501
|
+
const rightSideRemainingSpace = parentWidth - dataXPosition
|
|
502
|
+
|
|
503
|
+
const rightSide = rightSideRemainingSpace <= tooltipWidth && dataXPosition > parentWidth / 2 - 10
|
|
504
|
+
const maxWidth = rightSide ? dataXPosition - 10 : parentWidth - (dataXPosition + 6)
|
|
505
|
+
tooltipRef.current.node.style.maxWidth = `${maxWidth}px`
|
|
506
|
+
}, [tooltipOpen, tooltipData])
|
|
507
|
+
|
|
470
508
|
// Render Functions
|
|
471
509
|
const generatePairedBarAxis = () => {
|
|
472
510
|
const axisMaxHeight = bottomLabelStart + BOTTOM_LABEL_PADDING
|
|
@@ -611,7 +649,6 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
611
649
|
</>
|
|
612
650
|
)
|
|
613
651
|
}
|
|
614
|
-
|
|
615
652
|
return isNaN(width) ? (
|
|
616
653
|
<React.Fragment></React.Fragment>
|
|
617
654
|
) : (
|
|
@@ -624,7 +661,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
624
661
|
<svg
|
|
625
662
|
ref={svgRef}
|
|
626
663
|
onMouseMove={onMouseMove}
|
|
627
|
-
width={parentWidth}
|
|
664
|
+
width={parentWidth + config.yAxis.rightAxisSize}
|
|
628
665
|
height={isNoDataAvailable ? 1 : parentHeight}
|
|
629
666
|
className={`linear ${config.animate ? 'animated' : ''} ${animatedChart && config.animate ? 'animate' : ''} ${
|
|
630
667
|
debugSvg && 'debug'
|
|
@@ -632,6 +669,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
632
669
|
role='img'
|
|
633
670
|
aria-label={handleChartAriaLabels(config)}
|
|
634
671
|
style={{ overflow: 'visible' }}
|
|
672
|
+
onMouseLeave={() => setShowHoverLine(false)}
|
|
673
|
+
onMouseEnter={() => setShowHoverLine(true)}
|
|
635
674
|
>
|
|
636
675
|
{!isDraggingAnnotation && <Bar width={parentWidth} height={initialHeight} fill={'transparent'}></Bar>}{' '}
|
|
637
676
|
{/* GRID LINES */}
|
|
@@ -717,24 +756,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
717
756
|
yScale={yScale}
|
|
718
757
|
/>
|
|
719
758
|
)}
|
|
720
|
-
{((visualizationType === 'Area Chart' && config.visualizationSubType === 'regular') ||
|
|
721
|
-
(visualizationType === 'Combo' && config.visualizationSubType === 'regular')) && (
|
|
722
|
-
<AreaChart
|
|
723
|
-
xScale={xScale}
|
|
724
|
-
yScale={yScale}
|
|
725
|
-
yMax={yMax}
|
|
726
|
-
xMax={xMax}
|
|
727
|
-
chartRef={svgRef}
|
|
728
|
-
width={xMax}
|
|
729
|
-
height={yMax}
|
|
730
|
-
handleTooltipMouseOver={handleTooltipMouseOver}
|
|
731
|
-
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
732
|
-
tooltipData={tooltipData}
|
|
733
|
-
showTooltip={showTooltip}
|
|
734
|
-
/>
|
|
735
|
-
)}
|
|
736
759
|
{((visualizationType === 'Area Chart' && config.visualizationSubType === 'stacked') ||
|
|
737
|
-
|
|
760
|
+
visualizationType === 'Combo') && (
|
|
738
761
|
<AreaChartStacked
|
|
739
762
|
xScale={xScale}
|
|
740
763
|
yScale={yScale}
|
|
@@ -768,9 +791,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
768
791
|
chartRef={svgRef}
|
|
769
792
|
/>
|
|
770
793
|
)}
|
|
771
|
-
{(
|
|
772
|
-
visualizationType === 'Combo' ||
|
|
773
|
-
visualizationType === 'Bump Chart') && (
|
|
794
|
+
{(visualizationType === 'Combo' || visualizationType === 'Bump Chart') && (
|
|
774
795
|
<LineChart
|
|
775
796
|
xScale={xScale}
|
|
776
797
|
yScale={yScale}
|
|
@@ -784,9 +805,29 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
784
805
|
handleTooltipClick={handleTooltipClick}
|
|
785
806
|
tooltipData={tooltipData}
|
|
786
807
|
showTooltip={showTooltip}
|
|
787
|
-
chartRef={svgRef}
|
|
788
808
|
/>
|
|
789
809
|
)}
|
|
810
|
+
{/* Line chart */}
|
|
811
|
+
{/* TODO: Make this just line or combo? */}
|
|
812
|
+
{!['Paired Bar', 'Box Plot', 'Area Chart', 'Scatter Plot', 'Deviation Bar', 'Forecasting', 'Bar'].includes(
|
|
813
|
+
visualizationType
|
|
814
|
+
) &&
|
|
815
|
+
!convertLineToBarGraph && (
|
|
816
|
+
<>
|
|
817
|
+
<LineChart
|
|
818
|
+
xScale={xScale}
|
|
819
|
+
yScale={yScale}
|
|
820
|
+
getXAxisData={getXAxisData}
|
|
821
|
+
getYAxisData={getYAxisData}
|
|
822
|
+
xMax={xMax}
|
|
823
|
+
yMax={yMax}
|
|
824
|
+
seriesStyle={config.runtime.series}
|
|
825
|
+
tooltipData={tooltipData}
|
|
826
|
+
handleTooltipMouseOver={handleTooltipMouseOver}
|
|
827
|
+
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
828
|
+
/>
|
|
829
|
+
</>
|
|
830
|
+
)}
|
|
790
831
|
{(visualizationType === 'Forecasting' || visualizationType === 'Combo') && (
|
|
791
832
|
<Forecasting
|
|
792
833
|
showTooltip={showTooltip}
|
|
@@ -794,14 +835,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
794
835
|
xScale={xScale}
|
|
795
836
|
yScale={yScale}
|
|
796
837
|
width={xMax}
|
|
797
|
-
le
|
|
798
838
|
height={yMax}
|
|
799
839
|
xScaleNoPadding={xScaleNoPadding}
|
|
800
840
|
chartRef={svgRef}
|
|
801
|
-
getXValueFromCoordinate={getXValueFromCoordinate}
|
|
802
841
|
handleTooltipMouseOver={handleTooltipMouseOver}
|
|
803
842
|
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
804
|
-
isBrush={false}
|
|
805
843
|
/>
|
|
806
844
|
)}
|
|
807
845
|
{visualizationType === 'Forest Plot' && (
|
|
@@ -842,6 +880,9 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
842
880
|
xMax={xMax}
|
|
843
881
|
yMax={yMax}
|
|
844
882
|
seriesStyle={config.runtime.series}
|
|
883
|
+
tooltipData={tooltipData}
|
|
884
|
+
handleTooltipMouseOver={handleTooltipMouseOver}
|
|
885
|
+
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
845
886
|
/>
|
|
846
887
|
</>
|
|
847
888
|
)}
|
|
@@ -869,7 +910,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
869
910
|
strokeDasharray={handleLineType(anchor.lineStyle)}
|
|
870
911
|
stroke={anchor.color ? anchor.color : 'rgba(0,0,0,1)'}
|
|
871
912
|
className='anchor-y'
|
|
872
|
-
from={{ x: 0 + padding, y: position - middleOffset}}
|
|
913
|
+
from={{ x: 0 + padding, y: position - middleOffset }}
|
|
873
914
|
to={{ x: width - config.yAxis.rightAxisSize, y: position - middleOffset }}
|
|
874
915
|
/>
|
|
875
916
|
)
|
|
@@ -901,14 +942,14 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
901
942
|
return (
|
|
902
943
|
// prettier-ignore
|
|
903
944
|
<Line
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
945
|
+
key={`xAxis-${anchor.value}--${index}`}
|
|
946
|
+
strokeDasharray={handleLineType(anchor.lineStyle)}
|
|
947
|
+
stroke={anchor.color ? anchor.color : 'rgba(0,0,0,1)'}
|
|
948
|
+
fill={anchor.color ? anchor.color : 'rgba(0,0,0,1)'}
|
|
949
|
+
className='anchor-x'
|
|
950
|
+
from={{ x: Number(anchorPosition) + Number(padding), y: 0 }}
|
|
951
|
+
to={{ x: Number(anchorPosition) + Number(padding), y: yMax }}
|
|
952
|
+
/>
|
|
912
953
|
)
|
|
913
954
|
})}
|
|
914
955
|
{/* we are handling regions in bar charts differently, so that we can calculate the bar group into the region space. */}
|
|
@@ -926,36 +967,6 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
926
967
|
width={width}
|
|
927
968
|
/>
|
|
928
969
|
)}
|
|
929
|
-
{chartHasTooltipGuides && showTooltip && tooltipData && config.visual.verticalHoverLine && (
|
|
930
|
-
<Group key='tooltipLine-vertical' className='vertical-tooltip-line'>
|
|
931
|
-
<Line
|
|
932
|
-
from={{ x: tooltipData.dataXPosition - 10, y: 0 }}
|
|
933
|
-
to={{ x: tooltipData.dataXPosition - 10, y: yMax }}
|
|
934
|
-
stroke={'black'}
|
|
935
|
-
strokeWidth={1}
|
|
936
|
-
pointerEvents='none'
|
|
937
|
-
strokeDasharray='5,5'
|
|
938
|
-
className='vertical-tooltip-line'
|
|
939
|
-
/>
|
|
940
|
-
</Group>
|
|
941
|
-
)}
|
|
942
|
-
{chartHasTooltipGuides && showTooltip && tooltipData && config.visual.horizontalHoverLine && (
|
|
943
|
-
<Group
|
|
944
|
-
key='tooltipLine-horizontal'
|
|
945
|
-
className='horizontal-tooltip-line'
|
|
946
|
-
left={config.yAxis.size ? config.yAxis.size : 0}
|
|
947
|
-
>
|
|
948
|
-
<Line
|
|
949
|
-
from={{ x: 0, y: tooltipData.dataYPosition }}
|
|
950
|
-
to={{ x: xMax, y: tooltipData.dataYPosition }}
|
|
951
|
-
stroke={'black'}
|
|
952
|
-
strokeWidth={1}
|
|
953
|
-
pointerEvents='none'
|
|
954
|
-
strokeDasharray='5,5'
|
|
955
|
-
className='horizontal-tooltip-line'
|
|
956
|
-
/>
|
|
957
|
-
</Group>
|
|
958
|
-
)}
|
|
959
970
|
{isNoDataAvailable && (
|
|
960
971
|
<Text
|
|
961
972
|
x={Number(config.yAxis.size) + Number(xMax / 2)}
|
|
@@ -965,40 +976,12 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
965
976
|
{config.chartMessage.noData}
|
|
966
977
|
</Text>
|
|
967
978
|
)}
|
|
968
|
-
{
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
<
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
left={config.yAxis.size ? config.yAxis.size : 0}
|
|
975
|
-
>
|
|
976
|
-
<Line
|
|
977
|
-
from={{ x: 0, y: point.y }}
|
|
978
|
-
to={{ x: xMax, y: point.y }}
|
|
979
|
-
stroke={'black'}
|
|
980
|
-
strokeWidth={1}
|
|
981
|
-
pointerEvents='none'
|
|
982
|
-
strokeDasharray='5,5'
|
|
983
|
-
className='horizontal-tooltip-line'
|
|
984
|
-
/>
|
|
985
|
-
</Group>
|
|
986
|
-
)}
|
|
987
|
-
{(config.visualizationType === 'Bar' || convertLineToBarGraph) &&
|
|
988
|
-
config.tooltips.singleSeries &&
|
|
989
|
-
config.visual.verticalHoverLine && (
|
|
990
|
-
<Group key='tooltipLine-vertical' className='vertical-tooltip-line'>
|
|
991
|
-
<Line
|
|
992
|
-
from={{ x: point.x, y: 0 }}
|
|
993
|
-
to={{ x: point.x, y: yMax }}
|
|
994
|
-
stroke={'black'}
|
|
995
|
-
strokeWidth={1}
|
|
996
|
-
pointerEvents='none'
|
|
997
|
-
strokeDasharray='5,5'
|
|
998
|
-
className='vertical-tooltip-line'
|
|
999
|
-
/>
|
|
1000
|
-
</Group>
|
|
1001
|
-
)}
|
|
979
|
+
{showHoverLine && (
|
|
980
|
+
<>
|
|
981
|
+
<HoverLine xMax={xMax} yMax={yMax} point={point} tooltipData={tooltipData} orientation='horizontal' />
|
|
982
|
+
<HoverLine xMax={xMax} yMax={yMax} point={point} tooltipData={tooltipData} orientation='vertical' />
|
|
983
|
+
</>
|
|
984
|
+
)}
|
|
1002
985
|
<Group left={Number(config.runtime.yAxis.size)}>
|
|
1003
986
|
<Annotation.Draggable
|
|
1004
987
|
xScale={xScale}
|
|
@@ -1069,15 +1052,18 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1069
1052
|
|
|
1070
1053
|
// Vertical value/suffix vars
|
|
1071
1054
|
const lastTick = props.ticks.length - 1 === i
|
|
1072
|
-
const
|
|
1055
|
+
const useInlineLabel = lastTick && inlineLabel
|
|
1056
|
+
const hideTopTick = lastTick && inlineLabel && !inlineLabelHasNoSpace
|
|
1073
1057
|
const valueOnLinePadding = hideAxis ? -8 : -12
|
|
1074
1058
|
const labelXPadding = labelsAboveGridlines ? valueOnLinePadding : TICK_LABEL_MARGIN_RIGHT
|
|
1075
1059
|
const labelYPadding = labelsAboveGridlines ? 4 : 0
|
|
1076
1060
|
const labelX = tick.to.x - labelXPadding
|
|
1077
1061
|
const labelY = tick.to.y - labelYPadding
|
|
1078
1062
|
const labelVerticalAnchor = labelsAboveGridlines ? 'end' : 'middle'
|
|
1079
|
-
const
|
|
1080
|
-
|
|
1063
|
+
const combineDomInlineLabelWithValue = inlineLabel && labelsAboveGridlines && lastTick
|
|
1064
|
+
const formattedValue = useInlineLabel
|
|
1065
|
+
? tick.formattedValue.replace(config.dataFormat.suffix, '')
|
|
1066
|
+
: tick.formattedValue
|
|
1081
1067
|
|
|
1082
1068
|
return (
|
|
1083
1069
|
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
@@ -1196,11 +1182,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1196
1182
|
visualizationType !== 'Bump Chart' &&
|
|
1197
1183
|
!config.yAxis.hideLabel && (
|
|
1198
1184
|
<>
|
|
1199
|
-
{/*
|
|
1200
|
-
{/*
|
|
1201
|
-
{/* SPECIAL ONE CHAR CASE: a one character
|
|
1185
|
+
{/* INLINE LABEL BEHAVIOR: Dom suffix for 'inlineLabel' behavior */}
|
|
1186
|
+
{/* inline label is shown alone and is allowed to 'overflow' to the right */}
|
|
1187
|
+
{/* SPECIAL ONE CHAR CASE: a one character inlineLabel does not overflow */}
|
|
1202
1188
|
{/* IF VALUES ON LINE: suffix is combined with value to avoid having to calculate varying (now left-aligned) value widths */}
|
|
1203
|
-
{
|
|
1189
|
+
{inlineLabel && lastTick && !labelsAboveGridlines && (
|
|
1204
1190
|
<BlurStrokeText
|
|
1205
1191
|
innerRef={suffixRef}
|
|
1206
1192
|
display={isLogarithmicAxis ? showTicks : 'block'}
|
|
@@ -1209,7 +1195,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1209
1195
|
y={labelY}
|
|
1210
1196
|
angle={-Number(config.yAxis.tickRotation) || 0}
|
|
1211
1197
|
verticalAnchor={labelVerticalAnchor}
|
|
1212
|
-
textAnchor={
|
|
1198
|
+
textAnchor={inlineLabelHasNoSpace ? 'end' : 'start'}
|
|
1213
1199
|
fill={config.yAxis.tickLabelColor}
|
|
1214
1200
|
stroke={'#fff'}
|
|
1215
1201
|
paintOrder={'stroke'} // keeps stroke under fill
|
|
@@ -1217,7 +1203,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1217
1203
|
style={{ whiteSpace: 'pre-wrap' }} // prevents leading spaces from being trimmed
|
|
1218
1204
|
fontSize={tickLabelFontSize}
|
|
1219
1205
|
>
|
|
1220
|
-
{
|
|
1206
|
+
{inlineLabel}
|
|
1221
1207
|
</BlurStrokeText>
|
|
1222
1208
|
)}
|
|
1223
1209
|
|
|
@@ -1226,7 +1212,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1226
1212
|
innerRef={el => lastTick && (topYLabelRef.current = el)}
|
|
1227
1213
|
display={isLogarithmicAxis ? showTicks : 'block'}
|
|
1228
1214
|
dx={isLogarithmicAxis ? -6 : 0}
|
|
1229
|
-
x={
|
|
1215
|
+
x={inlineLabelHasNoSpace ? labelX - suffixWidth : labelX}
|
|
1230
1216
|
y={labelY + (config.runtime.horizontal ? horizontalTickOffset : 0)}
|
|
1231
1217
|
angle={-Number(config.yAxis.tickRotation) || 0}
|
|
1232
1218
|
verticalAnchor={config.runtime.horizontal ? 'start' : labelVerticalAnchor}
|
|
@@ -1239,7 +1225,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1239
1225
|
style={{ whiteSpace: 'pre-wrap' }} // prevents leading spaces from being trimmed
|
|
1240
1226
|
fontSize={tickLabelFontSize}
|
|
1241
1227
|
>
|
|
1242
|
-
{`${
|
|
1228
|
+
{`${formattedValue}${combineDomInlineLabelWithValue ? inlineLabel : ''}`}
|
|
1243
1229
|
</BlurStrokeText>
|
|
1244
1230
|
</>
|
|
1245
1231
|
)}
|
|
@@ -1543,13 +1529,15 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1543
1529
|
showTooltip &&
|
|
1544
1530
|
!tooltipData?.data?.some(subArray => subArray.some(item => item === undefined)) &&
|
|
1545
1531
|
tooltipData.dataYPosition &&
|
|
1546
|
-
tooltipData.dataXPosition &&
|
|
1532
|
+
tooltipData.dataXPosition &&
|
|
1533
|
+
!config.tooltips.singleSeries && (
|
|
1547
1534
|
<>
|
|
1548
1535
|
<style>{`.tooltip {background-color: rgba(255,255,255, ${
|
|
1549
1536
|
config.tooltips.opacity / 100
|
|
1550
1537
|
}) !important;`}</style>
|
|
1551
1538
|
<style>{`.tooltip {max-width:300px} !important; word-wrap: break-word; `}</style>
|
|
1552
1539
|
<TooltipWithBounds
|
|
1540
|
+
ref={tooltipRef}
|
|
1553
1541
|
key={Math.random()}
|
|
1554
1542
|
className={'tooltip cdc-open-viz-module'}
|
|
1555
1543
|
left={tooltipLeft}
|
|
@@ -1564,7 +1552,6 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1564
1552
|
</TooltipWithBounds>
|
|
1565
1553
|
</>
|
|
1566
1554
|
)}
|
|
1567
|
-
|
|
1568
1555
|
{config.visualizationType === 'Bump Chart' && (
|
|
1569
1556
|
<ReactTooltip
|
|
1570
1557
|
id={`bump-chart`}
|
|
@@ -1574,7 +1561,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1574
1561
|
style={{ background: `rgba(255,255,255, ${config.tooltips.opacity / 100})`, color: 'black' }}
|
|
1575
1562
|
/>
|
|
1576
1563
|
)}
|
|
1577
|
-
{
|
|
1564
|
+
{!isDraggingAnnotation && (
|
|
1578
1565
|
<ReactTooltip
|
|
1579
1566
|
id={`cdc-open-viz-tooltip-${runtime.uniqueId}`}
|
|
1580
1567
|
variant='light'
|
|
@@ -6,6 +6,7 @@ import { Text } from '@visx/text'
|
|
|
6
6
|
|
|
7
7
|
import ConfigContext from '../ConfigContext'
|
|
8
8
|
import { getContrastColor } from '@cdc/core/helpers/cove/accessibility'
|
|
9
|
+
import { APP_FONT_COLOR } from '@cdc/core/helpers/constants'
|
|
9
10
|
import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
|
|
10
11
|
|
|
11
12
|
const PairedBarChart = ({ width, height, originalWidth }) => {
|
|
@@ -47,8 +48,8 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
|
|
|
47
48
|
})
|
|
48
49
|
|
|
49
50
|
// Set label color
|
|
50
|
-
groupOne.labelColor = groupOne.color ? getContrastColor(
|
|
51
|
-
groupTwo.labelColor = groupTwo.color ? getContrastColor(
|
|
51
|
+
groupOne.labelColor = groupOne.color ? getContrastColor(APP_FONT_COLOR, groupOne.color) : APP_FONT_COLOR
|
|
52
|
+
groupTwo.labelColor = groupTwo.color ? getContrastColor(APP_FONT_COLOR, groupTwo.color) : APP_FONT_COLOR
|
|
52
53
|
|
|
53
54
|
const label = config.yAxis.label ? `${config.yAxis.label}: ` : ''
|
|
54
55
|
|