@cdc/chart 4.23.1 → 4.23.2

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 (52) hide show
  1. package/dist/cdcchart.js +54532 -696
  2. package/examples/Barchart_with_negative.json +34 -0
  3. package/examples/box-plot.json +2 -2
  4. package/examples/dynamic-legends.json +1 -1
  5. package/examples/example-bar-chart-nonnumeric.json +36 -0
  6. package/examples/example-bar-chart.json +33 -0
  7. package/examples/example-combo-bar-nonnumeric.json +105 -0
  8. package/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json +1 -1
  9. package/examples/gallery/bar-chart-vertical/vertical-bar-chart.json +2 -2
  10. package/examples/gallery/paired-bar/paired-bar-chart.json +65 -13
  11. package/examples/line-chart-nonnumeric.json +32 -0
  12. package/examples/line-chart.json +21 -63
  13. package/examples/newdata.json +1 -1
  14. package/examples/planet-combo-example-config.json +143 -20
  15. package/examples/planet-example-data-nonnumeric.json +56 -0
  16. package/examples/planet-example-data.json +2 -2
  17. package/examples/planet-pie-example-config-nonnumeric.json +30 -0
  18. package/examples/scatterplot-continuous.csv +17 -0
  19. package/examples/scatterplot.json +136 -0
  20. package/examples/sparkline-chart-nonnumeric.json +76 -0
  21. package/examples/stacked-vertical-bar-example-negative.json +154 -0
  22. package/examples/stacked-vertical-bar-example-nonnumerics.json +154 -0
  23. package/index.html +74 -0
  24. package/package.json +29 -23
  25. package/src/{CdcChart.tsx → CdcChart.jsx} +74 -56
  26. package/src/components/{BarChart.tsx → BarChart.jsx} +99 -91
  27. package/src/components/BoxPlot.jsx +88 -0
  28. package/src/components/{DataTable.tsx → DataTable.jsx} +102 -25
  29. package/src/components/{EditorPanel.js → EditorPanel.jsx} +228 -14
  30. package/src/components/{Filters.js → Filters.jsx} +6 -12
  31. package/src/components/{Legend.js → Legend.jsx} +120 -108
  32. package/src/components/{LineChart.tsx → LineChart.jsx} +26 -12
  33. package/src/components/{LinearChart.tsx → LinearChart.jsx} +67 -47
  34. package/src/components/{PairedBarChart.tsx → PairedBarChart.jsx} +45 -78
  35. package/src/components/{PieChart.tsx → PieChart.jsx} +17 -32
  36. package/src/components/ScatterPlot.jsx +48 -0
  37. package/src/components/{SparkLine.js → SparkLine.jsx} +49 -18
  38. package/src/components/{useIntersectionObserver.tsx → useIntersectionObserver.jsx} +1 -1
  39. package/src/data/initial-state.js +33 -3
  40. package/src/hooks/{useColorPalette.ts → useColorPalette.js} +10 -28
  41. package/src/hooks/{useReduceData.ts → useReduceData.js} +25 -14
  42. package/src/hooks/useRightAxis.js +3 -1
  43. package/src/index.jsx +16 -0
  44. package/src/scss/DataTable.scss +22 -0
  45. package/src/scss/main.scss +30 -10
  46. package/vite.config.js +4 -0
  47. package/dist/495.js +0 -3
  48. package/dist/703.js +0 -1
  49. package/src/components/BoxPlot.js +0 -92
  50. package/src/index.html +0 -67
  51. package/src/index.tsx +0 -18
  52. /package/src/{context.tsx → ConfigContext.jsx} +0 -0
@@ -0,0 +1,154 @@
1
+ {
2
+ "title": "Example Stacked Vertical",
3
+ "visualizationType": "Bar",
4
+ "visualizationSubType": "stacked",
5
+ "orientation": "vertical",
6
+ "animate": true,
7
+ "animateReplay": true,
8
+ "yAxis": {
9
+ "hideAxis": false,
10
+ "hideLabel": false,
11
+ "hideTicks": false,
12
+ "size": 50,
13
+ "gridLines": false
14
+ },
15
+ "barThickness": 0.35,
16
+ "height": 300,
17
+ "xAxis": {
18
+ "type": "categorical",
19
+ "hideAxis": false,
20
+ "hideLabel": false,
21
+ "hideTicks": false,
22
+ "size": 75,
23
+ "tickRotation": 0,
24
+ "dataKey": "Date"
25
+ },
26
+ "table": {
27
+ "label": "Data Table",
28
+ "expanded": true,
29
+ "show": true
30
+ },
31
+ "legend": {
32
+ "behavior": "isolate",
33
+ "position": "right",
34
+ "reverseLabelOrder": false
35
+ },
36
+ "series": [
37
+ {
38
+ "dataKey": "Data 1",
39
+ "type": "Bar"
40
+ },
41
+ {
42
+ "dataKey": "Data 2",
43
+ "type": "Bar"
44
+ }
45
+ ],
46
+ "data": [
47
+ {
48
+ "Date": "1/15/2016",
49
+ "Data 1": "90",
50
+ "Data 2": "NA",
51
+ "Data 3": "300",
52
+ "Data 4": "95",
53
+ "Data 5": "120",
54
+ "Data 6": "310",
55
+ "Data 7": "40",
56
+ "Data 8": "90",
57
+ "Data 9": "240",
58
+ "Data 10": "60",
59
+ "Data 11": "160",
60
+ "Data 12": "200"
61
+ },
62
+ {
63
+ "Date": "2/15/2016",
64
+ "Data 1": "40",
65
+ "Data 2": "90",
66
+ "Data 3": "240",
67
+ "Data 4": "60",
68
+ "Data 5": "160",
69
+ "Data 6": "200",
70
+ "Data 7": "40",
71
+ "Data 8": "90",
72
+ "Data 9": "240",
73
+ "Data 10": "60",
74
+ "Data 11": "160",
75
+ "Data 12": "200"
76
+ },
77
+ {
78
+ "Date": "3/15/2016",
79
+ "Data 1": "50",
80
+ "Data 2": "300",
81
+ "Data 3": "290",
82
+ "Data 4": "100",
83
+ "Data 5": "200",
84
+ "Data 6": "250",
85
+ "Data 7": "80",
86
+ "Data 8": "350",
87
+ "Data 9": "300",
88
+ "Data 10": "150",
89
+ "Data 11": "130",
90
+ "Data 12": "100"
91
+ },
92
+ {
93
+ "Date": "4/15/2016",
94
+ "Data 1": "120",
95
+ "Data 2": "160",
96
+ "Data 3": "230",
97
+ "Data 4": "180",
98
+ "Data 5": "160",
99
+ "Data 6": "220",
100
+ "Data 7": "40",
101
+ "Data 8": "90",
102
+ "Data 9": "240",
103
+ "Data 10": "60",
104
+ "Data 11": "160",
105
+ "Data 12": "200"
106
+ },
107
+ {
108
+ "Date": "5/15/2016",
109
+ "Data 1": "80",
110
+ "Data 2": "350",
111
+ "Data 3": "300",
112
+ "Data 4": "150",
113
+ "Data 5": "130",
114
+ "Data 6": "100",
115
+ "Data 7": "120",
116
+ "Data 8": "160",
117
+ "Data 9": "230",
118
+ "Data 10": "180",
119
+ "Data 11": "160",
120
+ "Data 12": "220"
121
+ },
122
+ {
123
+ "Date": "6/15/2016",
124
+ "Data 1": "90",
125
+ "Data 2": "220",
126
+ "Data 3": "320",
127
+ "Data 4": "100",
128
+ "Data 5": "220",
129
+ "Data 6": "300",
130
+ "Data 7": "40",
131
+ "Data 8": "90",
132
+ "Data 9": "240",
133
+ "Data 10": "60",
134
+ "Data 11": "160",
135
+ "Data 12": "200"
136
+ },
137
+ {
138
+ "Date": "7/15/2016",
139
+ "Data 1": "120",
140
+ "Data 2": "160",
141
+ "Data 3": "230",
142
+ "Data 4": "180",
143
+ "Data 5": "160",
144
+ "Data 6": "220",
145
+ "Data 7": "80",
146
+ "Data 8": "350",
147
+ "Data 9": "300",
148
+ "Data 10": "150",
149
+ "Data 11": "130",
150
+ "Data 12": "100"
151
+ }
152
+
153
+ ]
154
+ }
package/index.html ADDED
@@ -0,0 +1,74 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
7
+ <style>
8
+ body {
9
+ /* max-width: 1000px; */
10
+ margin: 0 auto !important;
11
+ display: flex;
12
+ flex-direction: column;
13
+ justify-content: center;
14
+ }
15
+
16
+ .react-container+.react-container {
17
+ margin-top: 3rem;
18
+ }
19
+ </style>
20
+ </head>
21
+
22
+ <body>
23
+ <!-- <div class="react-container" data-config="/examples/temp-example-config.json"></div> -->
24
+
25
+ <!-- <select id="cove_select">
26
+ <option value=""">Choose An Option</option>
27
+ <option value="Non-Hispanic White">Non-Hispanic White</option>
28
+ <option value="Hispanic or Latino">Test 2</option>
29
+ </select> -->
30
+
31
+ <!-- <div class="react-container" data-config="/examples/dynamic-legends.json"></div> -->
32
+ <!-- <div class="react-container" data-config="/examples/cutoff-example-config.json"></div> -->
33
+ <!-- <div class="react-container" data-config="/examples/covid-confidence-example-config.json"></div> -->
34
+ <!-- <div class="react-container" data-config="/examples/planet-example-config.json"></div> -->
35
+ <!-- <div class="react-container" data-config="/examples/planet-chart-horizontal-example-config.json"></div> -->
36
+ <!-- <div class="react-container" data-config="/examples/planet-example-config.json"></div> -->
37
+ <!-- <div class="react-container" data-config="/examples/date-exclusions-config.json"></div> -->
38
+ <!-- <div class="react-container" data-config="/examples/case-rate-example-config.json"></div> -->
39
+ <!-- <div class="react-container" data-config="/examples/private/textelements.json"></div> -->
40
+ <!-- <div class="react-container" data-config="/examples/private/example-bar-chart.json"></div> -->
41
+ <!-- <div class="react-container" data-config="/examples/example-sparkline.json"></div> -->
42
+ <!-- DATA PRESENTATION GALLERY: https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/bar-chart.html#examples -->
43
+
44
+ <!-- NONNUMERIC TESTS -->
45
+ <!-- <div class="react-container" data-config="/examples/planet-pie-example-config-nonnumeric.json"></div> -->
46
+ <div class="react-container" data-config="/examples/example-combo-bar-nonnumeric.json"></div>
47
+ <!-- <div class="react-container" data-config="/examples/example-bar-chart-nonnumeric.json"></div> -->
48
+ <!-- <div class="react-container" data-config="/examples/line-chart-nonnumeric.json"></div> -->
49
+ <!-- <div class="react-container" data-config="/examples/sparkline-chart-nonnumeric.json"></div> -->
50
+
51
+ <!-- HORIZONTAL BAR CHARTS -->
52
+ <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json"></div> -->
53
+ <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-bar-chart.json"></div> -->
54
+ <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-stacked.json"></div> -->
55
+
56
+ <!-- VERTICAL BAR CHARTS -->
57
+ <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/combo-line-chart.json"></div> -->
58
+ <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json"></div> -->
59
+ <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json"></div> -->
60
+ <!-- <div class="react-container" data-config="/examples/stacked-vertical-bar-example-nonnumerics.json"></div> -->
61
+ <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-with-confidence.json"></div> -->
62
+ <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart.json"></div> -->
63
+ <!-- <div class="react-container" data-config="/examples/box-plot.json"></div> -->
64
+
65
+ <!-- Paired bar Chart -->
66
+ <div class="react-container" data-config="/examples/gallery/paired-bar/paired-bar-chart.json"></div>
67
+
68
+ <noscript>You need to enable JavaScript to run this app.</noscript>
69
+ </body>
70
+
71
+ <script type="module" src="./src/index.jsx"></script>
72
+ </body>
73
+
74
+ </html>
package/package.json CHANGED
@@ -1,11 +1,15 @@
1
1
  {
2
2
  "name": "@cdc/chart",
3
- "version": "4.23.1",
3
+ "version": "4.23.2",
4
4
  "description": "React component for visualizing tabular data in various types of charts",
5
+ "moduleName": "CdcChart",
5
6
  "main": "dist/cdcchart",
7
+ "type": "module",
6
8
  "scripts": {
7
- "start": "npx webpack serve --mode development -c ../../webpack.config.js",
8
- "build": "npx webpack --mode production --env packageName=CdcChart --env folderName=chart -c ../../webpack.config.js",
9
+ "start": "vite --open",
10
+ "build": "vite build",
11
+ "preview": "vite preview",
12
+ "graph": "nx graph",
9
13
  "prepublishOnly": "lerna run --scope @cdc/chart build"
10
14
  },
11
15
  "repository": {
@@ -19,37 +23,39 @@
19
23
  },
20
24
  "license": "Apache-2.0",
21
25
  "dependencies": {
22
- "@cdc/core": "^1.1.4",
23
- "@visx/axis": "^1.0.0",
24
- "@visx/curve": "^1.0.0",
25
- "@visx/gradient": "^1.0.0",
26
- "@visx/group": "^1.0.0",
27
- "@visx/legend": "^1.1.0",
28
- "@visx/marker": "^1.1.0",
29
- "@visx/mock-data": "^1.0.0",
30
- "@visx/scale": "^1.0.0",
31
- "@visx/shape": "^1.0.0",
32
- "@visx/stats": "^2.17.0",
33
- "@visx/tooltip": "^1.1.0",
26
+ "@hello-pangea/dnd": "^16.2.0",
27
+ "@visx/axis": "^3.0.0",
28
+ "@visx/curve": "^3.0.0",
29
+ "@visx/gradient": "^3.0.0",
30
+ "@visx/group": "^3.0.0",
31
+ "@visx/legend": "^3.0.0",
32
+ "@visx/marker": "^3.0.0",
33
+ "@visx/mock-data": "^3.0.0",
34
+ "@visx/scale": "^3.0.0",
35
+ "@visx/shape": "^3.0.0",
36
+ "@visx/stats": "^3.0.0",
37
+ "@visx/text": "^3.0.0",
38
+ "@visx/tooltip": "^3.0.0",
34
39
  "chroma-js": "^2.1.2",
35
40
  "d3-array": "^2.8.0",
41
+ "d3-format": "^3.1.0",
36
42
  "d3-time-format": "^3.0.0",
37
- "html-react-parser": "1.4.9",
43
+ "html-react-parser": "^3.0.8",
38
44
  "js-base64": "^2.5.2",
39
45
  "papaparse": "^5.3.0",
40
46
  "react-accessible-accordion": "^3.3.4",
41
47
  "react-spring": "^8.0.27",
42
48
  "react-table": "^7.5.0",
43
- "react-tooltip": "4.2.8",
49
+ "react-tooltip": "5.8.2-beta.3",
44
50
  "use-debounce": "^6.0.1",
45
51
  "whatwg-fetch": "^3.6.2"
46
52
  },
47
53
  "peerDependencies": {
48
- "react": ">=16.8",
49
- "react-dom": ">=16"
54
+ "react": "^18.2.0",
55
+ "react-dom": "^18.2.0"
50
56
  },
51
- "resolutions": {
52
- "@types/react": "17.x"
53
- },
54
- "gitHead": "58163844cc9ce2c379235413b19f49679eab4bef"
57
+ "gitHead": "cd4216f47b1c41bfbc1de3b704f70c52cc7293c2",
58
+ "devDependencies": {
59
+ "resize-observer-polyfill": "^1.5.1"
60
+ }
55
61
  }
@@ -1,7 +1,6 @@
1
1
  import React, { useState, useEffect, useCallback } from 'react'
2
2
 
3
3
  // IE11
4
- import 'core-js/stable'
5
4
  import ResizeObserver from 'resize-observer-polyfill'
6
5
  import 'whatwg-fetch'
7
6
  import * as d3 from 'd3-array'
@@ -14,9 +13,10 @@ import { format } from 'd3-format'
14
13
  import Papa from 'papaparse'
15
14
  import parse from 'html-react-parser'
16
15
  import { Base64 } from 'js-base64'
16
+ import 'react-tooltip/dist/react-tooltip.css'
17
17
 
18
18
  // Primary Components
19
- import Context from './context'
19
+ import ConfigContext from './ConfigContext'
20
20
  import PieChart from './components/PieChart'
21
21
  import LinearChart from './components/LinearChart'
22
22
 
@@ -33,36 +33,35 @@ import defaults from './data/initial-state'
33
33
  import EditorPanel from './components/EditorPanel'
34
34
  import Loading from '@cdc/core/components/Loading'
35
35
  import Filters from './components/Filters'
36
- import CoveMediaControls from '@cdc/core/helpers/CoveMediaControls'
36
+ import CoveMediaControls from '@cdc/core/components/CoveMediaControls'
37
37
 
38
- // helpers
38
+ // Helpers
39
39
  import numberFromString from '@cdc/core/helpers/numberFromString'
40
40
  import getViewport from '@cdc/core/helpers/getViewport'
41
41
  import { DataTransform } from '@cdc/core/helpers/DataTransform'
42
42
  import cacheBustingString from '@cdc/core/helpers/cacheBustingString'
43
+ import isNumber from '@cdc/core/helpers/isNumber'
44
+ import cleanData from '@cdc/core/helpers/cleanData'
43
45
 
44
46
  import './scss/main.scss'
45
47
 
46
- 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 }) {
48
+ export default function CdcChart({ configUrl, config: configObj, isEditor = false, isDashboard = false, setConfig: setParentConfig, setEditing, hostname, link }) {
47
49
  const transform = new DataTransform()
48
- interface keyable {
49
- [key: string]: any
50
- }
51
50
 
52
- const [loading, setLoading] = useState<Boolean>(true)
53
- const [colorScale, setColorScale] = useState<any>(null)
54
- const [config, setConfig] = useState<keyable>({})
55
- const [stateData, setStateData] = useState<Array<Object>>(config.data || [])
56
- const [excludedData, setExcludedData] = useState<Array<Object>>()
57
- const [filteredData, setFilteredData] = useState<Array<Object>>()
58
- const [seriesHighlight, setSeriesHighlight] = useState<Array<String>>([])
59
- const [currentViewport, setCurrentViewport] = useState<String>('lg')
60
- const [dimensions, setDimensions] = useState<Array<Number>>([])
51
+ const [loading, setLoading] = useState(true)
52
+ const [colorScale, setColorScale] = useState(null)
53
+ const [config, setConfig] = useState({})
54
+ const [stateData, setStateData] = useState(config.data || [])
55
+ const [excludedData, setExcludedData] = useState()
56
+ const [filteredData, setFilteredData] = useState()
57
+ const [seriesHighlight, setSeriesHighlight] = useState([])
58
+ const [currentViewport, setCurrentViewport] = useState('lg')
59
+ const [dimensions, setDimensions] = useState([])
61
60
  const [externalFilters, setExternalFilters] = useState(null)
62
61
  const [container, setContainer] = useState()
63
62
  const [coveLoadedEventRan, setCoveLoadedEventRan] = useState(false)
64
63
  const [dynamicLegendItems, setDynamicLegendItems] = useState([])
65
- const [imageId, setImageId] = useState(`cove-${Math.random().toString(16).slice(-4)}`)
64
+ const [imageId] = useState(`cove-${Math.random().toString(16).slice(-4)}`)
66
65
 
67
66
  const legendGlyphSize = 15
68
67
  const legendGlyphSizeHalf = legendGlyphSize / 2
@@ -219,8 +218,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
219
218
  }
220
219
 
221
220
  if (newConfig.visualizationType === 'Box Plot' && newConfig.series) {
222
- console.log('hit', newConfig)
223
-
224
221
  // stats
225
222
  let allKeys = data.map(d => d[newConfig.xAxis.dataKey])
226
223
  let allValues = data.map(d => Number(d[newConfig?.series[0]?.dataKey]))
@@ -232,50 +229,57 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
232
229
  }
233
230
 
234
231
  const groups = uniqueArray(allKeys)
232
+ let tableData = []
235
233
  const plots = []
236
234
 
237
- console.log('d', data)
238
- console.log('newConfig', newConfig)
239
- console.log('groups', groups)
240
- console.log('allKeys', allKeys)
241
- console.log('allValues', allValues)
242
-
243
235
  // group specific statistics
244
236
  // prevent re-renders
245
- groups.map((g, index) => {
237
+ groups.forEach((g, index) => {
246
238
  if (!g) return
247
239
  // filter data by group
248
240
  let filteredData = data.filter(item => item[newConfig.xAxis.dataKey] === g)
249
241
  let filteredDataValues = filteredData.map(item => Number(item[newConfig?.series[0]?.dataKey]))
250
- console.log('g', g)
251
- console.log('item', filteredData)
252
- console.log('item', newConfig)
253
242
  // let filteredDataValues = filteredData.map(item => Number(item[newConfig.yAxis.dataKey]))
254
-
255
- const q1 = d3.quantile(filteredDataValues, 0.25)
256
- const q3 = d3.quantile(filteredDataValues, 0.75)
243
+ const q1 = d3.quantile(filteredDataValues, parseFloat(newConfig.boxplot.firstQuartilePercentage) / 100)
244
+ const q3 = d3.quantile(filteredDataValues, parseFloat(newConfig.boxplot.thirdQuartilePercentage) / 100)
257
245
  const iqr = q3 - q1
258
246
  const lowerBounds = q1 - (q3 - q1) * 1.5
259
247
  const upperBounds = q3 + (q3 - q1) * 1.5
260
248
  const outliers = filteredDataValues.filter(v => v < lowerBounds || v > upperBounds)
249
+ let nonOutliers = filteredDataValues
250
+
251
+ nonOutliers = nonOutliers.filter(item => !outliers.includes(item))
252
+
261
253
  plots.push({
262
254
  columnCategory: g,
263
- columnMean: d3.mean(filteredDataValues),
255
+ columnMax: Number(q3 + 1.5 * iqr).toFixed(2),
256
+ columnThirdQuartile: q3.toFixed(2),
264
257
  columnMedian: d3.median(filteredDataValues),
265
- columnFirstQuartile: q1,
266
- columnThirdQuartile: q3,
267
- columnMin: q1 - 1.5 * iqr,
268
- columnMax: q3 + 1.5 * iqr,
269
- columnIqr: iqr,
258
+ columnFirstQuartile: q1.toFixed(2),
259
+ columnMin: Number(q1 - 1.5 * iqr).toFixed(2),
260
+ columnCount: filteredDataValues.reduce((partialSum, a) => partialSum + a, 0),
261
+ columnSd: d3.deviation(filteredDataValues).toFixed(2),
262
+ columnMean: d3.mean(filteredDataValues).toFixed(2),
263
+ columnIqr: iqr.toFixed(2),
270
264
  columnOutliers: outliers,
271
- values: filteredDataValues
265
+ values: filteredDataValues,
266
+ nonOutlierValues: nonOutliers
272
267
  })
273
268
  })
274
269
 
270
+ // make deep copy so we can remove some fields for data
271
+ // this appears to be the easiest option instead of running logic against the datatable cell...
272
+ tableData = JSON.parse(JSON.stringify(plots))
273
+ tableData.map(table => {
274
+ delete table.columnIqr
275
+ delete table.nonOutlierValues
276
+ })
277
+
275
278
  // any other data we can add to boxplots
276
279
  newConfig.boxplot['allValues'] = allValues
277
280
  newConfig.boxplot['categories'] = groups
278
- newConfig.boxplot.push(...plots)
281
+ newConfig.boxplot.plots = plots
282
+ newConfig.boxplot.tableData = tableData
279
283
  }
280
284
 
281
285
  if (newConfig.visualizationType === 'Combo' && newConfig.series) {
@@ -328,6 +332,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
328
332
 
329
333
  data.forEach(row => {
330
334
  const value = row[columnName]
335
+ //@ts-ignore
331
336
  if (value && false === values.includes(value)) {
332
337
  values.push(value)
333
338
  }
@@ -352,7 +357,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
352
357
  }
353
358
 
354
359
  // Observes changes to outermost container and changes viewport size in state
355
- const resizeObserver: ResizeObserver = new ResizeObserver(entries => {
360
+ const resizeObserver = new ResizeObserver(entries => {
356
361
  for (let entry of entries) {
357
362
  let { width, height } = entry.contentRect
358
363
  let newViewport = getViewport(width)
@@ -408,13 +413,13 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
408
413
  * Another useEffect listens to externalFilterChanges and updates the config.
409
414
  */
410
415
  useEffect(() => {
411
- const handleFilterData = (e: CustomEvent) => {
416
+ const handleFilterData = e => {
412
417
  let tmp = []
413
418
  tmp.push(e.detail)
414
419
  setExternalFilters(tmp)
415
420
  }
416
421
 
417
- subscribe('cove_filterData', (e: CustomEvent) => handleFilterData(e))
422
+ subscribe('cove_filterData', e => handleFilterData(e))
418
423
 
419
424
  return () => {
420
425
  unsubscribe('cove_filterData', handleFilterData)
@@ -447,6 +452,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
447
452
 
448
453
  // Load data when configObj data changes
449
454
  if (configObj) {
455
+ // eslint-disable-next-line react-hooks/rules-of-hooks
450
456
  useEffect(() => {
451
457
  loadConfig()
452
458
  }, [configObj.data])
@@ -523,7 +529,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
523
529
 
524
530
  const section = config.orientation === 'horizontal' ? 'yAxis' : 'xAxis'
525
531
 
526
- const parseDate = (dateString: string) => {
532
+ const parseDate = dateString => {
527
533
  let date = timeParse(config.runtime[section].dateParseFormat)(dateString)
528
534
  if (!date) {
529
535
  config.runtime.editorErrorMessage = `Error parsing date "${dateString}". Try reviewing your data and date parse settings in the X Axis section.`
@@ -533,20 +539,18 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
533
539
  }
534
540
  }
535
541
 
536
- const formatDate = (date: Date) => {
542
+ const formatDate = date => {
537
543
  return timeFormat(config.runtime[section].dateDisplayFormat)(date)
538
544
  }
539
545
 
540
- const DownloadButton = ({ data }: any, type = 'link') => {
546
+ const DownloadButton = ({ data }, type = 'link') => {
541
547
  const fileName = `${config.title.substring(0, 50)}.csv`
542
548
 
543
549
  const csvData = Papa.unparse(data)
544
550
 
545
551
  const saveBlob = () => {
546
- //@ts-ignore
547
552
  if (typeof window.navigator.msSaveBlob === 'function') {
548
553
  const dataBlob = new Blob([csvData], { type: 'text/csv;charset=utf-8;' })
549
- //@ts-ignore
550
554
  window.navigator.msSaveBlob(dataBlob, fileName)
551
555
  }
552
556
  }
@@ -566,6 +570,16 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
566
570
  }
567
571
  }
568
572
 
573
+ // function calculates the width of given text and its font-size
574
+ function getTextWidth(text, font) {
575
+ const canvas = document.createElement('canvas')
576
+ const context = canvas.getContext('2d')
577
+
578
+ context.font = font || getComputedStyle(document.body).font
579
+
580
+ return Math.ceil(context.measureText(text).width)
581
+ }
582
+
569
583
  // Format numeric data based on settings in config
570
584
  const formatNumber = (num, axis) => {
571
585
  // if num is NaN return num
@@ -617,7 +631,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
617
631
  // Use commas also updates bars and the data table
618
632
  // We can't use commas when we're formatting the dataFormatted number
619
633
  // Example: commas -> 12,000; abbreviated -> 12k (correct); abbreviated & commas -> 12 (incorrect)
620
- if (axis === 'left' && commas && abbreviated) {
634
+ if ((axis === 'left' && commas && abbreviated) || (axis === 'bottom' && commas && abbreviated)) {
621
635
  num = num
622
636
  } else {
623
637
  num = num.toLocaleString('en-US', stringFormattingOptions)
@@ -660,7 +674,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
660
674
  Line: <LinearChart />,
661
675
  Combo: <LinearChart />,
662
676
  Pie: <PieChart />,
663
- 'Box Plot': <LinearChart />
677
+ 'Box Plot': <LinearChart />,
678
+ 'Scatter Plot': <LinearChart />
664
679
  }
665
680
 
666
681
  const missingRequiredSections = () => {
@@ -750,8 +765,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
750
765
  )
751
766
  }
752
767
 
753
- const getXAxisData = (d: any) => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
754
- const getYAxisData = (d: any, seriesKey: string) => d[seriesKey]
768
+ const getXAxisData = d => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
769
+ const getYAxisData = (d, seriesKey) => d[seriesKey]
755
770
 
756
771
  const contextValues = {
757
772
  getXAxisData,
@@ -785,7 +800,10 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
785
800
  dynamicLegendItems,
786
801
  setDynamicLegendItems,
787
802
  filterData,
788
- imageId
803
+ isNumber,
804
+ cleanData,
805
+ imageId,
806
+ getTextWidth
789
807
  }
790
808
 
791
809
  const classes = ['cdc-open-viz-module', 'type-chart', `${currentViewport}`, `font-${config.fontSize}`, `${config.theme}`]
@@ -795,10 +813,10 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
795
813
  isEditor && classes.push('isEditor')
796
814
 
797
815
  return (
798
- <Context.Provider value={contextValues}>
816
+ <ConfigContext.Provider value={contextValues}>
799
817
  <div className={`${classes.join(' ')}`} ref={outerContainerRef} data-lollipop={config.isLollipopChart} data-download-id={imageId}>
800
818
  {body}
801
819
  </div>
802
- </Context.Provider>
820
+ </ConfigContext.Provider>
803
821
  )
804
822
  }