@cdc/chart 4.26.6 → 4.26.10
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 +504 -368
- package/dist/cdcchart-CYc-Kayd.es.js +22488 -0
- package/dist/cdcchart-DCKn8NmI.es.js +20695 -0
- package/dist/cdcchart-Dyui9nk_.es.js +45828 -0
- package/dist/cdcchart.js +4 -96498
- package/examples/__data__/vega-remote-data.json +6 -0
- package/examples/dendrogram.json +18 -0
- package/examples/feature/bar/bar-chart-race-annual-change.json +68 -0
- package/examples/feature/heatmap/average-age-categorical.json +2 -2
- package/examples/feature/heatmap/calendar-heatmap.json +2 -2
- package/examples/feature/heatmap/cell-values-bottom-axis.json +2 -2
- package/examples/feature/heatmap/sparse-aggregation.json +2 -2
- package/examples/feature/line/line-chart-race.json +50 -0
- package/examples/feature/sankey/sankey-example-data.json +40 -1441
- package/examples/feature/sankey/sankey_chart_data.csv +9 -20
- package/examples/network.json +31 -0
- package/examples/private/box-plot.json +573 -0
- package/examples/private/custom-color-issue.json +625 -0
- package/examples/private/custom-colors.json +522 -0
- package/examples/private/cutoff.json +10750 -0
- package/examples/private/flueview.json +22051 -0
- package/examples/private/overlay-legend.json +485 -0
- package/examples/private/pie-test.json +469 -0
- package/examples/vega-remote.json +22 -0
- package/package.json +11 -13
- package/src/CdcChart.tsx +2 -2
- package/src/CdcChartComponent.tsx +444 -217
- package/src/_stories/Chart.BarRace.stories.tsx +443 -0
- package/src/_stories/Chart.BoxPlotNumericSort.stories.tsx +189 -0
- package/src/_stories/Chart.BoxPlotStatsParity.stories.tsx +207 -0
- package/src/_stories/Chart.ColorDistribution.stories.tsx +299 -0
- package/src/_stories/Chart.DataCutoff.stories.tsx +147 -0
- package/src/_stories/Chart.DataTableDownloadFilename.stories.tsx +60 -0
- package/src/_stories/Chart.Dendrogram.stories.tsx +373 -0
- package/src/_stories/Chart.Forecast.CILegend.stories.tsx +236 -0
- package/src/_stories/Chart.HeatMap.stories.tsx +170 -4
- package/src/_stories/Chart.Legend.AxisAlign.stories.tsx +119 -0
- package/src/_stories/Chart.LineRace.stories.tsx +149 -0
- package/src/_stories/Chart.Network.stories.tsx +432 -0
- package/src/_stories/Chart.PaletteConversion.Editor.stories.tsx +208 -0
- package/src/_stories/Chart.Patterns.smoke.stories.tsx +31 -0
- package/src/_stories/Chart.PercentageValue.stories.tsx +311 -0
- package/src/_stories/Chart.PieLabels.stories.tsx +49 -0
- package/src/_stories/Chart.RankByValueMutation.stories.tsx +206 -0
- package/src/_stories/Chart.RequiredFields.stories.tsx +681 -0
- package/src/_stories/Chart.Sankey.stories.tsx +417 -0
- package/src/_stories/Chart.SeriesColorAssignments.stories.tsx +47 -0
- package/src/_stories/Chart.SmallMultiplesNumericTileOrder.stories.tsx +137 -0
- package/src/_stories/Chart.TooltipSeriesLabels.stories.tsx +43 -0
- package/src/_stories/Chart.VegaRemoteData.stories.tsx +31 -0
- package/src/_stories/Chart.smoke.stories.tsx +14 -1
- package/src/_stories/ChartAnnotation.Editor.stories.tsx +78 -0
- package/src/_stories/ChartAxisTitles.smoke.stories.tsx +48 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +499 -57
- package/src/_stories/ChartBrush.Editor.stories.tsx +46 -67
- package/src/_stories/ChartBrush.Regression.stories.tsx +135 -0
- package/src/_stories/ChartEditor.Editor.stories.tsx +33 -3
- package/src/_stories/ChartLine.EffectCompatibility.stories.tsx +120 -0
- package/src/_stories/ChartPrefixSuffix.smoke.stories.tsx +28 -1
- package/src/_stories/_mock/annotation_event-line_mock.json +2 -2
- package/src/_stories/_mock/editor-test-configs.json +20 -10
- package/src/_stories/_mock/editor-test-datasets.json +38 -42
- package/src/_stories/_mock/heatmap-average-age-categorical.json +2 -2
- package/src/_stories/_mock/heatmap.json +2 -2
- package/src/_stories/_mock/legend-axis-align-stacked-bar.json +125 -0
- package/src/_stories/_mock/sankey_mock.json +23 -27
- package/src/components/Annotations/components/AnnotationDraggable.styles.css +52 -0
- package/src/components/Annotations/components/AnnotationDraggable.tsx +639 -139
- package/src/components/Annotations/components/AnnotationDropdown.styles.css +44 -4
- package/src/components/Annotations/components/AnnotationDropdown.tsx +10 -32
- package/src/components/Annotations/helpers/resolveAnnotationLayout.ts +212 -0
- package/src/components/Annotations/tests/AnnotationDraggable.test.tsx +612 -19
- package/src/components/Annotations/tests/AnnotationDropdown.test.tsx +50 -0
- package/src/components/Annotations/tests/resolveAnnotationLayout.test.ts +203 -0
- package/src/components/Axis/BottomAxis.tsx +1 -1
- package/src/components/Axis/Categorical.Axis.tsx +3 -3
- package/src/components/Axis/RightAxis.tsx +21 -13
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +39 -8
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +13 -4
- package/src/components/BarChart/components/BarChart.StackedVertical.test.ts +28 -0
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +30 -26
- package/src/components/BarChart/components/BarChart.Vertical.tsx +38 -28
- package/src/components/BarChart/components/PortionPatternOverlay.tsx +61 -0
- package/src/components/BarChart/components/context.tsx +6 -0
- package/src/components/BarChart/helpers/getBarData.ts +28 -28
- package/src/components/BarChart/helpers/getBarHeights.ts +2 -2
- package/src/components/BarChart/helpers/getPatternUrl.ts +2 -5
- package/src/components/BarChart/helpers/index.ts +8 -0
- package/src/components/BarChart/helpers/portionPattern.ts +243 -0
- package/src/components/BarChart/helpers/tests/addMinimumBarHeights.test.ts +42 -0
- package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +13 -0
- package/src/components/BarChart/helpers/tests/portionPattern.test.ts +280 -0
- package/src/components/BarChart/helpers/tests/useBarChart.test.tsx +202 -0
- package/src/components/BarChart/helpers/useBarChart.ts +60 -60
- package/src/components/BarChartRace/BarChartRace.test.tsx +199 -0
- package/src/components/BarChartRace/BarChartRace.tsx +230 -0
- package/src/components/BarChartRace/BarChartRaceFallback.test.tsx +61 -0
- package/src/components/BarChartRace/BarChartRaceFallback.tsx +48 -0
- package/src/components/BarChartRace/bar-chart-race.css +160 -0
- package/src/components/BarChartRace/helpers.test.ts +114 -0
- package/src/components/BarChartRace/helpers.ts +185 -0
- package/src/components/BarChartRace/index.ts +3 -0
- package/src/components/BoxPlot/BoxPlot.Horizontal.tsx +7 -6
- package/src/components/BoxPlot/BoxPlot.Vertical.tsx +9 -7
- package/src/components/BoxPlot/helpers/index.ts +13 -83
- package/src/components/Brush/BrushSelector.tsx +10 -24
- package/src/components/Brush/MiniChartPreview.tsx +33 -1
- package/src/components/Dendrogram/components/Dendrogram.tsx +374 -0
- package/src/components/Dendrogram/dendrogram.css +113 -0
- package/src/components/Dendrogram/helpers/layoutDendrogram.test.ts +95 -0
- package/src/components/Dendrogram/helpers/layoutDendrogram.ts +56 -0
- package/src/components/Dendrogram/helpers/prepareDendrogramData.test.ts +135 -0
- package/src/components/Dendrogram/helpers/prepareDendrogramData.ts +166 -0
- package/src/components/Dendrogram/helpers/resolveDendrogramLabels.test.ts +196 -0
- package/src/components/Dendrogram/helpers/resolveDendrogramLabels.ts +418 -0
- package/src/components/Dendrogram/index.tsx +1 -0
- package/src/components/Dendrogram/types/index.ts +66 -0
- package/src/components/EditorPanel/EditorPanel.tsx +1111 -805
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +50 -5
- package/src/components/EditorPanel/components/Panels/Panel.Dendrogram.css +10 -0
- package/src/components/EditorPanel/components/Panels/Panel.Dendrogram.tsx +211 -0
- package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +19 -8
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +104 -61
- package/src/components/EditorPanel/components/Panels/Panel.Network.css +9 -0
- package/src/components/EditorPanel/components/Panels/Panel.Network.tsx +202 -0
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +236 -36
- package/src/components/EditorPanel/components/Panels/Panel.Radar.tsx +6 -1
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +89 -105
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +21 -6
- package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +8 -66
- package/src/components/EditorPanel/components/Panels/RacingControls.test.tsx +131 -0
- package/src/components/EditorPanel/components/Panels/RacingControls.tsx +185 -0
- package/src/components/EditorPanel/components/Panels/SeriesColorAssignments.tsx +2 -2
- package/src/components/EditorPanel/components/Panels/index.tsx +4 -0
- package/src/components/EditorPanel/helpers/getVisualizationTypeConfigUpdate.ts +20 -7
- package/src/components/EditorPanel/helpers/tests/getVisualizationTypeConfigUpdate.test.ts +25 -2
- package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +5 -4
- package/src/components/EditorPanel/useEditorPermissions.test.tsx +94 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +75 -25
- package/src/components/Forecasting/Forecasting.tsx +16 -7
- package/src/components/HeatMap/components/HeatMap.tsx +511 -178
- package/src/components/HeatMap/heatmap.constants.ts +7 -3
- package/src/components/HeatMap/heatmap.css +101 -2
- package/src/components/HeatMap/helpers/layout.ts +80 -0
- package/src/components/HeatMap/tests/HeatMap.test.tsx +339 -16
- package/src/components/HeatMap/tests/helpers.test.ts +79 -0
- package/src/components/Legend/Legend.Component.tsx +163 -148
- package/src/components/Legend/Legend.Suppression.tsx +3 -3
- package/src/components/Legend/LegendGroup/LegendGroup.styles.css +7 -0
- package/src/components/Legend/LegendGroup/LegendGroup.tsx +47 -35
- package/src/components/Legend/helpers/createFormatLabels.test.ts +226 -0
- package/src/components/Legend/helpers/createFormatLabels.tsx +45 -51
- package/src/components/LineChart/components/LineChart.Circle.tsx +3 -3
- package/src/components/LineChart/helpers.test.ts +126 -38
- package/src/components/LineChart/helpers.ts +9 -6
- package/src/components/LineChart/index.tsx +71 -27
- package/src/components/LineChart/tests/LineChart.test.tsx +630 -0
- package/src/components/LineChartRace/LineChartRace.test.tsx +275 -0
- package/src/components/LineChartRace/LineChartRace.tsx +134 -0
- package/src/components/LineChartRace/LineChartRaceFallback.tsx +28 -0
- package/src/components/LineChartRace/helpers.test.ts +88 -0
- package/src/components/LineChartRace/helpers.ts +157 -0
- package/src/components/LineChartRace/index.ts +3 -0
- package/src/components/LineChartRace/line-chart-race.css +16 -0
- package/src/components/LinearChart/ValueAxisAnchors.tsx +58 -0
- package/src/components/LinearChart/VisualizationRenderer.tsx +18 -23
- package/src/components/LinearChart/tests/LinearChart.test.tsx +412 -13
- package/src/components/LinearChart/tests/VisualizationRenderer.test.tsx +141 -0
- package/src/components/LinearChart/tests/mockConfigContext.ts +2 -1
- package/src/components/LinearChart.tsx +85 -54
- package/src/components/Network/components/Network.tsx +372 -0
- package/src/components/Network/helpers/layoutNetwork.test.ts +68 -0
- package/src/components/Network/helpers/layoutNetwork.ts +87 -0
- package/src/components/Network/helpers/prepareNetworkData.test.ts +116 -0
- package/src/components/Network/helpers/prepareNetworkData.ts +101 -0
- package/src/components/Network/helpers/resolveNetworkLabels.test.ts +112 -0
- package/src/components/Network/helpers/resolveNetworkLabels.ts +206 -0
- package/src/components/Network/index.tsx +3 -0
- package/src/components/Network/network.css +107 -0
- package/src/components/Network/types/index.ts +56 -0
- package/src/components/PairedBarChart.jsx +5 -10
- package/src/components/PairedBarChart.test.tsx +71 -0
- package/src/components/PieChart/PieChart.tsx +121 -13
- package/src/components/PieChart/helpers/labelPlacement.test.ts +88 -0
- package/src/components/PieChart/helpers/labelPlacement.ts +95 -0
- package/src/components/RacingChartRenderer.tsx +44 -0
- package/src/components/Regions/components/Regions.test.tsx +179 -0
- package/src/components/Regions/components/Regions.tsx +104 -69
- package/src/components/Regions/index.tsx +2 -3
- package/src/components/Sankey/components/Sankey.tsx +264 -437
- package/src/components/Sankey/helpers/getSankeyTooltip.ts +12 -0
- package/src/components/Sankey/helpers/prepareSankeyData.test.ts +71 -0
- package/src/components/Sankey/helpers/prepareSankeyData.ts +90 -0
- package/src/components/Sankey/sankey.scss +57 -116
- package/src/components/Sankey/types/index.ts +41 -4
- package/src/components/ScatterPlot/ScatterPlot.jsx +28 -12
- package/src/components/ScatterPlot/ScatterPlot.test.tsx +60 -0
- package/src/components/SmallMultiples/SmallMultiples.tsx +12 -12
- package/src/components/SmallMultiples/tests/SmallMultipleTile.test.tsx +7 -5
- package/src/components/raceTiming.ts +18 -0
- package/src/data/initial-state.js +79 -31
- package/src/helpers/applyChartTypeContract.ts +71 -0
- package/src/helpers/axisLabelFontSize.ts +2 -2
- package/src/helpers/boxPlotStats.ts +60 -0
- package/src/helpers/bumpChartTooltip.ts +2 -1
- package/src/helpers/calculateHorizontalBarCategoryLabelWidth.test.ts +37 -0
- package/src/helpers/calculateHorizontalBarCategoryLabelWidth.ts +3 -2
- package/src/helpers/calculateRightYAxisWidth.ts +60 -0
- package/src/helpers/categoryOrder.ts +60 -0
- package/src/helpers/colorAssignmentHelpers.ts +2 -2
- package/src/helpers/createNewChartConfig.ts +56 -0
- package/src/helpers/dataDrivenYAxisCategories.ts +18 -0
- package/src/helpers/forecastLegend.ts +88 -0
- package/src/helpers/getBoxPlotConfig.ts +26 -38
- package/src/helpers/getChartTypeDefaultPalette.ts +29 -0
- package/src/helpers/getColorCodeCategoryColorMap.ts +26 -0
- package/src/helpers/getColorScale.ts +31 -22
- package/src/helpers/getComboChartConfig.ts +0 -1
- package/src/helpers/getDynamicYAxisCategories.ts +69 -0
- package/src/helpers/getExcludedData.ts +0 -1
- package/src/helpers/getHasBoundarySuppression.ts +4 -3
- package/src/helpers/getMinMax.ts +11 -8
- package/src/helpers/getNewRuntime.ts +4 -3
- package/src/helpers/getPiePercent.ts +3 -3
- package/src/helpers/getStackedSeriesMax.ts +51 -0
- package/src/helpers/getV21ChartDistributionColors.ts +57 -0
- package/src/helpers/handleRankByValue.ts +15 -15
- package/src/helpers/isConvertLineToBarGraph.ts +2 -2
- package/src/helpers/seriesColumnSettings.ts +31 -3
- package/src/helpers/sizeHelpers.ts +4 -5
- package/src/helpers/smallMultiplesHelpers.ts +10 -13
- package/src/helpers/tests/applyChartTypeContract.test.ts +37 -0
- package/src/helpers/tests/boxPlotStats.test.ts +31 -0
- package/src/helpers/tests/bumpChartTooltip.test.ts +29 -0
- package/src/helpers/tests/calculateRightYAxisWidth.test.ts +105 -0
- package/src/helpers/tests/categoryOrder.test.ts +57 -0
- package/src/helpers/tests/countNumOfTicks.test.ts +11 -0
- package/src/helpers/tests/createNewChartConfig.test.ts +182 -0
- package/src/helpers/tests/getBoxPlotConfig.test.ts +70 -0
- package/src/helpers/tests/getColorCodeCategoryColorMap.test.ts +113 -0
- package/src/helpers/tests/getColorScale.test.ts +226 -1
- package/src/helpers/tests/getDynamicYAxisCategories.test.ts +61 -0
- package/src/helpers/tests/getMinMax.test.ts +41 -0
- package/src/helpers/tests/getStackedSeriesMax.test.ts +26 -0
- package/src/helpers/tests/handleRankByValue.test.ts +55 -37
- package/src/helpers/tests/seriesColumnSettings.test.ts +83 -0
- package/src/helpers/tests/smallMultiplesHelpers.test.ts +37 -1
- package/src/helpers/tests/tooltipHelpers.test.ts +80 -0
- package/src/helpers/tooltipHelpers.ts +16 -0
- package/src/hooks/tests/useRightAxis.test.tsx +143 -2
- package/src/hooks/tests/useScales.test.tsx +3 -6
- package/src/hooks/tests/useTooltip.test.tsx +484 -0
- package/src/hooks/usePrefersReducedMotion.ts +22 -0
- package/src/hooks/useReduceData.ts +4 -36
- package/src/hooks/useRightAxis.ts +19 -26
- package/src/hooks/useScales.ts +15 -0
- package/src/hooks/useTooltip.tsx +106 -71
- package/src/scss/main.scss +74 -2
- package/src/store/chart.reducer.ts +4 -4
- package/src/test/CdcChart.dataTable.test.tsx +582 -14
- package/src/test/CdcChart.dendrogram.test.tsx +277 -0
- package/src/test/CdcChart.finalization.test.tsx +143 -0
- package/src/test/CdcChart.network.test.tsx +271 -0
- package/src/types/ChartConfig.ts +91 -54
- package/src/types/ChartContext.ts +5 -0
- package/src/types/Horizon.ts +1 -1
- package/LICENSE +0 -201
- package/dist/cdcchart-BWVIUcAF.es.js +0 -4802
- package/src/_stories/Chart.Sankey.smoke.stories.tsx +0 -62
- package/src/components/Sankey/components/ColumnList.tsx +0 -19
- package/src/components/Sankey/helpers/getSankeyTooltip.tsx +0 -34
- package/src/components/Sankey/useSankeyAlert.tsx +0 -60
- package/src/data/legacy-defaults.ts +0 -18
- package/src/helpers/ensureSpecialChartAxisTypes.ts +0 -11
- package/src/helpers/tests/ensureSpecialChartAxisTypes.test.ts +0 -30
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { expect } from 'storybook/test'
|
|
3
|
+
import DynamicSeriesBarConfig from './_mock/dynamic_series_bar_config.json'
|
|
4
|
+
import SuppressedBarConfig from './_mock/bar-chart-suppressed.json'
|
|
5
|
+
import { assertVisualizationRendered, waitForPresence } from '@cdc/core/helpers/testing'
|
|
6
|
+
|
|
7
|
+
import Chart from '../CdcChart'
|
|
8
|
+
import MinimalExampleConfig from '../../examples/minimal-example.json'
|
|
9
|
+
|
|
10
|
+
const meta: Meta<typeof Chart> = {
|
|
11
|
+
title: 'Components/Templates/Chart/Percentage Values',
|
|
12
|
+
component: Chart
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default meta
|
|
16
|
+
type Story = StoryObj<typeof Chart>
|
|
17
|
+
|
|
18
|
+
const percentageValueConfig = {
|
|
19
|
+
...MinimalExampleConfig,
|
|
20
|
+
title: 'Mixed Percentage and Numeric Values',
|
|
21
|
+
dataFormat: {
|
|
22
|
+
...MinimalExampleConfig.dataFormat,
|
|
23
|
+
roundTo: 1
|
|
24
|
+
},
|
|
25
|
+
data: [
|
|
26
|
+
{ category: 'Percentage', value: '12.5%' },
|
|
27
|
+
{ category: 'Count', value: 20 }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const horizontalPercentageValueConfig = {
|
|
32
|
+
...percentageValueConfig,
|
|
33
|
+
title: 'Horizontal Percentage Value',
|
|
34
|
+
orientation: 'horizontal'
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const findTooltipPath = (canvasElement: HTMLElement, ...requiredText: string[]) =>
|
|
38
|
+
Array.from(canvasElement.querySelectorAll<SVGPathElement>('path[data-tooltip-html]')).find(path => {
|
|
39
|
+
const tooltip = path.getAttribute('data-tooltip-html') || ''
|
|
40
|
+
|
|
41
|
+
return requiredText.every(text => tooltip.includes(text))
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const getPercentageBar = (canvasElement: HTMLElement) => findTooltipPath(canvasElement, 'Percentage')
|
|
45
|
+
|
|
46
|
+
const stackedPercentageValueConfig = {
|
|
47
|
+
...MinimalExampleConfig,
|
|
48
|
+
title: 'Stacked Percentage Value',
|
|
49
|
+
visualizationSubType: 'stacked',
|
|
50
|
+
orientation: 'vertical',
|
|
51
|
+
dataFormat: {
|
|
52
|
+
...MinimalExampleConfig.dataFormat,
|
|
53
|
+
roundTo: 1
|
|
54
|
+
},
|
|
55
|
+
data: [
|
|
56
|
+
{ category: 'Stack A', rate: '12.5%', count: 20 },
|
|
57
|
+
{ category: 'Stack B', rate: 5, count: 10 }
|
|
58
|
+
],
|
|
59
|
+
series: [
|
|
60
|
+
{ dataKey: 'rate', name: 'Rate', type: 'Bar', axis: 'Left', tooltip: true },
|
|
61
|
+
{ dataKey: 'count', name: 'Count', type: 'Bar', axis: 'Left', tooltip: true }
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const stackedHorizontalPercentageValueConfig = {
|
|
66
|
+
...stackedPercentageValueConfig,
|
|
67
|
+
title: 'Stacked Horizontal Percentage Value',
|
|
68
|
+
orientation: 'horizontal'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const dynamicPercentageData = DynamicSeriesBarConfig.data.map(row =>
|
|
72
|
+
row.YearStart === 2015 && row.Stratification1 === '65 years or older' ? { ...row, Data_Value: '56.4%' } : row
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
const dynamicPercentageValueConfig = {
|
|
76
|
+
...DynamicSeriesBarConfig,
|
|
77
|
+
title: 'Dynamic Series Percentage Value',
|
|
78
|
+
dataFormat: {
|
|
79
|
+
...DynamicSeriesBarConfig.dataFormat,
|
|
80
|
+
roundTo: 1
|
|
81
|
+
},
|
|
82
|
+
data: dynamicPercentageData,
|
|
83
|
+
formattedData: dynamicPercentageData
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const suppressionPercentageValueConfig = {
|
|
87
|
+
...SuppressedBarConfig,
|
|
88
|
+
data: SuppressedBarConfig.data.map((row, index) => (index === 1 ? { ...row, 'Data 2': '110%' } : row))
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const suppressionConfidenceData = [
|
|
92
|
+
{ Race_Ethnicity: 'American Indian or Alaska Native', Data_Value: '73.1', CI_Lower: '70.4', CI_Upper: '75.8' },
|
|
93
|
+
{ Race_Ethnicity: 'Asian', Data_Value: '77.2', CI_Lower: '75.3', CI_Upper: '79.1' },
|
|
94
|
+
{ Race_Ethnicity: 'Black or African American', Data_Value: '68.4', CI_Lower: '66.7', CI_Upper: '70.1' },
|
|
95
|
+
{ Race_Ethnicity: 'Hispanic or Latino', Data_Value: '71.6', CI_Lower: '70.2', CI_Upper: '73.0' },
|
|
96
|
+
{ Race_Ethnicity: 'More than one race', Data_Value: '72.8', CI_Lower: '70.5', CI_Upper: '75.1' },
|
|
97
|
+
{ Race_Ethnicity: 'White', Data_Value: '76.4', CI_Lower: '75.8', CI_Upper: '77.0' },
|
|
98
|
+
{
|
|
99
|
+
Race_Ethnicity: 'NHOPI',
|
|
100
|
+
Data_Value: 'Suppressed',
|
|
101
|
+
CI_Lower: 'Suppressed',
|
|
102
|
+
CI_Upper: 'Suppressed'
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
const wildcardSuppressionConfidenceConfig = {
|
|
107
|
+
...SuppressedBarConfig,
|
|
108
|
+
title: 'Wildcard Suppression with Confidence Intervals',
|
|
109
|
+
general: {
|
|
110
|
+
...SuppressedBarConfig.general,
|
|
111
|
+
showMissingDataLabel: false,
|
|
112
|
+
showSuppressedSymbol: true,
|
|
113
|
+
showZeroValueData: false
|
|
114
|
+
},
|
|
115
|
+
xAxis: {
|
|
116
|
+
...SuppressedBarConfig.xAxis,
|
|
117
|
+
dataKey: 'Race_Ethnicity',
|
|
118
|
+
type: 'categorical'
|
|
119
|
+
},
|
|
120
|
+
confidenceKeys: {
|
|
121
|
+
lower: 'CI_Lower',
|
|
122
|
+
upper: 'CI_Upper'
|
|
123
|
+
},
|
|
124
|
+
preliminaryData: [
|
|
125
|
+
{
|
|
126
|
+
...SuppressedBarConfig.preliminaryData[0],
|
|
127
|
+
column: '',
|
|
128
|
+
value: 'Suppressed',
|
|
129
|
+
hideBarSymbol: true
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
series: [{ ...SuppressedBarConfig.series[0], dataKey: 'Data_Value' }],
|
|
133
|
+
data: suppressionConfidenceData
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const dynamicSuppressionCategory = '65 years or older'
|
|
137
|
+
const dynamicSuppressionData = DynamicSeriesBarConfig.data.map(row =>
|
|
138
|
+
row.YearStart === 2015 && row.Stratification1 === dynamicSuppressionCategory ? { ...row, Data_Value: 'ABC' } : row
|
|
139
|
+
)
|
|
140
|
+
const dynamicSuppressionConfig = {
|
|
141
|
+
...DynamicSeriesBarConfig,
|
|
142
|
+
data: dynamicSuppressionData,
|
|
143
|
+
formattedData: dynamicSuppressionData,
|
|
144
|
+
preliminaryData: [
|
|
145
|
+
{
|
|
146
|
+
...SuppressedBarConfig.preliminaryData[0],
|
|
147
|
+
column: dynamicSuppressionCategory,
|
|
148
|
+
value: 'ABC'
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export const Percent_Decorated_Value_Renders_As_Bar_And_Tooltip: Story = {
|
|
154
|
+
args: {
|
|
155
|
+
config: percentageValueConfig
|
|
156
|
+
},
|
|
157
|
+
play: async ({ canvasElement }) => {
|
|
158
|
+
await assertVisualizationRendered(canvasElement)
|
|
159
|
+
await waitForPresence('path[data-tooltip-html]', canvasElement)
|
|
160
|
+
|
|
161
|
+
const percentageBar = getPercentageBar(canvasElement)
|
|
162
|
+
|
|
163
|
+
expect(percentageBar).toBeDefined()
|
|
164
|
+
expect(percentageBar?.closest('g[display]')).toHaveAttribute('display', 'block')
|
|
165
|
+
expect(percentageBar?.getBBox().height).toBeGreaterThan(3)
|
|
166
|
+
expect(percentageBar?.getAttribute('data-tooltip-html')).toContain('12.5%')
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export const Dynamic_Percent_Decoration_Is_Preserved_In_Tooltip: Story = {
|
|
171
|
+
args: {
|
|
172
|
+
config: dynamicPercentageValueConfig
|
|
173
|
+
},
|
|
174
|
+
play: async ({ canvasElement }) => {
|
|
175
|
+
await assertVisualizationRendered(canvasElement)
|
|
176
|
+
await waitForPresence('path[data-tooltip-html]', canvasElement)
|
|
177
|
+
|
|
178
|
+
const dynamicPercentageBar = findTooltipPath(canvasElement, '2015', '65 years or older')
|
|
179
|
+
|
|
180
|
+
expect(dynamicPercentageBar).toBeDefined()
|
|
181
|
+
expect(dynamicPercentageBar?.closest('g[display]')).toHaveAttribute('display', 'block')
|
|
182
|
+
expect(dynamicPercentageBar?.getAttribute('data-tooltip-html')).toContain('56.4%')
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export const Suppression_Config_Does_Not_Hide_Percentage_Bars: Story = {
|
|
187
|
+
args: {
|
|
188
|
+
config: suppressionPercentageValueConfig
|
|
189
|
+
},
|
|
190
|
+
play: async ({ canvasElement }) => {
|
|
191
|
+
await assertVisualizationRendered(canvasElement)
|
|
192
|
+
await waitForPresence('path[data-tooltip-html]', canvasElement)
|
|
193
|
+
|
|
194
|
+
const percentageBar = findTooltipPath(canvasElement, '110%')
|
|
195
|
+
const suppressedBarGroup = Array.from(canvasElement.querySelectorAll<SVGGElement>('g[display="block"]')).find(
|
|
196
|
+
group => group.textContent?.includes('†') && group.querySelector('path[data-tooltip-html]')
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
expect(percentageBar).toBeDefined()
|
|
200
|
+
expect(percentageBar?.closest('g[display]')).toHaveAttribute('display', 'block')
|
|
201
|
+
expect(percentageBar?.getBBox().height).toBeGreaterThan(3)
|
|
202
|
+
expect(suppressedBarGroup).toBeDefined()
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export const Wildcard_Suppression_Does_Not_Corrupt_Confidence_Domain: Story = {
|
|
207
|
+
args: {
|
|
208
|
+
config: wildcardSuppressionConfidenceConfig
|
|
209
|
+
},
|
|
210
|
+
play: async ({ canvasElement }) => {
|
|
211
|
+
await assertVisualizationRendered(canvasElement)
|
|
212
|
+
await waitForPresence('path[data-tooltip-html]', canvasElement)
|
|
213
|
+
await waitForPresence('path[stroke-width="px"]', canvasElement)
|
|
214
|
+
|
|
215
|
+
const visibleNumericBars = Array.from(
|
|
216
|
+
canvasElement.querySelectorAll<SVGPathElement>('path[data-tooltip-html]')
|
|
217
|
+
).filter(path => path.closest('g[display]')?.getAttribute('display') === 'block')
|
|
218
|
+
const visibleConfidenceIntervals = Array.from(
|
|
219
|
+
canvasElement.querySelectorAll<SVGPathElement>('path[stroke-width="px"]')
|
|
220
|
+
).filter(path => path.closest('g[display]')?.getAttribute('display') === 'block')
|
|
221
|
+
const suppressedBar = findTooltipPath(canvasElement, 'NHOPI')
|
|
222
|
+
const suppressedBarGroup = suppressedBar?.closest('g[display]')
|
|
223
|
+
|
|
224
|
+
expect(visibleNumericBars).toHaveLength(6)
|
|
225
|
+
visibleNumericBars.forEach(bar => {
|
|
226
|
+
expect(bar.getAttribute('d')).not.toContain('NaN')
|
|
227
|
+
expect(bar.getBBox().height).toBeGreaterThan(3)
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
expect(visibleConfidenceIntervals).toHaveLength(6)
|
|
231
|
+
visibleConfidenceIntervals.forEach(path => {
|
|
232
|
+
const pathData = path.getAttribute('d') || ''
|
|
233
|
+
const coordinates = pathData.match(/-?\d+(?:\.\d+)?/g)?.map(Number)
|
|
234
|
+
|
|
235
|
+
expect(pathData).not.toMatch(/NaN|Infinity/)
|
|
236
|
+
expect(coordinates?.length).toBeGreaterThan(0)
|
|
237
|
+
expect(coordinates?.every(Number.isFinite)).toBe(true)
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
expect(suppressedBar).toBeDefined()
|
|
241
|
+
expect(suppressedBarGroup).toHaveAttribute('display', 'none')
|
|
242
|
+
expect(suppressedBarGroup?.querySelector('rect[data-tooltip-html]')).toBeTruthy()
|
|
243
|
+
expect(suppressedBarGroup).not.toHaveTextContent('†')
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export const Dynamic_Suppression_Target_Is_Preserved: Story = {
|
|
248
|
+
args: {
|
|
249
|
+
config: dynamicSuppressionConfig
|
|
250
|
+
},
|
|
251
|
+
play: async ({ canvasElement }) => {
|
|
252
|
+
await assertVisualizationRendered(canvasElement)
|
|
253
|
+
await waitForPresence('path[data-tooltip-html]', canvasElement)
|
|
254
|
+
|
|
255
|
+
const suppressedBar = findTooltipPath(canvasElement, '2015', dynamicSuppressionCategory)
|
|
256
|
+
const suppressedBarGroup = suppressedBar?.closest('g[display]')
|
|
257
|
+
|
|
258
|
+
expect(suppressedBar).toBeDefined()
|
|
259
|
+
expect(suppressedBarGroup).toHaveAttribute('display', 'block')
|
|
260
|
+
expect(suppressedBarGroup).toHaveTextContent('†')
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export const Horizontal_Percent_Decoration_Is_Preserved_In_Tooltip: Story = {
|
|
265
|
+
args: {
|
|
266
|
+
config: horizontalPercentageValueConfig
|
|
267
|
+
},
|
|
268
|
+
play: async ({ canvasElement }) => {
|
|
269
|
+
await assertVisualizationRendered(canvasElement)
|
|
270
|
+
await waitForPresence('path[data-tooltip-html]', canvasElement)
|
|
271
|
+
|
|
272
|
+
const percentageBar = getPercentageBar(canvasElement)
|
|
273
|
+
|
|
274
|
+
expect(percentageBar).toBeDefined()
|
|
275
|
+
expect(percentageBar?.closest('g[display]')).toHaveAttribute('display', 'block')
|
|
276
|
+
expect(percentageBar?.getBBox().width).toBeGreaterThanOrEqual(3)
|
|
277
|
+
expect(percentageBar?.getAttribute('data-tooltip-html')).toContain('12.5%')
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export const Stacked_Vertical_Percent_Decoration_Is_Preserved_In_Tooltip: Story = {
|
|
282
|
+
args: {
|
|
283
|
+
config: stackedPercentageValueConfig
|
|
284
|
+
},
|
|
285
|
+
play: async ({ canvasElement }) => {
|
|
286
|
+
await assertVisualizationRendered(canvasElement)
|
|
287
|
+
await waitForPresence('path[data-tooltip-html]', canvasElement)
|
|
288
|
+
|
|
289
|
+
const percentageSegment = findTooltipPath(canvasElement, 'Stack A', 'Rate:')
|
|
290
|
+
|
|
291
|
+
expect(percentageSegment).toBeDefined()
|
|
292
|
+
expect(percentageSegment).toHaveStyle({ display: 'block' })
|
|
293
|
+
expect(percentageSegment?.getAttribute('data-tooltip-html')).toContain('12.5%')
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export const Stacked_Horizontal_Percent_Decoration_Is_Preserved_In_Tooltip: Story = {
|
|
298
|
+
args: {
|
|
299
|
+
config: stackedHorizontalPercentageValueConfig
|
|
300
|
+
},
|
|
301
|
+
play: async ({ canvasElement }) => {
|
|
302
|
+
await assertVisualizationRendered(canvasElement)
|
|
303
|
+
await waitForPresence('path[data-tooltip-html]', canvasElement)
|
|
304
|
+
|
|
305
|
+
const percentageSegment = findTooltipPath(canvasElement, 'Stack A', 'Rate:')
|
|
306
|
+
|
|
307
|
+
expect(percentageSegment).toBeDefined()
|
|
308
|
+
expect(percentageSegment).toHaveStyle({ display: 'block' })
|
|
309
|
+
expect(percentageSegment?.getAttribute('data-tooltip-html')).toContain('12.5%')
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { expect, within } from 'storybook/test'
|
|
3
|
+
import Chart from '../CdcChart'
|
|
4
|
+
import pieConfig from './_mock/pie_with_data.json'
|
|
5
|
+
import { editConfigKeys } from '@cdc/core/helpers/configHelpers'
|
|
6
|
+
import { assertVisualizationRendered, waitForEditor, waitForPresence } from '@cdc/core/helpers/testing'
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof Chart> = {
|
|
9
|
+
title: 'Components/Templates/Chart/Pie Labels',
|
|
10
|
+
component: Chart
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type Story = StoryObj<typeof Chart>
|
|
14
|
+
|
|
15
|
+
export const CategoryPercentageLabels: Story = {
|
|
16
|
+
args: {
|
|
17
|
+
config: editConfigKeys(pieConfig, [
|
|
18
|
+
{ path: ['labels'], value: true },
|
|
19
|
+
{ path: ['legend', 'hide'], value: true }
|
|
20
|
+
]),
|
|
21
|
+
isEditor: true
|
|
22
|
+
},
|
|
23
|
+
play: async ({ canvasElement }) => {
|
|
24
|
+
await waitForEditor(within(canvasElement))
|
|
25
|
+
await assertVisualizationRendered(canvasElement)
|
|
26
|
+
await waitForPresence('.pie-label', canvasElement)
|
|
27
|
+
expect(canvasElement.querySelector('line')).toBeNull()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const DonutCategoryPercentageLabels: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
config: editConfigKeys(pieConfig, [
|
|
34
|
+
{ path: ['labels'], value: true },
|
|
35
|
+
{ path: ['legend', 'hide'], value: true },
|
|
36
|
+
{ path: ['pieType'], value: 'Donut' }
|
|
37
|
+
]),
|
|
38
|
+
isEditor: true
|
|
39
|
+
},
|
|
40
|
+
play: async ({ canvasElement }) => {
|
|
41
|
+
await waitForEditor(within(canvasElement))
|
|
42
|
+
await assertVisualizationRendered(canvasElement)
|
|
43
|
+
await waitForPresence('.pie-label--outside', canvasElement)
|
|
44
|
+
expect(canvasElement.querySelector('.pie-label--inside')).toBeNull()
|
|
45
|
+
expect(canvasElement.querySelector('line')).toBeNull()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default meta
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react'
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
3
|
+
import { expect, waitFor } from 'storybook/test'
|
|
4
|
+
|
|
5
|
+
import { assertVisualizationRendered } from '@cdc/core/helpers/testing'
|
|
6
|
+
import Chart from '../CdcChartComponent'
|
|
7
|
+
import { ChartConfig } from '../types/ChartConfig'
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof RankByValueMutationHarness> = {
|
|
10
|
+
title: 'Components/Templates/Chart/Rank By Value Mutation Regression',
|
|
11
|
+
component: RankByValueMutationHarness,
|
|
12
|
+
parameters: {
|
|
13
|
+
layout: 'fullscreen'
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default meta
|
|
18
|
+
type Story = StoryObj<typeof RankByValueMutationHarness>
|
|
19
|
+
|
|
20
|
+
type RankRow = {
|
|
21
|
+
category: string
|
|
22
|
+
value: number
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const sourceOrder = 'Alpha, Charlie, Bravo'
|
|
26
|
+
const rankedOrder = 'Charlie, Bravo, Alpha'
|
|
27
|
+
const rankedExcludingAlphaOrder = 'Charlie, Bravo'
|
|
28
|
+
|
|
29
|
+
const getOrder = (rows: RankRow[]) => rows.map(row => row.category).join(', ')
|
|
30
|
+
|
|
31
|
+
const getRenderedCategoryOrder = (panel: Element) => {
|
|
32
|
+
const categoryNames = sourceOrder.split(', ')
|
|
33
|
+
return Array.from(panel.querySelectorAll('svg text'))
|
|
34
|
+
.filter(textElement => categoryNames.includes(textElement.textContent?.trim() || ''))
|
|
35
|
+
.sort((a, b) => a.getBoundingClientRect().left - b.getBoundingClientRect().left)
|
|
36
|
+
.map(textElement => textElement.textContent?.trim())
|
|
37
|
+
.join(', ')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const getConfig = (
|
|
41
|
+
title: string,
|
|
42
|
+
data: RankRow[],
|
|
43
|
+
rankByValue?: 'asc' | 'desc',
|
|
44
|
+
excludedCategories: string[] = []
|
|
45
|
+
): ChartConfig =>
|
|
46
|
+
({
|
|
47
|
+
version: '4.26.8',
|
|
48
|
+
type: 'chart',
|
|
49
|
+
visualizationType: 'Bar',
|
|
50
|
+
title,
|
|
51
|
+
rankByValue,
|
|
52
|
+
data,
|
|
53
|
+
animate: false,
|
|
54
|
+
legend: {
|
|
55
|
+
hide: true
|
|
56
|
+
},
|
|
57
|
+
table: {
|
|
58
|
+
show: false
|
|
59
|
+
},
|
|
60
|
+
xAxis: {
|
|
61
|
+
dataKey: 'category',
|
|
62
|
+
type: 'categorical',
|
|
63
|
+
label: 'Category'
|
|
64
|
+
},
|
|
65
|
+
yAxis: {
|
|
66
|
+
label: 'Value',
|
|
67
|
+
hideAxis: false,
|
|
68
|
+
hideTicks: false,
|
|
69
|
+
gridLines: true,
|
|
70
|
+
numTicks: 4
|
|
71
|
+
},
|
|
72
|
+
series: [
|
|
73
|
+
{
|
|
74
|
+
dataKey: 'value',
|
|
75
|
+
name: 'Value',
|
|
76
|
+
type: 'Bar'
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
dataFormat: {
|
|
80
|
+
roundTo: 0,
|
|
81
|
+
commas: false
|
|
82
|
+
},
|
|
83
|
+
exclusions: {
|
|
84
|
+
active: excludedCategories.length > 0,
|
|
85
|
+
keys: excludedCategories
|
|
86
|
+
}
|
|
87
|
+
} as ChartConfig)
|
|
88
|
+
|
|
89
|
+
const panelStyle = {
|
|
90
|
+
background: '#fff',
|
|
91
|
+
border: '1px solid #d9dfe7',
|
|
92
|
+
borderRadius: 6,
|
|
93
|
+
minWidth: 0,
|
|
94
|
+
padding: 16
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const labelStyle = {
|
|
98
|
+
color: '#4b5563',
|
|
99
|
+
fontSize: 12,
|
|
100
|
+
fontWeight: 700,
|
|
101
|
+
margin: '0 0 8px',
|
|
102
|
+
textTransform: 'uppercase' as const
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const diagnosticStyle = {
|
|
106
|
+
background: '#f7f8fa',
|
|
107
|
+
border: '1px solid #d9dfe7',
|
|
108
|
+
borderRadius: 6,
|
|
109
|
+
display: 'grid',
|
|
110
|
+
gap: 8,
|
|
111
|
+
gridColumn: '1 / -1',
|
|
112
|
+
padding: 12
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function RankByValueMutationHarness() {
|
|
116
|
+
const sharedRows = useMemo<RankRow[]>(
|
|
117
|
+
() => [
|
|
118
|
+
{ category: 'Alpha', value: 30 },
|
|
119
|
+
{ category: 'Charlie', value: 10 },
|
|
120
|
+
{ category: 'Bravo', value: 20 }
|
|
121
|
+
],
|
|
122
|
+
[]
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
const [observedOrder, setObservedOrder] = useState<string>('Checking shared data order...')
|
|
126
|
+
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
const timeoutId = window.setTimeout(() => {
|
|
129
|
+
setObservedOrder(getOrder(sharedRows))
|
|
130
|
+
}, 100)
|
|
131
|
+
|
|
132
|
+
return () => window.clearTimeout(timeoutId)
|
|
133
|
+
}, [sharedRows])
|
|
134
|
+
|
|
135
|
+
const rankedConfig = useMemo(() => getConfig('Ranked by value ascending', sharedRows, 'asc'), [sharedRows])
|
|
136
|
+
const rankedExclusionConfig = useMemo(
|
|
137
|
+
() => getConfig('Ranked by value ascending with Alpha excluded', sharedRows, 'asc', ['Alpha']),
|
|
138
|
+
[sharedRows]
|
|
139
|
+
)
|
|
140
|
+
const sourceOrderConfig = useMemo(() => getConfig('Should preserve source order', sharedRows), [sharedRows])
|
|
141
|
+
const isChecking = observedOrder === 'Checking shared data order...'
|
|
142
|
+
const hasMutated = !isChecking && observedOrder !== sourceOrder
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<div
|
|
146
|
+
style={{
|
|
147
|
+
background: '#eef2f7',
|
|
148
|
+
display: 'grid',
|
|
149
|
+
gap: 16,
|
|
150
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(360px, 1fr))',
|
|
151
|
+
padding: 16
|
|
152
|
+
}}
|
|
153
|
+
>
|
|
154
|
+
<section style={panelStyle} data-rank-by-value-panel='ranked'>
|
|
155
|
+
<p style={labelStyle}>Ranked chart</p>
|
|
156
|
+
<Chart config={rankedConfig} isEditor={false} interactionLabel='' />
|
|
157
|
+
</section>
|
|
158
|
+
|
|
159
|
+
<section style={panelStyle} data-rank-by-value-panel='source-order'>
|
|
160
|
+
<p style={labelStyle}>Source-order chart sharing the same data</p>
|
|
161
|
+
<Chart config={sourceOrderConfig} isEditor={false} interactionLabel='' />
|
|
162
|
+
</section>
|
|
163
|
+
|
|
164
|
+
<section style={panelStyle} data-rank-by-value-panel='ranked-exclusion'>
|
|
165
|
+
<p style={labelStyle}>Ranked chart with Alpha excluded</p>
|
|
166
|
+
<Chart config={rankedExclusionConfig} isEditor={false} interactionLabel='' />
|
|
167
|
+
</section>
|
|
168
|
+
|
|
169
|
+
<section style={diagnosticStyle} aria-label='Shared data order diagnostic'>
|
|
170
|
+
<div>
|
|
171
|
+
<strong>Expected shared data order:</strong> <span>{sourceOrder}</span>
|
|
172
|
+
</div>
|
|
173
|
+
<div>
|
|
174
|
+
<strong>Observed shared data order:</strong>{' '}
|
|
175
|
+
<span data-testid='rank-by-value-observed-order'>{observedOrder}</span>
|
|
176
|
+
</div>
|
|
177
|
+
<div data-testid='rank-by-value-mutation-status'>
|
|
178
|
+
<strong>Status:</strong> {hasMutated ? 'Shared data was mutated' : 'Shared data order is preserved'}
|
|
179
|
+
</div>
|
|
180
|
+
</section>
|
|
181
|
+
</div>
|
|
182
|
+
)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export const Shared_Data_Order_Is_Preserved: Story = {
|
|
186
|
+
play: async ({ canvasElement }) => {
|
|
187
|
+
await assertVisualizationRendered(canvasElement)
|
|
188
|
+
|
|
189
|
+
await waitFor(() => {
|
|
190
|
+
const rankedPanel = canvasElement.querySelector('[data-rank-by-value-panel="ranked"]')
|
|
191
|
+
const sourceOrderPanel = canvasElement.querySelector('[data-rank-by-value-panel="source-order"]')
|
|
192
|
+
const rankedExclusionPanel = canvasElement.querySelector('[data-rank-by-value-panel="ranked-exclusion"]')
|
|
193
|
+
|
|
194
|
+
expect(rankedPanel?.querySelector('svg')).toBeTruthy()
|
|
195
|
+
expect(sourceOrderPanel?.querySelector('svg')).toBeTruthy()
|
|
196
|
+
expect(rankedExclusionPanel?.querySelector('svg')).toBeTruthy()
|
|
197
|
+
expect(rankedPanel ? getRenderedCategoryOrder(rankedPanel) : '').toBe(rankedOrder)
|
|
198
|
+
expect(sourceOrderPanel ? getRenderedCategoryOrder(sourceOrderPanel) : '').toBe(sourceOrder)
|
|
199
|
+
expect(rankedExclusionPanel ? getRenderedCategoryOrder(rankedExclusionPanel) : '').toBe(rankedExcludingAlphaOrder)
|
|
200
|
+
expect(canvasElement.querySelector('[data-testid="rank-by-value-observed-order"]')?.textContent).toBe(sourceOrder)
|
|
201
|
+
expect(canvasElement.querySelector('[data-testid="rank-by-value-mutation-status"]')?.textContent).toContain(
|
|
202
|
+
'Shared data order is preserved'
|
|
203
|
+
)
|
|
204
|
+
})
|
|
205
|
+
}
|
|
206
|
+
}
|