@cdc/chart 4.25.5-1 → 4.25.6
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 +32848 -27824
- package/index.html +130 -130
- package/package.json +2 -2
- package/src/CdcChartComponent.tsx +66 -26
- package/src/_stories/Chart.stories.tsx +99 -93
- package/src/_stories/ChartPrefixSuffix.stories.tsx +29 -32
- package/src/_stories/_mock/pie_calculated_area.json +417 -0
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +4 -13
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +3 -14
- package/src/components/BarChart/components/BarChart.Vertical.tsx +2 -8
- package/src/components/Brush/BrushChart.tsx +73 -0
- package/src/components/Brush/BrushController..tsx +39 -0
- package/src/components/DeviationBar.jsx +0 -1
- package/src/components/EditorPanel/EditorPanel.tsx +232 -147
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +2 -2
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +3 -2
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +2 -1
- package/src/components/EditorPanel/components/Panels/panelVisual.styles.css +8 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +7 -4
- package/src/components/HoverLine/HoverLine.tsx +74 -0
- package/src/components/Legend/Legend.Suppression.tsx +47 -3
- package/src/components/Legend/helpers/index.ts +1 -1
- package/src/components/LineChart/index.tsx +3 -6
- package/src/components/LinearChart.tsx +161 -132
- package/src/components/PieChart/PieChart.tsx +58 -13
- package/src/data/initial-state.js +8 -5
- package/src/helpers/getNewRuntime.ts +35 -0
- package/src/helpers/getPiePercent.ts +22 -0
- package/src/helpers/getTransformedData.ts +22 -0
- package/src/helpers/tests/getNewRuntime.test.ts +82 -0
- package/src/helpers/tests/getPiePercent.test.ts +38 -0
- package/src/hooks/useRightAxis.ts +1 -1
- package/src/hooks/useScales.ts +8 -3
- package/src/hooks/useTooltip.tsx +24 -10
- package/src/store/chart.actions.ts +2 -6
- package/src/store/chart.reducer.ts +23 -23
- package/src/types/ChartConfig.ts +6 -3
- package/src/types/ChartContext.ts +0 -2
- package/src/components/ZoomBrush.tsx +0 -251
|
@@ -11,8 +11,7 @@ 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,
|
|
@@ -238,7 +253,9 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
238
253
|
const handleNumTicks = isForestPlot ? config.data.length : yTickCount
|
|
239
254
|
|
|
240
255
|
// Tooltip Helpers
|
|
241
|
-
|
|
256
|
+
|
|
257
|
+
const { tooltipData, showTooltip, hideTooltip, tooltipOpen, tooltipLeft, tooltipTop } =
|
|
258
|
+
useTooltip<UseTooltipReturn<TooltipData>>()
|
|
242
259
|
|
|
243
260
|
// prettier-ignore
|
|
244
261
|
const {
|
|
@@ -247,11 +264,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
247
264
|
handleTooltipMouseOff,
|
|
248
265
|
TooltipListItem,
|
|
249
266
|
} = useCoveTooltip({
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
267
|
+
xScale,
|
|
268
|
+
yScale,
|
|
269
|
+
seriesScale,
|
|
270
|
+
showTooltip,
|
|
271
|
+
hideTooltip
|
|
255
272
|
})
|
|
256
273
|
// get the number of months between the first and last date
|
|
257
274
|
const { dataKey } = runtime.xAxis
|
|
@@ -375,7 +392,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
375
392
|
if (!suffixEl) return setSuffixWidth(0)
|
|
376
393
|
const suffixElWidth = suffixEl.getBBox().width
|
|
377
394
|
setSuffixWidth(suffixElWidth)
|
|
378
|
-
}, [config.dataFormat.suffix,
|
|
395
|
+
}, [config.dataFormat.suffix, inlineLabel])
|
|
379
396
|
|
|
380
397
|
// forest plot x-axis label positioning
|
|
381
398
|
useEffect(() => {
|
|
@@ -401,11 +418,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
401
418
|
const topLabelOnGridline = topYLabelRef.current && yAxis.labelsAboveGridlines
|
|
402
419
|
|
|
403
420
|
// Heights to add
|
|
404
|
-
|
|
405
421
|
const brushHeight = brush?.active ? brush?.height + brush?.height : 0
|
|
422
|
+
const brushHeightWithMargin = config.brush?.active ? brushHeight + brushHeight : 0
|
|
406
423
|
const forestRowsHeight = isForestPlot ? config.data.length * forestPlot.rowHeight : 0
|
|
407
424
|
const topLabelOnGridlineHeight = topLabelOnGridline ? topYLabelRef.current.getBBox().height : 0
|
|
408
|
-
const additionalHeight = axisBottomHeight +
|
|
425
|
+
const additionalHeight = axisBottomHeight + brushHeightWithMargin + forestRowsHeight + topLabelOnGridlineHeight
|
|
409
426
|
const newHeight = initialHeight + additionalHeight
|
|
410
427
|
if (!parentRef.current) return
|
|
411
428
|
|
|
@@ -471,6 +488,23 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
471
488
|
setYAxisAutoPadding(newPadding * 100 + 0.1)
|
|
472
489
|
}, [maxValue, labelsOverflow, yScale, handleNumTicks])
|
|
473
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
|
+
|
|
474
508
|
// Render Functions
|
|
475
509
|
const generatePairedBarAxis = () => {
|
|
476
510
|
const axisMaxHeight = bottomLabelStart + BOTTOM_LABEL_PADDING
|
|
@@ -629,12 +663,13 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
629
663
|
onMouseMove={onMouseMove}
|
|
630
664
|
width={parentWidth + config.yAxis.rightAxisSize}
|
|
631
665
|
height={isNoDataAvailable ? 1 : parentHeight}
|
|
632
|
-
className={`linear ${config.animate ? 'animated' : ''} ${animatedChart && config.animate ? 'animate' : ''} ${
|
|
633
|
-
|
|
634
|
-
} ${isDraggingAnnotation && 'dragging-annotation'}`}
|
|
666
|
+
className={`linear ${config.animate ? 'animated' : ''} ${animatedChart && config.animate ? 'animate' : ''} ${debugSvg && 'debug'
|
|
667
|
+
} ${isDraggingAnnotation && 'dragging-annotation'}`}
|
|
635
668
|
role='img'
|
|
636
669
|
aria-label={handleChartAriaLabels(config)}
|
|
637
670
|
style={{ overflow: 'visible' }}
|
|
671
|
+
onMouseLeave={() => setShowHoverLine(false)}
|
|
672
|
+
onMouseEnter={() => setShowHoverLine(true)}
|
|
638
673
|
>
|
|
639
674
|
{!isDraggingAnnotation && <Bar width={parentWidth} height={initialHeight} fill={'transparent'}></Bar>}{' '}
|
|
640
675
|
{/* GRID LINES */}
|
|
@@ -722,20 +757,20 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
722
757
|
)}
|
|
723
758
|
{((visualizationType === 'Area Chart' && config.visualizationSubType === 'stacked') ||
|
|
724
759
|
visualizationType === 'Combo') && (
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
760
|
+
<AreaChartStacked
|
|
761
|
+
xScale={xScale}
|
|
762
|
+
yScale={yScale}
|
|
763
|
+
yMax={yMax}
|
|
764
|
+
xMax={xMax}
|
|
765
|
+
chartRef={svgRef}
|
|
766
|
+
width={xMax}
|
|
767
|
+
height={yMax}
|
|
768
|
+
handleTooltipMouseOver={handleTooltipMouseOver}
|
|
769
|
+
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
770
|
+
tooltipData={tooltipData}
|
|
771
|
+
showTooltip={showTooltip}
|
|
772
|
+
/>
|
|
773
|
+
)}
|
|
739
774
|
{(visualizationType === 'Bar' || visualizationType === 'Combo' || convertLineToBarGraph) && (
|
|
740
775
|
<BarChart
|
|
741
776
|
xScale={xScale}
|
|
@@ -771,6 +806,27 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
771
806
|
showTooltip={showTooltip}
|
|
772
807
|
/>
|
|
773
808
|
)}
|
|
809
|
+
{/* Line chart */}
|
|
810
|
+
{/* TODO: Make this just line or combo? */}
|
|
811
|
+
{!['Paired Bar', 'Box Plot', 'Area Chart', 'Scatter Plot', 'Deviation Bar', 'Forecasting', 'Bar'].includes(
|
|
812
|
+
visualizationType
|
|
813
|
+
) &&
|
|
814
|
+
!convertLineToBarGraph && (
|
|
815
|
+
<>
|
|
816
|
+
<LineChart
|
|
817
|
+
xScale={xScale}
|
|
818
|
+
yScale={yScale}
|
|
819
|
+
getXAxisData={getXAxisData}
|
|
820
|
+
getYAxisData={getYAxisData}
|
|
821
|
+
xMax={xMax}
|
|
822
|
+
yMax={yMax}
|
|
823
|
+
seriesStyle={config.runtime.series}
|
|
824
|
+
tooltipData={tooltipData}
|
|
825
|
+
handleTooltipMouseOver={handleTooltipMouseOver}
|
|
826
|
+
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
827
|
+
/>
|
|
828
|
+
</>
|
|
829
|
+
)}
|
|
774
830
|
{(visualizationType === 'Forecasting' || visualizationType === 'Combo') && (
|
|
775
831
|
<Forecasting
|
|
776
832
|
showTooltip={showTooltip}
|
|
@@ -778,13 +834,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
778
834
|
xScale={xScale}
|
|
779
835
|
yScale={yScale}
|
|
780
836
|
width={xMax}
|
|
781
|
-
le
|
|
782
837
|
height={yMax}
|
|
783
838
|
xScaleNoPadding={xScaleNoPadding}
|
|
784
839
|
chartRef={svgRef}
|
|
785
840
|
handleTooltipMouseOver={handleTooltipMouseOver}
|
|
786
841
|
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
787
|
-
isBrush={false}
|
|
788
842
|
/>
|
|
789
843
|
)}
|
|
790
844
|
{visualizationType === 'Forest Plot' && (
|
|
@@ -855,7 +909,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
855
909
|
strokeDasharray={handleLineType(anchor.lineStyle)}
|
|
856
910
|
stroke={anchor.color ? anchor.color : 'rgba(0,0,0,1)'}
|
|
857
911
|
className='anchor-y'
|
|
858
|
-
from={{ x: 0 + padding, y: position - middleOffset}}
|
|
912
|
+
from={{ x: 0 + padding, y: position - middleOffset }}
|
|
859
913
|
to={{ x: width - config.yAxis.rightAxisSize, y: position - middleOffset }}
|
|
860
914
|
/>
|
|
861
915
|
)
|
|
@@ -887,14 +941,14 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
887
941
|
return (
|
|
888
942
|
// prettier-ignore
|
|
889
943
|
<Line
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
944
|
+
key={`xAxis-${anchor.value}--${index}`}
|
|
945
|
+
strokeDasharray={handleLineType(anchor.lineStyle)}
|
|
946
|
+
stroke={anchor.color ? anchor.color : 'rgba(0,0,0,1)'}
|
|
947
|
+
fill={anchor.color ? anchor.color : 'rgba(0,0,0,1)'}
|
|
948
|
+
className='anchor-x'
|
|
949
|
+
from={{ x: Number(anchorPosition) + Number(padding), y: 0 }}
|
|
950
|
+
to={{ x: Number(anchorPosition) + Number(padding), y: yMax }}
|
|
951
|
+
/>
|
|
898
952
|
)
|
|
899
953
|
})}
|
|
900
954
|
{/* we are handling regions in bar charts differently, so that we can calculate the bar group into the region space. */}
|
|
@@ -921,35 +975,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
921
975
|
{config.chartMessage.noData}
|
|
922
976
|
</Text>
|
|
923
977
|
)}
|
|
924
|
-
{
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
>
|
|
930
|
-
<Line
|
|
931
|
-
from={{ x: 0, y: point.y }}
|
|
932
|
-
to={{ x: xMax, y: point.y }}
|
|
933
|
-
stroke={'black'}
|
|
934
|
-
strokeWidth={1}
|
|
935
|
-
pointerEvents='none'
|
|
936
|
-
strokeDasharray='5,5'
|
|
937
|
-
className='horizontal-tooltip-line'
|
|
938
|
-
/>
|
|
939
|
-
</Group>
|
|
940
|
-
)}
|
|
941
|
-
{config.visual.verticalHoverLine && tooltipData && (
|
|
942
|
-
<Group key={`tooltipLine-vertical${point.y}${point.x}`} className='vertical-tooltip-line'>
|
|
943
|
-
<Line
|
|
944
|
-
from={{ x: point.x, y: 0 }}
|
|
945
|
-
to={{ x: point.x, y: yMax }}
|
|
946
|
-
stroke={'black'}
|
|
947
|
-
strokeWidth={1}
|
|
948
|
-
pointerEvents='none'
|
|
949
|
-
strokeDasharray='5,5'
|
|
950
|
-
className='vertical-tooltip-line'
|
|
951
|
-
/>
|
|
952
|
-
</Group>
|
|
978
|
+
{showHoverLine && (
|
|
979
|
+
<>
|
|
980
|
+
<HoverLine xMax={xMax} yMax={yMax} point={point} tooltipData={tooltipData} orientation='horizontal' />
|
|
981
|
+
<HoverLine xMax={xMax} yMax={yMax} point={point} tooltipData={tooltipData} orientation='vertical' />
|
|
982
|
+
</>
|
|
953
983
|
)}
|
|
954
984
|
<Group left={Number(config.runtime.yAxis.size)}>
|
|
955
985
|
<Annotation.Draggable
|
|
@@ -988,10 +1018,10 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
988
1018
|
to={
|
|
989
1019
|
runtime.horizontal
|
|
990
1020
|
? {
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1021
|
+
x: 0,
|
|
1022
|
+
y:
|
|
1023
|
+
config.visualizationType === 'Forest Plot' ? parentHeight : Number(heights.horizontal)
|
|
1024
|
+
}
|
|
995
1025
|
: props.axisToPoint
|
|
996
1026
|
}
|
|
997
1027
|
stroke='#000'
|
|
@@ -1021,15 +1051,18 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1021
1051
|
|
|
1022
1052
|
// Vertical value/suffix vars
|
|
1023
1053
|
const lastTick = props.ticks.length - 1 === i
|
|
1024
|
-
const
|
|
1054
|
+
const useInlineLabel = lastTick && inlineLabel
|
|
1055
|
+
const hideTopTick = lastTick && inlineLabel && !inlineLabelHasNoSpace
|
|
1025
1056
|
const valueOnLinePadding = hideAxis ? -8 : -12
|
|
1026
1057
|
const labelXPadding = labelsAboveGridlines ? valueOnLinePadding : TICK_LABEL_MARGIN_RIGHT
|
|
1027
1058
|
const labelYPadding = labelsAboveGridlines ? 4 : 0
|
|
1028
1059
|
const labelX = tick.to.x - labelXPadding
|
|
1029
1060
|
const labelY = tick.to.y - labelYPadding
|
|
1030
1061
|
const labelVerticalAnchor = labelsAboveGridlines ? 'end' : 'middle'
|
|
1031
|
-
const
|
|
1032
|
-
|
|
1062
|
+
const combineDomInlineLabelWithValue = inlineLabel && labelsAboveGridlines && lastTick
|
|
1063
|
+
const formattedValue = useInlineLabel
|
|
1064
|
+
? tick.formattedValue.replace(config.dataFormat.suffix, '')
|
|
1065
|
+
: tick.formattedValue
|
|
1033
1066
|
|
|
1034
1067
|
return (
|
|
1035
1068
|
<Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
|
|
@@ -1049,13 +1082,12 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1049
1082
|
config.yAxis.labelPlacement === 'On Date/Category Axis' &&
|
|
1050
1083
|
!config.yAxis.hideLabel && (
|
|
1051
1084
|
<Text
|
|
1052
|
-
transform={`translate(${tick.to.x - 5}, ${
|
|
1053
|
-
config.isLollipopChart
|
|
1085
|
+
transform={`translate(${tick.to.x - 5}, ${config.isLollipopChart
|
|
1054
1086
|
? tick.to.y - minY
|
|
1055
1087
|
: tick.to.y -
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1088
|
+
minY +
|
|
1089
|
+
(Number(config.barHeight * config.runtime.series.length) - barMinHeight) / 2
|
|
1090
|
+
}) rotate(-${config.runtime.horizontal ? config.runtime.yAxis.tickRotation || 0 : 0})`}
|
|
1059
1091
|
verticalAnchor={'start'}
|
|
1060
1092
|
textAnchor={'end'}
|
|
1061
1093
|
fontSize={tickLabelFontSize}
|
|
@@ -1069,9 +1101,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1069
1101
|
config.yAxis.labelPlacement === 'On Date/Category Axis' &&
|
|
1070
1102
|
!config.yAxis.hideLabel && (
|
|
1071
1103
|
<Text
|
|
1072
|
-
transform={`translate(${tick.to.x - 5}, ${
|
|
1073
|
-
|
|
1074
|
-
}) rotate(-${runtime.horizontal ? runtime.yAxis.tickRotation : 0})`}
|
|
1104
|
+
transform={`translate(${tick.to.x - 5}, ${tick.to.y - minY + (Number(config.barHeight) - barMinHeight) / 2
|
|
1105
|
+
}) rotate(-${runtime.horizontal ? runtime.yAxis.tickRotation : 0})`}
|
|
1075
1106
|
verticalAnchor={'start'}
|
|
1076
1107
|
textAnchor={'end'}
|
|
1077
1108
|
fontSize={tickLabelFontSize}
|
|
@@ -1084,9 +1115,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1084
1115
|
visualizationType === 'Paired Bar' &&
|
|
1085
1116
|
!config.yAxis.hideLabel && (
|
|
1086
1117
|
<Text
|
|
1087
|
-
transform={`translate(${tick.to.x - 5}, ${
|
|
1088
|
-
|
|
1089
|
-
}) rotate(-${runtime.horizontal ? runtime.yAxis.tickRotation : 0})`}
|
|
1118
|
+
transform={`translate(${tick.to.x - 5}, ${tick.to.y - minY + Number(config.barHeight) / 2
|
|
1119
|
+
}) rotate(-${runtime.horizontal ? runtime.yAxis.tickRotation : 0})`}
|
|
1090
1120
|
textAnchor={'end'}
|
|
1091
1121
|
verticalAnchor='middle'
|
|
1092
1122
|
fontSize={tickLabelFontSize}
|
|
@@ -1098,11 +1128,10 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1098
1128
|
visualizationType === 'Deviation Bar' &&
|
|
1099
1129
|
!config.yAxis.hideLabel && (
|
|
1100
1130
|
<Text
|
|
1101
|
-
transform={`translate(${tick.to.x - 5}, ${
|
|
1102
|
-
config.isLollipopChart
|
|
1131
|
+
transform={`translate(${tick.to.x - 5}, ${config.isLollipopChart
|
|
1103
1132
|
? tick.to.y - minY + 2
|
|
1104
1133
|
: tick.to.y - minY + Number(config.barHeight) / 2
|
|
1105
|
-
|
|
1134
|
+
}) rotate(-${runtime.horizontal ? runtime.yAxis.tickRotation : 0})`}
|
|
1106
1135
|
textAnchor={'end'}
|
|
1107
1136
|
verticalAnchor='middle'
|
|
1108
1137
|
fontSize={tickLabelFontSize}
|
|
@@ -1133,14 +1162,14 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1133
1162
|
seriesHighlight.includes(
|
|
1134
1163
|
config.runtime.seriesLabelsAll[tick.formattedValue - 1]
|
|
1135
1164
|
)) && (
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1165
|
+
<rect
|
|
1166
|
+
x={0 - Number(config.yAxis.size)}
|
|
1167
|
+
y={tick.to.y - 8 + (config.runtime.horizontal ? horizontalTickOffset : 7)}
|
|
1168
|
+
width={Number(config.yAxis.size) + xScale(xScale.domain()[0])}
|
|
1169
|
+
height='2'
|
|
1170
|
+
fill={colorScale(config.runtime.seriesLabelsAll[tick.formattedValue - 1])}
|
|
1171
|
+
/>
|
|
1172
|
+
)}
|
|
1144
1173
|
</>
|
|
1145
1174
|
)}
|
|
1146
1175
|
{orientation === 'vertical' &&
|
|
@@ -1148,11 +1177,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1148
1177
|
visualizationType !== 'Bump Chart' &&
|
|
1149
1178
|
!config.yAxis.hideLabel && (
|
|
1150
1179
|
<>
|
|
1151
|
-
{/*
|
|
1152
|
-
{/*
|
|
1153
|
-
{/* SPECIAL ONE CHAR CASE: a one character
|
|
1180
|
+
{/* INLINE LABEL BEHAVIOR: Dom suffix for 'inlineLabel' behavior */}
|
|
1181
|
+
{/* inline label is shown alone and is allowed to 'overflow' to the right */}
|
|
1182
|
+
{/* SPECIAL ONE CHAR CASE: a one character inlineLabel does not overflow */}
|
|
1154
1183
|
{/* IF VALUES ON LINE: suffix is combined with value to avoid having to calculate varying (now left-aligned) value widths */}
|
|
1155
|
-
{
|
|
1184
|
+
{inlineLabel && lastTick && !labelsAboveGridlines && (
|
|
1156
1185
|
<BlurStrokeText
|
|
1157
1186
|
innerRef={suffixRef}
|
|
1158
1187
|
display={isLogarithmicAxis ? showTicks : 'block'}
|
|
@@ -1161,7 +1190,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1161
1190
|
y={labelY}
|
|
1162
1191
|
angle={-Number(config.yAxis.tickRotation) || 0}
|
|
1163
1192
|
verticalAnchor={labelVerticalAnchor}
|
|
1164
|
-
textAnchor={
|
|
1193
|
+
textAnchor={inlineLabelHasNoSpace ? 'end' : 'start'}
|
|
1165
1194
|
fill={config.yAxis.tickLabelColor}
|
|
1166
1195
|
stroke={'#fff'}
|
|
1167
1196
|
paintOrder={'stroke'} // keeps stroke under fill
|
|
@@ -1169,7 +1198,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1169
1198
|
style={{ whiteSpace: 'pre-wrap' }} // prevents leading spaces from being trimmed
|
|
1170
1199
|
fontSize={tickLabelFontSize}
|
|
1171
1200
|
>
|
|
1172
|
-
{
|
|
1201
|
+
{inlineLabel}
|
|
1173
1202
|
</BlurStrokeText>
|
|
1174
1203
|
)}
|
|
1175
1204
|
|
|
@@ -1178,7 +1207,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1178
1207
|
innerRef={el => lastTick && (topYLabelRef.current = el)}
|
|
1179
1208
|
display={isLogarithmicAxis ? showTicks : 'block'}
|
|
1180
1209
|
dx={isLogarithmicAxis ? -6 : 0}
|
|
1181
|
-
x={
|
|
1210
|
+
x={inlineLabelHasNoSpace ? labelX - suffixWidth : labelX}
|
|
1182
1211
|
y={labelY + (config.runtime.horizontal ? horizontalTickOffset : 0)}
|
|
1183
1212
|
angle={-Number(config.yAxis.tickRotation) || 0}
|
|
1184
1213
|
verticalAnchor={config.runtime.horizontal ? 'start' : labelVerticalAnchor}
|
|
@@ -1191,7 +1220,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1191
1220
|
style={{ whiteSpace: 'pre-wrap' }} // prevents leading spaces from being trimmed
|
|
1192
1221
|
fontSize={tickLabelFontSize}
|
|
1193
1222
|
>
|
|
1194
|
-
{`${
|
|
1223
|
+
{`${formattedValue}${combineDomInlineLabelWithValue ? inlineLabel : ''}`}
|
|
1195
1224
|
</BlurStrokeText>
|
|
1196
1225
|
</>
|
|
1197
1226
|
)}
|
|
@@ -1283,9 +1312,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1283
1312
|
className='y-label'
|
|
1284
1313
|
textAnchor='middle'
|
|
1285
1314
|
verticalAnchor='start'
|
|
1286
|
-
transform={`translate(${
|
|
1287
|
-
|
|
1288
|
-
}, ${axisCenter}) rotate(-90)`}
|
|
1315
|
+
transform={`translate(${config.yAxis.rightLabelOffsetSize ? config.yAxis.rightLabelOffsetSize : 0
|
|
1316
|
+
}, ${axisCenter}) rotate(-90)`}
|
|
1289
1317
|
fontWeight='bold'
|
|
1290
1318
|
fill={config.yAxis.rightAxisLabelColor}
|
|
1291
1319
|
fontSize={axisLabelFontSize}
|
|
@@ -1317,8 +1345,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1317
1345
|
runtime.horizontal && config.visualizationType !== 'Forest Plot'
|
|
1318
1346
|
? Number(heights.horizontal) + Number(config.xAxis.axisPadding)
|
|
1319
1347
|
: config.visualizationType === 'Forest Plot'
|
|
1320
|
-
|
|
1321
|
-
|
|
1348
|
+
? yMax + Number(config.xAxis.axisPadding)
|
|
1349
|
+
: yMax
|
|
1322
1350
|
}
|
|
1323
1351
|
left={config.visualizationType !== 'Forest Plot' ? Number(runtime.yAxis.size) : 0}
|
|
1324
1352
|
label={config[section].label}
|
|
@@ -1331,8 +1359,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1331
1359
|
config.runtime.xAxis.manual
|
|
1332
1360
|
? getTickValues(xAxisDataMapped, xScale, isDateTime ? xTickCount : getManualStep(), config)
|
|
1333
1361
|
: config.runtime.xAxis.type === 'date'
|
|
1334
|
-
|
|
1335
|
-
|
|
1362
|
+
? xAxisDataMapped
|
|
1363
|
+
: undefined
|
|
1336
1364
|
}
|
|
1337
1365
|
>
|
|
1338
1366
|
{props => {
|
|
@@ -1358,14 +1386,14 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1358
1386
|
// filter out every [distanceBetweenTicks] tick starting from the end, so the last tick is always labeled
|
|
1359
1387
|
const filteredTicks = useDateSpanMonths
|
|
1360
1388
|
? [...props.ticks]
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1389
|
+
.reverse()
|
|
1390
|
+
.filter((_, i) => i % distanceBetweenTicks === 0)
|
|
1391
|
+
.reverse()
|
|
1392
|
+
.map((tick, i, arr) => ({
|
|
1393
|
+
...tick,
|
|
1394
|
+
// reformat in case showYearsOnce, since first month of year may have changed
|
|
1395
|
+
formattedValue: handleBottomTickFormatting(tick.value, i, arr)
|
|
1396
|
+
}))
|
|
1369
1397
|
: props.ticks
|
|
1370
1398
|
|
|
1371
1399
|
const axisMaxHeight = bottomLabelStart + BOTTOM_LABEL_PADDING
|
|
@@ -1495,13 +1523,14 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1495
1523
|
showTooltip &&
|
|
1496
1524
|
!tooltipData?.data?.some(subArray => subArray.some(item => item === undefined)) &&
|
|
1497
1525
|
tooltipData.dataYPosition &&
|
|
1498
|
-
tooltipData.dataXPosition &&
|
|
1526
|
+
tooltipData.dataXPosition &&
|
|
1527
|
+
!config.tooltips.singleSeries && (
|
|
1499
1528
|
<>
|
|
1500
|
-
<style>{`.tooltip {background-color: rgba(255,255,255, ${
|
|
1501
|
-
|
|
1502
|
-
}) !important;`}</style>
|
|
1529
|
+
<style>{`.tooltip {background-color: rgba(255,255,255, ${config.tooltips.opacity / 100
|
|
1530
|
+
}) !important;`}</style>
|
|
1503
1531
|
<style>{`.tooltip {max-width:300px} !important; word-wrap: break-word; `}</style>
|
|
1504
1532
|
<TooltipWithBounds
|
|
1533
|
+
ref={tooltipRef}
|
|
1505
1534
|
key={Math.random()}
|
|
1506
1535
|
className={'tooltip cdc-open-viz-module'}
|
|
1507
1536
|
left={tooltipLeft}
|
|
@@ -1525,7 +1554,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
1525
1554
|
style={{ background: `rgba(255,255,255, ${config.tooltips.opacity / 100})`, color: 'black' }}
|
|
1526
1555
|
/>
|
|
1527
1556
|
)}
|
|
1528
|
-
{
|
|
1557
|
+
{!isDraggingAnnotation && (
|
|
1529
1558
|
<ReactTooltip
|
|
1530
1559
|
id={`cdc-open-viz-tooltip-${runtime.uniqueId}`}
|
|
1531
1560
|
variant='light'
|