@cdc/chart 4.22.10 → 4.22.11

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.
Files changed (72) hide show
  1. package/README.md +5 -5
  2. package/dist/cdcchart.js +4 -4
  3. package/examples/age-adjusted-rates.json +1486 -1218
  4. package/examples/case-rate-example-config.json +1 -1
  5. package/examples/covid-confidence-example-config.json +33 -33
  6. package/examples/covid-example-config.json +34 -34
  7. package/examples/covid-example-data-confidence.json +30 -30
  8. package/examples/covid-example-data.json +20 -20
  9. package/examples/cutoff-example-config.json +36 -36
  10. package/examples/cutoff-example-data.json +36 -36
  11. package/examples/date-exclusions-config.json +1 -1
  12. package/examples/dynamic-legends.json +124 -124
  13. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json +191 -197
  14. package/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json +230 -240
  15. package/examples/gallery/bar-chart-horizontal/horizontal-stacked.json +239 -247
  16. package/examples/gallery/bar-chart-vertical/combo-line-chart.json +136 -136
  17. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +79 -79
  18. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +80 -80
  19. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-with-confidence.json +67 -67
  20. package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +110 -110
  21. package/examples/gallery/lollipop/lollipop-style-horizontal.json +215 -219
  22. package/examples/gallery/paired-bar/paired-bar-chart.json +195 -195
  23. package/examples/horizontal-chart.json +35 -35
  24. package/examples/horizontal-stacked-bar-chart.json +34 -34
  25. package/examples/line-chart.json +75 -75
  26. package/examples/paired-bar-data.json +16 -14
  27. package/examples/paired-bar-example.json +48 -48
  28. package/examples/paired-bar-formatted.json +36 -36
  29. package/examples/planet-chart-horizontal-example-config.json +33 -33
  30. package/examples/planet-combo-example-config.json +34 -31
  31. package/examples/planet-example-config.json +35 -33
  32. package/examples/planet-example-data.json +56 -56
  33. package/examples/planet-pie-example-config.json +28 -28
  34. package/examples/private/filters.json +170 -0
  35. package/examples/private/line-test-data.json +21 -21
  36. package/examples/private/line-test-two.json +209 -215
  37. package/examples/private/line-test.json +101 -101
  38. package/examples/private/new.json +48800 -0
  39. package/examples/private/shawn.json +1105 -1295
  40. package/examples/private/test.json +10123 -10123
  41. package/examples/private/yaxis-test.json +4 -3
  42. package/examples/private/yaxis.json +26 -26
  43. package/examples/stacked-vertical-bar-example.json +1 -1
  44. package/examples/temp-example-config.json +61 -54
  45. package/examples/temp-example-data.json +1 -1
  46. package/package.json +2 -2
  47. package/src/CdcChart.tsx +339 -380
  48. package/src/components/BarChart.tsx +425 -469
  49. package/src/components/DataTable.tsx +164 -195
  50. package/src/components/EditorPanel.js +1009 -710
  51. package/src/components/Legend.js +279 -329
  52. package/src/components/LineChart.tsx +90 -79
  53. package/src/components/LinearChart.tsx +376 -434
  54. package/src/components/PairedBarChart.tsx +197 -213
  55. package/src/components/PieChart.tsx +95 -151
  56. package/src/components/SparkLine.js +179 -201
  57. package/src/components/useIntersectionObserver.tsx +17 -20
  58. package/src/context.tsx +3 -3
  59. package/src/data/initial-state.js +37 -16
  60. package/src/hooks/useActiveElement.js +13 -13
  61. package/src/hooks/useChartClasses.js +34 -28
  62. package/src/hooks/useColorPalette.ts +56 -63
  63. package/src/hooks/useLegendClasses.js +18 -10
  64. package/src/hooks/useReduceData.ts +62 -78
  65. package/src/hooks/useRightAxis.js +25 -0
  66. package/src/hooks/useTopAxis.js +6 -0
  67. package/src/index.html +45 -45
  68. package/src/index.tsx +13 -16
  69. package/src/scss/DataTable.scss +5 -4
  70. package/src/scss/editor-panel.scss +71 -69
  71. package/src/scss/main.scss +157 -114
  72. package/src/scss/variables.scss +1 -1
package/src/CdcChart.tsx CHANGED
@@ -1,156 +1,140 @@
1
- import React, { useState, useEffect, useCallback } from 'react';
1
+ import React, { useState, useEffect, useCallback } from 'react'
2
2
 
3
3
  // IE11
4
- import 'core-js/stable';
5
- import ResizeObserver from 'resize-observer-polyfill';
6
- import 'whatwg-fetch';
4
+ import 'core-js/stable'
5
+ import ResizeObserver from 'resize-observer-polyfill'
6
+ import 'whatwg-fetch'
7
7
 
8
8
  // External Libraries
9
- import { scaleOrdinal } from '@visx/scale';
10
- import ParentSize from '@visx/responsive/lib/components/ParentSize';
11
- import { timeParse, timeFormat } from 'd3-time-format';
12
- import Papa from 'papaparse';
13
- import parse from 'html-react-parser';
14
-
9
+ import { scaleOrdinal } from '@visx/scale'
10
+ import ParentSize from '@visx/responsive/lib/components/ParentSize'
11
+ import { timeParse, timeFormat } from 'd3-time-format'
12
+ import Papa from 'papaparse'
13
+ import parse from 'html-react-parser'
15
14
 
16
15
  // Primary Components
17
- import Context from './context';
18
- import PieChart from './components/PieChart';
19
- import LinearChart from './components/LinearChart';
16
+ import Context from './context'
17
+ import PieChart from './components/PieChart'
18
+ import LinearChart from './components/LinearChart'
20
19
 
21
- import {colorPalettesChart as colorPalettes} from '../../core/data/colorPalettes';
20
+ import { colorPalettesChart as colorPalettes } from '../../core/data/colorPalettes'
22
21
 
23
- import { publish, subscribe, unsubscribe } from '@cdc/core/helpers/events';
22
+ import { publish, subscribe, unsubscribe } from '@cdc/core/helpers/events'
24
23
 
25
- import useDataVizClasses from '@cdc/core/helpers/useDataVizClasses';
24
+ import useDataVizClasses from '@cdc/core/helpers/useDataVizClasses'
26
25
 
27
- import SparkLine from './components/SparkLine';
28
- import Legend from './components/Legend';
29
- import DataTable from './components/DataTable';
30
- import defaults from './data/initial-state';
31
- import EditorPanel from './components/EditorPanel';
32
- import Loading from '@cdc/core/components/Loading';
26
+ import SparkLine from './components/SparkLine'
27
+ import Legend from './components/Legend'
28
+ import DataTable from './components/DataTable'
29
+ import defaults from './data/initial-state'
30
+ import EditorPanel from './components/EditorPanel'
31
+ import Loading from '@cdc/core/components/Loading'
33
32
 
34
33
  // helpers
35
34
  import numberFromString from '@cdc/core/helpers/numberFromString'
36
- import getViewport from '@cdc/core/helpers/getViewport';
37
- import { DataTransform } from '@cdc/core/helpers/DataTransform';
38
- import cacheBustingString from '@cdc/core/helpers/cacheBustingString';
39
-
40
- import './scss/main.scss';
41
-
42
- export default function CdcChart(
43
- { configUrl, config: configObj, isEditor = false, isDashboard = false, setConfig: setParentConfig, setEditing, hostname,link} :
44
- { configUrl?: string, config?: any, isEditor?: boolean, isDashboard?: boolean, setConfig?, setEditing?, hostname?,link?:any }
45
- ) {
46
-
47
- const transform = new DataTransform();
48
-
49
- interface keyable { [key: string]: any }
50
-
51
- const [loading, setLoading] = useState<Boolean>(true);
52
- const [colorScale, setColorScale] = useState<any>(null);
53
- const [config, setConfig] = useState<keyable>({});
54
- const [stateData, setStateData] = useState<Array<Object>>(config.data || []);
55
- const [excludedData, setExcludedData] = useState<Array<Object>>();
56
- const [filteredData, setFilteredData] = useState<Array<Object>>();
57
- const [seriesHighlight, setSeriesHighlight] = useState<Array<String>>([]);
58
- const [currentViewport, setCurrentViewport] = useState<String>('lg');
59
- const [dimensions, setDimensions] = useState<Array<Number>>([]);
60
- const [externalFilters, setExternalFilters] = useState(null);
35
+ import getViewport from '@cdc/core/helpers/getViewport'
36
+ import { DataTransform } from '@cdc/core/helpers/DataTransform'
37
+ import cacheBustingString from '@cdc/core/helpers/cacheBustingString'
38
+
39
+ import './scss/main.scss'
40
+
41
+ export default function CdcChart({ configUrl, config: configObj, isEditor = false, isDashboard = false, setConfig: setParentConfig, setEditing, hostname, link }: { configUrl?: string; config?: any; isEditor?: boolean; isDashboard?: boolean; setConfig?; setEditing?; hostname?; link?: any }) {
42
+ const transform = new DataTransform()
43
+
44
+ interface keyable {
45
+ [key: string]: any
46
+ }
47
+
48
+ const [loading, setLoading] = useState<Boolean>(true)
49
+ const [colorScale, setColorScale] = useState<any>(null)
50
+ const [config, setConfig] = useState<keyable>({})
51
+ const [stateData, setStateData] = useState<Array<Object>>(config.data || [])
52
+ const [excludedData, setExcludedData] = useState<Array<Object>>()
53
+ const [filteredData, setFilteredData] = useState<Array<Object>>()
54
+ const [seriesHighlight, setSeriesHighlight] = useState<Array<String>>([])
55
+ const [currentViewport, setCurrentViewport] = useState<String>('lg')
56
+ const [dimensions, setDimensions] = useState<Array<Number>>([])
57
+ const [externalFilters, setExternalFilters] = useState(null)
61
58
  const [container, setContainer] = useState()
62
59
  const [coveLoadedEventRan, setCoveLoadedEventRan] = useState(false)
63
60
  const [dynamicLegendItems, setDynamicLegendItems] = useState([])
64
61
 
65
- const legendGlyphSize = 15;
66
- const legendGlyphSizeHalf = legendGlyphSize / 2;
62
+ const legendGlyphSize = 15
63
+ const legendGlyphSizeHalf = legendGlyphSize / 2
67
64
 
68
- const {
69
- barBorderClass,
70
- lineDatapointClass,
71
- contentClasses,
72
- innerContainerClasses,
73
- sparkLineStyles
74
- } = useDataVizClasses(config)
65
+ const { barBorderClass, lineDatapointClass, contentClasses, innerContainerClasses, sparkLineStyles } = useDataVizClasses(config)
75
66
 
76
67
  const handleChartTabbing = config.showSidebar ? `#legend` : config?.title ? `#dataTableSection__${config.title.replace(/\s/g, '')}` : `#dataTableSection`
77
68
 
78
-
79
-
80
-
81
69
  const handleChartAriaLabels = (state, testing = false) => {
82
- if(testing) console.log(`handleChartAriaLabels Testing On:`, state);
83
- try {
84
- if(!state.visualizationType) throw Error('handleChartAriaLabels: no visualization type found in state');
85
- let ariaLabel = '';
70
+ if (testing) console.log(`handleChartAriaLabels Testing On:`, state)
71
+ try {
72
+ if (!state.visualizationType) throw Error('handleChartAriaLabels: no visualization type found in state')
73
+ let ariaLabel = ''
86
74
 
87
- if(state.visualizationType) {
88
- ariaLabel += `${state.visualizationType} chart`
89
- }
90
-
91
- if(state.title && state.visualizationType) {
92
- ariaLabel += ` with the title: ${state.title}`
93
- }
75
+ if (state.visualizationType) {
76
+ ariaLabel += `${state.visualizationType} chart`
77
+ }
94
78
 
95
- return ariaLabel;
96
- } catch(e) {
97
- console.error(e.message)
79
+ if (state.title && state.visualizationType) {
80
+ ariaLabel += ` with the title: ${state.title}`
98
81
  }
82
+
83
+ return ariaLabel
84
+ } catch (e) {
85
+ console.error(e.message)
86
+ }
99
87
  }
100
88
 
101
89
  const loadConfig = async () => {
102
- let response = configObj || await (await fetch(configUrl)).json();
90
+ let response = configObj || (await (await fetch(configUrl)).json())
103
91
 
104
92
  // If data is included through a URL, fetch that and store
105
- let data = response.formattedData || response.data || {};
93
+ let data = response.formattedData || response.data || {}
106
94
 
107
95
  if (response.dataUrl) {
108
-
109
96
  try {
110
97
  const regex = /(?:\.([^.]+))?$/
111
98
 
112
- const ext = (regex.exec(response.dataUrl)[1])
99
+ const ext = regex.exec(response.dataUrl)[1]
113
100
  if ('csv' === ext) {
114
- data = await fetch(response.dataUrl + `?v=${cacheBustingString()}`)
115
- .then(response => response.text())
116
- .then(responseText => {
117
- const parsedCsv = Papa.parse(responseText, {
118
- header: true,
119
- dynamicTyping: true,
120
- skipEmptyLines: true
121
- })
122
- return parsedCsv.data
123
- })
101
+ data = await fetch(response.dataUrl + `?v=${cacheBustingString()}`)
102
+ .then(response => response.text())
103
+ .then(responseText => {
104
+ const parsedCsv = Papa.parse(responseText, {
105
+ header: true,
106
+ dynamicTyping: true,
107
+ skipEmptyLines: true
108
+ })
109
+ return parsedCsv.data
110
+ })
124
111
  }
125
112
 
126
113
  if ('json' === ext) {
127
- data = await fetch(response.dataUrl + `?v=${cacheBustingString()}`)
128
- .then(response => response.json())
114
+ data = await fetch(response.dataUrl + `?v=${cacheBustingString()}`).then(response => response.json())
129
115
  }
130
116
  } catch {
131
- console.error(`Cannot parse URL: ${response.dataUrl}`);
132
- data = [];
117
+ console.error(`Cannot parse URL: ${response.dataUrl}`)
118
+ data = []
133
119
  }
134
120
 
135
- if(response.dataDescription) {
136
- data = transform.autoStandardize(data);
137
- data = transform.developerStandardize(data, response.dataDescription);
121
+ if (response.dataDescription) {
122
+ data = transform.autoStandardize(data)
123
+ data = transform.developerStandardize(data, response.dataDescription)
138
124
  }
139
125
  }
140
126
 
141
- if(data) {
127
+ if (data) {
142
128
  setStateData(data)
143
129
  setExcludedData(data)
144
130
  }
145
131
 
146
- let newConfig = {...defaults, ...response}
147
- if(undefined === newConfig.table.show) newConfig.table.show = !isDashboard
148
- updateConfig(newConfig, data);
132
+ let newConfig = { ...defaults, ...response }
133
+ if (undefined === newConfig.table.show) newConfig.table.show = !isDashboard
134
+ updateConfig(newConfig, data)
149
135
  }
150
136
 
151
-
152
137
  const updateConfig = (newConfig, dataOverride = undefined) => {
153
-
154
138
  let data = dataOverride || stateData
155
139
 
156
140
  // Deeper copy
@@ -158,23 +142,17 @@ export default function CdcChart(
158
142
  if (newConfig[key] && 'object' === typeof newConfig[key] && !Array.isArray(newConfig[key])) {
159
143
  newConfig[key] = { ...defaults[key], ...newConfig[key] }
160
144
  }
161
- });
145
+ })
162
146
 
163
147
  // Loop through and set initial data with exclusions - this should persist through any following data transformations (ie. filters)
164
148
  let newExcludedData
165
149
 
166
150
  if (newConfig.exclusions && newConfig.exclusions.active) {
167
-
168
151
  if (newConfig.xAxis.type === 'categorical' && newConfig.exclusions.keys?.length > 0) {
169
152
  newExcludedData = data.filter(e => !newConfig.exclusions.keys.includes(e[newConfig.xAxis.dataKey]))
170
- } else if (
171
- newConfig.xAxis.type === 'date' &&
172
- (newConfig.exclusions.dateStart || newConfig.exclusions.dateEnd) &&
173
- newConfig.xAxis.dateParseFormat
174
- ) {
175
-
153
+ } else if (newConfig.xAxis.type === 'date' && (newConfig.exclusions.dateStart || newConfig.exclusions.dateEnd) && newConfig.xAxis.dateParseFormat) {
176
154
  // Filter dates
177
- const timestamp = (e) => new Date(e).getTime();
155
+ const timestamp = e => new Date(e).getTime()
178
156
 
179
157
  let startDate = timestamp(newConfig.exclusions.dateStart)
180
158
  let endDate = timestamp(newConfig.exclusions.dateEnd) + 86399999 //Increase by 24h in ms (86400000ms - 1ms) to include selected end date for .getTime() comparative
@@ -183,16 +161,12 @@ export default function CdcChart(
183
161
  let endDateValid = undefined !== typeof endDate && false === isNaN(endDate)
184
162
 
185
163
  if (startDateValid && endDateValid) {
186
- newExcludedData = data.filter(e =>
187
- (timestamp(e[newConfig.xAxis.dataKey]) >= startDate) &&
188
- (timestamp(e[newConfig.xAxis.dataKey]) <= endDate)
189
- )
164
+ newExcludedData = data.filter(e => timestamp(e[newConfig.xAxis.dataKey]) >= startDate && timestamp(e[newConfig.xAxis.dataKey]) <= endDate)
190
165
  } else if (startDateValid) {
191
166
  newExcludedData = data.filter(e => timestamp(e[newConfig.xAxis.dataKey]) >= startDate)
192
167
  } else if (endDateValid) {
193
168
  newExcludedData = data.filter(e => timestamp(e[newConfig.xAxis.dataKey]) <= endDate)
194
169
  }
195
-
196
170
  } else {
197
171
  newExcludedData = dataOverride || stateData
198
172
  }
@@ -203,134 +177,132 @@ export default function CdcChart(
203
177
  setExcludedData(newExcludedData)
204
178
 
205
179
  // After data is grabbed, loop through and generate filter column values if there are any
206
- let currentData;
180
+ let currentData
207
181
  if (newConfig.filters) {
208
-
209
182
  newConfig.filters.forEach((filter, index) => {
183
+ let filterValues = []
210
184
 
211
- let filterValues = [];
185
+ filterValues = filter.orderedValues || generateValuesForFilter(filter.columnName, newExcludedData)
212
186
 
213
- filterValues = generateValuesForFilter(filter.columnName, newExcludedData);
214
-
215
- newConfig.filters[index].values = filterValues;
216
- // Initial filter should be active
217
- newConfig.filters[index].active = filterValues[0];
218
-
219
- });
220
- currentData = filterData(newConfig.filters, newExcludedData);
221
- setFilteredData(currentData);
187
+ newConfig.filters[index].values = filterValues
188
+ // Initial filter should be active
189
+ newConfig.filters[index].active = filterValues[0]
190
+ })
191
+ currentData = filterData(newConfig.filters, newExcludedData)
192
+ setFilteredData(currentData)
222
193
  }
223
194
 
224
195
  //Enforce default values that need to be calculated at runtime
225
- newConfig.runtime = {};
226
- newConfig.runtime.seriesLabels = {};
227
- newConfig.runtime.seriesLabelsAll = [];
228
- newConfig.runtime.originalXAxis = newConfig.xAxis;
229
-
196
+ newConfig.runtime = {}
197
+ newConfig.runtime.seriesLabels = {}
198
+ newConfig.runtime.seriesLabelsAll = []
199
+ newConfig.runtime.originalXAxis = newConfig.xAxis
230
200
 
231
201
  if (newConfig.visualizationType === 'Pie') {
232
- newConfig.runtime.seriesKeys = (dataOverride || data).map(d => d[newConfig.xAxis.dataKey]);
233
- newConfig.runtime.seriesLabelsAll = newConfig.runtime.seriesKeys;
202
+ newConfig.runtime.seriesKeys = (dataOverride || data).map(d => d[newConfig.xAxis.dataKey])
203
+ newConfig.runtime.seriesLabelsAll = newConfig.runtime.seriesKeys
234
204
  } else {
235
- newConfig.runtime.seriesKeys = newConfig.series ? newConfig.series.map((series) => {
236
- newConfig.runtime.seriesLabels[series.dataKey] = series.label || series.dataKey;
237
- newConfig.runtime.seriesLabelsAll.push(series.label || series.dataKey);
238
- return series.dataKey;
239
- }) : [];
205
+ newConfig.runtime.seriesKeys = newConfig.series
206
+ ? newConfig.series.map(series => {
207
+ newConfig.runtime.seriesLabels[series.dataKey] = series.label || series.dataKey
208
+ newConfig.runtime.seriesLabelsAll.push(series.label || series.dataKey)
209
+ return series.dataKey
210
+ })
211
+ : []
240
212
  }
241
213
 
242
214
  if (newConfig.visualizationType === 'Combo' && newConfig.series) {
243
- newConfig.runtime.barSeriesKeys = [];
244
- newConfig.runtime.lineSeriesKeys = [];
245
- newConfig.series.forEach((series) => {
246
- if(series.type === 'Bar'){
247
- newConfig.runtime.barSeriesKeys.push(series.dataKey);
215
+ newConfig.runtime.barSeriesKeys = []
216
+ newConfig.runtime.lineSeriesKeys = []
217
+ newConfig.series.forEach(series => {
218
+ if (series.type === 'Bar') {
219
+ newConfig.runtime.barSeriesKeys.push(series.dataKey)
248
220
  }
249
- if(series.type === 'Line' || series.type === 'dashed-sm' || series.type === 'dashed-md' || series.type === 'dashed-lg'){
250
- newConfig.runtime.lineSeriesKeys.push(series.dataKey);
221
+ if (series.type === 'Line' || series.type === 'dashed-sm' || series.type === 'dashed-md' || series.type === 'dashed-lg') {
222
+ newConfig.runtime.lineSeriesKeys.push(series.dataKey)
251
223
  }
252
- });
224
+ })
253
225
  }
254
226
 
255
- if ( (newConfig.visualizationType === 'Bar' && newConfig.orientation === 'horizontal') || newConfig.visualizationType === 'Paired Bar') {
256
- newConfig.runtime.xAxis = newConfig.yAxis;
257
- newConfig.runtime.yAxis = newConfig.xAxis;
258
- newConfig.runtime.horizontal = true;
227
+ if ((newConfig.visualizationType === 'Bar' && newConfig.orientation === 'horizontal') || newConfig.visualizationType === 'Paired Bar') {
228
+ newConfig.runtime.xAxis = newConfig.yAxis
229
+ newConfig.runtime.yAxis = newConfig.xAxis
230
+ newConfig.runtime.horizontal = true
259
231
  } else {
260
- newConfig.runtime.xAxis = newConfig.xAxis;
261
- newConfig.runtime.yAxis = newConfig.yAxis;
262
- newConfig.runtime.horizontal = false;
232
+ newConfig.runtime.xAxis = newConfig.xAxis
233
+ newConfig.runtime.yAxis = newConfig.yAxis
234
+ newConfig.runtime.horizontal = false
263
235
  }
264
- newConfig.runtime.uniqueId = Date.now();
265
- newConfig.runtime.editorErrorMessage = newConfig.visualizationType === 'Pie' && !newConfig.yAxis.dataKey ? 'Data Key property in Y Axis section must be set for pie charts.' : '';
236
+ newConfig.runtime.uniqueId = Date.now()
237
+ newConfig.runtime.editorErrorMessage = newConfig.visualizationType === 'Pie' && !newConfig.yAxis.dataKey ? 'Data Key property in Y Axis section must be set for pie charts.' : ''
266
238
 
267
- setConfig(newConfig);
268
- };
239
+ setConfig(newConfig)
240
+ }
269
241
 
270
242
  const filterData = (filters, data) => {
271
- let filteredData = [];
243
+ let filteredData = []
272
244
 
273
- data.forEach((row) => {
274
- let add = true;
275
- filters.forEach((filter) => {
245
+ data.forEach(row => {
246
+ let add = true
247
+ filters.forEach(filter => {
276
248
  if (row[filter.columnName] !== filter.active) {
277
- add = false;
249
+ add = false
278
250
  }
279
- });
251
+ })
280
252
 
281
- if(add) filteredData.push(row);
282
- });
283
- return filteredData;
253
+ if (add) filteredData.push(row)
254
+ })
255
+ return filteredData
284
256
  }
285
257
 
286
258
  // Gets filer values from dataset
287
259
  const generateValuesForFilter = (columnName, data = this.state.data) => {
288
- const values = [];
260
+ const values = []
289
261
 
290
- data.forEach( (row) => {
291
- const value = row[columnName]
292
- if(value && false === values.includes(value)) {
293
- values.push(value)
294
- }
295
- });
262
+ data.forEach(row => {
263
+ const value = row[columnName]
264
+ if (value && false === values.includes(value)) {
265
+ values.push(value)
266
+ }
267
+ })
296
268
 
297
- return values;
269
+ return values
298
270
  }
299
271
 
300
272
  // Sorts data series for horizontal bar charts
301
273
  const sortData = (a, b) => {
302
- let sortKey = config.visualizationType === 'Bar' && config.visualizationSubType === 'horizontal' ? config.xAxis.dataKey : config.yAxis.sortKey;
303
- let aData = parseFloat(a[sortKey]);
304
- let bData = parseFloat(b[sortKey]);
305
-
306
- if(aData < bData){
307
- return config.sortData === 'ascending' ? 1 : -1;
308
- } else if (aData > bData){
309
- return config.sortData === 'ascending' ? -1 : 1;
274
+ let sortKey = config.visualizationType === 'Bar' && config.visualizationSubType === 'horizontal' ? config.xAxis.dataKey : config.yAxis.sortKey
275
+ let aData = parseFloat(a[sortKey])
276
+ let bData = parseFloat(b[sortKey])
277
+
278
+ if (aData < bData) {
279
+ return config.sortData === 'ascending' ? 1 : -1
280
+ } else if (aData > bData) {
281
+ return config.sortData === 'ascending' ? -1 : 1
310
282
  } else {
311
- return 0;
283
+ return 0
312
284
  }
313
285
  }
314
286
 
315
287
  // Observes changes to outermost container and changes viewport size in state
316
- const resizeObserver:ResizeObserver = new ResizeObserver(entries => {
288
+ const resizeObserver: ResizeObserver = new ResizeObserver(entries => {
317
289
  for (let entry of entries) {
318
290
  let { width, height } = entry.contentRect
319
291
  let newViewport = getViewport(width)
320
- let svgMarginWidth = 32;
321
- let editorWidth = 350;
292
+ let svgMarginWidth = 32
293
+ let editorWidth = 350
322
294
 
323
295
  setCurrentViewport(newViewport)
324
296
 
325
- if(isEditor) {
326
- width = width - editorWidth;
297
+ if (isEditor) {
298
+ width = width - editorWidth
327
299
  }
328
300
 
329
- if(entry.target.dataset.lollipop === 'true') {
330
- width = width - 2.5;
301
+ if (entry.target.dataset.lollipop === 'true') {
302
+ width = width - 2.5
331
303
  }
332
304
 
333
- width = width - svgMarginWidth;
305
+ width = width - svgMarginWidth
334
306
 
335
307
  setDimensions([width, height])
336
308
  }
@@ -338,268 +310,277 @@ export default function CdcChart(
338
310
 
339
311
  const outerContainerRef = useCallback(node => {
340
312
  if (node !== null) {
341
- resizeObserver.observe(node);
313
+ resizeObserver.observe(node)
342
314
  }
343
315
 
344
316
  setContainer(node)
345
- },[]);
317
+ }, [])
346
318
 
347
319
  function isEmpty(obj) {
348
- return Object.keys(obj).length === 0;
320
+ return Object.keys(obj).length === 0
349
321
  }
350
322
 
351
323
  // Load data when component first mounts
352
324
  useEffect(() => {
353
- loadConfig();
354
- }, []);
325
+ loadConfig()
326
+ }, [])
355
327
 
356
328
  /**
357
329
  * When cove has a config and container ref publish the cove_loaded event.
358
330
  */
359
331
  useEffect(() => {
360
- if(container && !isEmpty(config) && !coveLoadedEventRan) {
332
+ if (container && !isEmpty(config) && !coveLoadedEventRan) {
361
333
  publish('cove_loaded', { config: config })
362
334
  setCoveLoadedEventRan(true)
363
335
  }
336
+ }, [container, config])
364
337
 
365
- }, [container, config]);
366
-
367
-
368
- /**
369
- * Handles filter change events outside of COVE
370
- * Updates externalFilters state
371
- * Another useEffect listens to externalFilterChanges and updates the config.
372
- */
338
+ /**
339
+ * Handles filter change events outside of COVE
340
+ * Updates externalFilters state
341
+ * Another useEffect listens to externalFilterChanges and updates the config.
342
+ */
373
343
  useEffect(() => {
374
-
375
- const handleFilterData = (e:CustomEvent) => {
376
- let tmp = [];
377
- tmp.push(e.detail)
378
- setExternalFilters(tmp)
344
+ const handleFilterData = (e: CustomEvent) => {
345
+ let tmp = []
346
+ tmp.push(e.detail)
347
+ setExternalFilters(tmp)
379
348
  }
380
-
381
- subscribe('cove_filterData', (e:CustomEvent) => handleFilterData(e))
349
+
350
+ subscribe('cove_filterData', (e: CustomEvent) => handleFilterData(e))
382
351
 
383
352
  return () => {
384
- unsubscribe('cove_filterData', handleFilterData);
353
+ unsubscribe('cove_filterData', handleFilterData)
385
354
  }
355
+ }, [config])
386
356
 
387
- }, [config]);
388
-
389
-
390
- /**
391
- * Handles changes to externalFilters
392
- * For some reason e.detail is returning [order: "asc"] even though
393
- * we're not passing that in. The code here checks for an active prop instead of an empty array.
394
- */
357
+ /**
358
+ * Handles changes to externalFilters
359
+ * For some reason e.detail is returning [order: "asc"] even though
360
+ * we're not passing that in. The code here checks for an active prop instead of an empty array.
361
+ */
395
362
  useEffect(() => {
396
-
397
- if(externalFilters && externalFilters[0]) {
363
+ if (externalFilters && externalFilters[0]) {
398
364
  const hasActiveProperty = externalFilters[0].hasOwnProperty('active')
399
365
 
400
- if(!hasActiveProperty) {
401
- let configCopy = {...config }
366
+ if (!hasActiveProperty) {
367
+ let configCopy = { ...config }
402
368
  delete configCopy['filters']
403
369
  setConfig(configCopy)
404
- setFilteredData(filterData(externalFilters, excludedData));
370
+ setFilteredData(filterData(externalFilters, excludedData))
405
371
  }
406
372
  }
407
373
 
408
- if(externalFilters && externalFilters.length > 0 && externalFilters.length > 0 && externalFilters[0].hasOwnProperty('active')) {
409
- let newConfigHere = {...config, filters: externalFilters }
374
+ if (externalFilters && externalFilters.length > 0 && externalFilters.length > 0 && externalFilters[0].hasOwnProperty('active')) {
375
+ let newConfigHere = { ...config, filters: externalFilters }
410
376
  setConfig(newConfigHere)
411
- setFilteredData(filterData(externalFilters, excludedData));
377
+ setFilteredData(filterData(externalFilters, excludedData))
412
378
  }
413
-
414
- }, [externalFilters]);
379
+ }, [externalFilters])
415
380
 
416
-
417
381
  // Load data when configObj data changes
418
- if(configObj){
382
+ if (configObj) {
419
383
  useEffect(() => {
420
- loadConfig();
421
- }, [configObj.data]);
384
+ loadConfig()
385
+ }, [configObj.data])
422
386
  }
423
387
 
424
388
  // Generates color palette to pass to child chart component
425
389
  useEffect(() => {
426
- if(stateData && config.xAxis && config.runtime.seriesKeys) {
390
+ if (stateData && config.xAxis && config.runtime.seriesKeys) {
427
391
  let palette = config.customColors || colorPalettes[config.palette]
428
392
  let numberOfKeys = config.runtime.seriesKeys.length
429
- let newColorScale;
393
+ let newColorScale
430
394
 
431
- while(numberOfKeys > palette.length) {
432
- palette = palette.concat(palette);
395
+ while (numberOfKeys > palette.length) {
396
+ palette = palette.concat(palette)
433
397
  }
434
398
 
435
- palette = palette.slice(0, numberOfKeys);
399
+ palette = palette.slice(0, numberOfKeys)
436
400
 
437
- newColorScale = () => scaleOrdinal({
438
- domain: config.runtime.seriesLabelsAll,
439
- range: palette,
440
- });
401
+ newColorScale = () =>
402
+ scaleOrdinal({
403
+ domain: config.runtime.seriesLabelsAll,
404
+ range: palette
405
+ })
441
406
 
442
- setColorScale(newColorScale);
443
- setLoading(false);
407
+ setColorScale(newColorScale)
408
+ setLoading(false)
444
409
  }
445
410
 
446
- if(config && stateData && config.sortData){
447
- stateData.sort(sortData);
411
+ if (config && stateData && config.sortData) {
412
+ stateData.sort(sortData)
448
413
  }
449
414
  }, [config, stateData])
450
415
 
451
416
  // Called on legend click, highlights/unhighlights the data series with the given label
452
- const highlight = (label) => {
453
- const newSeriesHighlight = [];
417
+ const highlight = label => {
418
+ const newSeriesHighlight = []
454
419
 
455
420
  // If we're highlighting all the series, reset them
456
- if( (seriesHighlight.length + 1 === config.runtime.seriesKeys.length) && !config.legend.dynamicLegend) {
421
+ if (seriesHighlight.length + 1 === config.runtime.seriesKeys.length && !config.legend.dynamicLegend) {
457
422
  highlightReset()
458
423
  return
459
424
  }
460
425
 
461
- seriesHighlight.forEach((value) => {
462
- newSeriesHighlight.push(value);
463
- });
426
+ seriesHighlight.forEach(value => {
427
+ newSeriesHighlight.push(value)
428
+ })
464
429
 
465
- let newHighlight = label.datum;
466
- if(config.runtime.seriesLabels){
467
- for(let i = 0; i < config.runtime.seriesKeys.length; i++) {
468
- if(config.runtime.seriesLabels[config.runtime.seriesKeys[i]] === label.datum){
469
- newHighlight = config.runtime.seriesKeys[i];
470
- break;
430
+ let newHighlight = label.datum
431
+ if (config.runtime.seriesLabels) {
432
+ for (let i = 0; i < config.runtime.seriesKeys.length; i++) {
433
+ if (config.runtime.seriesLabels[config.runtime.seriesKeys[i]] === label.datum) {
434
+ newHighlight = config.runtime.seriesKeys[i]
435
+ break
471
436
  }
472
437
  }
473
438
  }
474
439
 
475
440
  if (newSeriesHighlight.indexOf(newHighlight) !== -1) {
476
- newSeriesHighlight.splice(newSeriesHighlight.indexOf(newHighlight), 1);
441
+ newSeriesHighlight.splice(newSeriesHighlight.indexOf(newHighlight), 1)
477
442
  } else {
478
- newSeriesHighlight.push(newHighlight);
443
+ newSeriesHighlight.push(newHighlight)
479
444
  }
480
- setSeriesHighlight(newSeriesHighlight);
481
- };
445
+ setSeriesHighlight(newSeriesHighlight)
446
+ }
482
447
 
483
448
  // Called on reset button click, unhighlights all data series
484
449
  const highlightReset = () => {
485
- if(config.legend.dynamicLegend && dynamicLegendItems) {
486
- setSeriesHighlight(dynamicLegendItems.map( item => item.text ))
450
+ if (config.legend.dynamicLegend && dynamicLegendItems) {
451
+ setSeriesHighlight(dynamicLegendItems.map(item => item.text))
487
452
  } else {
488
- setSeriesHighlight([]);
453
+ setSeriesHighlight([])
489
454
  }
490
455
  }
491
456
 
492
- const section = config.orientation ==='horizontal' ? 'yAxis' :'xAxis';
457
+ const section = config.orientation === 'horizontal' ? 'yAxis' : 'xAxis'
493
458
 
494
459
  const parseDate = (dateString: string) => {
495
- let date = timeParse(config.runtime[section].dateParseFormat)(dateString);
496
- if(!date) {
497
- config.runtime.editorErrorMessage = `Error parsing date "${dateString}". Try reviewing your data and date parse settings in the X Axis section.`;
498
- return new Date();
460
+ let date = timeParse(config.runtime[section].dateParseFormat)(dateString)
461
+ if (!date) {
462
+ config.runtime.editorErrorMessage = `Error parsing date "${dateString}". Try reviewing your data and date parse settings in the X Axis section.`
463
+ return new Date()
499
464
  } else {
500
- return date;
465
+ return date
501
466
  }
502
- };
503
-
467
+ }
504
468
 
505
469
  const formatDate = (date: Date) => {
506
- return timeFormat(config.runtime[section].dateDisplayFormat)(date);
507
- };
470
+ return timeFormat(config.runtime[section].dateDisplayFormat)(date)
471
+ }
508
472
 
509
473
  // Format numeric data based on settings in config
510
- const formatNumber = (num) => {
474
+ const formatNumber = (num, axis) => {
511
475
  // check if value contains comma and remove it. later will add comma below.
512
- if(String(num).indexOf(',') !== -1) num = num.replaceAll(',', '');
476
+ if (String(num).indexOf(',') !== -1) num = num.replaceAll(',', '')
513
477
  // if num is NaN return num
514
- if(isNaN(num)|| !num) return num ;
478
+ if (isNaN(num) || !num) return num
515
479
 
516
- let original = num;
517
- let prefix = config.dataFormat.prefix;
480
+ let original = num
481
+ let prefix = config.dataFormat.prefix
482
+ let stringFormattingOptions
518
483
 
519
- let stringFormattingOptions = {
520
- useGrouping: config.dataFormat.commas ? true : false,
521
- minimumFractionDigits: config.dataFormat.roundTo ? Number(config.dataFormat.roundTo) : 0,
522
- maximumFractionDigits: config.dataFormat.roundTo ? Number(config.dataFormat.roundTo) : 0
523
- };
484
+ if (axis !== 'right') {
485
+ stringFormattingOptions = {
486
+ useGrouping: config.dataFormat.commas ? true : false,
487
+ minimumFractionDigits: config.dataFormat.roundTo ? Number(config.dataFormat.roundTo) : 0,
488
+ maximumFractionDigits: config.dataFormat.roundTo ? Number(config.dataFormat.roundTo) : 0
489
+ }
490
+ } else {
491
+ stringFormattingOptions = {
492
+ useGrouping: config.dataFormat.rightCommas ? true : false,
493
+ minimumFractionDigits: config.dataFormat.rightRoundTo ? Number(config.dataFormat.rightRoundTo) : 0,
494
+ maximumFractionDigits: config.dataFormat.rightRoundTo ? Number(config.dataFormat.rightRoundTo) : 0
495
+ }
496
+ }
497
+
498
+ num = numberFromString(num)
524
499
 
525
- num = numberFromString(num);
526
-
527
500
  if (isNaN(num)) {
528
- config.runtime.editorErrorMessage = `Unable to parse number from data ${original}. Try reviewing your data and selections in the Data Series section.`;
501
+ config.runtime.editorErrorMessage = `Unable to parse number from data ${original}. Try reviewing your data and selections in the Data Series section.`
529
502
  return original
530
503
  }
531
504
 
532
- if (!config.dataFormat) return num;
533
- if (config.dataCutoff){
505
+ if (!config.dataFormat) return num
506
+ if (config.dataCutoff) {
534
507
  let cutoff = numberFromString(config.dataCutoff)
535
508
 
536
- if(num < cutoff) {
537
- num = cutoff;
509
+ if (num < cutoff) {
510
+ num = cutoff
538
511
  }
539
512
  }
540
513
  num = num.toLocaleString('en-US', stringFormattingOptions)
541
514
 
542
- let result = ""
515
+ let result = ''
543
516
 
544
- if(prefix) {
517
+ if (prefix && axis !== 'right') {
545
518
  result += prefix
546
519
  }
547
520
 
521
+ if (config.dataFormat.rightPrefix && axis === 'right') {
522
+ result += config.dataFormat.rightPrefix
523
+ }
524
+
548
525
  result += num
549
526
 
550
- if(config.dataFormat.suffix) {
527
+ if (config.dataFormat.suffix && axis !== 'right') {
551
528
  result += config.dataFormat.suffix
552
529
  }
530
+
531
+ if (config.dataFormat.rightSuffix && axis === 'right') {
532
+ result += config.dataFormat.rightSuffix
533
+ }
534
+
553
535
  return String(result)
554
- };
536
+ }
555
537
 
556
538
  // Destructure items from config for more readable JSX
557
- const { legend, title, description, visualizationType } = config;
539
+ const { legend, title, description, visualizationType } = config
558
540
 
559
541
  // Select appropriate chart type
560
542
  const chartComponents = {
561
- 'Paired Bar' : <LinearChart />,
562
- 'Bar' : <LinearChart />,
563
- 'Line' : <LinearChart />,
564
- 'Combo': <LinearChart />,
565
- 'Pie' : <PieChart />,
543
+ 'Paired Bar': <LinearChart />,
544
+ Bar: <LinearChart />,
545
+ Line: <LinearChart />,
546
+ Combo: <LinearChart />,
547
+ Pie: <PieChart />
566
548
  }
567
549
 
568
550
  const Filters = () => {
569
551
  const changeFilterActive = (index, value) => {
570
- let newFilters = config.filters;
552
+ let newFilters = config.filters
571
553
 
572
- newFilters[index].active = value;
554
+ newFilters[index].active = value
573
555
 
574
- setConfig({...config, filters: newFilters});
556
+ setConfig({ ...config, filters: newFilters })
575
557
 
576
- setFilteredData(filterData(newFilters, excludedData));
577
- };
558
+ setFilteredData(filterData(newFilters, excludedData))
559
+ }
578
560
 
579
- const announceChange = (text) => {};
561
+ const announceChange = text => {}
580
562
 
581
- let filterList = '';
563
+ let filterList = ''
582
564
  if (config.filters) {
583
-
584
565
  filterList = config.filters.map((singleFilter, index) => {
585
- const values = [];
566
+ const values = []
586
567
  const sortAsc = (a, b) => {
587
568
  return a.toString().localeCompare(b.toString(), 'en', { numeric: true })
588
- };
569
+ }
589
570
 
590
571
  const sortDesc = (a, b) => {
591
572
  return b.toString().localeCompare(a.toString(), 'en', { numeric: true })
592
- };
573
+ }
593
574
 
594
- if(!singleFilter.order || singleFilter.order === '' ){
575
+ if (!singleFilter.order || singleFilter.order === '') {
595
576
  singleFilter.order = 'asc'
596
577
  }
597
578
 
598
- if(singleFilter.order === 'desc') {
579
+ if (singleFilter.order === 'desc') {
599
580
  singleFilter.values = singleFilter.values.sort(sortDesc)
600
581
  }
601
582
 
602
- if(singleFilter.order === 'asc') {
583
+ if (singleFilter.order === 'asc') {
603
584
  singleFilter.values = singleFilter.values.sort(sortAsc)
604
585
  }
605
586
 
@@ -608,81 +589,68 @@ export default function CdcChart(
608
589
  <option key={index} value={filterOption}>
609
590
  {filterOption}
610
591
  </option>
611
- );
612
- });
592
+ )
593
+ })
613
594
 
614
595
  return (
615
- <div className="single-filter" key={index}>
596
+ <div className='single-filter' key={index}>
616
597
  <label htmlFor={`filter-${index}`}>{singleFilter.label}</label>
617
598
  <select
618
599
  id={`filter-${index}`}
619
- className="filter-select"
620
- data-index="0"
600
+ className='filter-select'
601
+ data-index='0'
621
602
  value={singleFilter.active}
622
- onChange={(val) => {
623
- changeFilterActive(index, val.target.value);
624
- announceChange(`Filter ${singleFilter.label} value has been changed to ${val.target.value}, please reference the data table to see updated values.`);
603
+ onChange={val => {
604
+ changeFilterActive(index, val.target.value)
605
+ announceChange(`Filter ${singleFilter.label} value has been changed to ${val.target.value}, please reference the data table to see updated values.`)
625
606
  }}
626
607
  >
627
608
  {values}
628
609
  </select>
629
610
  </div>
630
- );
631
- });
611
+ )
612
+ })
632
613
  }
633
614
 
634
- return (<section className="filters-section">{filterList}</section>)
615
+ return <section className='filters-section'>{filterList}</section>
635
616
  }
636
617
 
637
618
  const missingRequiredSections = () => {
638
619
  if (config.visualizationType === 'Pie') {
639
620
  if (undefined === config?.yAxis.dataKey) {
640
- return true;
621
+ return true
641
622
  }
642
623
  } else {
643
624
  if (undefined === config?.series || false === config?.series.length > 0) {
644
- return true;
625
+ return true
645
626
  }
646
627
  }
647
628
 
648
629
  if (!config.xAxis.dataKey) {
649
- return true;
630
+ return true
650
631
  }
651
632
 
652
- return false;
653
- };
633
+ return false
634
+ }
654
635
 
655
636
  // Prevent render if loading
656
- let body = (<Loading />)
657
-
658
-
659
- if(!loading) {
660
-
637
+ let body = <Loading />
661
638
 
639
+ if (!loading) {
662
640
  body = (
663
641
  <>
664
642
  {isEditor && <EditorPanel />}
665
643
  {!missingRequiredSections() && !config.newViz && (
666
- <div className="cdc-chart-inner-container">
644
+ <div className='cdc-chart-inner-container'>
667
645
  {/* Title */}
668
-
646
+
669
647
  {title && (
670
- <div
671
- role="heading"
672
- className={`chart-title ${config.theme} cove-component__header`}
673
- aria-level={2}
674
- >
675
- {config && (
676
- <sup className="superTitle">{parse(config.superTitle || '')}</sup>
677
- )}
648
+ <div role='heading' className={`chart-title ${config.theme} cove-component__header`} aria-level={2}>
649
+ {config && <sup className='superTitle'>{parse(config.superTitle || '')}</sup>}
678
650
  <div>{parse(title)}</div>
679
651
  </div>
680
652
  )}
681
- <a
682
- id="skip-chart-container"
683
- className="cdcdataviz-sr-only-focusable"
684
- href={handleChartTabbing}
685
- >
653
+ <a id='skip-chart-container' className='cdcdataviz-sr-only-focusable' href={handleChartTabbing}>
686
654
  Skip Over Chart Container
687
655
  </a>
688
656
  {/* Filters */}
@@ -690,22 +658,20 @@ export default function CdcChart(
690
658
  {/* Visualization */}
691
659
  {config?.introText && <section className="introText">{parse(config.introText)}</section>}
692
660
  <div
693
- className={`chart-container${
694
- config.legend.hide ? " legend-hidden" : ""
661
+ className={`chart-container ${config.legend.position==='bottom'? "bottom":""
662
+ }${config.legend.hide ? " legend-hidden" : ""
695
663
  }${lineDatapointClass}${barBorderClass} ${contentClasses.join(' ')}`}
696
664
  >
697
665
  {/* All charts except sparkline */}
698
- {config.visualizationType !== "Spark Line" &&
699
- chartComponents[visualizationType]
700
- }
666
+ {config.visualizationType !== 'Spark Line' && chartComponents[visualizationType]}
701
667
 
702
668
  {/* Sparkline */}
703
- {config.visualizationType === "Spark Line" && (
669
+ {config.visualizationType === 'Spark Line' && (
704
670
  <>
705
- { description && <div className="subtext">{parse(description)}</div>}
671
+ {description && <div className='subtext'>{parse(description)}</div>}
706
672
  <div style={sparkLineStyles}>
707
673
  <ParentSize>
708
- {(parent) => (
674
+ {parent => (
709
675
  <>
710
676
  <SparkLine width={parent.width} height={parent.height} />
711
677
  </>
@@ -713,26 +679,25 @@ export default function CdcChart(
713
679
  </ParentSize>
714
680
  </div>
715
681
  </>
716
- )
717
- }
718
- {!config.legend.hide && config.visualizationType !== "Spark Line" && <Legend />}
682
+ )}
683
+ {!config.legend.hide && config.visualizationType !== 'Spark Line' && <Legend />}
719
684
  </div>
720
685
  {/* Link */}
721
686
  {link && link}
722
687
  {/* Description */}
723
- {description && config.visualizationType !== "Spark Line" && <div className="subtext">{parse(description)}</div>}
688
+ {description && config.visualizationType !== 'Spark Line' && <div className='subtext'>{parse(description)}</div>}
724
689
  {/* Data Table */}
725
690
 
726
- {config.xAxis.dataKey && config.table.show && config.visualizationType !== "Spark Line" && <DataTable />}
727
- {config?.footnotes && <section className="footnotes">{parse(config.footnotes)}</section>}
691
+ {config.xAxis.dataKey && config.table.show && config.visualizationType !== 'Spark Line' && <DataTable />}
692
+ {config?.footnotes && <section className='footnotes'>{parse(config.footnotes)}</section>}
728
693
  </div>
729
694
  )}
730
695
  </>
731
- );
696
+ )
732
697
  }
733
698
 
734
- const getXAxisData = (d: any) => config.runtime.xAxis.type === 'date' ? (parseDate(d[config.runtime.originalXAxis.dataKey])).getTime() : d[config.runtime.originalXAxis.dataKey];
735
- const getYAxisData = (d: any, seriesKey: string) => d[seriesKey];
699
+ const getXAxisData = (d: any) => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
700
+ const getYAxisData = (d: any, seriesKey: string) => d[seriesKey]
736
701
 
737
702
  const contextValues = {
738
703
  getXAxisData,
@@ -767,15 +732,9 @@ export default function CdcChart(
767
732
  setDynamicLegendItems
768
733
  }
769
734
 
770
- const classes = [
771
- 'cdc-open-viz-module',
772
- 'type-chart',
773
- `${currentViewport}`,
774
- `font-${config.fontSize}`,
775
- `${config.theme}`
776
- ]
735
+ const classes = ['cdc-open-viz-module', 'type-chart', `${currentViewport}`, `font-${config.fontSize}`, `${config.theme}`]
777
736
 
778
- config.visualizationType === "Spark Line" && classes.push(`type-sparkline`)
737
+ config.visualizationType === 'Spark Line' && classes.push(`type-sparkline`)
779
738
  isEditor && classes.push('spacing-wrapper')
780
739
  isEditor && classes.push('isEditor')
781
740
 
@@ -785,5 +744,5 @@ export default function CdcChart(
785
744
  {body}
786
745
  </div>
787
746
  </Context.Provider>
788
- );
747
+ )
789
748
  }