@cdc/chart 4.25.7 → 4.25.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +9 -0
- package/dist/cdcchart.js +39551 -37016
- package/examples/feature/__data__/planet-example-data.json +0 -30
- package/examples/grouped-bar-test.json +400 -0
- package/examples/private/d.json +382 -0
- package/examples/private/example-2.json +49784 -0
- package/examples/private/f2.json +1 -0
- package/examples/private/f4.json +1577 -0
- package/examples/private/forecast.json +1180 -0
- package/examples/private/lollipop.json +468 -0
- package/examples/private/new.json +48756 -0
- package/examples/private/pie-chart-legend.json +904 -0
- package/examples/suppressed_tooltip.json +480 -0
- package/index.html +10 -22
- package/package.json +25 -7
- package/src/CdcChart.tsx +10 -4
- package/src/CdcChartComponent.tsx +188 -32
- package/src/_stories/Chart.Anchors.stories.tsx +2 -2
- package/src/_stories/Chart.BoxPlot.stories.tsx +1 -1
- package/src/_stories/Chart.CI.stories.tsx +1 -1
- package/src/_stories/Chart.CustomColors.stories.tsx +1 -1
- package/src/_stories/Chart.DynamicSeries.stories.tsx +2 -2
- package/src/_stories/Chart.Filters.stories.tsx +2 -2
- package/src/_stories/Chart.Legend.Gradient.stories.tsx +2 -2
- package/src/_stories/Chart.Patterns.stories.tsx +19 -0
- package/src/_stories/Chart.ScatterPlot.stories.tsx +1 -1
- package/src/_stories/Chart.stories.tsx +8 -5
- package/src/_stories/Chart.tooltip.stories.tsx +1 -1
- package/src/_stories/ChartAnnotation.stories.tsx +1 -1
- package/src/_stories/ChartAxisLabels.stories.tsx +2 -2
- package/src/_stories/ChartAxisTitles.stories.tsx +2 -2
- package/src/_stories/ChartEditor.stories.tsx +60 -60
- package/src/_stories/ChartLine.Suppression.stories.tsx +1 -1
- package/src/_stories/ChartLine.Symbols.stories.tsx +1 -1
- package/src/_stories/ChartPrefixSuffix.stories.tsx +2 -2
- package/src/_stories/_mock/stacked-pattern-test.json +520 -0
- package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -0
- package/src/components/Annotations/components/AnnotationDropdown.tsx +1 -1
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +170 -25
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +139 -6
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +215 -73
- package/src/components/BarChart/components/BarChart.Vertical.tsx +172 -23
- package/src/components/BarChart/helpers/index.ts +43 -4
- package/src/components/BarChart/helpers/lollipopColors.ts +27 -0
- package/src/components/BarChart/helpers/useBarChart.ts +25 -3
- package/src/components/BoxPlot/BoxPlot.Vertical.tsx +2 -1
- package/src/components/Brush/BrushChart.tsx +65 -10
- package/src/components/Brush/BrushController.tsx +37 -5
- package/src/components/Brush/types.tsx +8 -0
- package/src/components/DeviationBar.jsx +9 -6
- package/src/components/EditorPanel/EditorPanel.tsx +364 -39
- package/src/components/EditorPanel/EditorPanelContext.ts +3 -0
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +2 -2
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +414 -0
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +30 -54
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +115 -120
- package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
- package/src/components/EditorPanel/components/Panels/panelVisual.styles.css +0 -8
- package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +49 -48
- package/src/components/Forecasting/Forecasting.tsx +36 -6
- package/src/components/ForestPlot/ForestPlot.tsx +11 -7
- package/src/components/ForestPlot/ForestPlotProps.ts +1 -1
- package/src/components/Legend/Legend.Component.tsx +110 -2
- package/src/components/Legend/Legend.tsx +3 -1
- package/src/components/Legend/helpers/createFormatLabels.tsx +230 -171
- package/src/components/LegendWrapper.tsx +1 -1
- package/src/components/LineChart/components/LineChart.BumpCircle.tsx +27 -26
- package/src/components/LineChart/components/LineChart.Circle.tsx +2 -2
- package/src/components/LineChart/index.tsx +2 -2
- package/src/components/LinearChart.tsx +26 -9
- package/src/components/PairedBarChart.jsx +6 -4
- package/src/components/PieChart/PieChart.tsx +170 -54
- package/src/components/Sankey/components/Sankey.tsx +7 -1
- package/src/components/ScatterPlot/ScatterPlot.jsx +32 -4
- package/src/data/initial-state.js +315 -292
- package/src/helpers/buildForecastPaletteMappings.ts +112 -0
- package/src/helpers/buildForecastPaletteOptions.ts +109 -0
- package/src/helpers/getColorScale.ts +72 -8
- package/src/helpers/getNewRuntime.ts +1 -1
- package/src/helpers/getTransformedData.ts +1 -1
- package/src/hooks/useChartHoverAnalytics.tsx +44 -0
- package/src/hooks/useReduceData.ts +105 -70
- package/src/hooks/useTooltip.tsx +58 -16
- package/src/index.jsx +6 -3
- package/src/scss/main.scss +12 -0
- package/src/store/chart.reducer.ts +1 -1
- package/src/test/CdcChart.test.jsx +8 -3
- package/src/types/ChartConfig.ts +30 -6
- package/src/types/ChartContext.ts +1 -0
- package/vite.config.js +1 -1
- package/vitest.config.ts +16 -0
- package/src/coreStyles_chart.scss +0 -3
- package/src/helpers/configHelpers.ts +0 -28
- package/src/helpers/generateColorsArray.ts +0 -8
- package/src/hooks/useColorPalette.js +0 -76
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect, useCallback, useRef, useId, useContext, useReducer } from 'react'
|
|
1
|
+
import React, { useState, useEffect, useCallback, useRef, useId, useContext, useReducer, useMemo } from 'react'
|
|
2
2
|
|
|
3
3
|
// IE11
|
|
4
4
|
import ResizeObserver from 'resize-observer-polyfill'
|
|
@@ -24,7 +24,6 @@ import { Label } from './types/Label'
|
|
|
24
24
|
import ParentSize from '@visx/responsive/lib/components/ParentSize'
|
|
25
25
|
import { timeParse, timeFormat } from 'd3-time-format'
|
|
26
26
|
import parse from 'html-react-parser'
|
|
27
|
-
import 'react-tooltip/dist/react-tooltip.css'
|
|
28
27
|
import _ from 'lodash'
|
|
29
28
|
// Primary Components
|
|
30
29
|
import ConfigContext, { ChartDispatchContext } from './ConfigContext'
|
|
@@ -33,7 +32,8 @@ import SankeyChart from './components/Sankey'
|
|
|
33
32
|
import LinearChart from './components/LinearChart'
|
|
34
33
|
import { isDateScale } from '@cdc/core/helpers/cove/date'
|
|
35
34
|
|
|
36
|
-
import {
|
|
35
|
+
import { twoColorPalette } from '@cdc/core/data/colorPalettes'
|
|
36
|
+
import { filterChartColorPalettes } from '@cdc/core/helpers/filterColorPalettes'
|
|
37
37
|
|
|
38
38
|
import SparkLine from './components/Sparkline'
|
|
39
39
|
import Legend from './components/Legend'
|
|
@@ -46,7 +46,8 @@ import { handleChartAriaLabels } from './helpers/handleChartAriaLabels'
|
|
|
46
46
|
import { lineOptions } from './helpers/lineOptions'
|
|
47
47
|
import { handleLineType } from './helpers/handleLineType'
|
|
48
48
|
import { handleRankByValue } from './helpers/handleRankByValue'
|
|
49
|
-
import { generateColorsArray } from '
|
|
49
|
+
import { generateColorsArray } from '@cdc/core/helpers/generateColorsArray'
|
|
50
|
+
import { processMarkupVariables } from '@cdc/core/helpers/markupProcessor'
|
|
50
51
|
import Loading from '@cdc/core/components/Loading'
|
|
51
52
|
import Filters from '@cdc/core/components/Filters'
|
|
52
53
|
import MediaControls from '@cdc/core/components/MediaControls'
|
|
@@ -63,7 +64,7 @@ import numberFromString from '@cdc/core/helpers/numberFromString'
|
|
|
63
64
|
import getViewport from '@cdc/core/helpers/getViewport'
|
|
64
65
|
import isNumber from '@cdc/core/helpers/isNumber'
|
|
65
66
|
import coveUpdateWorker from '@cdc/core/helpers/coveUpdateWorker'
|
|
66
|
-
import EditorContext from '
|
|
67
|
+
import EditorContext from '@cdc/core/contexts/EditorContext'
|
|
67
68
|
import { EDITOR_WIDTH } from '@cdc/core/helpers/constants'
|
|
68
69
|
import { extractCoveData, updateVegaData } from '@cdc/core/helpers/vegaConfig'
|
|
69
70
|
// Local helpers
|
|
@@ -82,6 +83,9 @@ import { VizFilter } from '@cdc/core/types/VizFilter'
|
|
|
82
83
|
import { getNewRuntime } from './helpers/getNewRuntime'
|
|
83
84
|
import FootnotesStandAlone from '@cdc/core/components/Footnotes/FootnotesStandAlone'
|
|
84
85
|
import { Datasets } from '@cdc/core/types/DataSet'
|
|
86
|
+
import { publishAnalyticsEvent } from '@cdc/core/helpers/metrics/helpers'
|
|
87
|
+
import cloneConfig from '@cdc/core/helpers/cloneConfig'
|
|
88
|
+
import { getVizTitle, getVizSubType } from '@cdc/core/helpers/metrics/utils'
|
|
85
89
|
|
|
86
90
|
interface CdcChartProps {
|
|
87
91
|
config?: ChartConfig
|
|
@@ -96,6 +100,7 @@ interface CdcChartProps {
|
|
|
96
100
|
setSharedFilterValue?: (value: any) => void
|
|
97
101
|
dashboardConfig?: DashboardConfig
|
|
98
102
|
datasets?: Datasets
|
|
103
|
+
interactionLabel: string
|
|
99
104
|
}
|
|
100
105
|
const CdcChart: React.FC<CdcChartProps> = ({
|
|
101
106
|
config: configObj,
|
|
@@ -108,7 +113,8 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
108
113
|
setSharedFilter,
|
|
109
114
|
setSharedFilterValue,
|
|
110
115
|
dashboardConfig,
|
|
111
|
-
datasets
|
|
116
|
+
datasets,
|
|
117
|
+
interactionLabel
|
|
112
118
|
}) => {
|
|
113
119
|
const transform = new DataTransform()
|
|
114
120
|
const initialState = getInitialState(configObj)
|
|
@@ -149,6 +155,73 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
149
155
|
// Destructure items from config for more readable JSX
|
|
150
156
|
let { legend, title } = config
|
|
151
157
|
|
|
158
|
+
// Process markup variables for text fields (memoized to prevent re-processing on every render)
|
|
159
|
+
// Note: XSS Safety - The processed content is parsed using html-react-parser which sanitizes
|
|
160
|
+
// HTML input by default. The markup processor returns plain text with user data substituted.
|
|
161
|
+
const processedTextFields = useMemo(() => {
|
|
162
|
+
if (!config.enableMarkupVariables || !config.markupVariables?.length) {
|
|
163
|
+
return {
|
|
164
|
+
title,
|
|
165
|
+
superTitle: config.superTitle,
|
|
166
|
+
introText: config.introText,
|
|
167
|
+
legacyFootnotes: config.legacyFootnotes,
|
|
168
|
+
description: config.description
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
title: title
|
|
174
|
+
? processMarkupVariables(title, config.data || [], config.markupVariables, {
|
|
175
|
+
isEditor,
|
|
176
|
+
filters: config.filters || []
|
|
177
|
+
}).processedContent
|
|
178
|
+
: title,
|
|
179
|
+
superTitle: config.superTitle
|
|
180
|
+
? processMarkupVariables(config.superTitle, config.data || [], config.markupVariables, {
|
|
181
|
+
isEditor,
|
|
182
|
+
filters: config.filters || []
|
|
183
|
+
}).processedContent
|
|
184
|
+
: config.superTitle,
|
|
185
|
+
introText: config.introText
|
|
186
|
+
? processMarkupVariables(config.introText, config.data || [], config.markupVariables, {
|
|
187
|
+
isEditor,
|
|
188
|
+
filters: config.filters || []
|
|
189
|
+
}).processedContent
|
|
190
|
+
: config.introText,
|
|
191
|
+
legacyFootnotes: config.legacyFootnotes
|
|
192
|
+
? processMarkupVariables(config.legacyFootnotes, config.data || [], config.markupVariables, {
|
|
193
|
+
isEditor,
|
|
194
|
+
filters: config.filters || []
|
|
195
|
+
}).processedContent
|
|
196
|
+
: config.legacyFootnotes,
|
|
197
|
+
description: config.description
|
|
198
|
+
? processMarkupVariables(config.description, config.data || [], config.markupVariables, {
|
|
199
|
+
isEditor,
|
|
200
|
+
filters: config.filters || []
|
|
201
|
+
}).processedContent
|
|
202
|
+
: config.description
|
|
203
|
+
}
|
|
204
|
+
}, [
|
|
205
|
+
config.enableMarkupVariables,
|
|
206
|
+
config.markupVariables,
|
|
207
|
+
config.data,
|
|
208
|
+
config.filters,
|
|
209
|
+
title,
|
|
210
|
+
config.superTitle,
|
|
211
|
+
config.introText,
|
|
212
|
+
config.legacyFootnotes,
|
|
213
|
+
config.description,
|
|
214
|
+
isEditor
|
|
215
|
+
])
|
|
216
|
+
|
|
217
|
+
// Destructure processed values
|
|
218
|
+
title = processedTextFields.title
|
|
219
|
+
const processedSuperTitle = processedTextFields.superTitle
|
|
220
|
+
const processedIntroText = processedTextFields.introText
|
|
221
|
+
const processedLegacyFootnotes = processedTextFields.legacyFootnotes
|
|
222
|
+
const processedDescription = processedTextFields.description
|
|
223
|
+
// Note: Axis labels are processed within updateConfig to ensure they use the correct data
|
|
224
|
+
|
|
152
225
|
// set defaults on titles if blank AND only in editor
|
|
153
226
|
if (isEditor) {
|
|
154
227
|
if (!title || title === '') title = 'Chart Title'
|
|
@@ -166,7 +239,22 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
166
239
|
const convertLineToBarGraph = isConvertLineToBarGraph(config, filteredData)
|
|
167
240
|
|
|
168
241
|
const prepareConfig = (loadedConfig: ChartConfig) => {
|
|
169
|
-
|
|
242
|
+
// Create defaults without version to avoid overriding legacy configs
|
|
243
|
+
const defaultsWithoutPalette = { ...defaults }
|
|
244
|
+
|
|
245
|
+
// Only remove palette defaults for legacy (v1) configs
|
|
246
|
+
// New configs and v2 configs should get the v2 palette defaults
|
|
247
|
+
if (loadedConfig?.general?.palette || (!loadedConfig?.general && !loadedConfig?.color)) {
|
|
248
|
+
// Keep palette defaults for:
|
|
249
|
+
// 1. Configs that already have general.palette (v2 configs)
|
|
250
|
+
// 2. New configs (no general section and no legacy color property)
|
|
251
|
+
} else {
|
|
252
|
+
// Remove palette defaults for legacy configs that have color but no general.palette
|
|
253
|
+
delete defaultsWithoutPalette.general?.palette
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
let newConfig = { ...defaultsWithoutPalette, ...loadedConfig }
|
|
257
|
+
|
|
170
258
|
_.defaultsDeep(newConfig, {
|
|
171
259
|
table: { showVertical: false }
|
|
172
260
|
})
|
|
@@ -188,11 +276,30 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
188
276
|
}
|
|
189
277
|
|
|
190
278
|
const updateConfig = (_config: AllChartsConfig, dataOverride?: any[]) => {
|
|
191
|
-
const newConfig =
|
|
279
|
+
const newConfig = cloneConfig(_config)
|
|
192
280
|
let data = dataOverride || stateData
|
|
193
281
|
|
|
194
282
|
data = handleRankByValue(data, newConfig)
|
|
195
283
|
|
|
284
|
+
// Process axis labels for markup variables if enabled
|
|
285
|
+
let processedXAxis = newConfig.xAxis?.label
|
|
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
|
+
}
|
|
302
|
+
|
|
196
303
|
// Deeper copy
|
|
197
304
|
Object.keys(defaults).forEach(key => {
|
|
198
305
|
if (newConfig[key] && 'object' === typeof newConfig[key] && !Array.isArray(newConfig[key])) {
|
|
@@ -223,7 +330,9 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
223
330
|
newConfig.runtime.originalXAxis = newConfig.xAxis
|
|
224
331
|
|
|
225
332
|
if (newConfig.visualizationType === 'Pie') {
|
|
226
|
-
|
|
333
|
+
// Use the same data that will be passed to PieChart (after exclusions and filters)
|
|
334
|
+
const pieData = currentData.length > 0 ? currentData : newExcludedData
|
|
335
|
+
newConfig.runtime.seriesKeys = _.uniq(pieData.map(d => d[newConfig.xAxis.dataKey]))
|
|
227
336
|
newConfig.runtime.seriesLabelsAll = newConfig.runtime.seriesKeys
|
|
228
337
|
} else {
|
|
229
338
|
const finalData = dataOverride || newConfig.formattedData || newConfig.data
|
|
@@ -291,8 +400,15 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
291
400
|
newConfig.orientation === 'horizontal') ||
|
|
292
401
|
['Deviation Bar', 'Paired Bar', 'Forest Plot'].includes(newConfig.visualizationType)
|
|
293
402
|
) {
|
|
294
|
-
|
|
295
|
-
newConfig.runtime.
|
|
403
|
+
// For horizontal charts, axes are swapped, so processedYAxis goes to runtime.xAxis and vice versa
|
|
404
|
+
newConfig.runtime.xAxis = {
|
|
405
|
+
..._.cloneDeep(newConfig.yAxis.yAxis || newConfig.yAxis),
|
|
406
|
+
label: processedYAxis || (newConfig.yAxis.yAxis || newConfig.yAxis).label
|
|
407
|
+
}
|
|
408
|
+
newConfig.runtime.yAxis = {
|
|
409
|
+
..._.cloneDeep(newConfig.xAxis.xAxis || newConfig.xAxis),
|
|
410
|
+
label: processedXAxis || (newConfig.xAxis.xAxis || newConfig.xAxis).label
|
|
411
|
+
}
|
|
296
412
|
newConfig.runtime.yAxis.labelOffset *= -1
|
|
297
413
|
|
|
298
414
|
newConfig.runtime.horizontal = false
|
|
@@ -303,13 +419,13 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
303
419
|
['Scatter Plot', 'Area Chart', 'Line', 'Forecasting'].includes(newConfig.visualizationType) &&
|
|
304
420
|
!convertLineToBarGraph
|
|
305
421
|
) {
|
|
306
|
-
newConfig.runtime.xAxis = newConfig.xAxis
|
|
307
|
-
newConfig.runtime.yAxis = newConfig.yAxis
|
|
422
|
+
newConfig.runtime.xAxis = { ...newConfig.xAxis, label: processedXAxis || newConfig.xAxis.label }
|
|
423
|
+
newConfig.runtime.yAxis = { ...newConfig.yAxis, label: processedYAxis || newConfig.yAxis.label }
|
|
308
424
|
newConfig.runtime.horizontal = false
|
|
309
425
|
newConfig.orientation = 'vertical'
|
|
310
426
|
} else {
|
|
311
|
-
newConfig.runtime.xAxis = newConfig.xAxis
|
|
312
|
-
newConfig.runtime.yAxis = newConfig.yAxis
|
|
427
|
+
newConfig.runtime.xAxis = { ...newConfig.xAxis, label: processedXAxis || newConfig.xAxis.label }
|
|
428
|
+
newConfig.runtime.yAxis = { ...newConfig.yAxis, label: processedYAxis || newConfig.yAxis.label }
|
|
313
429
|
newConfig.runtime.horizontal = false
|
|
314
430
|
}
|
|
315
431
|
|
|
@@ -426,8 +542,16 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
426
542
|
} else if (newConfig.formattedData) {
|
|
427
543
|
newConfig.data = newConfig.formattedData
|
|
428
544
|
} else if (newConfig.dataDescription) {
|
|
429
|
-
|
|
430
|
-
|
|
545
|
+
// For dashboard contexts, get data from datasets if config.data is undefined
|
|
546
|
+
let dataToProcess = newConfig.data
|
|
547
|
+
if (!dataToProcess && isDashboard && datasets && newConfig.dataKey) {
|
|
548
|
+
dataToProcess = datasets[newConfig.dataKey]?.data
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (dataToProcess) {
|
|
552
|
+
newConfig.data = transform.autoStandardize(dataToProcess)
|
|
553
|
+
newConfig.data = transform.developerStandardize(newConfig.data, newConfig.dataDescription)
|
|
554
|
+
}
|
|
431
555
|
}
|
|
432
556
|
} catch (err) {
|
|
433
557
|
console.error('Error on prepareData function ', err)
|
|
@@ -554,6 +678,17 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
554
678
|
} catch (e) {
|
|
555
679
|
console.error('COVE:', e.message)
|
|
556
680
|
}
|
|
681
|
+
publishAnalyticsEvent({
|
|
682
|
+
vizType: config?.type,
|
|
683
|
+
vizSubType: getVizSubType(config),
|
|
684
|
+
eventType: 'chart_legend_reset',
|
|
685
|
+
eventAction: 'click',
|
|
686
|
+
eventLabel: interactionLabel,
|
|
687
|
+
vizTitle: getVizTitle(config),
|
|
688
|
+
...(config.visualizationType === 'Bar' && {
|
|
689
|
+
specifics: `orientation: ${config.orientation === 'horizontal' ? 'horizontal' : 'vertical'}`
|
|
690
|
+
})
|
|
691
|
+
})
|
|
557
692
|
dispatch({ type: 'SET_SERIES_HIGHLIGHT', payload: [] })
|
|
558
693
|
}
|
|
559
694
|
|
|
@@ -816,7 +951,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
816
951
|
}
|
|
817
952
|
|
|
818
953
|
const pivotDynamicSeries = (config: ChartConfig): TableConfig => {
|
|
819
|
-
const tableConfig: TableConfig =
|
|
954
|
+
const tableConfig: TableConfig = cloneConfig(config)
|
|
820
955
|
const dynamicSeries = tableConfig.series.find(series => !!series.dynamicCategory)
|
|
821
956
|
if (dynamicSeries) {
|
|
822
957
|
const pivot: Pivot = { columnName: dynamicSeries.dynamicCategory, valueColumns: [dynamicSeries.dataKey] }
|
|
@@ -888,16 +1023,17 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
888
1023
|
showTitle={config.showTitle}
|
|
889
1024
|
isDashboard={isDashboard}
|
|
890
1025
|
title={title}
|
|
891
|
-
superTitle={
|
|
1026
|
+
superTitle={processedSuperTitle}
|
|
892
1027
|
classes={['chart-title', `${config.theme}`, 'cove-component__header', 'mb-3']}
|
|
893
1028
|
style={undefined}
|
|
1029
|
+
config={config}
|
|
894
1030
|
/>
|
|
895
1031
|
|
|
896
1032
|
{/* Visualization Wrapper */}
|
|
897
1033
|
<div className={getChartWrapperClasses().join(' ')}>
|
|
898
1034
|
{/* Intro Text/Message */}
|
|
899
|
-
{
|
|
900
|
-
<section className={`introText mb-4`}>{parse(
|
|
1035
|
+
{processedIntroText && config.visualizationType !== 'Spark Line' && (
|
|
1036
|
+
<section className={`introText mb-4`}>{parse(processedIntroText)}</section>
|
|
901
1037
|
)}
|
|
902
1038
|
|
|
903
1039
|
{/* Filters */}
|
|
@@ -907,6 +1043,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
907
1043
|
setFilters={setFilters}
|
|
908
1044
|
excludedData={excludedData}
|
|
909
1045
|
dimensions={dimensions}
|
|
1046
|
+
interactionLabel={interactionLabel}
|
|
910
1047
|
/>
|
|
911
1048
|
)}
|
|
912
1049
|
<SkipTo skipId={handleChartTabbing(config, legendId)} skipMessage='Skip Over Chart Container' />
|
|
@@ -943,7 +1080,14 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
943
1080
|
|
|
944
1081
|
{config.visualizationType === 'Pie' && (
|
|
945
1082
|
<ParentSize className='justify-content-center d-flex' style={{ width: `100%` }}>
|
|
946
|
-
{parent =>
|
|
1083
|
+
{parent => (
|
|
1084
|
+
<PieChart
|
|
1085
|
+
ref={svgRef}
|
|
1086
|
+
parentWidth={parent.width}
|
|
1087
|
+
parentHeight={parent.height}
|
|
1088
|
+
interactionLabel={interactionLabel}
|
|
1089
|
+
/>
|
|
1090
|
+
)}
|
|
947
1091
|
</ParentSize>
|
|
948
1092
|
)}
|
|
949
1093
|
{/* Line Chart */}
|
|
@@ -985,10 +1129,11 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
985
1129
|
setFilters={setFilters}
|
|
986
1130
|
excludedData={excludedData}
|
|
987
1131
|
dimensions={dimensions}
|
|
1132
|
+
interactionLabel={interactionLabel}
|
|
988
1133
|
/>
|
|
989
|
-
{
|
|
1134
|
+
{processedIntroText && (
|
|
990
1135
|
<section className='introText mb-4' style={{ padding: '0px 0 35px' }}>
|
|
991
|
-
{parse(
|
|
1136
|
+
{parse(processedIntroText)}
|
|
992
1137
|
</section>
|
|
993
1138
|
)}
|
|
994
1139
|
<div style={{ height: `100px`, width: `100%`, ...sparkLineStyles }}>
|
|
@@ -1012,7 +1157,11 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1012
1157
|
{!config.legend.hide &&
|
|
1013
1158
|
config.visualizationType !== 'Spark Line' &&
|
|
1014
1159
|
config.visualizationType !== 'Sankey' && (
|
|
1015
|
-
<Legend
|
|
1160
|
+
<Legend
|
|
1161
|
+
ref={legendRef}
|
|
1162
|
+
skipId={handleChartTabbing(config, legendId)}
|
|
1163
|
+
interactionLabel={interactionLabel}
|
|
1164
|
+
/>
|
|
1016
1165
|
)}
|
|
1017
1166
|
</LegendWrapper>
|
|
1018
1167
|
{/* Link */}
|
|
@@ -1021,8 +1170,8 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1021
1170
|
: link && link}
|
|
1022
1171
|
{/* Description */}
|
|
1023
1172
|
|
|
1024
|
-
{
|
|
1025
|
-
<div className={getChartSubTextClasses().join(' ')}>{parse(
|
|
1173
|
+
{processedDescription && config.visualizationType !== 'Spark Line' && (
|
|
1174
|
+
<div className={getChartSubTextClasses().join(' ')}>{parse(processedDescription)}</div>
|
|
1026
1175
|
)}
|
|
1027
1176
|
|
|
1028
1177
|
{/* buttons */}
|
|
@@ -1034,6 +1183,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1034
1183
|
type='image'
|
|
1035
1184
|
state={config}
|
|
1036
1185
|
elementToCapture={imageId}
|
|
1186
|
+
interactionLabel={interactionLabel}
|
|
1037
1187
|
/>
|
|
1038
1188
|
)}
|
|
1039
1189
|
{config.table.showDownloadPdfButton && (
|
|
@@ -1043,6 +1193,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1043
1193
|
type='pdf'
|
|
1044
1194
|
state={config}
|
|
1045
1195
|
elementToCapture={imageId}
|
|
1196
|
+
interactionLabel={interactionLabel}
|
|
1046
1197
|
/>
|
|
1047
1198
|
)}
|
|
1048
1199
|
</MediaControls.Section>
|
|
@@ -1054,7 +1205,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1054
1205
|
(config.visualizationType === 'Sankey' && config.table.show)) && (
|
|
1055
1206
|
<DataTable
|
|
1056
1207
|
/* changing the "key" will force the table to re-render
|
|
1057
|
-
|
|
1208
|
+
when the default sort changes while editing */
|
|
1058
1209
|
key={dataTableDefaultSortBy}
|
|
1059
1210
|
config={pivotDynamicSeries(config)}
|
|
1060
1211
|
rawData={
|
|
@@ -1076,12 +1227,13 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1076
1227
|
viewport={currentViewport}
|
|
1077
1228
|
tabbingId={handleChartTabbing(config, legendId)}
|
|
1078
1229
|
colorScale={colorScale}
|
|
1230
|
+
interactionLabel={interactionLabel}
|
|
1079
1231
|
/>
|
|
1080
1232
|
)}
|
|
1081
1233
|
{config?.annotations?.length > 0 && <Annotation.Dropdown />}
|
|
1082
1234
|
{/* show pdf or image button */}
|
|
1083
|
-
{
|
|
1084
|
-
<section className='footnotes pt-2 mt-4'>{parse(
|
|
1235
|
+
{processedLegacyFootnotes && (
|
|
1236
|
+
<section className='footnotes pt-2 mt-4'>{parse(processedLegacyFootnotes)}</section>
|
|
1085
1237
|
)}
|
|
1086
1238
|
</div>
|
|
1087
1239
|
<FootnotesStandAlone
|
|
@@ -1105,6 +1257,9 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1105
1257
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
|
1106
1258
|
}
|
|
1107
1259
|
|
|
1260
|
+
// Get version-specific color palettes based on current config
|
|
1261
|
+
const colorPalettes = filterChartColorPalettes(config)
|
|
1262
|
+
|
|
1108
1263
|
const contextValues = {
|
|
1109
1264
|
...state,
|
|
1110
1265
|
capitalize,
|
|
@@ -1123,6 +1278,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1123
1278
|
handleChartTabbing,
|
|
1124
1279
|
highlight,
|
|
1125
1280
|
handleShowAll,
|
|
1281
|
+
interactionLabel,
|
|
1126
1282
|
isDashboard,
|
|
1127
1283
|
isDebug,
|
|
1128
1284
|
handleDragStateChange,
|
|
@@ -1136,7 +1292,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1136
1292
|
outerContainerRef,
|
|
1137
1293
|
parentRef,
|
|
1138
1294
|
parseDate,
|
|
1139
|
-
rawData:
|
|
1295
|
+
rawData: stateData ?? {},
|
|
1140
1296
|
setConfig,
|
|
1141
1297
|
setEditing,
|
|
1142
1298
|
setParentConfig,
|
|
@@ -1146,7 +1302,7 @@ const CdcChart: React.FC<CdcChartProps> = ({
|
|
|
1146
1302
|
tableData: filteredData || excludedData,
|
|
1147
1303
|
transformedData: getTransformedData({ brushData: state.brushData, filteredData, excludedData, clean }),
|
|
1148
1304
|
twoColorPalette,
|
|
1149
|
-
unfilteredData:
|
|
1305
|
+
unfilteredData: stateData,
|
|
1150
1306
|
updateConfig
|
|
1151
1307
|
}
|
|
1152
1308
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import { Meta, Story } from '@storybook/react'
|
|
2
|
+
import { Meta, Story } from '@storybook/react-vite'
|
|
3
3
|
import Chart from '../CdcChartComponent'
|
|
4
4
|
import exampleComboBarNonNumeric from './../../examples/feature/tests-date-exclusions/date-exclusions-config.json'
|
|
5
|
-
import { editConfigKeys } from '
|
|
5
|
+
import { editConfigKeys } from '@cdc/core/helpers/configHelpers'
|
|
6
6
|
|
|
7
7
|
export default {
|
|
8
8
|
title: 'Components/Templates/Chart/Anchors',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import barChartCiLabels from './_mock/bar_chart_ci_labels.json'
|
|
3
3
|
import lineChartDynamicCI from './_mock/line_chart_dynamic_ci.json'
|
|
4
4
|
import lineChartNonDynamicCI from './_mock/line_chart_non_dynamic_ci.json'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import DynamicSeriesConfig from './_mock/dynamic_series_config.json'
|
|
2
2
|
import DynamicSeriesBarConfig from './_mock/dynamic_series_bar_config.json'
|
|
3
3
|
import DynamicSeriesSuppression from './_mock/dynamic_series_suppression_mock.json'
|
|
4
|
-
import { Meta, StoryObj } from '@storybook/react'
|
|
4
|
+
import { Meta, StoryObj } from '@storybook/react-vite'
|
|
5
5
|
import Chart from '../CdcChartComponent'
|
|
6
6
|
|
|
7
7
|
const meta: Meta<typeof Chart> = {
|
|
@@ -43,7 +43,7 @@ export const LineHoverPoints: Story = {
|
|
|
43
43
|
export const Bar_Vertical: Story = {
|
|
44
44
|
args: {
|
|
45
45
|
config: DynamicSeriesBarConfig,
|
|
46
|
-
isEditor:
|
|
46
|
+
isEditor: true
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import Chart from '../CdcChartComponent'
|
|
3
|
-
import { editConfigKeys } from '
|
|
3
|
+
import { editConfigKeys } from '@cdc/core/helpers/configHelpers'
|
|
4
4
|
import scatterPlotDownloadImage from './_mock/scatterplot-image-download.json'
|
|
5
5
|
|
|
6
6
|
const meta: Meta<typeof Chart> = {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import chartGradientConfig from './_mock/legend.gradient_mock.json'
|
|
3
3
|
import chartGroupedLagend from './_mock/legend_groupBy_mock.json'
|
|
4
4
|
import SimplifiedLineConfig from './_mock/simplified_line.json'
|
|
5
5
|
|
|
6
6
|
import Chart from '../CdcChartComponent'
|
|
7
|
-
import { editConfigKeys } from '
|
|
7
|
+
import { editConfigKeys } from '@cdc/core/helpers/configHelpers'
|
|
8
8
|
|
|
9
9
|
const meta: Meta<typeof Chart> = {
|
|
10
10
|
title: 'Components/Templates/Chart/Legend',
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import StackedPattern from './_mock/stacked-pattern-test.json'
|
|
3
|
+
|
|
4
|
+
import Chart from '../CdcChartComponent'
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Chart> = {
|
|
7
|
+
title: 'Components/Templates/Chart/Patterns',
|
|
8
|
+
component: Chart
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type Story = StoryObj<typeof Chart>
|
|
12
|
+
|
|
13
|
+
export const Stacked_Bar_Pattern: Story = {
|
|
14
|
+
args: {
|
|
15
|
+
config: StackedPattern
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default meta
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
|
|
3
3
|
import Chart from '../CdcChart'
|
|
4
4
|
import lineChartTwoPointsRegressionTest from './_mock/line_chart_two_points_regression_test.json'
|
|
@@ -12,7 +12,7 @@ import pieConfig from './_mock/pie_with_data.json'
|
|
|
12
12
|
import pieCalculatedArea from './_mock/pie_calculated_area.json'
|
|
13
13
|
import areaChartStacked from './_mock/area_chart_stacked.json'
|
|
14
14
|
import multipleLines from './_mock/short_dates.json'
|
|
15
|
-
import { editConfigKeys } from '
|
|
15
|
+
import { editConfigKeys } from '@cdc/core/helpers/configHelpers'
|
|
16
16
|
|
|
17
17
|
const meta: Meta<typeof Chart> = {
|
|
18
18
|
title: 'Components/Templates/Chart',
|
|
@@ -67,18 +67,21 @@ export const BarChart_Labels: Story = {
|
|
|
67
67
|
|
|
68
68
|
export const Pie: Story = {
|
|
69
69
|
args: {
|
|
70
|
-
config: pieConfig
|
|
70
|
+
config: pieConfig,
|
|
71
|
+
isEditor: true
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
export const Pie_Calculated_Area: Story = {
|
|
74
75
|
args: {
|
|
75
|
-
config: pieCalculatedArea
|
|
76
|
+
config: pieCalculatedArea,
|
|
77
|
+
isEditor: true
|
|
76
78
|
}
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
export const Paired_Bar: Story = {
|
|
80
82
|
args: {
|
|
81
|
-
config: pairedBar
|
|
83
|
+
config: pairedBar,
|
|
84
|
+
isEditor: true
|
|
82
85
|
}
|
|
83
86
|
}
|
|
84
87
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import annotationConfig from './_mock/annotation_category_mock.json'
|
|
3
3
|
import annotationConfigDateLinear from './_mock/annotation_date-linear_mock.json'
|
|
4
4
|
import annotationConfigDateTime from './_mock/annotation_date-time_mock.json'
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import SimplifiedLineConfig from './_mock/simplified_line.json'
|
|
3
3
|
|
|
4
4
|
import Chart from '../CdcChartComponent'
|
|
5
|
-
import { editConfigKeys } from '
|
|
5
|
+
import { editConfigKeys } from '@cdc/core/helpers/configHelpers'
|
|
6
6
|
|
|
7
7
|
const meta: Meta<typeof Chart> = {
|
|
8
8
|
title: 'Components/Templates/Chart/Axis Labels',
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
2
|
import Chart from '../CdcChartComponent'
|
|
3
3
|
import longXLabelsConfig from './_mock/large_x_axis_labels.json'
|
|
4
4
|
import pairedBarConfig from './_mock/paired-bar.json'
|
|
5
|
-
import { editConfigKeys } from '
|
|
5
|
+
import { editConfigKeys } from '@cdc/core/helpers/configHelpers'
|
|
6
6
|
import { ChartConfig } from '../types/ChartConfig'
|
|
7
7
|
|
|
8
8
|
const meta: Meta<typeof Chart> = {
|