@cdc/chart 4.26.2 → 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 +39419 -35180
- package/examples/__data__/data-with-metadata.json +10 -0
- 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/pie/planet-pie-example-config.json +2 -1
- 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 +58 -0
- package/examples/minimal-example.json +24 -0
- package/examples/private/test2.json +35012 -0
- package/package.json +4 -4
- package/src/CdcChart.tsx +8 -4
- package/src/CdcChartComponent.tsx +326 -290
- package/src/_stories/Chart.CustomColors.smoke.stories.tsx +97 -0
- package/src/_stories/Chart.Defaults.smoke.stories.tsx +95 -0
- 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.SmallestLeftAxisMax.smoke.stories.tsx +64 -0
- package/src/_stories/{Chart.stories.tsx → Chart.smoke.stories.tsx} +48 -2
- package/src/_stories/{Chart.tooltip.stories.tsx → Chart.tooltip.smoke.stories.tsx} +68 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +177 -115
- package/src/_stories/ChartBrush.Editor.stories.tsx +11 -25
- package/src/_stories/ChartEditor.Editor.stories.tsx +24 -1
- package/src/_stories/{Chart.CustomColors.stories.tsx → ChartLine.DashedDates.smoke.stories.tsx} +4 -4
- package/src/_stories/_mock/line_chart_dashed_dates.json +276 -0
- package/src/_stories/_mock/paired-bar-abbr.json +421 -0
- package/src/_stories/_mock/paired-bar.json +1 -1
- package/src/_stories/_mock/pie_custom_colors.json +268 -0
- package/src/_stories/_mock/smallest_left_axis_max.json +104 -0
- package/src/components/Annotations/components/AnnotationDraggable.styles.css +10 -10
- package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -1
- package/src/components/Annotations/components/AnnotationDropdown.styles.css +1 -1
- package/src/components/Annotations/components/AnnotationList.styles.css +11 -11
- package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -2
- package/src/components/Axis/BottomAxis.tsx +10 -3
- package/src/components/Axis/LeftAxis.tsx +2 -4
- package/src/components/Axis/LeftAxisGridlines.tsx +1 -3
- package/src/components/Axis/PairedBarAxis.tsx +10 -4
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +21 -33
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +21 -35
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +21 -36
- package/src/components/BarChart/components/BarChart.Vertical.tsx +21 -34
- package/src/components/BarChart/components/BarChart.tsx +2 -6
- package/src/components/BarChart/helpers/getPatternUrl.ts +94 -0
- package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +134 -0
- package/src/components/BarChart/helpers/useBarChart.ts +4 -1
- package/src/components/BoxPlot/BoxPlot.Vertical.tsx +3 -3
- package/src/components/Brush/BrushSelector.tsx +2 -1
- package/src/components/Brush/MiniChartPreview.tsx +21 -26
- package/src/components/EditorPanel/EditorPanel.tsx +692 -954
- package/src/components/EditorPanel/EditorPanelContext.ts +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +218 -167
- package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +0 -78
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +39 -1
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +169 -135
- 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 +95 -28
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +45 -42
- package/src/components/EditorPanel/editor-panel.scss +1 -1
- package/src/components/EditorPanel/useEditorPermissions.ts +1 -10
- package/src/components/Forecasting/Forecasting.tsx +2 -2
- package/src/components/ForestPlot/ForestPlot.tsx +26 -22
- 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 +9 -4
- package/src/components/Legend/LegendGroup/LegendGroup.tsx +3 -1
- package/src/components/Legend/helpers/createFormatLabels.tsx +3 -2
- 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 +224 -0
- package/src/components/LinearChart/tests/mockConfigContext.ts +2 -0
- package/src/components/LinearChart.tsx +124 -47
- package/src/components/PairedBarChart.jsx +2 -2
- package/src/components/PieChart/PieChart.tsx +30 -13
- package/src/components/RadarChart/RadarChart.tsx +1 -1
- package/src/components/Regions/components/Regions.tsx +36 -26
- package/src/components/Sankey/components/Sankey.tsx +3 -3
- package/src/components/Sankey/sankey.scss +1 -1
- package/src/components/ScatterPlot/ScatterPlot.jsx +19 -17
- package/src/components/SmallMultiples/SmallMultipleTile.tsx +1 -0
- package/src/components/SmallMultiples/SmallMultiples.css +5 -5
- package/src/components/Sparkline/components/SparkLine.tsx +1 -1
- package/src/components/Sparkline/index.scss +4 -2
- package/src/components/WarmingStripes/WarmingStripes.tsx +5 -3
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +8 -8
- package/src/data/initial-state.js +24 -14
- package/src/data/legacy-defaults.ts +18 -0
- package/src/helpers/abbreviateNumber.ts +24 -17
- package/src/helpers/calculateLeftYAxisWidth.ts +193 -0
- package/src/helpers/getChartPatternId.ts +17 -0
- package/src/helpers/getMinMax.ts +16 -2
- package/src/helpers/seriesColumnSettings.ts +114 -0
- package/src/helpers/tests/countNumOfTicks.test.ts +77 -0
- package/src/helpers/tests/seriesColumnSettings.test.ts +84 -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/useRightAxis.ts +14 -0
- package/src/hooks/useScales.ts +92 -56
- package/src/hooks/useSmallMultipleSynchronization.ts +3 -4
- package/src/hooks/useTooltip.tsx +186 -40
- package/src/scss/main.scss +152 -79
- package/src/test/CdcChart.test.jsx +26 -2
- package/src/types/ChartConfig.ts +5 -0
- package/tests/fixtures/chart-config-with-metadata.json +29 -0
- package/tests/fixtures/data-with-metadata.json +10 -0
- 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/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.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/{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
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "chart",
|
|
3
|
+
"version": "4.26.3",
|
|
4
|
+
"visualizationType": "Line",
|
|
5
|
+
"visualizationSubType": "regular",
|
|
6
|
+
"title": "Smallest Left Axis Maximum Demo",
|
|
7
|
+
"titleStyle": "small",
|
|
8
|
+
"showTitle": true,
|
|
9
|
+
"theme": "theme-blue",
|
|
10
|
+
"animate": false,
|
|
11
|
+
"fontSize": "medium",
|
|
12
|
+
"lineDatapointStyle": "hover",
|
|
13
|
+
"lineDatapointColor": "Same as Line",
|
|
14
|
+
"isResponsiveTicks": false,
|
|
15
|
+
"general": {
|
|
16
|
+
"showDownloadButton": false,
|
|
17
|
+
"showMissingDataLabel": true,
|
|
18
|
+
"hideNullValue": true
|
|
19
|
+
},
|
|
20
|
+
"padding": { "left": 5, "right": 5 },
|
|
21
|
+
"heights": { "vertical": "300", "horizontal": 750 },
|
|
22
|
+
"barThickness": 0.35,
|
|
23
|
+
"orientation": "vertical",
|
|
24
|
+
"yAxis": {
|
|
25
|
+
"hideAxis": true,
|
|
26
|
+
"displayNumbersOnBar": false,
|
|
27
|
+
"hideLabel": false,
|
|
28
|
+
"hideTicks": true,
|
|
29
|
+
"size": "25",
|
|
30
|
+
"gridLines": true,
|
|
31
|
+
"enablePadding": false,
|
|
32
|
+
"min": "",
|
|
33
|
+
"max": "",
|
|
34
|
+
"numTicks": "5",
|
|
35
|
+
"scalePadding": "0",
|
|
36
|
+
"tickRotation": "",
|
|
37
|
+
"anchors": [],
|
|
38
|
+
"categories": [],
|
|
39
|
+
"label": "",
|
|
40
|
+
"inlineLabel": " cases",
|
|
41
|
+
"type": "linear",
|
|
42
|
+
"smallestLeftAxisMax": 5
|
|
43
|
+
},
|
|
44
|
+
"xAxis": {
|
|
45
|
+
"sortDates": false,
|
|
46
|
+
"anchors": [],
|
|
47
|
+
"type": "categorical",
|
|
48
|
+
"hideAxis": false,
|
|
49
|
+
"hideLabel": false,
|
|
50
|
+
"hideTicks": false,
|
|
51
|
+
"size": "0",
|
|
52
|
+
"tickRotation": "0",
|
|
53
|
+
"numTicks": "",
|
|
54
|
+
"labelOffset": 0,
|
|
55
|
+
"padding": "4",
|
|
56
|
+
"dataKey": "Month",
|
|
57
|
+
"label": "Month",
|
|
58
|
+
"tickWidthMax": 100
|
|
59
|
+
},
|
|
60
|
+
"table": {
|
|
61
|
+
"label": "Data Table",
|
|
62
|
+
"expanded": false,
|
|
63
|
+
"limitHeight": false,
|
|
64
|
+
"show": true,
|
|
65
|
+
"showDownloadUrl": false,
|
|
66
|
+
"showVertical": true
|
|
67
|
+
},
|
|
68
|
+
"series": [{ "dataKey": "Cases", "type": "Line", "axis": "Left", "tooltip": true }],
|
|
69
|
+
"tooltips": { "opacity": 90, "singleSeries": false },
|
|
70
|
+
"legend": {
|
|
71
|
+
"hide": true
|
|
72
|
+
},
|
|
73
|
+
"filters": [
|
|
74
|
+
{
|
|
75
|
+
"values": ["Region A", "Region B", "Region C"],
|
|
76
|
+
"active": "Region B",
|
|
77
|
+
"order": "asc",
|
|
78
|
+
"columnName": "Region",
|
|
79
|
+
"filterStyle": "dropdown"
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"data": [
|
|
83
|
+
{ "Month": "Jan", "Cases": "12", "Region": "Region A" },
|
|
84
|
+
{ "Month": "Feb", "Cases": "18", "Region": "Region A" },
|
|
85
|
+
{ "Month": "Mar", "Cases": "15", "Region": "Region A" },
|
|
86
|
+
{ "Month": "Apr", "Cases": "22", "Region": "Region A" },
|
|
87
|
+
{ "Month": "May", "Cases": "28", "Region": "Region A" },
|
|
88
|
+
{ "Month": "Jun", "Cases": "20", "Region": "Region A" },
|
|
89
|
+
|
|
90
|
+
{ "Month": "Jan", "Cases": "1", "Region": "Region B" },
|
|
91
|
+
{ "Month": "Feb", "Cases": "0", "Region": "Region B" },
|
|
92
|
+
{ "Month": "Mar", "Cases": "1", "Region": "Region B" },
|
|
93
|
+
{ "Month": "Apr", "Cases": "0", "Region": "Region B" },
|
|
94
|
+
{ "Month": "May", "Cases": "1", "Region": "Region B" },
|
|
95
|
+
{ "Month": "Jun", "Cases": "0", "Region": "Region B" },
|
|
96
|
+
|
|
97
|
+
{ "Month": "Jan", "Cases": "45", "Region": "Region C" },
|
|
98
|
+
{ "Month": "Feb", "Cases": "52", "Region": "Region C" },
|
|
99
|
+
{ "Month": "Mar", "Cases": "48", "Region": "Region C" },
|
|
100
|
+
{ "Month": "Apr", "Cases": "60", "Region": "Region C" },
|
|
101
|
+
{ "Month": "May", "Cases": "55", "Region": "Region C" },
|
|
102
|
+
{ "Month": "Jun", "Cases": "50", "Region": "Region C" }
|
|
103
|
+
]
|
|
104
|
+
}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
.
|
|
2
|
-
line-height: 1.1rem;
|
|
1
|
+
.cove-visualization.type-chart .annotation__desktop-label {
|
|
3
2
|
font-size: 16px;
|
|
3
|
+
line-height: 1.1rem;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
.
|
|
6
|
+
.cove-visualization.type-chart {
|
|
7
7
|
.annotation__mobile-label-circle {
|
|
8
8
|
stroke-width: 1;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
.annotation__has-dropdown-number {
|
|
12
|
-
display: flex;
|
|
13
|
-
justify-content: center;
|
|
14
12
|
align-items: center;
|
|
13
|
+
border: 1px solid #666;
|
|
15
14
|
border-radius: 50%;
|
|
16
|
-
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
display: flex;
|
|
17
|
+
font-size: 14px;
|
|
17
18
|
height: 24px;
|
|
18
|
-
|
|
19
|
+
justify-content: center;
|
|
19
20
|
min-height: 24px;
|
|
20
|
-
|
|
21
|
+
min-width: 24px;
|
|
21
22
|
text-align: center;
|
|
22
|
-
|
|
23
|
-
box-sizing: border-box;
|
|
23
|
+
width: 24px;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -218,7 +218,7 @@ const Annotations = ({
|
|
|
218
218
|
return (
|
|
219
219
|
<HtmlLabel
|
|
220
220
|
className='annotation__desktop-label'
|
|
221
|
-
containerStyle={{ width: `${labelWidth}px` }}
|
|
221
|
+
containerStyle={{ width: 'fit-content', maxWidth: `${labelWidth}px` }}
|
|
222
222
|
horizontalAnchor={horizontalAnchor}
|
|
223
223
|
verticalAnchor={verticalAnchor}
|
|
224
224
|
showAnchorLine={false}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
.
|
|
1
|
+
.cove-visualization.type-chart {
|
|
2
2
|
.annotation__title-circle {
|
|
3
|
-
display: flex;
|
|
4
|
-
justify-content: center;
|
|
5
3
|
align-items: center;
|
|
4
|
+
border: 1px solid #666;
|
|
6
5
|
border-radius: 50%;
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
display: flex;
|
|
7
|
+
font-size: 14px;
|
|
9
8
|
height: 24px;
|
|
10
|
-
|
|
9
|
+
justify-content: center;
|
|
11
10
|
line-height: 1.5rem;
|
|
12
|
-
|
|
11
|
+
margin-right: 5px;
|
|
12
|
+
padding: 8px;
|
|
13
13
|
text-align: center;
|
|
14
|
-
|
|
14
|
+
width: 24px;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
.annotation__title-wrapper {
|
|
18
|
+
align-items: center;
|
|
18
19
|
display: flex;
|
|
19
20
|
flex-wrap: nowrap;
|
|
20
|
-
align-items: center;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
.annotation__title-wrapper .annotation__title-text {
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
margin-top: 5px;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
.cove-
|
|
36
|
-
container-type: inline-size;
|
|
35
|
+
.cove-visualization__body {
|
|
37
36
|
container-name: content;
|
|
37
|
+
container-type: inline-size;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -11,7 +11,15 @@ import { Bar, AreaStack } from '@visx/shape'
|
|
|
11
11
|
import { Group } from '@visx/group'
|
|
12
12
|
import { approvedCurveTypes } from '@cdc/core/helpers/lineChartHelpers'
|
|
13
13
|
|
|
14
|
-
const AreaChartStacked = ({
|
|
14
|
+
const AreaChartStacked = ({
|
|
15
|
+
xScale,
|
|
16
|
+
yScale,
|
|
17
|
+
yMax,
|
|
18
|
+
xMax,
|
|
19
|
+
yAxisWidth,
|
|
20
|
+
handleTooltipMouseOver,
|
|
21
|
+
handleTooltipMouseOff
|
|
22
|
+
}) => {
|
|
15
23
|
// import data from context
|
|
16
24
|
let { transformedData: data, config, seriesHighlight, colorScale, rawData, parseDate } = useContext(ConfigContext)
|
|
17
25
|
// Draw transparent bars over the chart to get tooltip data
|
|
@@ -39,7 +47,7 @@ const AreaChartStacked = ({ xScale, yScale, yMax, xMax, handleTooltipMouseOver,
|
|
|
39
47
|
<Group
|
|
40
48
|
className='area-chart'
|
|
41
49
|
key='area-wrapper'
|
|
42
|
-
left={
|
|
50
|
+
left={yAxisWidth + strokeWidth / 2}
|
|
43
51
|
height={Number(yMax)}
|
|
44
52
|
style={{ overflow: 'hidden' }}
|
|
45
53
|
>
|
|
@@ -199,12 +199,13 @@ const BottomAxis: React.FC<BottomAxisProps> = ({
|
|
|
199
199
|
|
|
200
200
|
return (
|
|
201
201
|
<Group className='bottom-axis' width={parentWidth}>
|
|
202
|
-
{filteredTicks.map((tick, i
|
|
202
|
+
{filteredTicks.map((tick, i) => {
|
|
203
203
|
// when using LogScale show major ticks values only
|
|
204
204
|
const showTick = String(tick.value).startsWith('1') || tick.value === 0.1 ? 'block' : 'none'
|
|
205
205
|
const tickLength = showTick === 'block' ? MAJOR_TICK_LENGTH : DEFAULT_TICK_LENGTH
|
|
206
206
|
const to = { x: tick.to.x, y: tickLength }
|
|
207
|
-
const
|
|
207
|
+
const tickSlotWidth = filteredTicks.length > 0 ? xMax / filteredTicks.length : xMax
|
|
208
|
+
const limitedWidth = Math.max(Math.min(maxLengthOfTick, tickSlotWidth), 1)
|
|
208
209
|
|
|
209
210
|
// Configure rotation using effective values (computed above without mutations)
|
|
210
211
|
const tickRotation =
|
|
@@ -246,7 +247,13 @@ const BottomAxis: React.FC<BottomAxisProps> = ({
|
|
|
246
247
|
</Group>
|
|
247
248
|
)
|
|
248
249
|
})}
|
|
249
|
-
{!config.xAxis.hideAxis &&
|
|
250
|
+
{!config.xAxis.hideAxis && (
|
|
251
|
+
<Line
|
|
252
|
+
from={isForestPlot ? { ...props.axisFromPoint, x: 0 } : props.axisFromPoint}
|
|
253
|
+
to={props.axisToPoint}
|
|
254
|
+
stroke='#333'
|
|
255
|
+
/>
|
|
256
|
+
)}
|
|
250
257
|
<Text
|
|
251
258
|
innerRef={xAxisTitleRef}
|
|
252
259
|
className='x-axis-title-label'
|
|
@@ -36,7 +36,6 @@ interface LeftAxisProps {
|
|
|
36
36
|
suffixWidth?: number
|
|
37
37
|
horizontalYAxisLabelSpace?: number
|
|
38
38
|
categoryLabelSpace?: number
|
|
39
|
-
yLabelOffset?: number
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
const LeftAxis: React.FC<LeftAxisProps> = ({
|
|
@@ -53,8 +52,7 @@ const LeftAxis: React.FC<LeftAxisProps> = ({
|
|
|
53
52
|
suffixRef,
|
|
54
53
|
suffixWidth = 0,
|
|
55
54
|
horizontalYAxisLabelSpace = 0,
|
|
56
|
-
categoryLabelSpace = 0
|
|
57
|
-
yLabelOffset = 0
|
|
55
|
+
categoryLabelSpace = 0
|
|
58
56
|
}) => {
|
|
59
57
|
const { config, colorScale, seriesHighlight } = useContext(ConfigContext)
|
|
60
58
|
const { runtime, orientation, visualizationType, visualizationSubType, heights } = config
|
|
@@ -387,7 +385,7 @@ const LeftAxis: React.FC<LeftAxisProps> = ({
|
|
|
387
385
|
className='y-label'
|
|
388
386
|
textAnchor='middle'
|
|
389
387
|
verticalAnchor='start'
|
|
390
|
-
transform={`translate(${-1 * yAxisWidth
|
|
388
|
+
transform={`translate(${-1 * yAxisWidth}, ${axisCenter}) rotate(-90)`}
|
|
391
389
|
fontWeight='bold'
|
|
392
390
|
fill={config.yAxis.labelColor}
|
|
393
391
|
fontSize={axisLabelFontSize}
|
|
@@ -10,7 +10,6 @@ interface LeftAxisGridlinesProps {
|
|
|
10
10
|
xMax: number
|
|
11
11
|
yAxisWidth: number
|
|
12
12
|
numTicks: number
|
|
13
|
-
yLabelOffset: number
|
|
14
13
|
axisLabelFontSize: number
|
|
15
14
|
}
|
|
16
15
|
|
|
@@ -19,7 +18,6 @@ const LeftAxisGridlines: React.FC<LeftAxisGridlinesProps> = ({
|
|
|
19
18
|
xMax,
|
|
20
19
|
yAxisWidth,
|
|
21
20
|
numTicks,
|
|
22
|
-
yLabelOffset,
|
|
23
21
|
axisLabelFontSize
|
|
24
22
|
}) => {
|
|
25
23
|
const { config } = useContext(ConfigContext)
|
|
@@ -60,7 +58,7 @@ const LeftAxisGridlines: React.FC<LeftAxisGridlinesProps> = ({
|
|
|
60
58
|
className='y-label'
|
|
61
59
|
textAnchor='middle'
|
|
62
60
|
verticalAnchor='start'
|
|
63
|
-
transform={`translate(${-1 * yAxisWidth
|
|
61
|
+
transform={`translate(${-1 * yAxisWidth}, ${axisCenter}) rotate(-90)`}
|
|
64
62
|
fontWeight='bold'
|
|
65
63
|
fill={config.yAxis.labelColor}
|
|
66
64
|
fontSize={axisLabelFontSize}
|
|
@@ -63,7 +63,9 @@ export const PairedBarAxis: React.FC<PairedBarAxisProps> = ({
|
|
|
63
63
|
const numberOfTicks = filteredTicks?.length
|
|
64
64
|
const xMaxHalf = xScale.range()[0] || xMax / 2
|
|
65
65
|
|
|
66
|
-
const tickWidthAll = filteredTicks.map(tick =>
|
|
66
|
+
const tickWidthAll = filteredTicks.map(tick =>
|
|
67
|
+
getTextWidth(tick.formattedValue ?? formatNumber(tick.value, 'left', true), tickLabelFont)
|
|
68
|
+
)
|
|
67
69
|
const sumOfTickWidth = tickWidthAll.reduce((a, b) => a + b, BASE_TICK_WIDTH_ACCUMULATOR)
|
|
68
70
|
const spaceBetweenEachTick = (xMaxHalf - sumOfTickWidth) / numberOfTicks
|
|
69
71
|
|
|
@@ -115,7 +117,7 @@ export const PairedBarAxis: React.FC<PairedBarAxisProps> = ({
|
|
|
115
117
|
textAnchor={textAnchor}
|
|
116
118
|
fontSize={tickLabelFontSize}
|
|
117
119
|
>
|
|
118
|
-
{formatNumber(tick.value, 'left')}
|
|
120
|
+
{tick.formattedValue ?? formatNumber(tick.value, 'left', true)}
|
|
119
121
|
</Text>
|
|
120
122
|
)}
|
|
121
123
|
</Group>
|
|
@@ -129,7 +131,7 @@ export const PairedBarAxis: React.FC<PairedBarAxisProps> = ({
|
|
|
129
131
|
top={yMax}
|
|
130
132
|
left={yAxisWidth}
|
|
131
133
|
label={runtime.xAxis.label}
|
|
132
|
-
tickFormat={isDateScale(runtime.xAxis) ? formatDate : formatNumber}
|
|
134
|
+
tickFormat={isDateScale(runtime.xAxis) ? formatDate : tick => formatNumber(tick, 'left', true)}
|
|
133
135
|
scale={g1xScale}
|
|
134
136
|
stroke='#333'
|
|
135
137
|
tickStroke='#333'
|
|
@@ -150,7 +152,11 @@ export const PairedBarAxis: React.FC<PairedBarAxisProps> = ({
|
|
|
150
152
|
left={yAxisWidth}
|
|
151
153
|
label={runtime.xAxis.label}
|
|
152
154
|
tickFormat={
|
|
153
|
-
isDateScale(runtime.xAxis)
|
|
155
|
+
isDateScale(runtime.xAxis)
|
|
156
|
+
? formatDate
|
|
157
|
+
: runtime.xAxis.dataKey !== 'Year'
|
|
158
|
+
? tick => formatNumber(tick, 'left', true)
|
|
159
|
+
: tick => tick
|
|
154
160
|
}
|
|
155
161
|
scale={g2xScale}
|
|
156
162
|
stroke='#333'
|
|
@@ -24,6 +24,9 @@ import { ChartContext } from '../../../types/ChartContext'
|
|
|
24
24
|
import _ from 'lodash'
|
|
25
25
|
import { getBarData } from '../helpers/getBarData'
|
|
26
26
|
import { getHorizontalBarHeights } from '../helpers/getBarHeights'
|
|
27
|
+
import { getPatternUrl as getPatternUrlForBar } from '../helpers/getPatternUrl'
|
|
28
|
+
import { getChartPatternId } from '../../../helpers/getChartPatternId'
|
|
29
|
+
import { buildSeriesTooltipListHtml } from '../../../helpers/tooltipHelpers'
|
|
27
30
|
|
|
28
31
|
const BarChartHorizontal = () => {
|
|
29
32
|
const { xScale, yScale, yMax, seriesScale, barChart } = useContext<BarChartContextValues>(BarChartContext)
|
|
@@ -72,7 +75,7 @@ const BarChartHorizontal = () => {
|
|
|
72
75
|
return (
|
|
73
76
|
<defs>
|
|
74
77
|
{Object.entries(config.legend.patterns).map(([key, pattern]) => {
|
|
75
|
-
const patternId =
|
|
78
|
+
const patternId = getChartPatternId(key)
|
|
76
79
|
const size = pattern.patternSize || 8
|
|
77
80
|
|
|
78
81
|
switch (pattern.shape) {
|
|
@@ -241,11 +244,14 @@ const BarChartHorizontal = () => {
|
|
|
241
244
|
: xAxisValue
|
|
242
245
|
const additionalColTooltip = getAdditionalColumn(bar.key, hoveredBar)
|
|
243
246
|
const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${yAxisValue}`
|
|
244
|
-
const tooltip =
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
247
|
+
const tooltip = buildSeriesTooltipListHtml({
|
|
248
|
+
config,
|
|
249
|
+
colorScale,
|
|
250
|
+
heading: yAxisTooltip,
|
|
251
|
+
seriesKey: bar.key,
|
|
252
|
+
seriesText: tooltipBody,
|
|
253
|
+
extraRows: additionalColTooltip ? [additionalColTooltip] : []
|
|
254
|
+
})
|
|
249
255
|
|
|
250
256
|
// configure colors
|
|
251
257
|
let labelColor = APP_FONT_COLOR
|
|
@@ -324,33 +330,15 @@ const BarChartHorizontal = () => {
|
|
|
324
330
|
})
|
|
325
331
|
|
|
326
332
|
// Check if this bar should use a pattern
|
|
327
|
-
const
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
// and if the pattern's dataValue matches the current bar's value
|
|
337
|
-
if (pattern.dataKey === bar.key && String(bar.value) === String(pattern.dataValue)) {
|
|
338
|
-
return `url(#chart-pattern-${patternKey})`
|
|
339
|
-
}
|
|
340
|
-
// Fallback for non-grouped charts: check datum field value
|
|
341
|
-
else if (!config.series || config.series.length <= 1) {
|
|
342
|
-
const dataFieldValue = datum[pattern.dataKey]
|
|
343
|
-
if (String(dataFieldValue) === String(pattern.dataValue)) {
|
|
344
|
-
return `url(#chart-pattern-${patternKey})`
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
return null
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
const patternUrl = getPatternUrl()
|
|
333
|
+
const patternUrl = getPatternUrlForBar({
|
|
334
|
+
patterns: config.legend?.patterns,
|
|
335
|
+
datum,
|
|
336
|
+
seriesKey: bar.key,
|
|
337
|
+
seriesValue: bar.value,
|
|
338
|
+
seriesLabels: config.runtime?.seriesLabels,
|
|
339
|
+
seriesKeys: config.series?.map(series => series.dataKey),
|
|
340
|
+
allowNonSeriesFieldMatch: !config.series || config.series.length <= 1
|
|
341
|
+
})
|
|
354
342
|
const baseBackground = getBarBackgroundColor()
|
|
355
343
|
|
|
356
344
|
return (
|
|
@@ -14,6 +14,9 @@ import { type ChartContext } from '../../../types/ChartContext'
|
|
|
14
14
|
|
|
15
15
|
import createBarElement from '@cdc/core/components/createBarElement'
|
|
16
16
|
import { getHorizontalBarHeights } from '../helpers/getBarHeights'
|
|
17
|
+
import { getPatternUrl as getPatternUrlForBar } from '../helpers/getPatternUrl'
|
|
18
|
+
import { getChartPatternId } from '../../../helpers/getChartPatternId'
|
|
19
|
+
import { buildSeriesTooltipListHtml } from '../../../helpers/tooltipHelpers'
|
|
17
20
|
|
|
18
21
|
const BarChartStackedHorizontal = () => {
|
|
19
22
|
const { yMax, yScale, xScale, barChart } = useContext<BarChartContextValues>(BarChartContext)
|
|
@@ -55,7 +58,7 @@ const BarChartStackedHorizontal = () => {
|
|
|
55
58
|
return (
|
|
56
59
|
<defs>
|
|
57
60
|
{Object.entries(config.legend.patterns).map(([key, pattern]) => {
|
|
58
|
-
const patternId =
|
|
61
|
+
const patternId = getChartPatternId(key)
|
|
59
62
|
const size = pattern.patternSize || 8
|
|
60
63
|
|
|
61
64
|
switch (pattern.shape) {
|
|
@@ -159,42 +162,25 @@ const BarChartStackedHorizontal = () => {
|
|
|
159
162
|
const textWidth = getTextWidth(xAxisValue, `normal ${labelFontSize}px sans-serif`)
|
|
160
163
|
const additionalColTooltip = getAdditionalColumn(bar.key, hoveredBar)
|
|
161
164
|
const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${xAxisValue}`
|
|
162
|
-
const tooltip =
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
const tooltip = buildSeriesTooltipListHtml({
|
|
166
|
+
config,
|
|
167
|
+
colorScale,
|
|
168
|
+
heading: yAxisTooltip,
|
|
169
|
+
seriesKey: bar.key,
|
|
170
|
+
seriesText: tooltipBody,
|
|
171
|
+
extraRows: additionalColTooltip ? [additionalColTooltip] : []
|
|
172
|
+
})
|
|
167
173
|
|
|
168
174
|
// Check if this bar should use a pattern
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// and if the pattern's dataValue matches the current bar's value
|
|
179
|
-
const barValue = data[bar.index][bar.key]
|
|
180
|
-
if (pattern.dataKey === bar.key && String(barValue) === String(pattern.dataValue)) {
|
|
181
|
-
return `url(#chart-pattern-${patternKey})`
|
|
182
|
-
}
|
|
183
|
-
// Fallback for non-series pattern matching (like the original stacked pattern test)
|
|
184
|
-
// Only check this if the pattern dataKey is NOT a series key
|
|
185
|
-
else if (!config.runtime.seriesLabels || !config.runtime.seriesLabels[pattern.dataKey]) {
|
|
186
|
-
const dataFieldValue = data[bar.index][pattern.dataKey]
|
|
187
|
-
if (String(dataFieldValue) === String(pattern.dataValue)) {
|
|
188
|
-
return `url(#chart-pattern-${patternKey})`
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return null
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const patternUrl = getPatternUrl()
|
|
175
|
+
const patternUrl = getPatternUrlForBar({
|
|
176
|
+
patterns: config.legend?.patterns,
|
|
177
|
+
datum: data[bar.index],
|
|
178
|
+
seriesKey: bar.key,
|
|
179
|
+
seriesValue: data[bar.index][bar.key],
|
|
180
|
+
seriesLabels: config.runtime?.seriesLabels,
|
|
181
|
+
seriesKeys: config.series?.map(series => series.dataKey),
|
|
182
|
+
allowNonSeriesFieldMatch: true
|
|
183
|
+
})
|
|
198
184
|
|
|
199
185
|
return (
|
|
200
186
|
<React.Fragment key={`stack-${stackIndex}-bar-${index}-${barStack.index}`}>
|
|
@@ -8,6 +8,9 @@ import Regions from '../../Regions'
|
|
|
8
8
|
import { addMinimumBarHeights } from '../helpers'
|
|
9
9
|
|
|
10
10
|
import createBarElement from '@cdc/core/components/createBarElement'
|
|
11
|
+
import { getPatternUrl as getPatternUrlForBar } from '../helpers/getPatternUrl'
|
|
12
|
+
import { getChartPatternId } from '../../../helpers/getChartPatternId'
|
|
13
|
+
import { buildSeriesTooltipListHtml } from '../../../helpers/tooltipHelpers'
|
|
11
14
|
|
|
12
15
|
const BarChartStackedVertical = () => {
|
|
13
16
|
const [barWidth, setBarWidth] = useState(0)
|
|
@@ -40,7 +43,7 @@ const BarChartStackedVertical = () => {
|
|
|
40
43
|
return (
|
|
41
44
|
<defs>
|
|
42
45
|
{Object.entries(config.legend.patterns).map(([key, pattern]) => {
|
|
43
|
-
const patternId =
|
|
46
|
+
const patternId = getChartPatternId(key)
|
|
44
47
|
const size = pattern.patternSize || 8
|
|
45
48
|
|
|
46
49
|
switch (pattern.shape) {
|
|
@@ -141,45 +144,27 @@ const BarChartStackedVertical = () => {
|
|
|
141
144
|
: xAxisValue
|
|
142
145
|
const additionalColTooltip = getAdditionalColumn(bar.key, hoveredBar)
|
|
143
146
|
const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${yAxisValue}`
|
|
144
|
-
const tooltip =
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
const tooltip = buildSeriesTooltipListHtml({
|
|
148
|
+
config,
|
|
149
|
+
colorScale,
|
|
150
|
+
heading: xAxisTooltip,
|
|
151
|
+
seriesKey: bar.key,
|
|
152
|
+
seriesText: tooltipBody,
|
|
153
|
+
extraRows: additionalColTooltip ? [additionalColTooltip] : []
|
|
154
|
+
})
|
|
149
155
|
|
|
150
156
|
setBarWidth(barThickness)
|
|
151
157
|
|
|
152
158
|
// Check if this bar should use a pattern
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// For stacked bar charts, check if the pattern's dataKey matches the current bar's series key
|
|
163
|
-
// and if the pattern's dataValue matches the current bar's value
|
|
164
|
-
const barValue = bar.bar.data[bar.key]
|
|
165
|
-
if (pattern.dataKey === bar.key && String(barValue) === String(pattern.dataValue)) {
|
|
166
|
-
return `url(#chart-pattern-${patternKey})`
|
|
167
|
-
}
|
|
168
|
-
// Fallback for non-series pattern matching (like the original stacked pattern test)
|
|
169
|
-
// Only check this if the pattern dataKey is NOT a series key
|
|
170
|
-
else if (!config.runtime.seriesLabels || !config.runtime.seriesLabels[pattern.dataKey]) {
|
|
171
|
-
const dataFieldValue = bar.bar.data[pattern.dataKey]
|
|
172
|
-
if (String(dataFieldValue) === String(pattern.dataValue)) {
|
|
173
|
-
return `url(#chart-pattern-${patternKey})`
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return null
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const patternUrl = getPatternUrl()
|
|
159
|
+
const patternUrl = getPatternUrlForBar({
|
|
160
|
+
patterns: config.legend?.patterns,
|
|
161
|
+
datum: bar.bar.data,
|
|
162
|
+
seriesKey: bar.key,
|
|
163
|
+
seriesValue: bar.bar.data[bar.key],
|
|
164
|
+
seriesLabels: config.runtime?.seriesLabels,
|
|
165
|
+
seriesKeys: config.series?.map(series => series.dataKey),
|
|
166
|
+
allowNonSeriesFieldMatch: true
|
|
167
|
+
})
|
|
183
168
|
|
|
184
169
|
return (
|
|
185
170
|
<Group key={`${barStack.index}--${bar.index}--${orientation}`}>
|