@cdc/chart 4.26.3 → 4.26.5
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 +489 -0
- package/README.md +42 -17
- package/dist/cdcchart.js +39024 -36587
- package/examples/feature/bar/additional-column-tooltip.json +3 -3
- package/examples/feature/deviation/planet-deviation-config.json +2 -2
- package/examples/feature/heatmap/average-age-categorical.json +313 -0
- package/examples/feature/heatmap/calendar-heatmap.json +134 -0
- package/examples/feature/heatmap/cell-values-bottom-axis.json +181 -0
- package/examples/feature/heatmap/sparse-aggregation.json +158 -0
- 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/bump-chart.json +1116 -0
- package/examples/private/test-123.json +624 -0
- package/examples/private/test2.json +35012 -0
- package/package.json +5 -4
- package/src/CdcChartComponent.tsx +144 -60
- package/src/_stories/Chart.AltText.stories.tsx +136 -0
- package/src/_stories/{Chart.HTMLInDataTable.stories.tsx → Chart.HTMLInDataTable.smoke.stories.tsx} +10 -0
- package/src/_stories/Chart.HeatMap.stories.tsx +187 -0
- package/src/_stories/Chart.Minimal.smoke.stories.tsx +25 -0
- package/src/_stories/Chart.Sankey.smoke.stories.tsx +62 -0
- package/src/_stories/Chart.SmallMultiples.smoke.stories.tsx +108 -0
- 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/{ChartAxisTitles.stories.tsx → ChartAxisTitles.smoke.stories.tsx} +13 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +151 -85
- package/src/_stories/ChartBrush.Interaction.stories.tsx +112 -0
- package/src/_stories/{ChartBrush.stories.tsx → ChartBrush.smoke.stories.tsx} +13 -4
- package/src/_stories/ChartEditor.Editor.stories.tsx +23 -0
- package/src/_stories/ChartLine.DashedDates.smoke.stories.tsx +23 -0
- package/src/_stories/_mock/alt_text_metadata.json +38 -0
- package/src/_stories/_mock/heatmap-average-age-categorical.json +315 -0
- package/src/_stories/_mock/heatmap.json +156 -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/_stories/_mock/reported_pertussis_cases.json +1643 -0
- package/src/_stories/_mock/sankey_mock.json +78 -0
- package/src/_stories/_mock/small_multiples/small_multiples_lines.json +1 -1
- package/src/components/Annotations/components/AnnotationDraggable.tsx +2 -2
- package/src/components/Annotations/components/AnnotationDropdown.tsx +5 -2
- package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -2
- package/src/components/Axis/BottomAxis.tsx +1 -1
- package/src/components/Axis/LeftAxis.tsx +15 -14
- package/src/components/Axis/LeftAxisGridlines.tsx +14 -13
- 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/Brush/BrushSelector.tsx +88 -187
- package/src/components/Brush/brushInteraction.ts +22 -0
- package/src/components/Brush/tests/brushInteraction.test.ts +38 -0
- package/src/components/EditorPanel/EditorPanel.tsx +946 -960
- package/src/components/EditorPanel/EditorPanelContext.ts +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +229 -165
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +105 -13
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +169 -116
- package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +159 -109
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +14 -28
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +1 -1
- package/src/components/EditorPanel/helpers/getVisualizationTypeConfigUpdate.ts +57 -0
- package/src/components/EditorPanel/helpers/tests/getVisualizationTypeConfigUpdate.test.ts +56 -0
- package/src/components/EditorPanel/useEditorPermissions.test.tsx +70 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +32 -21
- package/src/components/Forecasting/Forecasting.tsx +2 -2
- package/src/components/HeatMap/components/HeatMap.tsx +762 -0
- package/src/components/HeatMap/components/HeatMapGradientLegend.tsx +114 -0
- package/src/components/HeatMap/heatmap.constants.ts +13 -0
- package/src/components/HeatMap/heatmap.css +71 -0
- package/src/components/HeatMap/helpers/index.ts +261 -0
- package/src/components/HeatMap/index.tsx +5 -0
- package/src/components/HeatMap/tests/HeatMap.test.tsx +1040 -0
- package/src/components/HeatMap/tests/helpers.test.ts +167 -0
- 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 +22 -24
- package/src/components/LineChart/helpers.test.ts +345 -0
- package/src/components/LineChart/helpers.ts +15 -5
- package/src/components/LineChart/index.tsx +18 -5
- package/src/components/LinearChart/VisualizationRenderer.tsx +11 -1
- package/src/components/LinearChart/tests/LinearChart.test.tsx +228 -7
- package/src/components/LinearChart/tests/mockConfigContext.ts +1 -0
- package/src/components/LinearChart.tsx +155 -77
- package/src/components/PairedBarChart.jsx +2 -2
- package/src/components/PieChart/PieChart.tsx +15 -10
- package/src/components/RadarChart/RadarChart.tsx +3 -1
- package/src/components/Regions/components/Regions.tsx +199 -35
- package/src/components/Sankey/components/Sankey.tsx +7 -3
- package/src/components/Sankey/helpers/getSankeyTooltip.tsx +7 -6
- package/src/components/ScatterPlot/ScatterPlot.jsx +19 -17
- package/src/components/SmallMultiples/SmallMultipleTile.tsx +31 -3
- package/src/components/SmallMultiples/SmallMultiples.css +12 -0
- package/src/components/SmallMultiples/SmallMultiples.tsx +15 -9
- package/src/components/SmallMultiples/tests/SmallMultipleTile.test.tsx +152 -0
- package/src/components/Sparkline/components/SparkLine.tsx +5 -10
- package/src/components/WarmingStripes/WarmingStripes.tsx +5 -3
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +1 -1
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.tsx +2 -2
- package/src/data/initial-state.js +12 -0
- package/src/helpers/axisLabelFontSize.ts +8 -0
- package/src/helpers/bumpChartTooltip.ts +54 -0
- package/src/helpers/calculateLeftYAxisWidth.ts +197 -0
- package/src/helpers/ensureSpecialChartAxisTypes.ts +11 -0
- package/src/helpers/getMinMax.ts +2 -3
- package/src/helpers/getYAxisAutoPadding.ts +8 -6
- package/src/helpers/getYAxisAutoPaddingMode.ts +17 -0
- package/src/helpers/handleChartAriaLabels.ts +23 -10
- package/src/helpers/seriesHighlight.ts +26 -0
- package/src/helpers/tests/axisLabelFontSize.test.ts +15 -0
- package/src/helpers/tests/bumpChartTooltip.test.ts +75 -0
- package/src/helpers/tests/ensureSpecialChartAxisTypes.test.ts +30 -0
- package/src/helpers/tests/getYAxisAutoPadding.test.ts +37 -0
- package/src/helpers/tests/getYAxisAutoPaddingMode.test.ts +90 -0
- package/src/helpers/tests/handleChartAriaLabels.test.ts +71 -0
- package/src/helpers/tests/seriesHighlight.test.ts +61 -0
- package/src/helpers/tests/tooltipHelpers.test.ts +151 -0
- package/src/helpers/tooltipHelpers.ts +176 -0
- package/src/hooks/tests/useScales.test.tsx +105 -0
- package/src/hooks/useHighlightedBars.ts +9 -16
- package/src/hooks/useProgrammaticTooltip.ts +16 -2
- package/src/hooks/useScales.ts +19 -9
- package/src/hooks/useSmallMultipleSynchronization.ts +3 -4
- package/src/hooks/useTooltip.tsx +167 -38
- package/src/index.jsx +5 -2
- package/src/scss/main.scss +32 -49
- package/src/test/CdcChart.test.jsx +24 -0
- package/src/types/ChartConfig.ts +19 -0
- package/src/types/ChartContext.ts +2 -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/src/_stories/Chart.SmallMultiples.stories.tsx +0 -63
- /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/{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/{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
|
@@ -115,16 +115,16 @@ const SankeySettings: React.FC<PanelProps> = props => {
|
|
|
115
115
|
</div>
|
|
116
116
|
))}
|
|
117
117
|
{data?.storyNodeText?.length < 3 && (
|
|
118
|
-
<
|
|
118
|
+
<Button
|
|
119
119
|
type='button'
|
|
120
|
-
|
|
120
|
+
variant='editor-primary'
|
|
121
121
|
onClick={e => {
|
|
122
122
|
e.preventDefault()
|
|
123
123
|
addStoryNode()
|
|
124
124
|
}}
|
|
125
125
|
>
|
|
126
126
|
Add StoryNode
|
|
127
|
-
</
|
|
127
|
+
</Button>
|
|
128
128
|
)}
|
|
129
129
|
{config.data?.[0]?.tooltips?.length > 0 && (
|
|
130
130
|
<CheckBox
|
|
@@ -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,17 +653,17 @@ 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
|
}
|
|
659
660
|
|
|
660
661
|
return (
|
|
661
662
|
config.series &&
|
|
662
|
-
config.series.length > 1 && (
|
|
663
|
-
<
|
|
663
|
+
(config.series.length > 1 || config.visualizationType === 'HeatMap') && (
|
|
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
|
}
|
|
@@ -709,12 +710,14 @@ const SeriesItem = props => {
|
|
|
709
710
|
}
|
|
710
711
|
>
|
|
711
712
|
<Icon display='move' size={15} style={{ cursor: 'default' }} />
|
|
712
|
-
{series.dataKey}
|
|
713
|
-
<Series.Button.Remove series={series} index={i} />
|
|
713
|
+
{config.visualizationType === 'HeatMap' ? series.name || series.dataKey : series.dataKey}
|
|
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
|
|
@@ -306,7 +306,7 @@ const PanelVisual: FC<PanelProps> = props => {
|
|
|
306
306
|
/>
|
|
307
307
|
</>
|
|
308
308
|
)}
|
|
309
|
-
{(
|
|
309
|
+
{(visSupportsSequentialPallete() || visSupportsNonSequentialPallete()) && (
|
|
310
310
|
<>
|
|
311
311
|
<label>
|
|
312
312
|
<span className='edit-label'>Chart Color Palette</span>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type ChartConfig, type VisualizationType } from '../../../types/ChartConfig'
|
|
2
|
+
import { HEATMAP_CONFIG_DEFAULTS } from '../../HeatMap/heatmap.constants'
|
|
3
|
+
|
|
4
|
+
export const getVisualizationTypeConfigUpdate = (
|
|
5
|
+
config: ChartConfig,
|
|
6
|
+
visualizationType: VisualizationType
|
|
7
|
+
): ChartConfig | undefined => {
|
|
8
|
+
if (visualizationType === 'Forecasting' && config.xAxis.type === 'categorical') {
|
|
9
|
+
return {
|
|
10
|
+
...config,
|
|
11
|
+
visualizationType,
|
|
12
|
+
xAxis: {
|
|
13
|
+
...config.xAxis,
|
|
14
|
+
type: 'date',
|
|
15
|
+
dateParseFormat: config.xAxis.dateParseFormat || '%Y-%m-%d',
|
|
16
|
+
dateDisplayFormat: config.xAxis.dateDisplayFormat || '%Y-%m-%d'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (visualizationType === 'HeatMap') {
|
|
22
|
+
return {
|
|
23
|
+
...config,
|
|
24
|
+
visualizationType,
|
|
25
|
+
series: [],
|
|
26
|
+
yAxis: {
|
|
27
|
+
...config.yAxis,
|
|
28
|
+
type: 'categorical',
|
|
29
|
+
titlePlacement: 'side'
|
|
30
|
+
},
|
|
31
|
+
heatmap: {
|
|
32
|
+
cellPadding: config.heatmap?.cellPadding ?? HEATMAP_CONFIG_DEFAULTS.cellPadding,
|
|
33
|
+
rowLabelGap: config.heatmap?.rowLabelGap ?? HEATMAP_CONFIG_DEFAULTS.rowLabelGap,
|
|
34
|
+
columnLabelGap: config.heatmap?.columnLabelGap ?? HEATMAP_CONFIG_DEFAULTS.columnLabelGap,
|
|
35
|
+
colorBucketCount: config.heatmap?.colorBucketCount ?? HEATMAP_CONFIG_DEFAULTS.colorBucketCount,
|
|
36
|
+
xAxisPosition: config.heatmap?.xAxisPosition ?? HEATMAP_CONFIG_DEFAULTS.xAxisPosition,
|
|
37
|
+
showCellValues: config.heatmap?.showCellValues ?? HEATMAP_CONFIG_DEFAULTS.showCellValues
|
|
38
|
+
},
|
|
39
|
+
legend: {
|
|
40
|
+
...config.legend,
|
|
41
|
+
position: 'top',
|
|
42
|
+
style: 'gradient',
|
|
43
|
+
subStyle: 'smooth'
|
|
44
|
+
},
|
|
45
|
+
general: {
|
|
46
|
+
...config.general,
|
|
47
|
+
palette: config.general?.palette || {
|
|
48
|
+
isReversed: false,
|
|
49
|
+
version: '2.0',
|
|
50
|
+
name: 'sequential_blue'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return undefined
|
|
57
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { type ChartConfig } from '../../../../types/ChartConfig'
|
|
3
|
+
import { HEATMAP_CONFIG_DEFAULTS } from '../../../HeatMap/heatmap.constants'
|
|
4
|
+
import { getVisualizationTypeConfigUpdate } from '../getVisualizationTypeConfigUpdate'
|
|
5
|
+
|
|
6
|
+
const buildConfig = (overrides: Partial<ChartConfig> = {}) =>
|
|
7
|
+
({
|
|
8
|
+
visualizationType: 'Bar',
|
|
9
|
+
xAxis: {
|
|
10
|
+
type: 'categorical'
|
|
11
|
+
},
|
|
12
|
+
yAxis: {
|
|
13
|
+
type: 'linear'
|
|
14
|
+
},
|
|
15
|
+
series: [{ dataKey: 'Value' }],
|
|
16
|
+
legend: {
|
|
17
|
+
position: 'bottom',
|
|
18
|
+
style: 'circles',
|
|
19
|
+
subStyle: 'linear blocks'
|
|
20
|
+
},
|
|
21
|
+
general: {},
|
|
22
|
+
...overrides
|
|
23
|
+
} as ChartConfig)
|
|
24
|
+
|
|
25
|
+
describe('getVisualizationTypeConfigUpdate', () => {
|
|
26
|
+
it('does not build a special config update for chart types without transition rules', () => {
|
|
27
|
+
expect(getVisualizationTypeConfigUpdate(buildConfig(), 'Line')).toBeUndefined()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('normalizes categorical x-axis settings when switching to Forecasting', () => {
|
|
31
|
+
const updatedConfig = getVisualizationTypeConfigUpdate(buildConfig(), 'Forecasting')
|
|
32
|
+
|
|
33
|
+
expect(updatedConfig?.visualizationType).toBe('Forecasting')
|
|
34
|
+
expect(updatedConfig?.xAxis.type).toBe('date')
|
|
35
|
+
expect(updatedConfig?.xAxis.dateParseFormat).toBe('%Y-%m-%d')
|
|
36
|
+
expect(updatedConfig?.xAxis.dateDisplayFormat).toBe('%Y-%m-%d')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('applies HeatMap defaults and required editor config when switching to HeatMap', () => {
|
|
40
|
+
const updatedConfig = getVisualizationTypeConfigUpdate(buildConfig(), 'HeatMap')
|
|
41
|
+
|
|
42
|
+
expect(updatedConfig?.visualizationType).toBe('HeatMap')
|
|
43
|
+
expect(updatedConfig?.series).toEqual([])
|
|
44
|
+
expect(updatedConfig?.yAxis.type).toBe('categorical')
|
|
45
|
+
expect(updatedConfig?.yAxis.titlePlacement).toBe('side')
|
|
46
|
+
expect(updatedConfig?.heatmap).toEqual(HEATMAP_CONFIG_DEFAULTS)
|
|
47
|
+
expect(updatedConfig?.legend.position).toBe('top')
|
|
48
|
+
expect(updatedConfig?.legend.style).toBe('gradient')
|
|
49
|
+
expect(updatedConfig?.legend.subStyle).toBe('smooth')
|
|
50
|
+
expect(updatedConfig?.general.palette).toEqual({
|
|
51
|
+
isReversed: false,
|
|
52
|
+
version: '2.0',
|
|
53
|
+
name: 'sequential_blue'
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
})
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { renderHook } from '@testing-library/react'
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
import ConfigContext from '../../ConfigContext'
|
|
5
|
+
import { useEditorPermissions } from './useEditorPermissions'
|
|
6
|
+
import { createMockChartContext, createMockConfig } from '../LinearChart/tests/mockConfigContext'
|
|
7
|
+
import { ChartConfig } from '../../types/ChartConfig'
|
|
8
|
+
|
|
9
|
+
const renderUseEditorPermissions = (configOverrides: Partial<ChartConfig>) => {
|
|
10
|
+
const config = createMockConfig(configOverrides)
|
|
11
|
+
const context = createMockChartContext(config)
|
|
12
|
+
const wrapper = ({ children }: React.PropsWithChildren) => (
|
|
13
|
+
<ConfigContext.Provider value={context}>{children}</ConfigContext.Provider>
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
return renderHook(() => useEditorPermissions(), { wrapper })
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe('useEditorPermissions', () => {
|
|
20
|
+
it('shows manual y-axis padding controls when auto-padding mode is none', () => {
|
|
21
|
+
const { result } = renderUseEditorPermissions({
|
|
22
|
+
yAxis: {
|
|
23
|
+
...createMockConfig().yAxis,
|
|
24
|
+
titlePlacement: 'side',
|
|
25
|
+
inlineLabel: 'Rate'
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
expect(result.current.visSupportsYPadding()).toBe(true)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('hides manual y-axis padding controls for inline-label auto-padding', () => {
|
|
33
|
+
const { result } = renderUseEditorPermissions({
|
|
34
|
+
yAxis: {
|
|
35
|
+
...createMockConfig().yAxis,
|
|
36
|
+
titlePlacement: 'side',
|
|
37
|
+
inlineLabel: 'per 100k'
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
expect(result.current.visSupportsYPadding()).toBe(false)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('hides manual y-axis padding controls for top-title auto-padding', () => {
|
|
45
|
+
const { result } = renderUseEditorPermissions({
|
|
46
|
+
yAxis: {
|
|
47
|
+
...createMockConfig().yAxis,
|
|
48
|
+
titlePlacement: 'top',
|
|
49
|
+
label: 'Y-Axis',
|
|
50
|
+
inlineLabel: ''
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
expect(result.current.visSupportsYPadding()).toBe(false)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('shows manual y-axis padding controls when a top y-axis title is hidden', () => {
|
|
58
|
+
const { result } = renderUseEditorPermissions({
|
|
59
|
+
hideYAxisLabel: true,
|
|
60
|
+
yAxis: {
|
|
61
|
+
...createMockConfig().yAxis,
|
|
62
|
+
titlePlacement: 'top',
|
|
63
|
+
label: 'Y-Axis',
|
|
64
|
+
inlineLabel: ''
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
expect(result.current.visSupportsYPadding()).toBe(true)
|
|
69
|
+
})
|
|
70
|
+
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useContext } from 'react'
|
|
2
2
|
import ConfigContext from '../../ConfigContext'
|
|
3
|
+
import { getYAxisAutoPaddingMode } from '../../helpers/getYAxisAutoPaddingMode'
|
|
3
4
|
|
|
4
5
|
export const useEditorPermissions = () => {
|
|
5
6
|
const { config } = useContext(ConfigContext)
|
|
@@ -16,6 +17,7 @@ export const useEditorPermissions = () => {
|
|
|
16
17
|
'Deviation Bar',
|
|
17
18
|
'Forecasting',
|
|
18
19
|
// 'Forest Plot',
|
|
20
|
+
'HeatMap',
|
|
19
21
|
'Horizon Chart',
|
|
20
22
|
'Line',
|
|
21
23
|
'Paired Bar',
|
|
@@ -58,7 +60,7 @@ export const useEditorPermissions = () => {
|
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
const visSupportsClickingLegend = () => {
|
|
61
|
-
const disabledCharts = ['Horizon Chart']
|
|
63
|
+
const disabledCharts = ['HeatMap', 'Horizon Chart']
|
|
62
64
|
if (disabledCharts.includes(visualizationType)) return false
|
|
63
65
|
return true
|
|
64
66
|
}
|
|
@@ -75,6 +77,7 @@ export const useEditorPermissions = () => {
|
|
|
75
77
|
'Box Plot',
|
|
76
78
|
'Bump Chart',
|
|
77
79
|
'Forest Plot',
|
|
80
|
+
'HeatMap',
|
|
78
81
|
'Horizon Chart',
|
|
79
82
|
'Pie',
|
|
80
83
|
'Radar',
|
|
@@ -93,6 +96,7 @@ export const useEditorPermissions = () => {
|
|
|
93
96
|
'Box Plot',
|
|
94
97
|
'Bump Chart',
|
|
95
98
|
'Forest Plot',
|
|
99
|
+
'HeatMap',
|
|
96
100
|
'Radar',
|
|
97
101
|
'Sankey',
|
|
98
102
|
'Scatter Plot',
|
|
@@ -109,6 +113,8 @@ export const useEditorPermissions = () => {
|
|
|
109
113
|
return true
|
|
110
114
|
case 'Forest Plot':
|
|
111
115
|
return false
|
|
116
|
+
case 'HeatMap':
|
|
117
|
+
return true
|
|
112
118
|
case 'Spark Line':
|
|
113
119
|
return false
|
|
114
120
|
case 'Sankey':
|
|
@@ -197,9 +203,13 @@ export const useEditorPermissions = () => {
|
|
|
197
203
|
}
|
|
198
204
|
}
|
|
199
205
|
|
|
200
|
-
const visHasSelectableLegendValues = ![
|
|
201
|
-
|
|
202
|
-
|
|
206
|
+
const visHasSelectableLegendValues = ![
|
|
207
|
+
'Box Plot',
|
|
208
|
+
'Forest Plot',
|
|
209
|
+
'HeatMap',
|
|
210
|
+
'Spark Line',
|
|
211
|
+
'Warming Stripes'
|
|
212
|
+
].includes(visualizationType)
|
|
203
213
|
const visHasLegendAxisAlign = () => {
|
|
204
214
|
return visualizationType === 'Bar' && visualizationSubType === 'stacked' && config.legend.behavior === 'isolate'
|
|
205
215
|
}
|
|
@@ -208,7 +218,7 @@ export const useEditorPermissions = () => {
|
|
|
208
218
|
}
|
|
209
219
|
|
|
210
220
|
const visSupportsTooltipOpacity = () => {
|
|
211
|
-
const disabledCharts = ['Spark Line', 'Sankey', 'Warming Stripes']
|
|
221
|
+
const disabledCharts = ['HeatMap', 'Spark Line', 'Sankey', 'Warming Stripes']
|
|
212
222
|
if (disabledCharts.includes(visualizationType)) return false
|
|
213
223
|
return true
|
|
214
224
|
}
|
|
@@ -226,7 +236,7 @@ export const useEditorPermissions = () => {
|
|
|
226
236
|
}
|
|
227
237
|
|
|
228
238
|
const visSupportsNonSequentialPallete = () => {
|
|
229
|
-
const disabledCharts = ['Paired Bar', 'Deviation Bar', 'Forest Plot', 'Forecasting', 'Sankey']
|
|
239
|
+
const disabledCharts = ['HeatMap', 'Paired Bar', 'Deviation Bar', 'Forest Plot', 'Forecasting', 'Sankey']
|
|
230
240
|
if (disabledCharts.includes(visualizationType)) return false
|
|
231
241
|
return true
|
|
232
242
|
}
|
|
@@ -238,19 +248,19 @@ export const useEditorPermissions = () => {
|
|
|
238
248
|
}
|
|
239
249
|
|
|
240
250
|
const visSupportsDateCategoryAxisLabel = () => {
|
|
241
|
-
const disabledCharts = ['Forest Plot', 'Spark Line', 'Bump Chart', 'Warming Stripes']
|
|
251
|
+
const disabledCharts = ['Forest Plot', 'HeatMap', 'Spark Line', 'Bump Chart', 'Warming Stripes']
|
|
242
252
|
if (disabledCharts.includes(visualizationType)) return false
|
|
243
253
|
return true
|
|
244
254
|
}
|
|
245
255
|
|
|
246
256
|
const visSupportsDateCategoryAxisLine = () => {
|
|
247
|
-
const disabledCharts = ['Forest Plot', 'Spark Line', 'Warming Stripes']
|
|
257
|
+
const disabledCharts = ['Forest Plot', 'HeatMap', 'Spark Line', 'Warming Stripes']
|
|
248
258
|
if (disabledCharts.includes(visualizationType)) return false
|
|
249
259
|
return true
|
|
250
260
|
}
|
|
251
261
|
|
|
252
262
|
const visSupportsDateCategoryAxisTicks = () => {
|
|
253
|
-
const disabledCharts = ['Forest Plot', 'Spark Line', 'Warming Stripes']
|
|
263
|
+
const disabledCharts = ['Forest Plot', 'HeatMap', 'Spark Line', 'Warming Stripes']
|
|
254
264
|
if (disabledCharts.includes(visualizationType)) return false
|
|
255
265
|
return true
|
|
256
266
|
}
|
|
@@ -262,13 +272,13 @@ export const useEditorPermissions = () => {
|
|
|
262
272
|
}
|
|
263
273
|
|
|
264
274
|
const visSupportsDateCategoryNumTicks = () => {
|
|
265
|
-
const disabledCharts = ['Spark Line']
|
|
275
|
+
const disabledCharts = ['HeatMap', 'Spark Line']
|
|
266
276
|
if (disabledCharts.includes(visualizationType)) return false
|
|
267
277
|
return true
|
|
268
278
|
}
|
|
269
279
|
|
|
270
280
|
const visSupportsResponsiveTicks = () => {
|
|
271
|
-
const disabledCharts = ['Spark Line']
|
|
281
|
+
const disabledCharts = ['HeatMap', 'Spark Line']
|
|
272
282
|
if (disabledCharts.includes(visualizationType)) return false
|
|
273
283
|
return true
|
|
274
284
|
}
|
|
@@ -277,6 +287,7 @@ export const useEditorPermissions = () => {
|
|
|
277
287
|
const disabledCharts = [
|
|
278
288
|
'Forest Plot',
|
|
279
289
|
'Horizon Chart',
|
|
290
|
+
'HeatMap',
|
|
280
291
|
'Pie',
|
|
281
292
|
'Paired Bar',
|
|
282
293
|
'Radar',
|
|
@@ -289,13 +300,13 @@ export const useEditorPermissions = () => {
|
|
|
289
300
|
}
|
|
290
301
|
|
|
291
302
|
const visSupportsValueAxisMax = () => {
|
|
292
|
-
const disabledCharts = ['Forest Plot']
|
|
303
|
+
const disabledCharts = ['Forest Plot', 'HeatMap']
|
|
293
304
|
if (disabledCharts.includes(visualizationType)) return false
|
|
294
305
|
return true
|
|
295
306
|
}
|
|
296
307
|
|
|
297
308
|
const visSupportsValueAxisMin = () => {
|
|
298
|
-
const disabledCharts = ['Forest Plot']
|
|
309
|
+
const disabledCharts = ['Forest Plot', 'HeatMap']
|
|
299
310
|
if (disabledCharts.includes(visualizationType)) return false
|
|
300
311
|
return true
|
|
301
312
|
}
|
|
@@ -307,14 +318,14 @@ export const useEditorPermissions = () => {
|
|
|
307
318
|
}
|
|
308
319
|
|
|
309
320
|
const visSupportsValueAxisGridLines = () => {
|
|
310
|
-
const disabledCharts = ['Forest Plot']
|
|
321
|
+
const disabledCharts = ['Forest Plot', 'HeatMap']
|
|
311
322
|
if (disabledCharts.includes(visualizationType)) return false
|
|
312
323
|
return true
|
|
313
324
|
}
|
|
314
325
|
|
|
315
326
|
// implement later
|
|
316
327
|
const visSupportsValueAxisTicks = () => {
|
|
317
|
-
const disabledCharts = ['Forest Plot']
|
|
328
|
+
const disabledCharts = ['Forest Plot', 'HeatMap']
|
|
318
329
|
if (disabledCharts.includes(visualizationType)) return false
|
|
319
330
|
return true
|
|
320
331
|
}
|
|
@@ -328,7 +339,7 @@ export const useEditorPermissions = () => {
|
|
|
328
339
|
|
|
329
340
|
// implement later
|
|
330
341
|
const visSupportsValueAxisLabels = () => {
|
|
331
|
-
const disabledCharts = ['Forest Plot', 'Bump Chart']
|
|
342
|
+
const disabledCharts = ['Forest Plot', 'HeatMap', 'Bump Chart']
|
|
332
343
|
if (disabledCharts.includes(visualizationType)) return false
|
|
333
344
|
return true
|
|
334
345
|
}
|
|
@@ -341,7 +352,7 @@ export const useEditorPermissions = () => {
|
|
|
341
352
|
}
|
|
342
353
|
|
|
343
354
|
const visSupportsBarThickness = () => {
|
|
344
|
-
const disabledCharts = ['Forest Plot', 'Warming Stripes']
|
|
355
|
+
const disabledCharts = ['Forest Plot', 'HeatMap', 'Warming Stripes']
|
|
345
356
|
if (disabledCharts.includes(visualizationType)) return false
|
|
346
357
|
return true
|
|
347
358
|
}
|
|
@@ -353,7 +364,7 @@ export const useEditorPermissions = () => {
|
|
|
353
364
|
}
|
|
354
365
|
const visSupportsMobileChartHeight = () => {
|
|
355
366
|
// TODO: this is a soft release. Support should eventually match visSupportsChartHeight
|
|
356
|
-
const enabledCharts = ['Bar', 'Line', 'Combo', 'Area Chart', 'Radar']
|
|
367
|
+
const enabledCharts = ['Bar', 'Line', 'Combo', 'Area Chart', 'HeatMap', 'Radar']
|
|
357
368
|
if (enabledCharts.includes(visualizationType)) return true
|
|
358
369
|
return false
|
|
359
370
|
}
|
|
@@ -365,13 +376,13 @@ export const useEditorPermissions = () => {
|
|
|
365
376
|
}
|
|
366
377
|
|
|
367
378
|
const visSupportsRankByValue = () => {
|
|
368
|
-
const disabledCharts = ['Spark Line']
|
|
379
|
+
const disabledCharts = ['HeatMap', 'Spark Line']
|
|
369
380
|
if (disabledCharts.includes(visualizationType)) return false
|
|
370
381
|
return true
|
|
371
382
|
}
|
|
372
383
|
|
|
373
384
|
const visSupportsDateCategoryHeight = () => {
|
|
374
|
-
const disabledCharts = ['Spark Line', 'Sankey', 'Bump Chart']
|
|
385
|
+
const disabledCharts = ['HeatMap', 'Spark Line', 'Sankey', 'Bump Chart']
|
|
375
386
|
if (disabledCharts.includes(visualizationType)) return false
|
|
376
387
|
if (config.orientation !== 'horizontal') return false
|
|
377
388
|
if (config.orientation === 'horizontal' && visualizationType === 'Bar' && !config.isLollipopChart) return false
|
|
@@ -416,7 +427,7 @@ export const useEditorPermissions = () => {
|
|
|
416
427
|
}
|
|
417
428
|
|
|
418
429
|
const visSupportsYPadding = () => {
|
|
419
|
-
return
|
|
430
|
+
return getYAxisAutoPaddingMode(config) === 'none'
|
|
420
431
|
}
|
|
421
432
|
|
|
422
433
|
const visHasSingleSeriesTooltip = () => {
|
|
@@ -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) => {
|