@cdc/chart 4.26.1 → 4.26.3
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/CLAUDE.local.md +79 -0
- package/LICENSE +201 -0
- package/dist/{cdcchart-dgT_1dIT.es.js → cdcchart-DQ00cQCm.es.js} +1 -20
- package/dist/cdcchart.js +54742 -49796
- package/examples/data/data-with-metadata.json +10 -0
- package/examples/default.json +378 -0
- package/examples/feature/__data__/horizon-chart-data.json +373 -0
- package/examples/feature/annotations/index.json +3 -6
- package/examples/feature/horizon/horizon-chart.json +395 -0
- package/examples/feature/pie/planet-pie-example-config.json +2 -1
- package/examples/line-chart-states.json +1085 -0
- package/examples/metadata-variables.json +58 -0
- package/examples/private/123.json +694 -0
- package/examples/private/anchor-issue.json +4094 -0
- package/examples/private/backwards-slider.json +10430 -0
- package/examples/private/georgia.csv +160 -0
- package/examples/private/timeline-data.json +1 -0
- package/examples/private/timeline.json +389 -0
- package/examples/radar-chart-simple.json +133 -0
- package/examples/radar-chart.json +148 -0
- package/index.html +1 -31
- package/package.json +57 -59
- package/src/CdcChart.tsx +8 -4
- package/src/CdcChartComponent.tsx +398 -284
- package/src/_stories/Chart.Anchors.stories.tsx +10 -0
- package/src/_stories/Chart.BoxPlot.stories.tsx +7 -0
- package/src/_stories/Chart.CI.stories.tsx +13 -0
- package/src/_stories/Chart.Combo.stories.tsx +17 -0
- package/src/_stories/Chart.CustomColors.stories.tsx +78 -0
- package/src/_stories/Chart.Defaults.stories.tsx +95 -0
- package/src/_stories/Chart.DynamicSeries.stories.tsx +19 -0
- package/src/_stories/Chart.Filters.stories.tsx +4 -0
- package/src/_stories/Chart.Forecast.stories.tsx +4 -0
- package/src/_stories/Chart.HTMLInDataTable.stories.tsx +22 -0
- package/src/_stories/Chart.Legend.Gradient.stories.tsx +28 -0
- package/src/_stories/Chart.Patterns.stories.tsx +4 -0
- package/src/_stories/Chart.PreserveDecimals.stories.tsx +25 -0
- package/src/_stories/Chart.Regions.Categorical.stories.tsx +13 -0
- package/src/_stories/Chart.Regions.DateScale.stories.tsx +19 -0
- package/src/_stories/Chart.Regions.DateTimeScale.stories.tsx +25 -10
- package/src/_stories/Chart.ScatterPlot.stories.tsx +4 -0
- package/src/_stories/Chart.SmallMultiples.stories.tsx +16 -0
- package/src/_stories/Chart.SmallestLeftAxisMax.stories.tsx +64 -0
- package/src/_stories/Chart.stories.tsx +72 -1
- package/src/_stories/Chart.tooltip.stories.tsx +7 -0
- package/src/_stories/ChartAnnotation.stories.tsx +10 -0
- package/src/_stories/ChartAxisLabels.stories.tsx +4 -0
- package/src/_stories/ChartAxisTitles.stories.tsx +10 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +97 -38
- package/src/_stories/ChartBrush.Editor.stories.tsx +11 -25
- package/src/_stories/ChartBrush.Matrix.Continuous.stories.tsx +41 -0
- package/src/_stories/ChartBrush.Matrix.Date.stories.tsx +114 -0
- package/src/_stories/ChartBrush.Matrix.DateTime.stories.tsx +78 -0
- package/src/_stories/ChartBrush.stories.tsx +7 -0
- package/src/_stories/ChartEditor.Editor.stories.tsx +1 -1
- package/src/_stories/ChartEditor.stories.tsx +7 -0
- package/src/_stories/ChartLine.QuadrantAngles.stories.tsx +89 -0
- package/src/_stories/ChartLine.Suppression.stories.tsx +7 -0
- package/src/_stories/ChartLine.Symbols.stories.tsx +4 -0
- package/src/_stories/ChartPrefixSuffix.stories.tsx +46 -1
- package/src/_stories/TechAdoptionWithLinks.stories.tsx +7 -0
- package/src/_stories/_mock/brush_continuous.json +86 -0
- package/src/_stories/_mock/brush_date_large.json +176 -0
- package/src/_stories/_mock/line_chart_angle_near_zero_fall.json +195 -0
- package/src/_stories/_mock/line_chart_angle_near_zero_rise.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q1_steep_upward.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q2_gentle_downward.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q3_steep_downward.json +195 -0
- package/src/_stories/_mock/line_chart_angle_q4_gentle_upward.json +195 -0
- package/src/_stories/_mock/line_chart_quadrant_angles.json +264 -0
- package/src/_stories/_mock/paired-bar-abbr.json +421 -0
- 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 +14 -20
- package/src/components/Annotations/components/AnnotationDraggable.tsx +240 -116
- package/src/components/Annotations/components/AnnotationDropdown.styles.css +1 -2
- package/src/components/Annotations/components/AnnotationDropdown.tsx +8 -12
- package/src/components/Annotations/components/AnnotationList.styles.css +12 -18
- package/src/components/Annotations/components/AnnotationList.tsx +5 -4
- package/src/components/Annotations/components/findNearestDatum.ts +75 -85
- package/src/components/Annotations/helpers/getVisibleAnnotations.ts +38 -0
- package/src/components/Axis/BottomAxis.tsx +277 -0
- package/src/components/Axis/LeftAxis.tsx +404 -0
- package/src/components/Axis/LeftAxisGridlines.tsx +77 -0
- package/src/components/Axis/PairedBarAxis.tsx +192 -0
- package/src/components/Axis/README.md +94 -0
- package/src/components/Axis/RightAxis.tsx +108 -0
- package/src/components/Axis/axis.constants.ts +21 -0
- package/src/components/Axis/index.ts +7 -0
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +12 -28
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +12 -30
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +12 -31
- package/src/components/BarChart/components/BarChart.Vertical.tsx +12 -28
- package/src/components/BarChart/components/BarChart.tsx +7 -1
- 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 +3 -0
- package/src/components/Brush/BrushSelector.tsx +155 -22
- package/src/components/Brush/MiniChartPreview.tsx +133 -21
- package/src/components/EditorPanel/EditorPanel.tsx +81 -54
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +67 -29
- package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +0 -78
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +120 -2
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +25 -43
- package/src/components/EditorPanel/components/Panels/Panel.Radar.tsx +353 -0
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +83 -3
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +66 -43
- package/src/components/EditorPanel/components/Panels/index.tsx +2 -0
- package/src/components/EditorPanel/editor-panel.scss +1 -1
- package/src/components/EditorPanel/useEditorPermissions.ts +55 -26
- package/src/components/ForestPlot/ForestPlot.tsx +26 -22
- package/src/components/HorizonChart/HorizonChart.tsx +131 -0
- package/src/components/HorizonChart/components/HorizonBand.tsx +160 -0
- package/src/components/HorizonChart/helpers/calculateHorizonBands.ts +27 -0
- package/src/components/HorizonChart/helpers/getHorizonLayerColors.ts +40 -0
- package/src/components/HorizonChart/index.tsx +3 -0
- package/src/components/Legend/Legend.Component.tsx +52 -4
- package/src/components/Legend/Legend.tsx +1 -1
- package/src/components/Legend/LegendGroup/LegendGroup.styles.css +4 -4
- package/src/components/Legend/LegendValueRange.tsx +77 -0
- package/src/components/Legend/helpers/createFormatLabels.tsx +16 -2
- package/src/components/Legend/helpers/generateValueRanges.ts +92 -0
- package/src/components/LineChart/helpers/README.md +292 -0
- package/src/components/LineChart/helpers/labelPositioning.test.ts +245 -0
- package/src/components/LineChart/helpers/labelPositioning.ts +304 -0
- package/src/components/LineChart/index.tsx +44 -8
- package/src/components/LinearChart/README.md +109 -0
- package/src/components/LinearChart/VisualizationRenderer.tsx +267 -0
- package/src/components/LinearChart/linearChart.constants.ts +84 -0
- package/src/components/LinearChart/tests/LinearChart.test.tsx +278 -0
- package/src/components/LinearChart/tests/mockConfigContext.ts +131 -0
- package/src/components/LinearChart/utils/tickFormatting.ts +146 -0
- package/src/components/LinearChart.tsx +268 -1057
- package/src/components/PieChart/PieChart.tsx +20 -5
- package/src/components/RadarChart/RadarAxis.tsx +78 -0
- package/src/components/RadarChart/RadarChart.tsx +298 -0
- package/src/components/RadarChart/RadarGrid.tsx +64 -0
- package/src/components/RadarChart/RadarPolygon.tsx +91 -0
- package/src/components/RadarChart/helpers.ts +83 -0
- package/src/components/RadarChart/index.tsx +3 -0
- package/src/components/Regions/components/Regions.tsx +6 -6
- package/src/components/Sankey/components/Sankey.tsx +3 -3
- package/src/components/Sankey/sankey.scss +1 -1
- package/src/components/SmallMultiples/SmallMultiples.css +5 -5
- package/src/components/Sparkline/index.scss +4 -2
- package/src/components/WarmingStripes/WarmingStripes.tsx +95 -25
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +8 -8
- package/src/data/initial-state.js +37 -15
- package/src/data/legacy-defaults.ts +18 -0
- package/src/helpers/abbreviateNumber.ts +24 -17
- package/src/helpers/getChartPatternId.ts +17 -0
- package/src/helpers/getExcludedData.ts +4 -0
- package/src/helpers/getMinMax.ts +16 -2
- package/src/helpers/handleChartAriaLabels.ts +19 -19
- package/src/helpers/handleLineType.ts +22 -18
- 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/hooks/useProgrammaticTooltip.ts +23 -2
- package/src/hooks/useRightAxis.ts +14 -0
- package/src/hooks/useScales.ts +99 -56
- package/src/hooks/useTooltip.tsx +23 -3
- package/src/scss/main.scss +157 -79
- package/src/selectors/README.md +68 -0
- package/src/store/chart.reducer.ts +2 -0
- package/src/test/CdcChart.test.jsx +2 -2
- package/src/types/ChartConfig.ts +22 -0
- package/src/types/ChartContext.ts +1 -0
- package/src/types/Horizon.ts +64 -0
- package/tests/fixtures/chart-config-with-metadata.json +29 -0
- package/tests/fixtures/data-with-metadata.json +10 -0
- package/preview.html +0 -1616
- package/src/components/Annotations/components/helpers/index.tsx +0 -46
|
@@ -5,7 +5,7 @@ import ResizeObserver from 'resize-observer-polyfill'
|
|
|
5
5
|
import 'whatwg-fetch'
|
|
6
6
|
// Core components
|
|
7
7
|
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
|
|
8
|
-
import
|
|
8
|
+
import { VisualizationContainer, VisualizationContent } from '@cdc/core/components/Layout'
|
|
9
9
|
import Confirm from '@cdc/core/components/elements/Confirm'
|
|
10
10
|
import Error from '@cdc/core/components/elements/Error'
|
|
11
11
|
import SkipTo from '@cdc/core/components/elements/SkipTo'
|
|
@@ -22,15 +22,30 @@ import { Runtime } from '@cdc/core/types/Runtime'
|
|
|
22
22
|
import { Label } from './types/Label'
|
|
23
23
|
// External Libraries
|
|
24
24
|
import ParentSize from '@visx/responsive/lib/components/ParentSize'
|
|
25
|
-
import { timeParse
|
|
25
|
+
import { timeParse } from 'd3-time-format'
|
|
26
26
|
import parse from 'html-react-parser'
|
|
27
|
-
import
|
|
27
|
+
import cloneDeep from 'lodash/cloneDeep'
|
|
28
|
+
import defaultsDeep from 'lodash/defaultsDeep'
|
|
29
|
+
import lodashDefaults from 'lodash/defaults'
|
|
30
|
+
import findKey from 'lodash/findKey'
|
|
31
|
+
import forEach from 'lodash/forEach'
|
|
32
|
+
import get from 'lodash/get'
|
|
33
|
+
import isEmpty from 'lodash/isEmpty'
|
|
34
|
+
import isEqual from 'lodash/isEqual'
|
|
35
|
+
import isString from 'lodash/isString'
|
|
36
|
+
import kebabCase from 'lodash/kebabCase'
|
|
37
|
+
import pick from 'lodash/pick'
|
|
38
|
+
import remove from 'lodash/remove'
|
|
39
|
+
import set from 'lodash/set'
|
|
40
|
+
import uniq from 'lodash/uniq'
|
|
41
|
+
import xor from 'lodash/xor'
|
|
28
42
|
// Primary Components
|
|
29
43
|
import ConfigContext, { ChartDispatchContext } from './ConfigContext'
|
|
30
44
|
import PieChart from './components/PieChart'
|
|
45
|
+
import RadarChart from './components/RadarChart'
|
|
31
46
|
import SankeyChart from './components/Sankey'
|
|
32
47
|
import LinearChart from './components/LinearChart'
|
|
33
|
-
import { isDateScale } from '@cdc/core/helpers/cove/date'
|
|
48
|
+
import { isDateScale, formatDate as coreFormatDate } from '@cdc/core/helpers/cove/date'
|
|
34
49
|
|
|
35
50
|
import { twoColorPalette } from '@cdc/core/data/colorPalettes'
|
|
36
51
|
import { filterChartColorPalettes } from '@cdc/core/helpers/filterColorPalettes'
|
|
@@ -39,6 +54,7 @@ import SparkLine from './components/Sparkline'
|
|
|
39
54
|
import Legend from './components/Legend'
|
|
40
55
|
import WarmingStripesGradientLegend from './components/WarmingStripes/WarmingStripesGradientLegend'
|
|
41
56
|
import defaults from './data/initial-state'
|
|
57
|
+
import { LEGACY_CHART_DEFAULTS } from './data/legacy-defaults'
|
|
42
58
|
import EditorPanel from './components/EditorPanel'
|
|
43
59
|
import { abbreviateNumber } from './helpers/abbreviateNumber'
|
|
44
60
|
import { handleChartTabbing } from './helpers/handleChartTabbing'
|
|
@@ -53,8 +69,10 @@ import Loading from '@cdc/core/components/Loading'
|
|
|
53
69
|
import Filters from '@cdc/core/components/Filters'
|
|
54
70
|
import MediaControls from '@cdc/core/components/MediaControls'
|
|
55
71
|
import Annotation from './components/Annotations'
|
|
72
|
+
import { getVisibleAnnotations } from './components/Annotations/helpers/getVisibleAnnotations'
|
|
56
73
|
// Core Helpers
|
|
57
74
|
import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
75
|
+
import { backfillDefaults } from '@cdc/core/helpers/backfillDefaults'
|
|
58
76
|
import { isLegendWrapViewport } from '@cdc/core/helpers/viewports'
|
|
59
77
|
import { missingRequiredSections } from '@cdc/core/helpers/missingRequiredSections'
|
|
60
78
|
import { filterVizData } from '@cdc/core/helpers/filterVizData'
|
|
@@ -88,6 +106,8 @@ import { Datasets } from '@cdc/core/types/DataSet'
|
|
|
88
106
|
import { publishAnalyticsEvent } from '@cdc/core/helpers/metrics/helpers'
|
|
89
107
|
import cloneConfig from '@cdc/core/helpers/cloneConfig'
|
|
90
108
|
import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
|
|
109
|
+
import { ENABLE_CHART_MAP_TP5_TREATMENT, ENABLE_CHART_VISUAL_SETTINGS } from '@cdc/core/helpers/constants'
|
|
110
|
+
import CalloutFlag from '@cdc/core/assets/callout-flag.svg?url'
|
|
91
111
|
|
|
92
112
|
interface CdcChartProps {
|
|
93
113
|
config?: ChartConfig
|
|
@@ -133,7 +153,8 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
133
153
|
coveLoadedEventRan,
|
|
134
154
|
imageId,
|
|
135
155
|
seriesHighlight,
|
|
136
|
-
colorScale
|
|
156
|
+
colorScale,
|
|
157
|
+
brushData
|
|
137
158
|
} = state
|
|
138
159
|
const { description, visualizationType } = config
|
|
139
160
|
const svgRef = useRef(null)
|
|
@@ -171,36 +192,32 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
171
192
|
}
|
|
172
193
|
}
|
|
173
194
|
|
|
195
|
+
const markupOptions = {
|
|
196
|
+
isEditor,
|
|
197
|
+
filters: config.filters || [],
|
|
198
|
+
locale: config.locale,
|
|
199
|
+
dataMetadata: config.dataMetadata
|
|
200
|
+
}
|
|
201
|
+
|
|
174
202
|
return {
|
|
175
203
|
title: title
|
|
176
|
-
? processMarkupVariables(title, config.data || [], config.markupVariables,
|
|
177
|
-
isEditor,
|
|
178
|
-
filters: config.filters || []
|
|
179
|
-
}).processedContent
|
|
204
|
+
? processMarkupVariables(title, config.data || [], config.markupVariables, markupOptions).processedContent
|
|
180
205
|
: title,
|
|
181
206
|
superTitle: config.superTitle
|
|
182
|
-
? processMarkupVariables(config.superTitle, config.data || [], config.markupVariables,
|
|
183
|
-
|
|
184
|
-
filters: config.filters || []
|
|
185
|
-
}).processedContent
|
|
207
|
+
? processMarkupVariables(config.superTitle, config.data || [], config.markupVariables, markupOptions)
|
|
208
|
+
.processedContent
|
|
186
209
|
: config.superTitle,
|
|
187
210
|
introText: config.introText
|
|
188
|
-
? processMarkupVariables(config.introText, config.data || [], config.markupVariables,
|
|
189
|
-
|
|
190
|
-
filters: config.filters || []
|
|
191
|
-
}).processedContent
|
|
211
|
+
? processMarkupVariables(config.introText, config.data || [], config.markupVariables, markupOptions)
|
|
212
|
+
.processedContent
|
|
192
213
|
: config.introText,
|
|
193
214
|
legacyFootnotes: config.legacyFootnotes
|
|
194
|
-
? processMarkupVariables(config.legacyFootnotes, config.data || [], config.markupVariables,
|
|
195
|
-
|
|
196
|
-
filters: config.filters || []
|
|
197
|
-
}).processedContent
|
|
215
|
+
? processMarkupVariables(config.legacyFootnotes, config.data || [], config.markupVariables, markupOptions)
|
|
216
|
+
.processedContent
|
|
198
217
|
: config.legacyFootnotes,
|
|
199
218
|
description: config.description
|
|
200
|
-
? processMarkupVariables(config.description, config.data || [], config.markupVariables,
|
|
201
|
-
|
|
202
|
-
filters: config.filters || []
|
|
203
|
-
}).processedContent
|
|
219
|
+
? processMarkupVariables(config.description, config.data || [], config.markupVariables, markupOptions)
|
|
220
|
+
.processedContent
|
|
204
221
|
: config.description
|
|
205
222
|
}
|
|
206
223
|
}, [
|
|
@@ -234,10 +251,6 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
234
251
|
const { lineDatapointClass, contentClasses, sparkLineStyles } = useDataVizClasses(config)
|
|
235
252
|
const legendId = useId()
|
|
236
253
|
|
|
237
|
-
const hasDateAxis =
|
|
238
|
-
(config.xAxis || config.yAxis) && ['date-time', 'date'].includes((config.xAxis || config.yAxis).type)
|
|
239
|
-
const dataTableDefaultSortBy = hasDateAxis && config.xAxis.dataKey
|
|
240
|
-
|
|
241
254
|
const convertLineToBarGraph = isConvertLineToBarGraph(config, filteredData)
|
|
242
255
|
|
|
243
256
|
// Declaratively calculate series keys for pie charts based on filtered data
|
|
@@ -245,7 +258,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
245
258
|
if (config.visualizationType !== 'Pie' || !config.xAxis?.dataKey) return null
|
|
246
259
|
const data = filteredData?.length > 0 ? filteredData : excludedData
|
|
247
260
|
if (!data) return null
|
|
248
|
-
return
|
|
261
|
+
return uniq(data.map(d => d[config.xAxis.dataKey]))
|
|
249
262
|
}, [config.visualizationType, config.xAxis?.dataKey, filteredData, excludedData])
|
|
250
263
|
|
|
251
264
|
const prepareConfig = (loadedConfig: ChartConfig) => {
|
|
@@ -263,16 +276,47 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
263
276
|
delete defaultsWithoutPalette.general?.palette
|
|
264
277
|
}
|
|
265
278
|
|
|
279
|
+
// Override palette defaults for Line charts specifically
|
|
280
|
+
if (loadedConfig?.visualizationType === 'Line' && !loadedConfig?.general?.palette) {
|
|
281
|
+
if (!defaultsWithoutPalette.general) {
|
|
282
|
+
defaultsWithoutPalette.general = {}
|
|
283
|
+
}
|
|
284
|
+
defaultsWithoutPalette.general.palette = {
|
|
285
|
+
isReversed: false,
|
|
286
|
+
version: '2.0',
|
|
287
|
+
name: 'divergent_blue_cyan'
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Override palette defaults for Horizon Chart specifically
|
|
292
|
+
if (loadedConfig?.visualizationType === 'Horizon Chart' && !loadedConfig?.general?.palette) {
|
|
293
|
+
if (!defaultsWithoutPalette.general) {
|
|
294
|
+
defaultsWithoutPalette.general = {}
|
|
295
|
+
}
|
|
296
|
+
defaultsWithoutPalette.general.palette = {
|
|
297
|
+
isReversed: false,
|
|
298
|
+
version: '2.0',
|
|
299
|
+
name: 'sequential_blue'
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
266
303
|
let newConfig = { ...defaultsWithoutPalette, ...loadedConfig }
|
|
267
304
|
|
|
268
|
-
|
|
305
|
+
// Ensure Horizon Chart has enough palette colors for all layers
|
|
306
|
+
if (newConfig.visualizationType === 'Horizon Chart') {
|
|
307
|
+
const numLayers = newConfig.horizon?.numLayers ?? 4
|
|
308
|
+
const currentCount = get(newConfig, 'general.paletteColorCount', 4)
|
|
309
|
+
set(newConfig, 'general.paletteColorCount', Math.max(currentCount, numLayers))
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
defaultsDeep(newConfig, {
|
|
269
313
|
table: { showVertical: false }
|
|
270
314
|
})
|
|
271
315
|
|
|
272
|
-
|
|
316
|
+
set(newConfig, 'table.show', get(newConfig, 'table.show', !isDashboard))
|
|
273
317
|
|
|
274
|
-
|
|
275
|
-
|
|
318
|
+
forEach(newConfig.series, series => {
|
|
319
|
+
lodashDefaults(series, {
|
|
276
320
|
tooltip: true,
|
|
277
321
|
axis: 'Left'
|
|
278
322
|
})
|
|
@@ -291,15 +335,18 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
291
335
|
let processedYAxis = targetConfig.yAxis?.label
|
|
292
336
|
|
|
293
337
|
if (targetConfig.enableMarkupVariables && targetConfig.markupVariables?.length) {
|
|
338
|
+
const axisMarkupOptions = {
|
|
339
|
+
isEditor,
|
|
340
|
+
filters: targetConfig.filters || [],
|
|
341
|
+
locale: targetConfig.locale,
|
|
342
|
+
dataMetadata: targetConfig.dataMetadata
|
|
343
|
+
}
|
|
294
344
|
if (targetConfig.xAxis?.label) {
|
|
295
345
|
processedXAxis = processMarkupVariables(
|
|
296
346
|
targetConfig.xAxis.label,
|
|
297
347
|
dataSource || [],
|
|
298
348
|
targetConfig.markupVariables,
|
|
299
|
-
|
|
300
|
-
isEditor,
|
|
301
|
-
filters: targetConfig.filters || []
|
|
302
|
-
}
|
|
349
|
+
axisMarkupOptions
|
|
303
350
|
).processedContent
|
|
304
351
|
}
|
|
305
352
|
if (targetConfig.yAxis?.label) {
|
|
@@ -307,10 +354,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
307
354
|
targetConfig.yAxis.label,
|
|
308
355
|
dataSource || [],
|
|
309
356
|
targetConfig.markupVariables,
|
|
310
|
-
|
|
311
|
-
isEditor,
|
|
312
|
-
filters: targetConfig.filters || []
|
|
313
|
-
}
|
|
357
|
+
axisMarkupOptions
|
|
314
358
|
).processedContent
|
|
315
359
|
}
|
|
316
360
|
}
|
|
@@ -342,12 +386,17 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
342
386
|
const { processedXAxis, processedYAxis, runtimeXAxisLabel, runtimeYAxisLabel, isHorizontalVariant } =
|
|
343
387
|
getProcessedAxisLabels(newConfig, data || [])
|
|
344
388
|
|
|
345
|
-
//
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
389
|
+
// Backfill missing properties from defaults, respecting legacy values
|
|
390
|
+
backfillDefaults(newConfig, defaults, LEGACY_CHART_DEFAULTS)
|
|
391
|
+
|
|
392
|
+
// Auto-populate table.defaultSort for date-axis charts if not already set by user
|
|
393
|
+
const hasDateAxisType = ['date-time', 'date'].includes(newConfig.xAxis?.type)
|
|
394
|
+
if (hasDateAxisType && newConfig.xAxis?.dataKey && !newConfig.table?.defaultSort?.column) {
|
|
395
|
+
newConfig.table = {
|
|
396
|
+
...newConfig.table,
|
|
397
|
+
defaultSort: { column: newConfig.xAxis.dataKey, sortDirection: 'desc' }
|
|
349
398
|
}
|
|
350
|
-
}
|
|
399
|
+
}
|
|
351
400
|
|
|
352
401
|
const newExcludedData: any[] = getExcludedData(newConfig, dataOverride || stateData)
|
|
353
402
|
dispatch({ type: 'SET_EXCLUDED_DATA', payload: newExcludedData })
|
|
@@ -374,7 +423,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
374
423
|
const shouldPreserveError = existingErrorMessage && !isPieChartValidationError
|
|
375
424
|
|
|
376
425
|
newConfig.runtime = {} as Runtime
|
|
377
|
-
newConfig.runtime.series =
|
|
426
|
+
newConfig.runtime.series = cloneDeep(newConfig.series)
|
|
378
427
|
newConfig.runtime.seriesLabels = {}
|
|
379
428
|
newConfig.runtime.seriesLabelsAll = []
|
|
380
429
|
newConfig.runtime.originalXAxis = newConfig.xAxis
|
|
@@ -382,17 +431,22 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
382
431
|
if (newConfig.visualizationType === 'Pie') {
|
|
383
432
|
// Use the same data that will be passed to PieChart (after exclusions and filters)
|
|
384
433
|
const pieData = currentData.length > 0 ? currentData : newExcludedData
|
|
385
|
-
newConfig.runtime.seriesKeys =
|
|
434
|
+
newConfig.runtime.seriesKeys = uniq(pieData.map(d => d[newConfig.xAxis.dataKey]))
|
|
386
435
|
newConfig.runtime.seriesLabelsAll = newConfig.runtime.seriesKeys
|
|
387
436
|
newConfig.runtime.isPieChart = true // Flag to know when to use derived keys
|
|
437
|
+
} else if (newConfig.visualizationType === 'Radar') {
|
|
438
|
+
// Radar chart: seriesKeys are the entity names from xAxis.dataKey
|
|
439
|
+
const radarData = currentData.length > 0 ? currentData : newExcludedData
|
|
440
|
+
newConfig.runtime.seriesKeys = uniq(radarData.map(d => d[newConfig.xAxis.dataKey]))
|
|
441
|
+
newConfig.runtime.seriesLabelsAll = newConfig.runtime.seriesKeys
|
|
388
442
|
} else {
|
|
389
443
|
const finalData = dataOverride || newConfig.formattedData || newConfig.data
|
|
390
444
|
newConfig.runtime.seriesKeys = (newConfig.runtime.series || []).flatMap(series => {
|
|
391
445
|
if (series.dynamicCategory) {
|
|
392
|
-
|
|
393
|
-
|
|
446
|
+
remove(newConfig.runtime.seriesLabelsAll, label => label === series.dataKey)
|
|
447
|
+
remove(newConfig.runtime.series, s => s.dataKey === series.dataKey)
|
|
394
448
|
// grab the dynamic series keys from the data
|
|
395
|
-
const seriesKeys: string[] =
|
|
449
|
+
const seriesKeys: string[] = uniq(finalData.map(d => d[series.dynamicCategory]))
|
|
396
450
|
// for each of those keys perform side effects
|
|
397
451
|
seriesKeys.forEach(dataKey => {
|
|
398
452
|
newConfig.runtime.seriesLabels[dataKey] = dataKey
|
|
@@ -458,10 +512,26 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
458
512
|
newConfig.visualizationSubType = 'stacked'
|
|
459
513
|
}
|
|
460
514
|
|
|
515
|
+
if (newConfig.visualizationType === 'Horizon Chart' && newConfig.series) {
|
|
516
|
+
// Apply horizon defaults if not set
|
|
517
|
+
newConfig.horizon = {
|
|
518
|
+
numLayers: 4,
|
|
519
|
+
mode: 'offset', // Always offset for now, mirror hidden from UI
|
|
520
|
+
bandGap: 15,
|
|
521
|
+
bottomPadding: 15,
|
|
522
|
+
...newConfig.horizon
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Set categorical as default xAxis type for horizon charts if not already set
|
|
526
|
+
if (!newConfig.xAxis.type) {
|
|
527
|
+
newConfig.xAxis.type = 'categorical'
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
461
531
|
if (isHorizontalVariant) {
|
|
462
532
|
// For horizontal charts, axes are swapped, so processedYAxis goes to runtime.xAxis and vice versa
|
|
463
|
-
const horizontalXAxisSource =
|
|
464
|
-
const horizontalYAxisSource =
|
|
533
|
+
const horizontalXAxisSource = cloneDeep((newConfig.yAxis as any)?.yAxis || newConfig.yAxis)
|
|
534
|
+
const horizontalYAxisSource = cloneDeep((newConfig.xAxis as any)?.xAxis || newConfig.xAxis)
|
|
465
535
|
newConfig.runtime.xAxis = {
|
|
466
536
|
...horizontalXAxisSource,
|
|
467
537
|
label: runtimeXAxisLabel ?? horizontalXAxisSource?.label
|
|
@@ -604,7 +674,8 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
604
674
|
if (newConfig.dataUrl && !urlFilters) {
|
|
605
675
|
// handle urls with spaces in the name.
|
|
606
676
|
if (newConfig.dataUrl) newConfig.dataUrl = `${newConfig.dataUrl}`
|
|
607
|
-
let newData = await fetchRemoteData(newConfig.dataUrl)
|
|
677
|
+
let { data: newData, dataMetadata } = await fetchRemoteData(newConfig.dataUrl)
|
|
678
|
+
newConfig.dataMetadata = dataMetadata
|
|
608
679
|
|
|
609
680
|
if (newConfig.vegaConfig) {
|
|
610
681
|
newData = extractCoveData(updateVegaData(newConfig.vegaConfig, newData))
|
|
@@ -618,7 +689,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
618
689
|
if (newData) {
|
|
619
690
|
newConfig.data = newData
|
|
620
691
|
}
|
|
621
|
-
} else if (newConfig.formattedData) {
|
|
692
|
+
} else if (newConfig.formattedData && Array.isArray(newConfig.formattedData)) {
|
|
622
693
|
newConfig.data = newConfig.formattedData
|
|
623
694
|
} else if (newConfig.dataDescription) {
|
|
624
695
|
// For dashboard contexts, get data from datasets if config.data is undefined
|
|
@@ -654,7 +725,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
654
725
|
updateConfig(preparedConfig, preppedData.data)
|
|
655
726
|
}
|
|
656
727
|
} catch (err) {
|
|
657
|
-
console.error('Could not Load!')
|
|
728
|
+
console.error('Could not Load!', err)
|
|
658
729
|
}
|
|
659
730
|
}
|
|
660
731
|
|
|
@@ -665,7 +736,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
665
736
|
* When cove has a config and container ref publish the cove_loaded event.
|
|
666
737
|
*/
|
|
667
738
|
useEffect(() => {
|
|
668
|
-
if (container && !isLoading && !
|
|
739
|
+
if (container && !isLoading && !isEmpty(config) && !coveLoadedEventRan) {
|
|
669
740
|
publish('cove_loaded', { config: config })
|
|
670
741
|
dispatch({ type: 'SET_LOADED_EVENT', payload: true })
|
|
671
742
|
}
|
|
@@ -720,7 +791,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
720
791
|
}, [externalFilters]) // eslint-disable-line
|
|
721
792
|
|
|
722
793
|
// Declaratively update runtime series keys for pie charts when derived value changes
|
|
723
|
-
if (config.runtime?.isPieChart && pieSeriesKeys && !
|
|
794
|
+
if (config.runtime?.isPieChart && pieSeriesKeys && !isEqual(pieSeriesKeys, config.runtime?.seriesKeys)) {
|
|
724
795
|
const newConfig = {
|
|
725
796
|
...config,
|
|
726
797
|
runtime: {
|
|
@@ -746,11 +817,21 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
746
817
|
}
|
|
747
818
|
}, [config, stateData]) // eslint-disable-line
|
|
748
819
|
|
|
820
|
+
// Clear brush selection when brush slider is disabled
|
|
821
|
+
useEffect(() => {
|
|
822
|
+
const isBrushDisabled = !config?.xAxis?.brushActive
|
|
823
|
+
const hasBrushData = Array.isArray(brushData) && brushData.length > 0
|
|
824
|
+
|
|
825
|
+
if (isBrushDisabled && hasBrushData) {
|
|
826
|
+
dispatch({ type: 'SET_BRUSH_DATA', payload: [] })
|
|
827
|
+
}
|
|
828
|
+
}, [config?.xAxis?.brushActive, brushData])
|
|
829
|
+
|
|
749
830
|
// Updates runtime axis labels when config or data changes when using markup variables
|
|
750
831
|
useEffect(() => {
|
|
751
832
|
if (
|
|
752
833
|
!config?.runtime ||
|
|
753
|
-
|
|
834
|
+
isEmpty(config.runtime) ||
|
|
754
835
|
(!config.runtime.xAxis && !config.runtime.yAxis) ||
|
|
755
836
|
!config.markupVariables?.length
|
|
756
837
|
) {
|
|
@@ -760,7 +841,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
760
841
|
const dataSource = (stateData && stateData.length ? stateData : config.data) || []
|
|
761
842
|
const { runtimeXAxisLabel, runtimeYAxisLabel, isHorizontalVariant } = getProcessedAxisLabels(config, dataSource)
|
|
762
843
|
|
|
763
|
-
const runtimeClone =
|
|
844
|
+
const runtimeClone = cloneDeep(config.runtime)
|
|
764
845
|
|
|
765
846
|
if (!runtimeClone?.xAxis || !runtimeClone?.yAxis) {
|
|
766
847
|
return
|
|
@@ -799,9 +880,9 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
799
880
|
return handleShowAll()
|
|
800
881
|
}
|
|
801
882
|
|
|
802
|
-
const newHighlight =
|
|
883
|
+
const newHighlight = findKey(config.runtime.seriesLabels, v => v === label.datum) || label.datum
|
|
803
884
|
|
|
804
|
-
const newSeriesHighlight =
|
|
885
|
+
const newSeriesHighlight = xor(seriesHighlight, [newHighlight])
|
|
805
886
|
dispatch({ type: 'SET_SERIES_HIGHLIGHT', payload: newSeriesHighlight })
|
|
806
887
|
}
|
|
807
888
|
// Called on reset button click, unhighlights all data series
|
|
@@ -844,15 +925,11 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
844
925
|
const formatDate = (date, i, ticks) => {
|
|
845
926
|
const displayFormat =
|
|
846
927
|
config.runtime[section].dateDisplayFormat || config.runtime[section].dateParseFormat || '%Y-%m-%d'
|
|
847
|
-
let formattedDate =
|
|
848
|
-
// Handle the case where all months work with '%b.' except for May
|
|
849
|
-
if (displayFormat?.includes('%b.') && formattedDate.includes('May.')) {
|
|
850
|
-
formattedDate = formattedDate.replace(/May\./g, 'May')
|
|
851
|
-
}
|
|
928
|
+
let formattedDate = coreFormatDate(displayFormat, date, config.locale)
|
|
852
929
|
// Show years only once
|
|
853
930
|
if (config.xAxis.showYearsOnce && displayFormat?.includes('%Y') && ticks) {
|
|
854
931
|
const prevDate = ticks[i - 1] ? ticks[i - 1].value : null
|
|
855
|
-
const prevFormattedDate =
|
|
932
|
+
const prevFormattedDate = coreFormatDate(displayFormat, prevDate, config.locale)
|
|
856
933
|
const year = formattedDate.match(/\d{4}/)
|
|
857
934
|
const prevYear = prevFormattedDate.match(/\d{4}/)
|
|
858
935
|
if (year && prevYear && year[0] === prevYear[0]) {
|
|
@@ -863,7 +940,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
863
940
|
}
|
|
864
941
|
|
|
865
942
|
const formatTooltipsDate = date => {
|
|
866
|
-
return
|
|
943
|
+
return coreFormatDate(config.tooltips.dateDisplayFormat, date, config.locale)
|
|
867
944
|
}
|
|
868
945
|
|
|
869
946
|
// Format numeric data based on settings in config OR from passed in settings for Additional Columns
|
|
@@ -1005,16 +1082,16 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1005
1082
|
) {
|
|
1006
1083
|
num = num // eslint-disable-line
|
|
1007
1084
|
} else {
|
|
1008
|
-
num = num.toLocaleString(
|
|
1085
|
+
num = num.toLocaleString(config.locale, stringFormattingOptions)
|
|
1009
1086
|
}
|
|
1010
1087
|
let result = ''
|
|
1011
1088
|
|
|
1012
1089
|
if (abbreviated && axis === 'left' && shouldAbbreviate) {
|
|
1013
|
-
num = abbreviateNumber(parseFloat(num))
|
|
1090
|
+
num = abbreviateNumber(parseFloat(num), config.locale)
|
|
1014
1091
|
}
|
|
1015
1092
|
|
|
1016
1093
|
if (bottomAbbreviated && axis === 'bottom' && shouldAbbreviate) {
|
|
1017
|
-
num = abbreviateNumber(parseFloat(num))
|
|
1094
|
+
num = abbreviateNumber(parseFloat(num), config.locale)
|
|
1018
1095
|
}
|
|
1019
1096
|
|
|
1020
1097
|
if (addColPrefix && axis === 'left') {
|
|
@@ -1082,8 +1159,8 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1082
1159
|
if (!Array.isArray(data)) return []
|
|
1083
1160
|
if (config.visualizationType === 'Forecasting') return data
|
|
1084
1161
|
// specify keys that needs to be cleaned to render chart and skip rest
|
|
1085
|
-
const CIkeys: string[] = Object.values(
|
|
1086
|
-
const seriesKeys: string[] =
|
|
1162
|
+
const CIkeys: string[] = Object.values(get(config, 'confidenceKeys', {})) as string[]
|
|
1163
|
+
const seriesKeys: string[] = get(config, 'series', []).map((s: any) => s.dataKey)
|
|
1087
1164
|
const keysToClean: string[] = [...(seriesKeys ?? []), ...(CIkeys ?? [])]
|
|
1088
1165
|
|
|
1089
1166
|
// key that does not need to be cleaned
|
|
@@ -1105,7 +1182,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1105
1182
|
.map(col => col.name)
|
|
1106
1183
|
.concat([dynamicSeries.dynamicCategory, dynamicSeries.dataKey])
|
|
1107
1184
|
if (config.xAxis?.dataKey) usedColumns.push(config.xAxis.dataKey)
|
|
1108
|
-
return data.map(d =>
|
|
1185
|
+
return data.map(d => pick(d, usedColumns))
|
|
1109
1186
|
}
|
|
1110
1187
|
|
|
1111
1188
|
const pivotDynamicSeries = (config: ChartConfig): TableConfig => {
|
|
@@ -1118,17 +1195,56 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1118
1195
|
return tableConfig
|
|
1119
1196
|
}
|
|
1120
1197
|
|
|
1198
|
+
// Transform and clean data for chart rendering
|
|
1199
|
+
const transformedData = getTransformedData({ brushData: state.brushData, filteredData, excludedData, clean })
|
|
1200
|
+
|
|
1201
|
+
// Filter annotations to only those visible in current data view
|
|
1202
|
+
const visibleAnnotations = getVisibleAnnotations(config.annotations, transformedData, config.xAxis?.dataKey)
|
|
1203
|
+
const isTp5Treatment = ENABLE_CHART_MAP_TP5_TREATMENT && config.visual?.tp5Treatment
|
|
1204
|
+
const visualSettingClasses = new Set([
|
|
1205
|
+
'component--has-border-color-theme',
|
|
1206
|
+
'component--has-accent',
|
|
1207
|
+
'component--has-background',
|
|
1208
|
+
'component--hide-background-color'
|
|
1209
|
+
])
|
|
1210
|
+
const tp5Classes = new Set(['component--tp5-treatment', 'component--tp5-treatment-background'])
|
|
1211
|
+
const bodyClasses = contentClasses.filter(className => {
|
|
1212
|
+
if (!ENABLE_CHART_VISUAL_SETTINGS && visualSettingClasses.has(className)) return false
|
|
1213
|
+
if (!ENABLE_CHART_MAP_TP5_TREATMENT && tp5Classes.has(className)) return false
|
|
1214
|
+
return true
|
|
1215
|
+
})
|
|
1216
|
+
if (config.visualizationType === 'Spark Line' && config.visual?.background) {
|
|
1217
|
+
bodyClasses.push('component--has-background')
|
|
1218
|
+
}
|
|
1219
|
+
if (config.visualizationType === 'Spark Line' && config.visual?.hideBackgroundColor) {
|
|
1220
|
+
bodyClasses.push('component--hide-background-color')
|
|
1221
|
+
}
|
|
1222
|
+
if (isTp5Treatment && !bodyClasses.includes('no-borders')) bodyClasses.push('no-borders')
|
|
1223
|
+
const chartTitle = (
|
|
1224
|
+
<Title
|
|
1225
|
+
showTitle={config.showTitle}
|
|
1226
|
+
isDashboard={isDashboard}
|
|
1227
|
+
title={title}
|
|
1228
|
+
superTitle={processedSuperTitle}
|
|
1229
|
+
titleStyle={isTp5Treatment ? 'small' : config.titleStyle}
|
|
1230
|
+
classes={['chart-title', `${config.theme}`, 'cove-visualization__title', isTp5Treatment ? '' : 'mb-3']}
|
|
1231
|
+
style={undefined}
|
|
1232
|
+
config={config}
|
|
1233
|
+
/>
|
|
1234
|
+
)
|
|
1235
|
+
|
|
1121
1236
|
// Prevent render if loading
|
|
1122
1237
|
let body = <Loading />
|
|
1123
1238
|
|
|
1124
1239
|
const makeClassName = string => {
|
|
1125
|
-
if (!
|
|
1240
|
+
if (!isString(string)) return undefined
|
|
1126
1241
|
|
|
1127
|
-
return
|
|
1242
|
+
return kebabCase(string)
|
|
1128
1243
|
}
|
|
1129
1244
|
const getChartWrapperClasses = () => {
|
|
1130
1245
|
const isLegendOnBottom = legend?.position === 'bottom' || isLegendWrapViewport(currentViewport)
|
|
1131
|
-
const classes = ['chart-container', 'p-relative']
|
|
1246
|
+
const classes = ['chart-container', 'visualization-container', 'p-relative']
|
|
1247
|
+
const visualSettingClasses = ['component--has-border-color-theme', 'component--has-accent']
|
|
1132
1248
|
if (legend?.position) {
|
|
1133
1249
|
if (isLegendWrapViewport(currentViewport) && legend?.position !== 'top') {
|
|
1134
1250
|
classes.push('legend-bottom')
|
|
@@ -1137,16 +1253,23 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1137
1253
|
}
|
|
1138
1254
|
}
|
|
1139
1255
|
if (legend?.hide) classes.push('legend-hidden')
|
|
1256
|
+
if (contentClasses.includes('sparkline')) classes.push('sparkline')
|
|
1140
1257
|
if (lineDatapointClass) classes.push(lineDatapointClass)
|
|
1141
1258
|
if (!config.barHasBorder) classes.push('chart-bar--no-border')
|
|
1142
1259
|
if (config.xAxis.brushActive && dashboardConfig?.type === 'dashboard' && (!isLegendOnBottom || legend.hide))
|
|
1143
1260
|
classes.push('dashboard-brush')
|
|
1144
|
-
|
|
1261
|
+
|
|
1262
|
+
if (!ENABLE_CHART_VISUAL_SETTINGS) {
|
|
1263
|
+
const filtered = classes.filter(className => !visualSettingClasses.includes(className))
|
|
1264
|
+
if (!filtered.includes('no-borders')) filtered.push('no-borders')
|
|
1265
|
+
return filtered
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1145
1268
|
return classes
|
|
1146
1269
|
}
|
|
1147
1270
|
|
|
1148
1271
|
const getChartSubTextClasses = () => {
|
|
1149
|
-
const classes = ['subtext
|
|
1272
|
+
const classes = ['subtext']
|
|
1150
1273
|
const isLegendOnBottom = legend?.position === 'bottom' || isLegendWrapViewport(currentViewport)
|
|
1151
1274
|
|
|
1152
1275
|
if (config.isResponsiveTicks) classes.push('subtext--responsive-ticks ')
|
|
@@ -1161,198 +1284,34 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1161
1284
|
)
|
|
1162
1285
|
body = (
|
|
1163
1286
|
<>
|
|
1164
|
-
{
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
const hasError = errorMessage && typeof errorMessage === 'string' && errorMessage.trim() !== ''
|
|
1190
|
-
const shouldShow = undefined === config.newViz && isEditor && config.runtime && hasError
|
|
1191
|
-
return shouldShow ? <Error errorMessage={errorMessage} /> : null
|
|
1192
|
-
})()} */}
|
|
1193
|
-
|
|
1194
|
-
{/* Visualization Wrapper */}
|
|
1195
|
-
<div className={getChartWrapperClasses().join(' ')}>
|
|
1196
|
-
{/* Intro Text/Message */}
|
|
1197
|
-
{processedIntroText && config.visualizationType !== 'Spark Line' && (
|
|
1198
|
-
<section className={`introText mb-4`}>{parse(processedIntroText)}</section>
|
|
1199
|
-
)}
|
|
1200
|
-
|
|
1201
|
-
{/* Filters */}
|
|
1202
|
-
{config.filters && !externalFilters && config.visualizationType !== 'Spark Line' && (
|
|
1203
|
-
<Filters
|
|
1204
|
-
config={config}
|
|
1205
|
-
setFilters={setFilters}
|
|
1206
|
-
excludedData={excludedData}
|
|
1207
|
-
dimensions={dimensions}
|
|
1208
|
-
interactionLabel={interactionLabel}
|
|
1209
|
-
/>
|
|
1210
|
-
)}
|
|
1211
|
-
<SkipTo skipId={handleChartTabbing(config, legendId)} skipMessage='Skip Over Chart Container' />
|
|
1212
|
-
{config.annotations?.length > 0 && (
|
|
1213
|
-
<SkipTo
|
|
1214
|
-
skipId={handleChartTabbing(config, legendId)}
|
|
1215
|
-
skipMessage={`Skip over annotations`}
|
|
1216
|
-
key={`skip-annotations`}
|
|
1217
|
-
/>
|
|
1218
|
-
)}
|
|
1219
|
-
<LegendWrapper>
|
|
1220
|
-
<div
|
|
1221
|
-
className={
|
|
1222
|
-
legend.hide || isLegendWrapViewport(currentViewport)
|
|
1223
|
-
? 'w-100'
|
|
1224
|
-
: legend.position === 'bottom' ||
|
|
1225
|
-
legend.position === 'top' ||
|
|
1226
|
-
visualizationType === 'Sankey' ||
|
|
1227
|
-
visualizationType === 'Spark Line'
|
|
1228
|
-
? 'w-100'
|
|
1229
|
-
: 'w-75'
|
|
1230
|
-
}
|
|
1231
|
-
>
|
|
1232
|
-
{/* Check if there is data to display */}
|
|
1233
|
-
{(!filteredData || filteredData.length === 0) && (
|
|
1234
|
-
<div className='no-data-message' style={{ padding: '2rem', textAlign: 'center', color: '#666' }}>
|
|
1235
|
-
{config.chartMessage?.noData || 'No Data Available'}
|
|
1236
|
-
</div>
|
|
1237
|
-
)}
|
|
1238
|
-
|
|
1239
|
-
{/* All charts with LinearChart */}
|
|
1240
|
-
{filteredData &&
|
|
1241
|
-
filteredData.length > 0 &&
|
|
1242
|
-
!['Spark Line', 'Line', 'Sankey', 'Pie', 'Sankey'].includes(config.visualizationType) && (
|
|
1243
|
-
<div ref={parentRef} style={{ width: `100%` }}>
|
|
1244
|
-
<ParentSize>
|
|
1245
|
-
{parent => (
|
|
1246
|
-
<LinearChart ref={svgRef} parentWidth={parent.width} parentHeight={parent.height} />
|
|
1247
|
-
)}
|
|
1248
|
-
</ParentSize>
|
|
1249
|
-
</div>
|
|
1250
|
-
)}
|
|
1251
|
-
|
|
1252
|
-
{filteredData && filteredData.length > 0 && config.visualizationType === 'Pie' && (
|
|
1253
|
-
<ParentSize className='justify-content-center d-flex' style={{ width: `100%` }}>
|
|
1254
|
-
{parent => (
|
|
1255
|
-
<PieChart
|
|
1256
|
-
ref={svgRef}
|
|
1257
|
-
parentWidth={parent.width}
|
|
1258
|
-
parentHeight={parent.height}
|
|
1259
|
-
interactionLabel={interactionLabel}
|
|
1260
|
-
/>
|
|
1261
|
-
)}
|
|
1262
|
-
</ParentSize>
|
|
1263
|
-
)}
|
|
1264
|
-
{/* Line Chart */}
|
|
1265
|
-
{filteredData &&
|
|
1266
|
-
filteredData.length > 0 &&
|
|
1267
|
-
config.visualizationType === 'Line' &&
|
|
1268
|
-
(convertLineToBarGraph ? (
|
|
1269
|
-
<div ref={parentRef} style={{ width: `100%` }}>
|
|
1270
|
-
<ParentSize>
|
|
1271
|
-
{parent => (
|
|
1272
|
-
<LinearChart ref={svgRef} parentWidth={parent.width} parentHeight={parent.height} />
|
|
1273
|
-
)}
|
|
1274
|
-
</ParentSize>
|
|
1275
|
-
</div>
|
|
1276
|
-
) : (
|
|
1277
|
-
<div ref={parentRef} style={{ width: '100%' }}>
|
|
1278
|
-
<ParentSize>
|
|
1279
|
-
{parent => {
|
|
1280
|
-
const labelMargin = 120
|
|
1281
|
-
const widthReduction =
|
|
1282
|
-
config.showLineSeriesLabels &&
|
|
1283
|
-
(config.legend.position !== 'right' || config.legend.hide)
|
|
1284
|
-
? labelMargin
|
|
1285
|
-
: 0
|
|
1286
|
-
return (
|
|
1287
|
-
<LinearChart
|
|
1288
|
-
ref={svgRef}
|
|
1289
|
-
parentWidth={parent.width - widthReduction}
|
|
1290
|
-
parentHeight={parent.height}
|
|
1291
|
-
/>
|
|
1292
|
-
)
|
|
1293
|
-
}}
|
|
1294
|
-
</ParentSize>
|
|
1295
|
-
</div>
|
|
1296
|
-
))}
|
|
1297
|
-
{/* Sparkline */}
|
|
1298
|
-
{config.visualizationType === 'Spark Line' && (
|
|
1299
|
-
<>
|
|
1300
|
-
<Filters
|
|
1301
|
-
config={config}
|
|
1302
|
-
setFilters={setFilters}
|
|
1303
|
-
excludedData={excludedData}
|
|
1304
|
-
dimensions={dimensions}
|
|
1305
|
-
interactionLabel={interactionLabel}
|
|
1306
|
-
/>
|
|
1307
|
-
{processedIntroText && (
|
|
1308
|
-
<section className='introText mb-4' style={{ padding: '0px 0 35px' }}>
|
|
1309
|
-
{parse(processedIntroText)}
|
|
1310
|
-
</section>
|
|
1311
|
-
)}
|
|
1312
|
-
<div style={{ height: `100px`, width: `100%`, ...sparkLineStyles }}>
|
|
1313
|
-
<ParentSize>{parent => <SparkLine width={parent.width} height={parent.height} />}</ParentSize>
|
|
1314
|
-
</div>
|
|
1315
|
-
{description && (
|
|
1316
|
-
<div className='subtext' style={{ padding: '35px 0 15px' }}>
|
|
1317
|
-
{parse(description)}
|
|
1318
|
-
</div>
|
|
1319
|
-
)}
|
|
1320
|
-
</>
|
|
1321
|
-
)}
|
|
1322
|
-
{/* Sankey */}
|
|
1323
|
-
{config.visualizationType === 'Sankey' && (
|
|
1324
|
-
<ParentSize aria-hidden='true'>
|
|
1325
|
-
{parent => <SankeyChart runtime={config.runtime} width={parent.width} height={parent.height} />}
|
|
1326
|
-
</ParentSize>
|
|
1327
|
-
)}
|
|
1328
|
-
</div>
|
|
1329
|
-
{/* Legend */}
|
|
1330
|
-
{!config.legend.hide &&
|
|
1331
|
-
config.visualizationType !== 'Spark Line' &&
|
|
1332
|
-
config.visualizationType !== 'Sankey' &&
|
|
1333
|
-
!(config.visualizationType === 'Warming Stripes' && config.legend?.style === 'gradient') &&
|
|
1334
|
-
!(config.visualizationType === 'Warming Stripes' && config.smallMultiples?.mode) && (
|
|
1335
|
-
<Legend
|
|
1336
|
-
ref={legendRef}
|
|
1337
|
-
skipId={handleChartTabbing(config, legendId)}
|
|
1338
|
-
interactionLabel={interactionLabel}
|
|
1339
|
-
/>
|
|
1340
|
-
)}
|
|
1341
|
-
{config.visualizationType === 'Warming Stripes' &&
|
|
1342
|
-
config.legend?.style === 'gradient' &&
|
|
1343
|
-
!config.smallMultiples?.mode && <WarmingStripesGradientLegend />}
|
|
1344
|
-
</LegendWrapper>
|
|
1345
|
-
{/* Link */}
|
|
1287
|
+
{config.newViz && <Confirm updateConfig={updateConfig} config={config} />}
|
|
1288
|
+
{!missingRequiredSections(config) && !config.newViz && (
|
|
1289
|
+
<VisualizationContent
|
|
1290
|
+
innerClassName={`type-${makeClassName(config.visualizationType)}`}
|
|
1291
|
+
innerProps={{ 'aria-label': handleChartAriaLabels(config), tabIndex: 0 }}
|
|
1292
|
+
bodyClassName={bodyClasses.join(' ')}
|
|
1293
|
+
bodyWrapClassName={isTp5Treatment ? 'cdc-callout d-flex flex-column tp5-chart-callout' : ''}
|
|
1294
|
+
filters={
|
|
1295
|
+
config.filters?.length > 0 && !externalFilters && config.visualizationType !== 'Spark Line' ? (
|
|
1296
|
+
<Filters
|
|
1297
|
+
config={config}
|
|
1298
|
+
setFilters={setFilters}
|
|
1299
|
+
excludedData={excludedData}
|
|
1300
|
+
dimensions={dimensions}
|
|
1301
|
+
interactionLabel={interactionLabel}
|
|
1302
|
+
/>
|
|
1303
|
+
) : undefined
|
|
1304
|
+
}
|
|
1305
|
+
bodySubtext={
|
|
1306
|
+
processedDescription && config.visualizationType !== 'Spark Line' ? (
|
|
1307
|
+
<div className={getChartSubTextClasses().join(' ')}>{parse(processedDescription)}</div>
|
|
1308
|
+
) : null
|
|
1309
|
+
}
|
|
1310
|
+
bodyFooter={
|
|
1311
|
+
<>
|
|
1346
1312
|
{isDashboard && config.table && config.table.show && config.table.showDataTableLink
|
|
1347
1313
|
? tableLink
|
|
1348
1314
|
: link && link}
|
|
1349
|
-
{/* Description */}
|
|
1350
|
-
|
|
1351
|
-
{processedDescription && config.visualizationType !== 'Spark Line' && (
|
|
1352
|
-
<div className={getChartSubTextClasses().join(' ')}>{parse(processedDescription)}</div>
|
|
1353
|
-
)}
|
|
1354
|
-
|
|
1355
|
-
{/* Data Table */}
|
|
1356
1315
|
{(config.xAxis.dataKey &&
|
|
1357
1316
|
config.table.show &&
|
|
1358
1317
|
config.visualizationType !== 'Spark Line' &&
|
|
@@ -1381,15 +1340,12 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1381
1340
|
|
|
1382
1341
|
return (
|
|
1383
1342
|
<DataTable
|
|
1384
|
-
|
|
1385
|
-
when the default sort changes while editing */
|
|
1386
|
-
key={dataTableDefaultSortBy}
|
|
1343
|
+
key={config.table?.defaultSort?.column || ''}
|
|
1387
1344
|
config={dataTableConfig}
|
|
1388
1345
|
rawData={dataTableRawData}
|
|
1389
1346
|
runtimeData={dataTableRuntimeData}
|
|
1390
1347
|
expandDataTable={config.table.expanded}
|
|
1391
1348
|
columns={dataTableColumns}
|
|
1392
|
-
defaultSortBy={dataTableDefaultSortBy}
|
|
1393
1349
|
displayGeoName={name => name}
|
|
1394
1350
|
applyLegendToRow={applyLegendToRow}
|
|
1395
1351
|
tableTitle={config.table.label}
|
|
@@ -1402,6 +1358,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1402
1358
|
showDownloadImgButton={config.table.showDownloadImgButton}
|
|
1403
1359
|
showDownloadPdfButton={config.table.showDownloadPdfButton}
|
|
1404
1360
|
includeContextInDownload={config.table?.includeContextInDownload}
|
|
1361
|
+
hasSubtextAbove={Boolean(processedDescription && config.visualizationType !== 'Spark Line')}
|
|
1405
1362
|
interactionLabel={interactionLabel}
|
|
1406
1363
|
/>
|
|
1407
1364
|
)
|
|
@@ -1432,22 +1389,178 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1432
1389
|
</MediaControls.Section>
|
|
1433
1390
|
</div>
|
|
1434
1391
|
)}
|
|
1435
|
-
{
|
|
1436
|
-
{/* show pdf or image button */}
|
|
1392
|
+
{visibleAnnotations.length > 0 && <Annotation.Dropdown />}
|
|
1437
1393
|
{processedLegacyFootnotes && (
|
|
1438
1394
|
<section className='footnotes pt-2 mt-4'>{parse(processedLegacyFootnotes)}</section>
|
|
1439
1395
|
)}
|
|
1440
|
-
|
|
1396
|
+
</>
|
|
1397
|
+
}
|
|
1398
|
+
header={isTp5Treatment ? null : chartTitle}
|
|
1399
|
+
messageIsIntroText={config.visualizationType !== 'Spark Line' && !!processedIntroText}
|
|
1400
|
+
message={config.visualizationType !== 'Spark Line' && processedIntroText ? parse(processedIntroText) : null}
|
|
1401
|
+
footer={
|
|
1441
1402
|
<FootnotesStandAlone
|
|
1442
1403
|
config={configObj.footnotes}
|
|
1443
1404
|
filters={config.filters?.filter(f => f.filterFootnotes)}
|
|
1444
1405
|
markupVariables={config.markupVariables}
|
|
1445
1406
|
enableMarkupVariables={config.enableMarkupVariables}
|
|
1446
1407
|
data={config.data}
|
|
1408
|
+
dataMetadata={config.dataMetadata}
|
|
1447
1409
|
/>
|
|
1410
|
+
}
|
|
1411
|
+
>
|
|
1412
|
+
{isTp5Treatment && <img src={CalloutFlag} alt='' className='cdc-callout__flag' aria-hidden='true' />}
|
|
1413
|
+
{isTp5Treatment && chartTitle}
|
|
1414
|
+
<div className={getChartWrapperClasses().join(' ')}>
|
|
1415
|
+
<SkipTo skipId={handleChartTabbing(config, legendId)} skipMessage='Skip Over Chart Container' />
|
|
1416
|
+
{visibleAnnotations.length > 0 && (
|
|
1417
|
+
<SkipTo
|
|
1418
|
+
skipId={handleChartTabbing(config, legendId)}
|
|
1419
|
+
skipMessage={`Skip over annotations`}
|
|
1420
|
+
key={`skip-annotations`}
|
|
1421
|
+
/>
|
|
1422
|
+
)}
|
|
1423
|
+
<LegendWrapper>
|
|
1424
|
+
<div
|
|
1425
|
+
className={
|
|
1426
|
+
legend.hide || isLegendWrapViewport(currentViewport)
|
|
1427
|
+
? 'w-100'
|
|
1428
|
+
: legend.position === 'bottom' ||
|
|
1429
|
+
legend.position === 'top' ||
|
|
1430
|
+
visualizationType === 'Sankey' ||
|
|
1431
|
+
visualizationType === 'Spark Line'
|
|
1432
|
+
? 'w-100'
|
|
1433
|
+
: 'w-75'
|
|
1434
|
+
}
|
|
1435
|
+
>
|
|
1436
|
+
{/* Check if there is data to display */}
|
|
1437
|
+
{(!filteredData || filteredData.length === 0) && (
|
|
1438
|
+
<div className='no-data-message' style={{ padding: '2rem', textAlign: 'center', color: '#666' }}>
|
|
1439
|
+
{config.chartMessage?.noData || 'No Data Available'}
|
|
1440
|
+
</div>
|
|
1441
|
+
)}
|
|
1442
|
+
|
|
1443
|
+
{/* All charts with LinearChart */}
|
|
1444
|
+
{filteredData &&
|
|
1445
|
+
filteredData.length > 0 &&
|
|
1446
|
+
!['Spark Line', 'Line', 'Sankey', 'Pie', 'Radar'].includes(config.visualizationType) && (
|
|
1447
|
+
<div ref={parentRef} style={{ width: `100%` }}>
|
|
1448
|
+
<ParentSize>
|
|
1449
|
+
{parent => (
|
|
1450
|
+
<LinearChart ref={svgRef} parentWidth={parent.width} parentHeight={parent.height} />
|
|
1451
|
+
)}
|
|
1452
|
+
</ParentSize>
|
|
1453
|
+
</div>
|
|
1454
|
+
)}
|
|
1455
|
+
|
|
1456
|
+
{filteredData && filteredData.length > 0 && config.visualizationType === 'Pie' && (
|
|
1457
|
+
<ParentSize className='justify-content-center d-flex' style={{ width: `100%` }}>
|
|
1458
|
+
{parent => (
|
|
1459
|
+
<PieChart
|
|
1460
|
+
ref={svgRef}
|
|
1461
|
+
parentWidth={parent.width}
|
|
1462
|
+
parentHeight={parent.height}
|
|
1463
|
+
interactionLabel={interactionLabel}
|
|
1464
|
+
/>
|
|
1465
|
+
)}
|
|
1466
|
+
</ParentSize>
|
|
1467
|
+
)}
|
|
1468
|
+
{/* Radar Chart */}
|
|
1469
|
+
{filteredData && filteredData.length > 0 && config.visualizationType === 'Radar' && (
|
|
1470
|
+
<ParentSize className='justify-content-center d-flex' style={{ width: `100%` }}>
|
|
1471
|
+
{parent => (
|
|
1472
|
+
<RadarChart
|
|
1473
|
+
ref={svgRef}
|
|
1474
|
+
parentWidth={parent.width}
|
|
1475
|
+
parentHeight={parent.height}
|
|
1476
|
+
interactionLabel={interactionLabel}
|
|
1477
|
+
/>
|
|
1478
|
+
)}
|
|
1479
|
+
</ParentSize>
|
|
1480
|
+
)}
|
|
1481
|
+
{/* Line Chart */}
|
|
1482
|
+
{filteredData &&
|
|
1483
|
+
filteredData.length > 0 &&
|
|
1484
|
+
config.visualizationType === 'Line' &&
|
|
1485
|
+
(convertLineToBarGraph ? (
|
|
1486
|
+
<div ref={parentRef} style={{ width: `100%` }}>
|
|
1487
|
+
<ParentSize>
|
|
1488
|
+
{parent => (
|
|
1489
|
+
<LinearChart ref={svgRef} parentWidth={parent.width} parentHeight={parent.height} />
|
|
1490
|
+
)}
|
|
1491
|
+
</ParentSize>
|
|
1492
|
+
</div>
|
|
1493
|
+
) : (
|
|
1494
|
+
<div ref={parentRef} style={{ width: '100%' }}>
|
|
1495
|
+
<ParentSize>
|
|
1496
|
+
{parent => {
|
|
1497
|
+
const labelMargin = 120
|
|
1498
|
+
const widthReduction =
|
|
1499
|
+
config.showLineSeriesLabels && (config.legend.position !== 'right' || config.legend.hide)
|
|
1500
|
+
? labelMargin
|
|
1501
|
+
: 0
|
|
1502
|
+
return (
|
|
1503
|
+
<LinearChart
|
|
1504
|
+
ref={svgRef}
|
|
1505
|
+
parentWidth={parent.width - widthReduction}
|
|
1506
|
+
parentHeight={parent.height}
|
|
1507
|
+
/>
|
|
1508
|
+
)
|
|
1509
|
+
}}
|
|
1510
|
+
</ParentSize>
|
|
1511
|
+
</div>
|
|
1512
|
+
))}
|
|
1513
|
+
{/* Sparkline */}
|
|
1514
|
+
{config.visualizationType === 'Spark Line' && (
|
|
1515
|
+
<>
|
|
1516
|
+
<Filters
|
|
1517
|
+
config={config}
|
|
1518
|
+
setFilters={setFilters}
|
|
1519
|
+
excludedData={excludedData}
|
|
1520
|
+
dimensions={dimensions}
|
|
1521
|
+
interactionLabel={interactionLabel}
|
|
1522
|
+
/>
|
|
1523
|
+
{processedIntroText && (
|
|
1524
|
+
<section className='introText' style={{ padding: '0px 0 35px' }}>
|
|
1525
|
+
{parse(processedIntroText)}
|
|
1526
|
+
</section>
|
|
1527
|
+
)}
|
|
1528
|
+
<div style={{ height: `100px`, width: `100%`, ...sparkLineStyles }}>
|
|
1529
|
+
<ParentSize>{parent => <SparkLine width={parent.width} height={parent.height} />}</ParentSize>
|
|
1530
|
+
</div>
|
|
1531
|
+
{processedDescription && (
|
|
1532
|
+
<div className='subtext' style={{ padding: '35px 0 1.5rem' }}>
|
|
1533
|
+
{parse(processedDescription)}
|
|
1534
|
+
</div>
|
|
1535
|
+
)}
|
|
1536
|
+
</>
|
|
1537
|
+
)}
|
|
1538
|
+
{/* Sankey */}
|
|
1539
|
+
{config.visualizationType === 'Sankey' && (
|
|
1540
|
+
<ParentSize aria-hidden='true'>
|
|
1541
|
+
{parent => <SankeyChart runtime={config.runtime} width={parent.width} height={parent.height} />}
|
|
1542
|
+
</ParentSize>
|
|
1543
|
+
)}
|
|
1544
|
+
</div>
|
|
1545
|
+
{/* Legend */}
|
|
1546
|
+
{!config.legend.hide &&
|
|
1547
|
+
config.visualizationType !== 'Spark Line' &&
|
|
1548
|
+
config.visualizationType !== 'Sankey' &&
|
|
1549
|
+
!(config.visualizationType === 'Warming Stripes' && config.legend?.style === 'gradient') &&
|
|
1550
|
+
!(config.visualizationType === 'Warming Stripes' && config.smallMultiples?.mode) && (
|
|
1551
|
+
<Legend
|
|
1552
|
+
ref={legendRef}
|
|
1553
|
+
skipId={handleChartTabbing(config, legendId)}
|
|
1554
|
+
interactionLabel={interactionLabel}
|
|
1555
|
+
/>
|
|
1556
|
+
)}
|
|
1557
|
+
{config.visualizationType === 'Warming Stripes' &&
|
|
1558
|
+
config.legend?.style === 'gradient' &&
|
|
1559
|
+
!config.smallMultiples?.mode && <WarmingStripesGradientLegend />}
|
|
1560
|
+
</LegendWrapper>
|
|
1448
1561
|
</div>
|
|
1449
|
-
|
|
1450
|
-
|
|
1562
|
+
</VisualizationContent>
|
|
1563
|
+
)}
|
|
1451
1564
|
</>
|
|
1452
1565
|
)
|
|
1453
1566
|
}
|
|
@@ -1505,25 +1618,26 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1505
1618
|
setSharedFilterValue,
|
|
1506
1619
|
svgRef,
|
|
1507
1620
|
tableData: filteredData || excludedData,
|
|
1508
|
-
transformedData
|
|
1621
|
+
transformedData,
|
|
1509
1622
|
twoColorPalette,
|
|
1510
1623
|
unfilteredData: stateData,
|
|
1511
|
-
updateConfig
|
|
1624
|
+
updateConfig,
|
|
1625
|
+
visibleAnnotations
|
|
1512
1626
|
}
|
|
1513
1627
|
|
|
1514
1628
|
return (
|
|
1515
1629
|
<ConfigContext.Provider value={contextValues}>
|
|
1516
1630
|
<ChartDispatchContext.Provider value={dispatch}>
|
|
1517
|
-
<
|
|
1631
|
+
<VisualizationContainer
|
|
1518
1632
|
config={config}
|
|
1519
1633
|
isEditor={isEditor}
|
|
1520
1634
|
currentViewport={currentViewport}
|
|
1521
1635
|
ref={outerContainerRef}
|
|
1522
1636
|
imageId={imageId}
|
|
1523
|
-
|
|
1637
|
+
editorPanel={!isLoading ? <EditorPanel datasets={datasets} /> : null}
|
|
1524
1638
|
>
|
|
1525
1639
|
{body}
|
|
1526
|
-
</
|
|
1640
|
+
</VisualizationContainer>
|
|
1527
1641
|
</ChartDispatchContext.Provider>
|
|
1528
1642
|
</ConfigContext.Provider>
|
|
1529
1643
|
)
|