@cdc/chart 4.25.10 → 4.26.1
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/dist/{cdcchart-1a1724a1.es.js → cdcchart-dgT_1dIT.es.js} +136 -151
- package/dist/cdcchart.js +44003 -43518
- package/examples/feature/__data__/planet-example-data.json +1 -1
- package/examples/feature/boxplot/valid-boxplot.csv +38 -17
- package/examples/feature/pie/planet-pie-example-config.json +48 -2
- package/examples/private/DEV-11825.json +573 -0
- package/examples/private/DEV-12100.json +1303 -0
- package/examples/private/cat-y.json +1235 -0
- package/examples/private/data-points.json +228 -0
- package/examples/private/height.json +3915 -0
- package/examples/private/links.json +569 -0
- package/examples/private/na.json +913 -0
- package/examples/private/quadrant.txt +30 -0
- package/examples/private/test-data.csv +28 -0
- package/examples/private/test-forecast.json +5510 -0
- package/examples/private/warming-stripe-test.json +2578 -0
- package/examples/private/warming-stripes.json +4763 -0
- package/examples/tech-adoption-with-links.json +560 -0
- package/index.html +16 -140
- package/package.json +6 -5
- package/preview.html +1616 -0
- package/src/CdcChart.tsx +8 -11
- package/src/CdcChartComponent.tsx +329 -124
- package/src/_stories/Chart.Combo.stories.tsx +18 -0
- package/src/_stories/Chart.Forecast.stories.tsx +36 -0
- package/src/_stories/Chart.HTMLInDataTable.stories.tsx +520 -0
- package/src/_stories/Chart.Patterns.stories.tsx +2 -1
- package/src/_stories/Chart.PreserveDecimals.stories.tsx +220 -0
- package/src/_stories/Chart.Regions.Categorical.stories.tsx +148 -0
- package/src/_stories/Chart.Regions.DateScale.stories.tsx +197 -0
- package/src/_stories/Chart.Regions.DateTimeScale.stories.tsx +297 -0
- package/src/_stories/Chart.SmallMultiples.stories.tsx +47 -0
- package/src/_stories/Chart.stories.tsx +8 -0
- package/src/_stories/ChartAnnotation.stories.tsx +6 -3
- package/src/_stories/ChartBar.Editor.stories.tsx +3585 -0
- package/src/_stories/ChartBrush.Editor.stories.tsx +295 -0
- package/src/_stories/ChartBrush.stories.tsx +50 -0
- package/src/_stories/ChartEditor.Editor.stories.tsx +656 -0
- package/src/_stories/ChartEditor.stories.tsx +1 -2
- package/src/_stories/TechAdoptionWithLinks.stories.tsx +27 -0
- package/src/_stories/_mock/brush_enabled.json +326 -0
- package/src/_stories/_mock/brush_mock.json +2 -69
- package/src/_stories/_mock/combo.json +451 -0
- package/src/_stories/_mock/editor-test-configs.json +376 -0
- package/src/_stories/_mock/editor-test-datasets.json +477 -0
- package/src/_stories/_mock/editor-tests/bar-chart-editor-test.json +255 -0
- package/src/_stories/_mock/editor-tests/bar-chart-general-test.json +267 -0
- package/src/_stories/_mock/editor-tests/bar-chart-test.json +237 -0
- package/src/_stories/_mock/forecast_combo_with_gaps.json +913 -0
- package/src/_stories/_mock/horizontal-bars-dynamic-y-axis.json +413 -0
- package/src/_stories/_mock/pie_config.json +257 -62
- package/src/_stories/_mock/small_multiples/small_multiples_bars.json +1944 -0
- package/src/_stories/_mock/small_multiples/small_multiples_big_data_bars.json +1114 -0
- package/src/_stories/_mock/small_multiples/small_multiples_lines.json +2646 -0
- package/src/_stories/_mock/small_multiples/small_multiples_lines_colors.json +1305 -0
- package/src/_stories/_mock/small_multiples/small_multiples_stacked_bars.json +1936 -0
- package/src/components/Annotations/components/findNearestDatum.ts +6 -41
- package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -7
- package/src/components/AreaChart/index.tsx +1 -2
- package/src/components/Axis/Categorical.Axis.tsx +6 -7
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +181 -27
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +3 -1
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +1 -0
- package/src/components/BarChart/components/BarChart.Vertical.tsx +8 -9
- package/src/components/BarChart/components/context.tsx +1 -0
- package/src/components/BarChart/helpers/useBarChart.ts +14 -2
- package/src/components/BoxPlot/helpers/index.ts +3 -3
- package/src/components/Brush/BrushSelector.tsx +1258 -0
- package/src/components/Brush/MiniChartPreview.tsx +283 -0
- package/src/components/DeviationBar.jsx +9 -7
- package/src/components/EditorPanel/EditorPanel.tsx +2720 -2586
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +96 -111
- package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +56 -34
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +76 -31
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +104 -55
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +54 -49
- package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +427 -0
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +96 -48
- package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
- package/src/components/EditorPanel/editor-panel.scss +0 -20
- package/src/components/EditorPanel/useEditorPermissions.ts +36 -31
- package/src/components/Forecasting/Forecasting.tsx +139 -21
- package/src/components/Legend/Legend.Component.tsx +16 -9
- package/src/components/Legend/Legend.tsx +3 -2
- package/src/components/Legend/helpers/createFormatLabels.tsx +325 -176
- package/src/components/Legend/helpers/getLegendClasses.ts +0 -1
- package/src/components/Legend/helpers/index.ts +10 -6
- package/src/components/LineChart/LineChartProps.ts +0 -3
- package/src/components/LineChart/helpers.ts +1 -1
- package/src/components/LineChart/index.tsx +36 -13
- package/src/components/LinearChart.tsx +559 -499
- package/src/components/PairedBarChart.jsx +20 -3
- package/src/components/Regions/components/Regions.tsx +366 -144
- package/src/components/Sankey/types/index.ts +1 -1
- package/src/components/ScatterPlot/ScatterPlot.jsx +2 -2
- package/src/components/SmallMultiples/SmallMultipleTile.tsx +202 -0
- package/src/components/SmallMultiples/SmallMultiples.css +32 -0
- package/src/components/SmallMultiples/SmallMultiples.tsx +271 -0
- package/src/components/SmallMultiples/index.ts +2 -0
- package/src/components/WarmingStripes/WarmingStripes.tsx +160 -0
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +35 -0
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.tsx +104 -0
- package/src/components/WarmingStripes/index.tsx +3 -0
- package/src/data/initial-state.js +16 -2
- package/src/helpers/buildForecastPaletteOptions.ts +0 -38
- package/src/helpers/calculateHorizontalBarCategoryLabelWidth.ts +57 -0
- package/src/helpers/getColorScale.ts +10 -0
- package/src/{hooks/useMinMax.ts → helpers/getMinMax.ts} +26 -14
- package/src/helpers/getYAxisAutoPadding.ts +53 -0
- package/src/helpers/sizeHelpers.ts +0 -20
- package/src/helpers/smallMultiplesHelpers.ts +529 -0
- package/src/hooks/useChartHoverAnalytics.tsx +10 -9
- package/src/hooks/useProgrammaticTooltip.ts +96 -0
- package/src/hooks/useScales.ts +98 -34
- package/src/hooks/useSmallMultipleSynchronization.ts +59 -0
- package/src/hooks/useTooltip.tsx +91 -25
- package/src/scss/DataTable.scss +0 -4
- package/src/scss/main.scss +18 -83
- package/src/store/chart.actions.ts +2 -0
- package/src/store/chart.reducer.ts +4 -0
- package/src/test/CdcChart.test.jsx +1 -1
- package/src/types/ChartConfig.ts +27 -6
- package/src/types/ChartContext.ts +3 -0
- package/src/types/Label.ts +1 -0
- package/src/utils/analyticsTracking.ts +19 -0
- package/LICENSE +0 -201
- package/src/_stories/_mock/pie_data.json +0 -218
- package/src/components/AreaChart/components/AreaChart.jsx +0 -109
- package/src/components/Brush/BrushChart.tsx +0 -128
- package/src/components/Brush/BrushController.tsx +0 -71
- package/src/components/Brush/types.tsx +0 -8
- package/src/components/BrushChart.tsx +0 -223
- package/src/helpers/sort.ts +0 -7
- package/src/hooks/useActiveElement.js +0 -19
- package/src/hooks/useChartClasses.js +0 -41
|
@@ -37,6 +37,7 @@ import { filterChartColorPalettes } from '@cdc/core/helpers/filterColorPalettes'
|
|
|
37
37
|
|
|
38
38
|
import SparkLine from './components/Sparkline'
|
|
39
39
|
import Legend from './components/Legend'
|
|
40
|
+
import WarmingStripesGradientLegend from './components/WarmingStripes/WarmingStripesGradientLegend'
|
|
40
41
|
import defaults from './data/initial-state'
|
|
41
42
|
import EditorPanel from './components/EditorPanel'
|
|
42
43
|
import { abbreviateNumber } from './helpers/abbreviateNumber'
|
|
@@ -75,6 +76,7 @@ import { getExcludedData } from './helpers/getExcludedData'
|
|
|
75
76
|
import { getColorScale } from './helpers/getColorScale'
|
|
76
77
|
import { getTransformedData } from './helpers/getTransformedData'
|
|
77
78
|
import { getPiePercent } from './helpers/getPiePercent'
|
|
79
|
+
import { prepareSmallMultiplesDataTable } from './helpers/smallMultiplesHelpers'
|
|
78
80
|
|
|
79
81
|
// styles
|
|
80
82
|
import './scss/main.scss'
|
|
@@ -238,6 +240,14 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
238
240
|
|
|
239
241
|
const convertLineToBarGraph = isConvertLineToBarGraph(config, filteredData)
|
|
240
242
|
|
|
243
|
+
// Declaratively calculate series keys for pie charts based on filtered data
|
|
244
|
+
const pieSeriesKeys = useMemo(() => {
|
|
245
|
+
if (config.visualizationType !== 'Pie' || !config.xAxis?.dataKey) return null
|
|
246
|
+
const data = filteredData?.length > 0 ? filteredData : excludedData
|
|
247
|
+
if (!data) return null
|
|
248
|
+
return _.uniq(data.map(d => d[config.xAxis.dataKey]))
|
|
249
|
+
}, [config.visualizationType, config.xAxis?.dataKey, filteredData, excludedData])
|
|
250
|
+
|
|
241
251
|
const prepareConfig = (loadedConfig: ChartConfig) => {
|
|
242
252
|
// Create defaults without version to avoid overriding legacy configs
|
|
243
253
|
const defaultsWithoutPalette = { ...defaults }
|
|
@@ -275,30 +285,62 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
275
285
|
return newConfig
|
|
276
286
|
}
|
|
277
287
|
|
|
288
|
+
const getProcessedAxisLabels = useCallback(
|
|
289
|
+
(targetConfig: AllChartsConfig, dataSource: any[] = []) => {
|
|
290
|
+
let processedXAxis = targetConfig.xAxis?.label
|
|
291
|
+
let processedYAxis = targetConfig.yAxis?.label
|
|
292
|
+
|
|
293
|
+
if (targetConfig.enableMarkupVariables && targetConfig.markupVariables?.length) {
|
|
294
|
+
if (targetConfig.xAxis?.label) {
|
|
295
|
+
processedXAxis = processMarkupVariables(
|
|
296
|
+
targetConfig.xAxis.label,
|
|
297
|
+
dataSource || [],
|
|
298
|
+
targetConfig.markupVariables,
|
|
299
|
+
{
|
|
300
|
+
isEditor,
|
|
301
|
+
filters: targetConfig.filters || []
|
|
302
|
+
}
|
|
303
|
+
).processedContent
|
|
304
|
+
}
|
|
305
|
+
if (targetConfig.yAxis?.label) {
|
|
306
|
+
processedYAxis = processMarkupVariables(
|
|
307
|
+
targetConfig.yAxis.label,
|
|
308
|
+
dataSource || [],
|
|
309
|
+
targetConfig.markupVariables,
|
|
310
|
+
{
|
|
311
|
+
isEditor,
|
|
312
|
+
filters: targetConfig.filters || []
|
|
313
|
+
}
|
|
314
|
+
).processedContent
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const isHorizontalVariant =
|
|
319
|
+
((targetConfig.visualizationType === 'Bar' || targetConfig.visualizationType === 'Box Plot') &&
|
|
320
|
+
targetConfig.orientation === 'horizontal') ||
|
|
321
|
+
['Deviation Bar', 'Paired Bar', 'Forest Plot'].includes(targetConfig.visualizationType)
|
|
322
|
+
|
|
323
|
+
const runtimeXAxisLabel = isHorizontalVariant
|
|
324
|
+
? processedYAxis ?? (targetConfig.yAxis as any)?.yAxis?.label ?? targetConfig.yAxis?.label
|
|
325
|
+
: processedXAxis ?? targetConfig.xAxis?.label
|
|
326
|
+
|
|
327
|
+
const runtimeYAxisLabel = isHorizontalVariant
|
|
328
|
+
? processedXAxis ?? (targetConfig.xAxis as any)?.xAxis?.label ?? targetConfig.xAxis?.label
|
|
329
|
+
: processedYAxis ?? targetConfig.yAxis?.label
|
|
330
|
+
|
|
331
|
+
return { processedXAxis, processedYAxis, runtimeXAxisLabel, runtimeYAxisLabel, isHorizontalVariant }
|
|
332
|
+
},
|
|
333
|
+
[isEditor]
|
|
334
|
+
)
|
|
335
|
+
|
|
278
336
|
const updateConfig = (_config: AllChartsConfig, dataOverride?: any[]) => {
|
|
279
337
|
const newConfig = cloneConfig(_config)
|
|
280
338
|
let data = dataOverride || stateData
|
|
281
339
|
|
|
282
340
|
data = handleRankByValue(data, newConfig)
|
|
283
341
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
let processedYAxis = newConfig.yAxis?.label
|
|
287
|
-
|
|
288
|
-
if (newConfig.enableMarkupVariables && newConfig.markupVariables?.length) {
|
|
289
|
-
if (newConfig.xAxis?.label) {
|
|
290
|
-
processedXAxis = processMarkupVariables(newConfig.xAxis.label, data || [], newConfig.markupVariables, {
|
|
291
|
-
isEditor,
|
|
292
|
-
filters: newConfig.filters || []
|
|
293
|
-
}).processedContent
|
|
294
|
-
}
|
|
295
|
-
if (newConfig.yAxis?.label) {
|
|
296
|
-
processedYAxis = processMarkupVariables(newConfig.yAxis.label, data || [], newConfig.markupVariables, {
|
|
297
|
-
isEditor,
|
|
298
|
-
filters: newConfig.filters || []
|
|
299
|
-
}).processedContent
|
|
300
|
-
}
|
|
301
|
-
}
|
|
342
|
+
const { processedXAxis, processedYAxis, runtimeXAxisLabel, runtimeYAxisLabel, isHorizontalVariant } =
|
|
343
|
+
getProcessedAxisLabels(newConfig, data || [])
|
|
302
344
|
|
|
303
345
|
// Deeper copy
|
|
304
346
|
Object.keys(defaults).forEach(key => {
|
|
@@ -323,6 +365,14 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
323
365
|
}
|
|
324
366
|
|
|
325
367
|
//Enforce default values that need to be calculated at runtime
|
|
368
|
+
// Preserve error messages that were set outside of updateConfig (e.g., from pattern settings)
|
|
369
|
+
const existingErrorMessage = _config.runtime?.editorErrorMessage || ''
|
|
370
|
+
const isPieChartValidationError =
|
|
371
|
+
existingErrorMessage === 'Data column section must be set for pie charts.' ||
|
|
372
|
+
existingErrorMessage === 'Segment labels section must be set for pie charts.' ||
|
|
373
|
+
existingErrorMessage === 'Data column and Segment labels sections must be set for pie charts.'
|
|
374
|
+
const shouldPreserveError = existingErrorMessage && !isPieChartValidationError
|
|
375
|
+
|
|
326
376
|
newConfig.runtime = {} as Runtime
|
|
327
377
|
newConfig.runtime.series = _.cloneDeep(newConfig.series)
|
|
328
378
|
newConfig.runtime.seriesLabels = {}
|
|
@@ -334,6 +384,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
334
384
|
const pieData = currentData.length > 0 ? currentData : newExcludedData
|
|
335
385
|
newConfig.runtime.seriesKeys = _.uniq(pieData.map(d => d[newConfig.xAxis.dataKey]))
|
|
336
386
|
newConfig.runtime.seriesLabelsAll = newConfig.runtime.seriesKeys
|
|
387
|
+
newConfig.runtime.isPieChart = true // Flag to know when to use derived keys
|
|
337
388
|
} else {
|
|
338
389
|
const finalData = dataOverride || newConfig.formattedData || newConfig.data
|
|
339
390
|
newConfig.runtime.seriesKeys = (newConfig.runtime.series || []).flatMap(series => {
|
|
@@ -384,6 +435,18 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
384
435
|
newConfig.runtime.forecastingSeriesKeys.push(series)
|
|
385
436
|
}
|
|
386
437
|
})
|
|
438
|
+
|
|
439
|
+
// Default to date scaling type for Forecasting charts
|
|
440
|
+
if (newConfig.xAxis.type === 'categorical') {
|
|
441
|
+
newConfig.xAxis.type = 'date'
|
|
442
|
+
// Initialize date parsing formats if they don't exist
|
|
443
|
+
if (!newConfig.xAxis.dateParseFormat) {
|
|
444
|
+
newConfig.xAxis.dateParseFormat = '%Y-%m-%d'
|
|
445
|
+
}
|
|
446
|
+
if (!newConfig.xAxis.dateDisplayFormat) {
|
|
447
|
+
newConfig.xAxis.dateDisplayFormat = '%Y-%m-%d'
|
|
448
|
+
}
|
|
449
|
+
}
|
|
387
450
|
}
|
|
388
451
|
|
|
389
452
|
if (newConfig.visualizationType === 'Area Chart' && newConfig.series) {
|
|
@@ -395,19 +458,17 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
395
458
|
newConfig.visualizationSubType = 'stacked'
|
|
396
459
|
}
|
|
397
460
|
|
|
398
|
-
if (
|
|
399
|
-
((newConfig.visualizationType === 'Bar' || newConfig.visualizationType === 'Box Plot') &&
|
|
400
|
-
newConfig.orientation === 'horizontal') ||
|
|
401
|
-
['Deviation Bar', 'Paired Bar', 'Forest Plot'].includes(newConfig.visualizationType)
|
|
402
|
-
) {
|
|
461
|
+
if (isHorizontalVariant) {
|
|
403
462
|
// For horizontal charts, axes are swapped, so processedYAxis goes to runtime.xAxis and vice versa
|
|
463
|
+
const horizontalXAxisSource = _.cloneDeep((newConfig.yAxis as any)?.yAxis || newConfig.yAxis)
|
|
464
|
+
const horizontalYAxisSource = _.cloneDeep((newConfig.xAxis as any)?.xAxis || newConfig.xAxis)
|
|
404
465
|
newConfig.runtime.xAxis = {
|
|
405
|
-
...
|
|
406
|
-
label:
|
|
466
|
+
...horizontalXAxisSource,
|
|
467
|
+
label: runtimeXAxisLabel ?? horizontalXAxisSource?.label
|
|
407
468
|
}
|
|
408
469
|
newConfig.runtime.yAxis = {
|
|
409
|
-
...
|
|
410
|
-
label:
|
|
470
|
+
...horizontalYAxisSource,
|
|
471
|
+
label: runtimeYAxisLabel ?? horizontalYAxisSource?.label
|
|
411
472
|
}
|
|
412
473
|
newConfig.runtime.yAxis.labelOffset *= -1
|
|
413
474
|
|
|
@@ -419,24 +480,40 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
419
480
|
['Scatter Plot', 'Area Chart', 'Line', 'Forecasting'].includes(newConfig.visualizationType) &&
|
|
420
481
|
!convertLineToBarGraph
|
|
421
482
|
) {
|
|
422
|
-
newConfig.runtime.xAxis = { ...newConfig.xAxis, label:
|
|
423
|
-
newConfig.runtime.yAxis = { ...newConfig.yAxis, label:
|
|
483
|
+
newConfig.runtime.xAxis = { ...newConfig.xAxis, label: runtimeXAxisLabel ?? newConfig.xAxis.label }
|
|
484
|
+
newConfig.runtime.yAxis = { ...newConfig.yAxis, label: runtimeYAxisLabel ?? newConfig.yAxis.label }
|
|
424
485
|
newConfig.runtime.horizontal = false
|
|
425
486
|
newConfig.orientation = 'vertical'
|
|
426
487
|
} else {
|
|
427
|
-
newConfig.runtime.xAxis = { ...newConfig.xAxis, label:
|
|
428
|
-
newConfig.runtime.yAxis = { ...newConfig.yAxis, label:
|
|
488
|
+
newConfig.runtime.xAxis = { ...newConfig.xAxis, label: runtimeXAxisLabel ?? newConfig.xAxis.label }
|
|
489
|
+
newConfig.runtime.yAxis = { ...newConfig.yAxis, label: runtimeYAxisLabel ?? newConfig.yAxis.label }
|
|
429
490
|
newConfig.runtime.horizontal = false
|
|
430
491
|
}
|
|
431
492
|
|
|
432
493
|
newConfig.runtime.uniqueId = Date.now()
|
|
433
|
-
newConfig.runtime.editorErrorMessage =
|
|
434
|
-
newConfig.visualizationType === 'Pie' && !newConfig.yAxis.dataKey
|
|
435
|
-
? 'Data Key property in Y Axis section must be set for pie charts.'
|
|
436
|
-
: ''
|
|
437
494
|
|
|
438
|
-
//
|
|
439
|
-
|
|
495
|
+
// Set error messages: preserve external errors (from pattern settings, etc.) or set validation errors
|
|
496
|
+
if (shouldPreserveError) {
|
|
497
|
+
// Preserve error messages set by editor panels (e.g., pattern contrast errors)
|
|
498
|
+
newConfig.runtime.editorErrorMessage = existingErrorMessage
|
|
499
|
+
} else if (newConfig.visualizationType === 'Pie') {
|
|
500
|
+
// Check for Pie chart validation errors
|
|
501
|
+
const missingDataColumn = !newConfig.yAxis.dataKey || newConfig.yAxis.dataKey === ''
|
|
502
|
+
const missingSegmentLabels = !newConfig.xAxis.dataKey || newConfig.xAxis.dataKey === ''
|
|
503
|
+
|
|
504
|
+
if (missingDataColumn && missingSegmentLabels) {
|
|
505
|
+
newConfig.runtime.editorErrorMessage = 'Data column and Segment labels sections must be set for pie charts.'
|
|
506
|
+
} else if (missingDataColumn) {
|
|
507
|
+
newConfig.runtime.editorErrorMessage = 'Data column section must be set for pie charts.'
|
|
508
|
+
} else if (missingSegmentLabels) {
|
|
509
|
+
newConfig.runtime.editorErrorMessage = 'Segment labels section must be set for pie charts.'
|
|
510
|
+
} else {
|
|
511
|
+
newConfig.runtime.editorErrorMessage = ''
|
|
512
|
+
}
|
|
513
|
+
} else {
|
|
514
|
+
// No errors
|
|
515
|
+
newConfig.runtime.editorErrorMessage = ''
|
|
516
|
+
}
|
|
440
517
|
|
|
441
518
|
if (newConfig.legend.seriesHighlight?.length) {
|
|
442
519
|
dispatch({ type: 'SET_SERIES_HIGHLIGHT', payload: newConfig.legend?.seriesHighlight })
|
|
@@ -492,11 +569,13 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
492
569
|
for (let entry of entries) {
|
|
493
570
|
let { width, height } = entry.contentRect
|
|
494
571
|
|
|
495
|
-
|
|
572
|
+
const editorIsOpen = isEditor
|
|
573
|
+
width = editorIsOpen ? width - EDITOR_WIDTH : width
|
|
496
574
|
|
|
497
575
|
const newViewport = getViewport(width)
|
|
498
576
|
|
|
499
577
|
dispatch({ type: 'SET_VIEWPORT', payload: newViewport })
|
|
578
|
+
dispatch({ type: 'SET_VIZ_VIEWPORT', payload: newViewport })
|
|
500
579
|
|
|
501
580
|
if (entry.target.dataset.lollipop === 'true') {
|
|
502
581
|
width = width - 2.5
|
|
@@ -640,6 +719,19 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
640
719
|
}
|
|
641
720
|
}, [externalFilters]) // eslint-disable-line
|
|
642
721
|
|
|
722
|
+
// Declaratively update runtime series keys for pie charts when derived value changes
|
|
723
|
+
if (config.runtime?.isPieChart && pieSeriesKeys && !_.isEqual(pieSeriesKeys, config.runtime?.seriesKeys)) {
|
|
724
|
+
const newConfig = {
|
|
725
|
+
...config,
|
|
726
|
+
runtime: {
|
|
727
|
+
...config.runtime,
|
|
728
|
+
seriesKeys: pieSeriesKeys,
|
|
729
|
+
seriesLabelsAll: pieSeriesKeys
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
setConfig(newConfig)
|
|
733
|
+
}
|
|
734
|
+
|
|
643
735
|
// Generates color palette to pass to child chart component
|
|
644
736
|
useEffect(() => {
|
|
645
737
|
if (stateData && config.xAxis && config.runtime?.seriesKeys) {
|
|
@@ -654,6 +746,49 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
654
746
|
}
|
|
655
747
|
}, [config, stateData]) // eslint-disable-line
|
|
656
748
|
|
|
749
|
+
// Updates runtime axis labels when config or data changes when using markup variables
|
|
750
|
+
useEffect(() => {
|
|
751
|
+
if (
|
|
752
|
+
!config?.runtime ||
|
|
753
|
+
_.isEmpty(config.runtime) ||
|
|
754
|
+
(!config.runtime.xAxis && !config.runtime.yAxis) ||
|
|
755
|
+
!config.markupVariables?.length
|
|
756
|
+
) {
|
|
757
|
+
return
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const dataSource = (stateData && stateData.length ? stateData : config.data) || []
|
|
761
|
+
const { runtimeXAxisLabel, runtimeYAxisLabel, isHorizontalVariant } = getProcessedAxisLabels(config, dataSource)
|
|
762
|
+
|
|
763
|
+
const runtimeClone = _.cloneDeep(config.runtime)
|
|
764
|
+
|
|
765
|
+
if (!runtimeClone?.xAxis || !runtimeClone?.yAxis) {
|
|
766
|
+
return
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
let shouldUpdateLabels = false
|
|
770
|
+
|
|
771
|
+
if (typeof runtimeXAxisLabel !== 'undefined' && runtimeClone.xAxis.label !== runtimeXAxisLabel) {
|
|
772
|
+
runtimeClone.xAxis = { ...runtimeClone.xAxis, label: runtimeXAxisLabel }
|
|
773
|
+
shouldUpdateLabels = true
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (typeof runtimeYAxisLabel !== 'undefined' && runtimeClone.yAxis.label !== runtimeYAxisLabel) {
|
|
777
|
+
runtimeClone.yAxis = { ...runtimeClone.yAxis, label: runtimeYAxisLabel }
|
|
778
|
+
shouldUpdateLabels = true
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
if (shouldUpdateLabels) {
|
|
782
|
+
runtimeClone.uniqueId = Date.now()
|
|
783
|
+
const updatedConfig = { ...config, runtime: runtimeClone } as ChartConfig
|
|
784
|
+
dispatch({ type: 'SET_CONFIG', payload: updatedConfig })
|
|
785
|
+
|
|
786
|
+
if (isEditor && !isDashboard) {
|
|
787
|
+
editorContext.setTempConfig(updatedConfig)
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}, [config, stateData, getProcessedAxisLabels, dispatch, editorContext, isEditor, isDashboard])
|
|
791
|
+
|
|
657
792
|
// Called on legend click, highlights/unhighlights the data series with the given label
|
|
658
793
|
const highlight = (label: Label): void => {
|
|
659
794
|
if (
|
|
@@ -707,15 +842,17 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
707
842
|
}
|
|
708
843
|
|
|
709
844
|
const formatDate = (date, i, ticks) => {
|
|
710
|
-
|
|
845
|
+
const displayFormat =
|
|
846
|
+
config.runtime[section].dateDisplayFormat || config.runtime[section].dateParseFormat || '%Y-%m-%d'
|
|
847
|
+
let formattedDate = timeFormat(displayFormat)(date)
|
|
711
848
|
// Handle the case where all months work with '%b.' except for May
|
|
712
|
-
if (
|
|
849
|
+
if (displayFormat?.includes('%b.') && formattedDate.includes('May.')) {
|
|
713
850
|
formattedDate = formattedDate.replace(/May\./g, 'May')
|
|
714
851
|
}
|
|
715
852
|
// Show years only once
|
|
716
|
-
if (config.xAxis.showYearsOnce &&
|
|
853
|
+
if (config.xAxis.showYearsOnce && displayFormat?.includes('%Y') && ticks) {
|
|
717
854
|
const prevDate = ticks[i - 1] ? ticks[i - 1].value : null
|
|
718
|
-
const prevFormattedDate = timeFormat(
|
|
855
|
+
const prevFormattedDate = timeFormat(displayFormat)(prevDate)
|
|
719
856
|
const year = formattedDate.match(/\d{4}/)
|
|
720
857
|
const prevYear = prevFormattedDate.match(/\d{4}/)
|
|
721
858
|
if (year && prevYear && year[0] === prevYear[0]) {
|
|
@@ -769,7 +906,8 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
769
906
|
rightSuffix,
|
|
770
907
|
bottomPrefix,
|
|
771
908
|
bottomSuffix,
|
|
772
|
-
bottomAbbreviated
|
|
909
|
+
bottomAbbreviated,
|
|
910
|
+
preserveOriginalDecimals
|
|
773
911
|
}
|
|
774
912
|
} = config
|
|
775
913
|
|
|
@@ -788,32 +926,52 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
788
926
|
} else {
|
|
789
927
|
roundToPlace = roundTo ? Number(roundTo) : 0
|
|
790
928
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
929
|
+
|
|
930
|
+
// If preserveOriginalDecimals is enabled, don't force decimal places
|
|
931
|
+
if (preserveOriginalDecimals) {
|
|
932
|
+
stringFormattingOptions = {
|
|
933
|
+
useGrouping: addColRoundTo ? true : config.dataFormat.commas ? true : false
|
|
934
|
+
}
|
|
935
|
+
} else {
|
|
936
|
+
stringFormattingOptions = {
|
|
937
|
+
useGrouping: addColRoundTo ? true : config.dataFormat.commas ? true : false,
|
|
938
|
+
minimumFractionDigits: roundToPlace,
|
|
939
|
+
maximumFractionDigits: roundToPlace
|
|
940
|
+
}
|
|
795
941
|
}
|
|
796
942
|
}
|
|
797
943
|
|
|
798
944
|
if (axis === 'right') {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
945
|
+
if (preserveOriginalDecimals) {
|
|
946
|
+
stringFormattingOptions = {
|
|
947
|
+
useGrouping: config.dataFormat.rightCommas ? true : false
|
|
948
|
+
}
|
|
949
|
+
} else {
|
|
950
|
+
stringFormattingOptions = {
|
|
951
|
+
useGrouping: config.dataFormat.rightCommas ? true : false,
|
|
952
|
+
minimumFractionDigits: rightRoundTo ? Number(rightRoundTo) : 0,
|
|
953
|
+
maximumFractionDigits: rightRoundTo ? Number(rightRoundTo) : 0
|
|
954
|
+
}
|
|
803
955
|
}
|
|
804
956
|
}
|
|
805
957
|
|
|
806
958
|
const resolveBottomTickRounding = () => {
|
|
807
|
-
if (config.forestPlot
|
|
959
|
+
if (config.forestPlot?.type === 'Logarithmic' && !bottomRoundTo) return 2
|
|
808
960
|
if (Number(bottomRoundTo)) return Number(bottomRoundTo)
|
|
809
961
|
return 0
|
|
810
962
|
}
|
|
811
963
|
|
|
812
964
|
if (axis === 'bottom') {
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
965
|
+
if (preserveOriginalDecimals) {
|
|
966
|
+
stringFormattingOptions = {
|
|
967
|
+
useGrouping: config.dataFormat.bottomCommas ? true : false
|
|
968
|
+
}
|
|
969
|
+
} else {
|
|
970
|
+
stringFormattingOptions = {
|
|
971
|
+
useGrouping: config.dataFormat.bottomCommas ? true : false,
|
|
972
|
+
minimumFractionDigits: resolveBottomTickRounding(),
|
|
973
|
+
maximumFractionDigits: resolveBottomTickRounding()
|
|
974
|
+
}
|
|
817
975
|
}
|
|
818
976
|
}
|
|
819
977
|
|
|
@@ -992,8 +1150,6 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
992
1150
|
const isLegendOnBottom = legend?.position === 'bottom' || isLegendWrapViewport(currentViewport)
|
|
993
1151
|
|
|
994
1152
|
if (config.isResponsiveTicks) classes.push('subtext--responsive-ticks ')
|
|
995
|
-
if (config.xAxis.brushActive && !isLegendOnBottom) classes.push('subtext--brush-active ')
|
|
996
|
-
if (config.xAxis.brushActive && config.legend.hide) classes.push('subtext--brush-active ')
|
|
997
1153
|
return classes
|
|
998
1154
|
}
|
|
999
1155
|
|
|
@@ -1008,9 +1164,6 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1008
1164
|
{isEditor && <EditorPanel datasets={datasets} />}
|
|
1009
1165
|
<Layout.Responsive isEditor={isEditor}>
|
|
1010
1166
|
{config.newViz && <Confirm updateConfig={updateConfig} config={config} />}
|
|
1011
|
-
{undefined === config.newViz && isEditor && config.runtime && config.runtime?.editorErrorMessage && (
|
|
1012
|
-
<Error errorMessage={config.runtime.editorErrorMessage} />
|
|
1013
|
-
)}
|
|
1014
1167
|
{!missingRequiredSections(config) && !config.newViz && (
|
|
1015
1168
|
<div
|
|
1016
1169
|
className={`cdc-chart-inner-container cove-component__content type-${makeClassName(
|
|
@@ -1024,11 +1177,20 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1024
1177
|
isDashboard={isDashboard}
|
|
1025
1178
|
title={title}
|
|
1026
1179
|
superTitle={processedSuperTitle}
|
|
1180
|
+
titleStyle={config.titleStyle}
|
|
1027
1181
|
classes={['chart-title', `${config.theme}`, 'cove-component__header', 'mb-3']}
|
|
1028
1182
|
style={undefined}
|
|
1029
1183
|
config={config}
|
|
1030
1184
|
/>
|
|
1031
1185
|
|
|
1186
|
+
{/* Error Message Display - Show at top before visualization wrapper */}
|
|
1187
|
+
{/* {(() => {
|
|
1188
|
+
const errorMessage = config.runtime?.editorErrorMessage
|
|
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
|
+
|
|
1032
1194
|
{/* Visualization Wrapper */}
|
|
1033
1195
|
<div className={getChartWrapperClasses().join(' ')}>
|
|
1034
1196
|
{/* Intro Text/Message */}
|
|
@@ -1067,18 +1229,27 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1067
1229
|
: 'w-75'
|
|
1068
1230
|
}
|
|
1069
1231
|
>
|
|
1070
|
-
{/*
|
|
1071
|
-
{!
|
|
1072
|
-
<div
|
|
1073
|
-
|
|
1074
|
-
{parent => (
|
|
1075
|
-
<LinearChart ref={svgRef} parentWidth={parent.width} parentHeight={parent.height} />
|
|
1076
|
-
)}
|
|
1077
|
-
</ParentSize>
|
|
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'}
|
|
1078
1236
|
</div>
|
|
1079
1237
|
)}
|
|
1080
1238
|
|
|
1081
|
-
{
|
|
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' && (
|
|
1082
1253
|
<ParentSize className='justify-content-center d-flex' style={{ width: `100%` }}>
|
|
1083
1254
|
{parent => (
|
|
1084
1255
|
<PieChart
|
|
@@ -1091,7 +1262,9 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1091
1262
|
</ParentSize>
|
|
1092
1263
|
)}
|
|
1093
1264
|
{/* Line Chart */}
|
|
1094
|
-
{
|
|
1265
|
+
{filteredData &&
|
|
1266
|
+
filteredData.length > 0 &&
|
|
1267
|
+
config.visualizationType === 'Line' &&
|
|
1095
1268
|
(convertLineToBarGraph ? (
|
|
1096
1269
|
<div ref={parentRef} style={{ width: `100%` }}>
|
|
1097
1270
|
<ParentSize>
|
|
@@ -1156,13 +1329,18 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1156
1329
|
{/* Legend */}
|
|
1157
1330
|
{!config.legend.hide &&
|
|
1158
1331
|
config.visualizationType !== 'Spark Line' &&
|
|
1159
|
-
config.visualizationType !== 'Sankey' &&
|
|
1332
|
+
config.visualizationType !== 'Sankey' &&
|
|
1333
|
+
!(config.visualizationType === 'Warming Stripes' && config.legend?.style === 'gradient') &&
|
|
1334
|
+
!(config.visualizationType === 'Warming Stripes' && config.smallMultiples?.mode) && (
|
|
1160
1335
|
<Legend
|
|
1161
1336
|
ref={legendRef}
|
|
1162
1337
|
skipId={handleChartTabbing(config, legendId)}
|
|
1163
1338
|
interactionLabel={interactionLabel}
|
|
1164
1339
|
/>
|
|
1165
1340
|
)}
|
|
1341
|
+
{config.visualizationType === 'Warming Stripes' &&
|
|
1342
|
+
config.legend?.style === 'gradient' &&
|
|
1343
|
+
!config.smallMultiples?.mode && <WarmingStripesGradientLegend />}
|
|
1166
1344
|
</LegendWrapper>
|
|
1167
1345
|
{/* Link */}
|
|
1168
1346
|
{isDashboard && config.table && config.table.show && config.table.showDataTableLink
|
|
@@ -1174,62 +1352,86 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1174
1352
|
<div className={getChartSubTextClasses().join(' ')}>{parse(processedDescription)}</div>
|
|
1175
1353
|
)}
|
|
1176
1354
|
|
|
1177
|
-
{/* buttons */}
|
|
1178
|
-
<MediaControls.Section classes={['download-buttons']}>
|
|
1179
|
-
{config.table.showDownloadImgButton && (
|
|
1180
|
-
<MediaControls.Button
|
|
1181
|
-
text='Download Image'
|
|
1182
|
-
title='Download Chart as Image'
|
|
1183
|
-
type='image'
|
|
1184
|
-
state={config}
|
|
1185
|
-
elementToCapture={imageId}
|
|
1186
|
-
interactionLabel={interactionLabel}
|
|
1187
|
-
/>
|
|
1188
|
-
)}
|
|
1189
|
-
{config.table.showDownloadPdfButton && (
|
|
1190
|
-
<MediaControls.Button
|
|
1191
|
-
text='Download PDF'
|
|
1192
|
-
title='Download Chart as PDF'
|
|
1193
|
-
type='pdf'
|
|
1194
|
-
state={config}
|
|
1195
|
-
elementToCapture={imageId}
|
|
1196
|
-
interactionLabel={interactionLabel}
|
|
1197
|
-
/>
|
|
1198
|
-
)}
|
|
1199
|
-
</MediaControls.Section>
|
|
1200
1355
|
{/* Data Table */}
|
|
1201
|
-
{(
|
|
1356
|
+
{(config.xAxis.dataKey &&
|
|
1202
1357
|
config.table.show &&
|
|
1203
1358
|
config.visualizationType !== 'Spark Line' &&
|
|
1204
1359
|
config.visualizationType !== 'Sankey') ||
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1360
|
+
(config.visualizationType === 'Sankey' && config.table.show)
|
|
1361
|
+
? (() => {
|
|
1362
|
+
let dataTableConfig = pivotDynamicSeries(config)
|
|
1363
|
+
let dataTableColumns = config.columns
|
|
1364
|
+
let dataTableRuntimeData = getTableRuntimeData()
|
|
1365
|
+
let dataTableRawData =
|
|
1366
|
+
config.visualizationType === 'Sankey'
|
|
1367
|
+
? config?.data?.[0]?.tableData
|
|
1368
|
+
: config.table.customTableConfig
|
|
1369
|
+
? filterVizData(config.filters, config.data)
|
|
1370
|
+
: config.data
|
|
1371
|
+
|
|
1372
|
+
if (config.smallMultiples?.mode) {
|
|
1373
|
+
const prepared = prepareSmallMultiplesDataTable(config, config.columns, dataTableRuntimeData)
|
|
1374
|
+
dataTableConfig = prepared.config
|
|
1375
|
+
dataTableColumns = prepared.columns
|
|
1376
|
+
dataTableRuntimeData = prepared.runtimeData
|
|
1377
|
+
if (config.smallMultiples.mode === 'by-column') {
|
|
1378
|
+
dataTableRawData = prepared.config.data
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
return (
|
|
1383
|
+
<DataTable
|
|
1384
|
+
/* changing the "key" will force the table to re-render
|
|
1385
|
+
when the default sort changes while editing */
|
|
1386
|
+
key={dataTableDefaultSortBy}
|
|
1387
|
+
config={dataTableConfig}
|
|
1388
|
+
rawData={dataTableRawData}
|
|
1389
|
+
runtimeData={dataTableRuntimeData}
|
|
1390
|
+
expandDataTable={config.table.expanded}
|
|
1391
|
+
columns={dataTableColumns}
|
|
1392
|
+
defaultSortBy={dataTableDefaultSortBy}
|
|
1393
|
+
displayGeoName={name => name}
|
|
1394
|
+
applyLegendToRow={applyLegendToRow}
|
|
1395
|
+
tableTitle={config.table.label}
|
|
1396
|
+
indexTitle={config.table.indexLabel}
|
|
1397
|
+
vizTitle={title}
|
|
1398
|
+
viewport={currentViewport}
|
|
1399
|
+
tabbingId={handleChartTabbing(config, legendId)}
|
|
1400
|
+
colorScale={colorScale}
|
|
1401
|
+
imageRef={imageId}
|
|
1402
|
+
showDownloadImgButton={config.table.showDownloadImgButton}
|
|
1403
|
+
showDownloadPdfButton={config.table.showDownloadPdfButton}
|
|
1404
|
+
includeContextInDownload={config.table?.includeContextInDownload}
|
|
1405
|
+
interactionLabel={interactionLabel}
|
|
1406
|
+
/>
|
|
1407
|
+
)
|
|
1408
|
+
})()
|
|
1409
|
+
: (config.table.showDownloadImgButton || config.table.showDownloadPdfButton) && (
|
|
1410
|
+
<div className='w-100 d-flex justify-content-end'>
|
|
1411
|
+
<MediaControls.Section classes={['download-links', 'mt-4', 'mb-2']}>
|
|
1412
|
+
{config.table.showDownloadImgButton && (
|
|
1413
|
+
<MediaControls.DownloadLink
|
|
1414
|
+
type='image'
|
|
1415
|
+
title='Download Chart as Image'
|
|
1416
|
+
state={config}
|
|
1417
|
+
elementToCapture={imageId}
|
|
1418
|
+
interactionLabel={interactionLabel}
|
|
1419
|
+
includeContextInDownload={config.table?.includeContextInDownload}
|
|
1420
|
+
/>
|
|
1421
|
+
)}
|
|
1422
|
+
{config.table.showDownloadPdfButton && (
|
|
1423
|
+
<MediaControls.DownloadLink
|
|
1424
|
+
type='pdf'
|
|
1425
|
+
title='Download Chart as PDF'
|
|
1426
|
+
state={config}
|
|
1427
|
+
elementToCapture={imageId}
|
|
1428
|
+
interactionLabel={interactionLabel}
|
|
1429
|
+
includeContextInDownload={config.table?.includeContextInDownload}
|
|
1430
|
+
/>
|
|
1431
|
+
)}
|
|
1432
|
+
</MediaControls.Section>
|
|
1433
|
+
</div>
|
|
1434
|
+
)}
|
|
1233
1435
|
{config?.annotations?.length > 0 && <Annotation.Dropdown />}
|
|
1234
1436
|
{/* show pdf or image button */}
|
|
1235
1437
|
{processedLegacyFootnotes && (
|
|
@@ -1239,6 +1441,9 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1239
1441
|
<FootnotesStandAlone
|
|
1240
1442
|
config={configObj.footnotes}
|
|
1241
1443
|
filters={config.filters?.filter(f => f.filterFootnotes)}
|
|
1444
|
+
markupVariables={config.markupVariables}
|
|
1445
|
+
enableMarkupVariables={config.enableMarkupVariables}
|
|
1446
|
+
data={config.data}
|
|
1242
1447
|
/>
|
|
1243
1448
|
</div>
|
|
1244
1449
|
)}
|