@cdc/chart 4.26.3 → 4.26.4
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/CONFIG.md +169 -0
- package/README.md +42 -17
- package/dist/cdcchart.js +34725 -33730
- package/examples/feature/bar/additional-column-tooltip.json +3 -3
- package/examples/feature/deviation/planet-deviation-config.json +2 -2
- package/examples/feature/paired-bar/paired-bar-example.json +2 -2
- package/examples/feature/tests-case-rate/case-rate-example-config.json +2 -2
- package/examples/feature/tests-covid/covid-confidence-example-config.json +2 -2
- package/examples/feature/tests-covid/covid-example-config.json +2 -2
- package/examples/feature/tests-cutoff/cutoff-example-config.json +2 -2
- package/examples/feature/tests-non-numerics/planet-pie-example-config-nonnumeric.json +2 -2
- package/examples/metadata-variables.json +1 -1
- package/examples/minimal-example.json +24 -0
- package/examples/private/test2.json +35012 -0
- package/package.json +4 -4
- package/src/CdcChartComponent.tsx +9 -6
- package/src/_stories/{Chart.HTMLInDataTable.stories.tsx → Chart.HTMLInDataTable.smoke.stories.tsx} +10 -0
- package/src/_stories/Chart.Minimal.smoke.stories.tsx +25 -0
- package/src/_stories/{Chart.SmallMultiples.stories.tsx → Chart.SmallMultiples.smoke.stories.tsx} +17 -1
- package/src/_stories/{Chart.stories.tsx → Chart.smoke.stories.tsx} +12 -0
- package/src/_stories/{Chart.tooltip.stories.tsx → Chart.tooltip.smoke.stories.tsx} +68 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +88 -85
- package/src/_stories/ChartEditor.Editor.stories.tsx +23 -0
- package/src/_stories/ChartLine.DashedDates.smoke.stories.tsx +23 -0
- package/src/_stories/_mock/line_chart_dashed_dates.json +276 -0
- package/src/_stories/_mock/paired-bar-abbr.json +1 -1
- package/src/_stories/_mock/paired-bar.json +1 -1
- package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -1
- package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -2
- package/src/components/Axis/BottomAxis.tsx +1 -1
- package/src/components/Axis/LeftAxis.tsx +2 -4
- package/src/components/Axis/LeftAxisGridlines.tsx +1 -3
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +9 -5
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +9 -5
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +9 -5
- package/src/components/BarChart/components/BarChart.Vertical.tsx +9 -6
- package/src/components/BarChart/components/BarChart.tsx +2 -6
- package/src/components/BarChart/helpers/useBarChart.ts +1 -1
- package/src/components/BoxPlot/BoxPlot.Vertical.tsx +3 -3
- package/src/components/EditorPanel/EditorPanel.tsx +633 -908
- package/src/components/EditorPanel/EditorPanelContext.ts +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +216 -165
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +168 -116
- package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +154 -109
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +12 -26
- package/src/components/EditorPanel/useEditorPermissions.ts +1 -10
- package/src/components/Forecasting/Forecasting.tsx +2 -2
- package/src/components/HorizonChart/HorizonChart.tsx +10 -2
- package/src/components/HoverLine/HoverLine.tsx +6 -8
- package/src/components/Legend/Legend.Component.tsx +4 -4
- package/src/components/Legend/LegendGroup/LegendGroup.styles.css +5 -0
- package/src/components/Legend/LegendGroup/LegendGroup.tsx +3 -1
- package/src/components/Legend/helpers/index.ts +0 -2
- package/src/components/LineChart/LineChartProps.ts +1 -0
- package/src/components/LineChart/components/LineChart.BumpCircle.tsx +3 -2
- package/src/components/LineChart/index.tsx +11 -4
- package/src/components/LinearChart/VisualizationRenderer.tsx +11 -1
- package/src/components/LinearChart/tests/LinearChart.test.tsx +147 -0
- package/src/components/LinearChart.tsx +98 -41
- package/src/components/PairedBarChart.jsx +2 -2
- package/src/components/PieChart/PieChart.tsx +11 -9
- package/src/components/Regions/components/Regions.tsx +30 -20
- package/src/components/ScatterPlot/ScatterPlot.jsx +19 -17
- package/src/components/SmallMultiples/SmallMultipleTile.tsx +1 -0
- package/src/components/Sparkline/components/SparkLine.tsx +1 -1
- package/src/components/WarmingStripes/WarmingStripes.tsx +5 -3
- package/src/data/initial-state.js +1 -0
- package/src/helpers/calculateLeftYAxisWidth.ts +193 -0
- package/src/helpers/tests/tooltipHelpers.test.ts +151 -0
- package/src/helpers/tooltipHelpers.ts +176 -0
- package/src/hooks/useHighlightedBars.ts +9 -16
- package/src/hooks/useProgrammaticTooltip.ts +16 -2
- package/src/hooks/useSmallMultipleSynchronization.ts +3 -4
- package/src/hooks/useTooltip.tsx +167 -38
- package/src/test/CdcChart.test.jsx +24 -0
- package/src/types/ChartConfig.ts +1 -0
- package/LICENSE +0 -201
- package/examples/chart-regression-2.json +0 -2360
- package/examples/feature/__data__/age-adjusted-rates.json +0 -1486
- package/examples/feature/__data__/city-temperature.json +0 -2198
- package/examples/feature/bar/Barchart_with_negative.json +0 -34
- package/examples/feature/boxplot/box-plot-data.json +0 -71
- package/examples/feature/boxplot/boxplot-data.json +0 -156
- package/examples/feature/combo/combochart-categories_are_numbers .json +0 -18
- package/examples/feature/forest-plot/log.json +0 -26
- package/examples/feature/tests-date-exclusions/date-exclusions-data.json +0 -162
- package/examples/region-issue.json +0 -2065
- package/examples/xaxis.json +0 -493
- /package/examples/{data → __data__}/data-with-metadata.json +0 -0
- /package/examples/feature/bar/{tall-data.json → __data__/tall-data.json} +0 -0
- /package/examples/feature/deviation/{planet-deviation-data.json → __data__/planet-deviation-data.json} +0 -0
- /package/examples/feature/paired-bar/{paired-bar-data.json → __data__/paired-bar-data.json} +0 -0
- /package/examples/feature/paired-bar/{paired-bar-formatted.json → __data__/paired-bar-formatted.json} +0 -0
- /package/examples/feature/tests-case-rate/{case-rate-example-data.json → __data__/case-rate-example-data.json} +0 -0
- /package/examples/feature/tests-covid/{covid-example-data-confidence.json → __data__/covid-example-data-confidence.json} +0 -0
- /package/examples/feature/tests-covid/{covid-example-data.json → __data__/covid-example-data.json} +0 -0
- /package/examples/feature/tests-cutoff/{cutoff-example-data.json → __data__/cutoff-example-data.json} +0 -0
- /package/examples/feature/tests-non-numerics/{planet-example-data-nonnumeric.json → __data__/planet-example-data-nonnumeric.json} +0 -0
- /package/src/_stories/{Chart.Anchors.stories.tsx → Chart.Anchors.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.BoxPlot.stories.tsx → Chart.BoxPlot.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.CI.stories.tsx → Chart.CI.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Combo.stories.tsx → Chart.Combo.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.CustomColors.stories.tsx → Chart.CustomColors.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Defaults.stories.tsx → Chart.Defaults.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.DynamicSeries.stories.tsx → Chart.DynamicSeries.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Filters.stories.tsx → Chart.Filters.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Forecast.stories.tsx → Chart.Forecast.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Legend.Gradient.stories.tsx → Chart.Legend.Gradient.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Patterns.stories.tsx → Chart.Patterns.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.PreserveDecimals.stories.tsx → Chart.PreserveDecimals.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Regions.Categorical.stories.tsx → Chart.Regions.Categorical.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Regions.DateScale.stories.tsx → Chart.Regions.DateScale.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.Regions.DateTimeScale.stories.tsx → Chart.Regions.DateTimeScale.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.ScatterPlot.stories.tsx → Chart.ScatterPlot.smoke.stories.tsx} +0 -0
- /package/src/_stories/{Chart.SmallestLeftAxisMax.stories.tsx → Chart.SmallestLeftAxisMax.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartAnnotation.stories.tsx → ChartAnnotation.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartAxisLabels.stories.tsx → ChartAxisLabels.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartAxisTitles.stories.tsx → ChartAxisTitles.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartBrush.Matrix.Continuous.stories.tsx → ChartBrush.Matrix.Continuous.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartBrush.Matrix.Date.stories.tsx → ChartBrush.Matrix.Date.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartBrush.Matrix.DateTime.stories.tsx → ChartBrush.Matrix.DateTime.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartBrush.stories.tsx → ChartBrush.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartLine.QuadrantAngles.stories.tsx → ChartLine.QuadrantAngles.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartLine.Suppression.stories.tsx → ChartLine.Suppression.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartLine.Symbols.stories.tsx → ChartLine.Symbols.smoke.stories.tsx} +0 -0
- /package/src/_stories/{ChartPrefixSuffix.stories.tsx → ChartPrefixSuffix.smoke.stories.tsx} +0 -0
- /package/src/_stories/{TechAdoptionWithLinks.stories.tsx → TechAdoptionWithLinks.smoke.stories.tsx} +0 -0
|
@@ -9,6 +9,7 @@ import { updatePaletteNames } from '@cdc/core/helpers/updatePaletteNames'
|
|
|
9
9
|
import { getColorPaletteVersion } from '@cdc/core/helpers/getColorPaletteVersion'
|
|
10
10
|
import Icon from '@cdc/core/components/ui/Icon'
|
|
11
11
|
import { CheckBox, Select, TextField } from '@cdc/core/components/EditorPanel/Inputs'
|
|
12
|
+
import Button from '@cdc/core/components/elements/Button'
|
|
12
13
|
import { buildForecastPaletteOptions } from '../../../../helpers/buildForecastPaletteOptions'
|
|
13
14
|
import { getSeriesColumnConfig, upsertSeriesColumnConfig } from '../../../../helpers/seriesColumnSettings'
|
|
14
15
|
|
|
@@ -20,7 +21,7 @@ import {
|
|
|
20
21
|
AccordionItemPanel,
|
|
21
22
|
AccordionItemButton
|
|
22
23
|
} from 'react-accessible-accordion'
|
|
23
|
-
import { Draggable
|
|
24
|
+
import { Draggable } from '@hello-pangea/dnd'
|
|
24
25
|
import Tooltip from '@cdc/core/components/ui/Tooltip'
|
|
25
26
|
|
|
26
27
|
const SeriesContext = React.createContext({})
|
|
@@ -375,8 +376,8 @@ const SeriesDropdownConfidenceInterval = props => {
|
|
|
375
376
|
)
|
|
376
377
|
})}
|
|
377
378
|
</Accordion>
|
|
378
|
-
<
|
|
379
|
-
|
|
379
|
+
<Button
|
|
380
|
+
variant='editor-primary'
|
|
380
381
|
onClick={e => {
|
|
381
382
|
e.preventDefault()
|
|
382
383
|
let copiedIndex = null
|
|
@@ -397,7 +398,7 @@ const SeriesDropdownConfidenceInterval = props => {
|
|
|
397
398
|
}}
|
|
398
399
|
>
|
|
399
400
|
Add Confidence Interval Group
|
|
400
|
-
</
|
|
401
|
+
</Button>
|
|
401
402
|
</fieldset>
|
|
402
403
|
</div>
|
|
403
404
|
)
|
|
@@ -652,7 +653,7 @@ const SeriesButtonRemove = props => {
|
|
|
652
653
|
}
|
|
653
654
|
}
|
|
654
655
|
|
|
655
|
-
const handleRemoveSeries = (e, series
|
|
656
|
+
const handleRemoveSeries = (e, series) => {
|
|
656
657
|
e.preventDefault()
|
|
657
658
|
removeSeries(series.dataKey)
|
|
658
659
|
}
|
|
@@ -660,9 +661,9 @@ const SeriesButtonRemove = props => {
|
|
|
660
661
|
return (
|
|
661
662
|
config.series &&
|
|
662
663
|
config.series.length > 1 && (
|
|
663
|
-
<
|
|
664
|
+
<Button variant='danger' size='sm' className='grouped-list__remove' onClick={e => handleRemoveSeries(e, series)}>
|
|
664
665
|
Remove
|
|
665
|
-
</
|
|
666
|
+
</Button>
|
|
666
667
|
)
|
|
667
668
|
)
|
|
668
669
|
}
|
|
@@ -710,11 +711,13 @@ const SeriesItem = props => {
|
|
|
710
711
|
>
|
|
711
712
|
<Icon display='move' size={15} style={{ cursor: 'default' }} />
|
|
712
713
|
{series.dataKey}
|
|
713
|
-
<Series.Button.Remove series={series} index={i} />
|
|
714
714
|
</AccordionItemButton>
|
|
715
715
|
</AccordionItemHeading>
|
|
716
716
|
{chartsWithOptions.includes(config.visualizationType) && (
|
|
717
717
|
<AccordionItemPanel>
|
|
718
|
+
<div className='series-item__panel-actions'>
|
|
719
|
+
<Series.Button.Remove series={series} index={i} />
|
|
720
|
+
</div>
|
|
718
721
|
<Series.Input.Name series={series} index={i} />
|
|
719
722
|
<Series.Input.ColumnSettings series={series} index={i} />
|
|
720
723
|
{showDynamicCategory && (
|
|
@@ -773,22 +776,6 @@ const SeriesItem = props => {
|
|
|
773
776
|
)
|
|
774
777
|
}
|
|
775
778
|
|
|
776
|
-
const SeriesList = props => {
|
|
777
|
-
const { series, getItemStyle, sortableItemStyles, chartsWithOptions } = props
|
|
778
|
-
return series.map((series, i) => {
|
|
779
|
-
return (
|
|
780
|
-
<SeriesItem
|
|
781
|
-
getItemStyle={getItemStyle}
|
|
782
|
-
sortableItemStyles={sortableItemStyles}
|
|
783
|
-
chartsWithOptions={chartsWithOptions}
|
|
784
|
-
series={series}
|
|
785
|
-
index={i}
|
|
786
|
-
key={`series-list-${i}`}
|
|
787
|
-
/>
|
|
788
|
-
)
|
|
789
|
-
})
|
|
790
|
-
}
|
|
791
|
-
|
|
792
779
|
const Series = {
|
|
793
780
|
Wrapper: SeriesWrapper,
|
|
794
781
|
Dropdown: {
|
|
@@ -811,8 +798,7 @@ const Series = {
|
|
|
811
798
|
Button: {
|
|
812
799
|
Remove: SeriesButtonRemove
|
|
813
800
|
},
|
|
814
|
-
Item: SeriesItem
|
|
815
|
-
List: SeriesList
|
|
801
|
+
Item: SeriesItem
|
|
816
802
|
}
|
|
817
803
|
|
|
818
804
|
export default Series
|
|
@@ -274,16 +274,7 @@ export const useEditorPermissions = () => {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
const visSupportsRegions = () => {
|
|
277
|
-
const disabledCharts = [
|
|
278
|
-
'Forest Plot',
|
|
279
|
-
'Horizon Chart',
|
|
280
|
-
'Pie',
|
|
281
|
-
'Paired Bar',
|
|
282
|
-
'Radar',
|
|
283
|
-
'Spark Line',
|
|
284
|
-
'Sankey',
|
|
285
|
-
'Warming Stripes'
|
|
286
|
-
]
|
|
277
|
+
const disabledCharts = ['Forest Plot', 'Pie', 'Paired Bar', 'Radar', 'Spark Line', 'Sankey', 'Warming Stripes']
|
|
287
278
|
if (disabledCharts.includes(visualizationType)) return false
|
|
288
279
|
return true
|
|
289
280
|
}
|
|
@@ -110,7 +110,7 @@ const prepareForecastData = (
|
|
|
110
110
|
return segments.length > 0 ? segments : [sortedData]
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
const Forecasting = ({ xScale, yScale, height, width, handleTooltipMouseOver, handleTooltipMouseOff }) => {
|
|
113
|
+
const Forecasting = ({ xScale, yScale, height, width, yAxisWidth, handleTooltipMouseOver, handleTooltipMouseOff }) => {
|
|
114
114
|
const { transformedData: data, rawData, config, seriesHighlight, parseDate } = useContext(ConfigContext)
|
|
115
115
|
const { xAxis, yAxis, legend, runtime } = config
|
|
116
116
|
const DEBUG = false
|
|
@@ -143,7 +143,7 @@ const Forecasting = ({ xScale, yScale, height, width, handleTooltipMouseOver, ha
|
|
|
143
143
|
return (
|
|
144
144
|
data && (
|
|
145
145
|
<ErrorBoundary component='ForecastingChart'>
|
|
146
|
-
<Group className='forecasting-items' key='forecasting-items-wrapper' left={
|
|
146
|
+
<Group className='forecasting-items' key='forecasting-items-wrapper' left={yAxisWidth}>
|
|
147
147
|
{runtime.forecastingSeriesKeys?.map((group, index) => {
|
|
148
148
|
if (!group || !group.stages) return false
|
|
149
149
|
return group.stages.map((stage, stageIndex) => {
|
|
@@ -23,13 +23,21 @@ type HorizonChartProps = {
|
|
|
23
23
|
yScale: any
|
|
24
24
|
xMax: number
|
|
25
25
|
yMax: number
|
|
26
|
+
yAxisWidth: number
|
|
26
27
|
handleTooltipMouseOver: (e: any, additionalData?: any) => void
|
|
27
28
|
handleTooltipMouseOff: () => void
|
|
28
29
|
tooltipData?: any
|
|
29
30
|
showTooltip?: boolean
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
const HorizonChart = ({
|
|
33
|
+
const HorizonChart = ({
|
|
34
|
+
xScale,
|
|
35
|
+
xMax,
|
|
36
|
+
yMax,
|
|
37
|
+
yAxisWidth,
|
|
38
|
+
handleTooltipMouseOver,
|
|
39
|
+
handleTooltipMouseOff
|
|
40
|
+
}: HorizonChartProps) => {
|
|
33
41
|
// Get data and config from context
|
|
34
42
|
const { transformedData: data, config, colorScale, rawData, parseDate } = useContext(ConfigContext)
|
|
35
43
|
|
|
@@ -94,7 +102,7 @@ const HorizonChart = ({ xScale, xMax, yMax, handleTooltipMouseOver, handleToolti
|
|
|
94
102
|
|
|
95
103
|
return (
|
|
96
104
|
<ErrorBoundary component='HorizonChart'>
|
|
97
|
-
<Group className='horizon-chart' key='horizon-wrapper' left={
|
|
105
|
+
<Group className='horizon-chart' key='horizon-wrapper' left={yAxisWidth} height={Number(yMax)}>
|
|
98
106
|
{seriesKeys.map((seriesKey, index) => {
|
|
99
107
|
const rowY = getRowY(index)
|
|
100
108
|
return (
|
|
@@ -9,9 +9,10 @@ type HoverLineProps = {
|
|
|
9
9
|
yMax?: number
|
|
10
10
|
point: { x: number; y: number }
|
|
11
11
|
orientation: 'horizontal' | 'vertical'
|
|
12
|
+
yAxisWidth: number
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
const HoverLine: React.FC<HoverLineProps> = ({ tooltipData, xMax, yMax, point, orientation }) => {
|
|
15
|
+
const HoverLine: React.FC<HoverLineProps> = ({ tooltipData, xMax, yMax, point, orientation, yAxisWidth }) => {
|
|
15
16
|
const { config } = useContext(ConfigContext)
|
|
16
17
|
const { verticalHoverLine, horizontalHoverLine } = config.visual
|
|
17
18
|
const { visualizationType } = config
|
|
@@ -23,8 +24,9 @@ const HoverLine: React.FC<HoverLineProps> = ({ tooltipData, xMax, yMax, point, o
|
|
|
23
24
|
const showHorizontalHoverLine = horizontalHoverLine || (horizontalHoverLine && isScatterPlot)
|
|
24
25
|
|
|
25
26
|
const getX = () => {
|
|
26
|
-
if (point.x
|
|
27
|
-
if (
|
|
27
|
+
if (point.x < yAxisWidth) return yAxisWidth
|
|
28
|
+
if (xMax === undefined) return point.x
|
|
29
|
+
if (point.x > xMax + yAxisWidth) return xMax + yAxisWidth
|
|
28
30
|
return point.x
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -52,11 +54,7 @@ const HoverLine: React.FC<HoverLineProps> = ({ tooltipData, xMax, yMax, point, o
|
|
|
52
54
|
if (isHorizontal) {
|
|
53
55
|
return (
|
|
54
56
|
showHorizontalHoverLine && (
|
|
55
|
-
<Group
|
|
56
|
-
key={`tooltipLine-horizontal${point.y}${point.x}`}
|
|
57
|
-
className='horizontal-tooltip-line'
|
|
58
|
-
left={config.yAxis.size ? config.yAxis.size : 0}
|
|
59
|
-
>
|
|
57
|
+
<Group key={`tooltipLine-horizontal${point.y}${point.x}`} className='horizontal-tooltip-line' left={yAxisWidth}>
|
|
60
58
|
<Line
|
|
61
59
|
from={{ x: 0, y: getY() }}
|
|
62
60
|
to={{ x: xMax, y: getY() }}
|
|
@@ -117,8 +117,8 @@ const Legend: React.FC<LegendProps> = forwardRef(
|
|
|
117
117
|
>
|
|
118
118
|
{(legend.label || legend.description) && (
|
|
119
119
|
<div className={legend.description ? 'mb-3' : 'mb-2'}>
|
|
120
|
-
{legend.label && <h3 className='fw-bold'>{parse(legend.label)}</h3>}
|
|
121
|
-
{legend.description && <p className='mt-2'>{parse(legend.description)}</p>}
|
|
120
|
+
{legend.label && <h3 className='fw-bold cove-prose'>{parse(legend.label)}</h3>}
|
|
121
|
+
{legend.description && <p className='mt-2 cove-prose'>{parse(legend.description)}</p>}
|
|
122
122
|
</div>
|
|
123
123
|
)}
|
|
124
124
|
<LegendGradient
|
|
@@ -242,7 +242,7 @@ const Legend: React.FC<LegendProps> = forwardRef(
|
|
|
242
242
|
</>
|
|
243
243
|
)}
|
|
244
244
|
</>
|
|
245
|
-
<LegendLabel align='left' className='m-0'>
|
|
245
|
+
<LegendLabel align='left' className='m-0 cove-prose'>
|
|
246
246
|
{parse(label.text)}
|
|
247
247
|
</LegendLabel>
|
|
248
248
|
</LegendItem>
|
|
@@ -361,7 +361,7 @@ const Legend: React.FC<LegendProps> = forwardRef(
|
|
|
361
361
|
/>
|
|
362
362
|
</svg>
|
|
363
363
|
</span>
|
|
364
|
-
<LegendLabel align='left' className='m-0'>
|
|
364
|
+
<LegendLabel align='left' className='m-0 cove-prose'>
|
|
365
365
|
{parse(String((pattern as any)?.label || key))}
|
|
366
366
|
</LegendLabel>
|
|
367
367
|
</LegendItem>
|
|
@@ -32,7 +32,7 @@ const LegendGroup = ({ formatLabels }) => {
|
|
|
32
32
|
|
|
33
33
|
const groups: string[] = getSubGroups(data, config.legend.groupBy)
|
|
34
34
|
|
|
35
|
-
const classNames = ['legend-group', 'container', config.legend.position, currentViewport
|
|
35
|
+
const classNames = ['legend-group', 'legend-group-grid', 'container', config.legend.position, currentViewport]
|
|
36
36
|
|
|
37
37
|
const gridCol =
|
|
38
38
|
currentViewport === 'xs'
|
|
@@ -47,6 +47,8 @@ const LegendGroup = ({ formatLabels }) => {
|
|
|
47
47
|
|
|
48
48
|
let classNameItem = ['legend-group group-item', isSigleCol]
|
|
49
49
|
|
|
50
|
+
if (groups.length === 0) return null
|
|
51
|
+
|
|
50
52
|
return (
|
|
51
53
|
<div className={classNames.join(' ')}>
|
|
52
54
|
{groups.map(group => {
|
|
@@ -40,8 +40,6 @@ export const getMarginBottom = (isLegendBottom, config) => {
|
|
|
40
40
|
|
|
41
41
|
if (isLegendTop) marginBottom = 27
|
|
42
42
|
|
|
43
|
-
if (isLegendTop && config.yAxis?.inlineLabel) marginBottom += 9
|
|
44
|
-
|
|
45
43
|
if (isLegendBottom) marginBottom += 9
|
|
46
44
|
|
|
47
45
|
if (hasSuppression) marginBottom += 40
|
|
@@ -10,10 +10,11 @@ type LineChartBumpCircleProp = {
|
|
|
10
10
|
xScale: any
|
|
11
11
|
yScale: any
|
|
12
12
|
parseDate: any
|
|
13
|
+
yAxisWidth: number
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
const LineChartBumpCircle = (props: LineChartBumpCircleProp) => {
|
|
16
|
-
const { config, xScale, yScale, parseDate } = props
|
|
17
|
+
const { config, xScale, yScale, parseDate, yAxisWidth } = props
|
|
17
18
|
|
|
18
19
|
// get xScale and yScale...
|
|
19
20
|
if (!config?.runtime?.series) return
|
|
@@ -55,7 +56,7 @@ const LineChartBumpCircle = (props: LineChartBumpCircleProp) => {
|
|
|
55
56
|
let axis_dataKey = d[config.xAxis.dataKey]
|
|
56
57
|
return (
|
|
57
58
|
<React.Fragment key={`bump-circle-${series_dataKey}-${dataIndex}`}>
|
|
58
|
-
<Group left={
|
|
59
|
+
<Group left={yAxisWidth}>
|
|
59
60
|
{series_dataKey && (
|
|
60
61
|
<>
|
|
61
62
|
<circle
|
|
@@ -36,6 +36,7 @@ const LineChart = (props: LineChartProps) => {
|
|
|
36
36
|
xScale,
|
|
37
37
|
yMax,
|
|
38
38
|
yScale,
|
|
39
|
+
yAxisWidth,
|
|
39
40
|
} = props
|
|
40
41
|
|
|
41
42
|
// prettier-ignore
|
|
@@ -55,7 +56,7 @@ const LineChart = (props: LineChartProps) => {
|
|
|
55
56
|
|
|
56
57
|
return (
|
|
57
58
|
<ErrorBoundary component='LineChart'>
|
|
58
|
-
<Group left={
|
|
59
|
+
<Group left={yAxisWidth} className='line-chart-group'>
|
|
59
60
|
{/* left - expects a number not a string */}
|
|
60
61
|
{(config.runtime.lineSeriesKeys || config.runtime.seriesKeys).map((seriesKey, index) => {
|
|
61
62
|
const seriesData = config.runtime.series.find(item => item.dataKey === seriesKey)
|
|
@@ -264,7 +265,7 @@ const LineChart = (props: LineChartProps) => {
|
|
|
264
265
|
}
|
|
265
266
|
styles={createStyles({
|
|
266
267
|
preliminaryData: config.preliminaryData,
|
|
267
|
-
data:
|
|
268
|
+
data: _data,
|
|
268
269
|
stroke: colorScale(config.runtime.seriesLabels[seriesKey]),
|
|
269
270
|
strokeWidth: seriesData.weight || 2,
|
|
270
271
|
handleLineType,
|
|
@@ -496,7 +497,7 @@ const LineChart = (props: LineChartProps) => {
|
|
|
496
497
|
</Text>
|
|
497
498
|
)}
|
|
498
499
|
</Group>
|
|
499
|
-
<Group left={
|
|
500
|
+
<Group left={yAxisWidth} className='glyph-tooltip-group'>
|
|
500
501
|
<Group key={`tooltip-group`} display={'block'}>
|
|
501
502
|
{/* tooltips */}
|
|
502
503
|
<Bar
|
|
@@ -543,7 +544,13 @@ const LineChart = (props: LineChartProps) => {
|
|
|
543
544
|
</Group>
|
|
544
545
|
</Group>
|
|
545
546
|
{config.visualizationType === 'Bump Chart' && (
|
|
546
|
-
<LineChartBumpCircle
|
|
547
|
+
<LineChartBumpCircle
|
|
548
|
+
config={config}
|
|
549
|
+
xScale={xScale}
|
|
550
|
+
yScale={yScale}
|
|
551
|
+
parseDate={parseDate}
|
|
552
|
+
yAxisWidth={yAxisWidth}
|
|
553
|
+
/>
|
|
547
554
|
)}
|
|
548
555
|
</ErrorBoundary>
|
|
549
556
|
)
|
|
@@ -76,13 +76,16 @@ const VisualizationRenderer: React.FC<VisualizationRendererProps> = ({
|
|
|
76
76
|
)}
|
|
77
77
|
|
|
78
78
|
{/* Paired Bar Chart */}
|
|
79
|
-
{visualizationType === 'Paired Bar' &&
|
|
79
|
+
{visualizationType === 'Paired Bar' && (
|
|
80
|
+
<PairedBarChart originalWidth={parentWidth} width={xMax} height={yMax} yAxisWidth={yAxisWidth} />
|
|
81
|
+
)}
|
|
80
82
|
|
|
81
83
|
{/* Scatter Plot */}
|
|
82
84
|
{visualizationType === 'Scatter Plot' && (
|
|
83
85
|
<ScatterPlot
|
|
84
86
|
xScale={xScale}
|
|
85
87
|
yScale={yScale}
|
|
88
|
+
yAxisWidth={yAxisWidth}
|
|
86
89
|
getXAxisData={getXAxisData}
|
|
87
90
|
getYAxisData={getYAxisData}
|
|
88
91
|
xMax={xMax}
|
|
@@ -102,6 +105,7 @@ const VisualizationRenderer: React.FC<VisualizationRendererProps> = ({
|
|
|
102
105
|
yScale={yScale}
|
|
103
106
|
xMax={xMax}
|
|
104
107
|
yMax={yMax}
|
|
108
|
+
yAxisWidth={yAxisWidth}
|
|
105
109
|
synchronizedXValue={synchronizedXValue}
|
|
106
110
|
showTooltip={showTooltip}
|
|
107
111
|
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
@@ -115,6 +119,7 @@ const VisualizationRenderer: React.FC<VisualizationRendererProps> = ({
|
|
|
115
119
|
yScale={yScale}
|
|
116
120
|
xMax={xMax}
|
|
117
121
|
yMax={yMax}
|
|
122
|
+
yAxisWidth={yAxisWidth}
|
|
118
123
|
handleTooltipMouseOver={handleTooltipMouseOver}
|
|
119
124
|
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
120
125
|
tooltipData={tooltipData}
|
|
@@ -132,6 +137,7 @@ const VisualizationRenderer: React.FC<VisualizationRendererProps> = ({
|
|
|
132
137
|
max={max}
|
|
133
138
|
xScale={xScale}
|
|
134
139
|
yScale={yScale}
|
|
140
|
+
yAxisWidth={yAxisWidth}
|
|
135
141
|
/>
|
|
136
142
|
)}
|
|
137
143
|
|
|
@@ -156,6 +162,7 @@ const VisualizationRenderer: React.FC<VisualizationRendererProps> = ({
|
|
|
156
162
|
yScale={yScale}
|
|
157
163
|
yMax={yMax}
|
|
158
164
|
xMax={xMax}
|
|
165
|
+
yAxisWidth={yAxisWidth}
|
|
159
166
|
chartRef={svgRef}
|
|
160
167
|
width={xMax}
|
|
161
168
|
height={yMax}
|
|
@@ -193,6 +200,7 @@ const VisualizationRenderer: React.FC<VisualizationRendererProps> = ({
|
|
|
193
200
|
<LineChart
|
|
194
201
|
xScale={xScale}
|
|
195
202
|
yScale={yScale}
|
|
203
|
+
yAxisWidth={yAxisWidth}
|
|
196
204
|
getXAxisData={getXAxisData}
|
|
197
205
|
getYAxisData={getYAxisData}
|
|
198
206
|
xMax={xMax}
|
|
@@ -211,6 +219,7 @@ const VisualizationRenderer: React.FC<VisualizationRendererProps> = ({
|
|
|
211
219
|
<LineChart
|
|
212
220
|
xScale={xScale}
|
|
213
221
|
yScale={yScale}
|
|
222
|
+
yAxisWidth={yAxisWidth}
|
|
214
223
|
getXAxisData={getXAxisData}
|
|
215
224
|
getYAxisData={getYAxisData}
|
|
216
225
|
xMax={xMax}
|
|
@@ -229,6 +238,7 @@ const VisualizationRenderer: React.FC<VisualizationRendererProps> = ({
|
|
|
229
238
|
tooltipData={tooltipData}
|
|
230
239
|
xScale={xScale}
|
|
231
240
|
yScale={yScale}
|
|
241
|
+
yAxisWidth={yAxisWidth}
|
|
232
242
|
width={xMax}
|
|
233
243
|
height={yMax}
|
|
234
244
|
xScaleNoPadding={xScaleNoPadding}
|
|
@@ -67,6 +67,11 @@ const renderLinearChart = (
|
|
|
67
67
|
)
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
const getLeftAxisLabelTransforms = container =>
|
|
71
|
+
Array.from(container.querySelectorAll('.left-axis text.y-label'))
|
|
72
|
+
.map(label => label.getAttribute('transform'))
|
|
73
|
+
.filter(Boolean)
|
|
74
|
+
|
|
70
75
|
describe('LinearChart', () => {
|
|
71
76
|
describe('rendering', () => {
|
|
72
77
|
it('renders without crashing', () => {
|
|
@@ -258,6 +263,148 @@ describe('LinearChart', () => {
|
|
|
258
263
|
// The axis line should be hidden, but grid lines may still render
|
|
259
264
|
expect(container.querySelector('svg')).toBeTruthy()
|
|
260
265
|
})
|
|
266
|
+
|
|
267
|
+
it('ignores yAxis.labelOffset when positioning the vertical left-axis title', () => {
|
|
268
|
+
const baseRuntime = {
|
|
269
|
+
xAxis: {
|
|
270
|
+
type: 'date',
|
|
271
|
+
dataKey: 'Date',
|
|
272
|
+
label: 'X-Axis'
|
|
273
|
+
},
|
|
274
|
+
yAxis: {
|
|
275
|
+
size: 50,
|
|
276
|
+
label: 'Y-Axis',
|
|
277
|
+
gridLines: true,
|
|
278
|
+
labelOffset: 0
|
|
279
|
+
},
|
|
280
|
+
originalXAxis: {
|
|
281
|
+
dataKey: 'Date'
|
|
282
|
+
},
|
|
283
|
+
series: [],
|
|
284
|
+
seriesKeys: [],
|
|
285
|
+
seriesLabelsAll: [],
|
|
286
|
+
uniqueId: 'test-chart'
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const baseRender = renderLinearChart({
|
|
290
|
+
yAxis: {
|
|
291
|
+
hideAxis: false,
|
|
292
|
+
hideLabel: false,
|
|
293
|
+
hideTicks: false,
|
|
294
|
+
size: '50',
|
|
295
|
+
gridLines: true,
|
|
296
|
+
label: 'Y-Axis',
|
|
297
|
+
tickRotation: 0,
|
|
298
|
+
anchors: [],
|
|
299
|
+
axisPadding: 0,
|
|
300
|
+
labelPlacement: 'On Date/Category Axis',
|
|
301
|
+
rightAxisSize: 0,
|
|
302
|
+
labelOffset: 0
|
|
303
|
+
},
|
|
304
|
+
runtime: baseRuntime
|
|
305
|
+
})
|
|
306
|
+
const offsetRender = renderLinearChart({
|
|
307
|
+
yAxis: {
|
|
308
|
+
hideAxis: false,
|
|
309
|
+
hideLabel: false,
|
|
310
|
+
hideTicks: false,
|
|
311
|
+
size: '50',
|
|
312
|
+
gridLines: true,
|
|
313
|
+
label: 'Y-Axis',
|
|
314
|
+
tickRotation: 0,
|
|
315
|
+
anchors: [],
|
|
316
|
+
axisPadding: 0,
|
|
317
|
+
labelPlacement: 'On Date/Category Axis',
|
|
318
|
+
rightAxisSize: 0,
|
|
319
|
+
labelOffset: 240
|
|
320
|
+
},
|
|
321
|
+
runtime: {
|
|
322
|
+
...baseRuntime,
|
|
323
|
+
yAxis: {
|
|
324
|
+
...baseRuntime.yAxis,
|
|
325
|
+
labelOffset: 240
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
const baseTransforms = getLeftAxisLabelTransforms(baseRender.container)
|
|
331
|
+
const offsetTransforms = getLeftAxisLabelTransforms(offsetRender.container)
|
|
332
|
+
|
|
333
|
+
expect(baseTransforms.length).toBeGreaterThan(0)
|
|
334
|
+
expect(offsetTransforms).toEqual(baseTransforms)
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
it('ignores horizontal xAxis.labelOffset when positioning the left-side axis title', () => {
|
|
338
|
+
const baseRuntime = {
|
|
339
|
+
xAxis: {
|
|
340
|
+
type: 'linear',
|
|
341
|
+
dataKey: 'Value',
|
|
342
|
+
label: 'X-Axis'
|
|
343
|
+
},
|
|
344
|
+
yAxis: {
|
|
345
|
+
size: 50,
|
|
346
|
+
label: 'Y-Axis',
|
|
347
|
+
gridLines: true,
|
|
348
|
+
labelOffset: 0
|
|
349
|
+
},
|
|
350
|
+
originalXAxis: {
|
|
351
|
+
dataKey: 'Date'
|
|
352
|
+
},
|
|
353
|
+
series: [],
|
|
354
|
+
seriesKeys: [],
|
|
355
|
+
seriesLabelsAll: [],
|
|
356
|
+
uniqueId: 'test-chart'
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const baseRender = renderLinearChart({
|
|
360
|
+
orientation: 'horizontal',
|
|
361
|
+
xAxis: {
|
|
362
|
+
type: 'linear',
|
|
363
|
+
dataKey: 'Value',
|
|
364
|
+
label: 'X-Axis',
|
|
365
|
+
hideAxis: false,
|
|
366
|
+
hideLabel: false,
|
|
367
|
+
hideTicks: false,
|
|
368
|
+
size: '50',
|
|
369
|
+
tickRotation: 0,
|
|
370
|
+
maxTickRotation: 90,
|
|
371
|
+
anchors: [],
|
|
372
|
+
axisPadding: 0,
|
|
373
|
+
labelOffset: 0
|
|
374
|
+
},
|
|
375
|
+
runtime: baseRuntime
|
|
376
|
+
})
|
|
377
|
+
const offsetRender = renderLinearChart({
|
|
378
|
+
orientation: 'horizontal',
|
|
379
|
+
xAxis: {
|
|
380
|
+
type: 'linear',
|
|
381
|
+
dataKey: 'Value',
|
|
382
|
+
label: 'X-Axis',
|
|
383
|
+
hideAxis: false,
|
|
384
|
+
hideLabel: false,
|
|
385
|
+
hideTicks: false,
|
|
386
|
+
size: '50',
|
|
387
|
+
tickRotation: 0,
|
|
388
|
+
maxTickRotation: 90,
|
|
389
|
+
anchors: [],
|
|
390
|
+
axisPadding: 0,
|
|
391
|
+
labelOffset: 240
|
|
392
|
+
},
|
|
393
|
+
runtime: {
|
|
394
|
+
...baseRuntime,
|
|
395
|
+
yAxis: {
|
|
396
|
+
...baseRuntime.yAxis,
|
|
397
|
+
labelOffset: 240
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
const baseTransforms = getLeftAxisLabelTransforms(baseRender.container)
|
|
403
|
+
const offsetTransforms = getLeftAxisLabelTransforms(offsetRender.container)
|
|
404
|
+
|
|
405
|
+
expect(baseTransforms.length).toBeGreaterThan(0)
|
|
406
|
+
expect(offsetTransforms).toEqual(baseTransforms)
|
|
407
|
+
})
|
|
261
408
|
})
|
|
262
409
|
|
|
263
410
|
describe('SVG dimensions', () => {
|