@cdc/chart 4.23.11 → 4.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/cdcchart.js +30220 -29764
  2. package/examples/feature/bar/additional-column-tooltip.json +446 -0
  3. package/examples/feature/bar/tall-data.json +98 -0
  4. package/examples/feature/forest-plot/forest-plot.json +63 -19
  5. package/examples/feature/forest-plot/linear.json +52 -3
  6. package/examples/feature/forest-plot/log.json +26 -0
  7. package/examples/feature/forest-plot/logarithmic.json +0 -35
  8. package/examples/feature/line/line-chart-preliminary.json +346 -0
  9. package/examples/feature/scatterplot/scatterplot.json +272 -33
  10. package/examples/private/chart-t.json +3740 -0
  11. package/examples/private/combo.json +369 -0
  12. package/examples/private/epi-data.csv +13 -0
  13. package/examples/private/epi-data.json +62 -0
  14. package/examples/private/epi.json +403 -0
  15. package/examples/private/occupancy.json +109283 -0
  16. package/examples/private/prod-line-config.json +401 -0
  17. package/examples/private/region-data.json +822 -0
  18. package/examples/private/region-testing.json +312 -0
  19. package/examples/private/scaling.json +45325 -0
  20. package/examples/private/testing-data.json +1739 -0
  21. package/examples/private/testing.json +816 -0
  22. package/index.html +7 -7
  23. package/package.json +2 -2
  24. package/src/CdcChart.tsx +29 -210
  25. package/src/ConfigContext.tsx +6 -0
  26. package/src/_stories/ChartEditor.stories.tsx +22 -0
  27. package/src/_stories/ChartLine.preliminary.tsx +19 -0
  28. package/src/_stories/_mock/pie_config.json +191 -0
  29. package/src/_stories/_mock/pie_data.json +218 -0
  30. package/src/_stories/_mock/preliminary_mock.json +346 -0
  31. package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +2 -2
  32. package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +1 -1
  33. package/src/components/AreaChart/index.tsx +4 -0
  34. package/src/components/{BarChart.Horizontal.tsx → BarChart/components/BarChart.Horizontal.tsx} +8 -8
  35. package/src/components/{BarChart.StackedHorizontal.tsx → BarChart/components/BarChart.StackedHorizontal.tsx} +37 -7
  36. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +106 -0
  37. package/src/components/{BarChart.Vertical.tsx → BarChart/components/BarChart.Vertical.tsx} +41 -57
  38. package/src/components/BarChart/components/BarChart.jsx +39 -0
  39. package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
  40. package/src/components/BarChart/components/context.tsx +13 -0
  41. package/src/components/BarChart/index.tsx +3 -0
  42. package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +1 -1
  43. package/src/components/BoxPlot/index.tsx +3 -0
  44. package/src/components/{EditorPanel.jsx → EditorPanel/EditorPanel.tsx} +667 -851
  45. package/src/components/EditorPanel/components/Panel.DateHighlighting.tsx +109 -0
  46. package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panel.ForestPlotSettings.tsx} +87 -166
  47. package/src/components/EditorPanel/components/Panel.Regions.tsx +168 -0
  48. package/src/components/{Series.jsx → EditorPanel/components/Panel.Series.tsx} +1 -1
  49. package/src/components/EditorPanel/components/PanelProps.ts +3 -0
  50. package/src/components/EditorPanel/components/Panels.tsx +13 -0
  51. package/src/components/EditorPanel/components/panels.scss +72 -0
  52. package/src/components/EditorPanel/editor-panel.scss +751 -0
  53. package/src/components/EditorPanel/index.tsx +3 -0
  54. package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +29 -2
  55. package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
  56. package/src/components/Forecasting/index.tsx +3 -0
  57. package/src/components/ForestPlot/ForestPlot.tsx +254 -0
  58. package/src/components/ForestPlot/ForestPlotProps.ts +7 -0
  59. package/src/components/ForestPlot/index.tsx +1 -209
  60. package/src/components/{Legend.jsx → Legend/Legend.tsx} +150 -113
  61. package/src/components/Legend/index.tsx +3 -0
  62. package/src/components/LineChart/LineChartProps.ts +29 -0
  63. package/src/components/LineChart/{LineChart.Circle.tsx → components/LineChart.Circle.tsx} +12 -3
  64. package/src/components/LineChart/helpers.ts +45 -0
  65. package/src/components/LineChart/index.tsx +20 -8
  66. package/src/components/LinearChart.jsx +52 -69
  67. package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +16 -7
  68. package/src/components/PieChart/index.tsx +3 -0
  69. package/src/components/Regions/components/Regions.tsx +135 -0
  70. package/src/components/Regions/index.tsx +3 -0
  71. package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
  72. package/src/components/ScatterPlot/index.tsx +3 -0
  73. package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
  74. package/src/components/Sparkline/index.tsx +3 -0
  75. package/src/data/initial-state.js +5 -6
  76. package/src/helpers/abbreviateNumber.ts +17 -0
  77. package/src/helpers/computeMarginBottom.ts +55 -0
  78. package/src/helpers/filterData.ts +18 -0
  79. package/src/helpers/generateColorsArray.ts +8 -0
  80. package/src/helpers/getQuartiles.ts +30 -0
  81. package/src/helpers/handleChartAriaLabels.ts +19 -0
  82. package/src/helpers/handleLineType.ts +18 -0
  83. package/src/helpers/lineOptions.ts +18 -0
  84. package/src/helpers/sort.ts +7 -0
  85. package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
  86. package/src/hooks/useBarChart.js +7 -6
  87. package/src/hooks/useScales.ts +1 -1
  88. package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +23 -21
  89. package/src/scss/main.scss +67 -3
  90. package/src/types/ChartConfig.ts +158 -23
  91. package/src/types/ChartContext.ts +26 -10
  92. package/src/types/ForestPlot.ts +7 -14
  93. package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
  94. package/src/ConfigContext.jsx +0 -5
  95. package/src/components/BarChart.StackedVertical.tsx +0 -91
  96. package/src/components/BarChart.jsx +0 -30
  97. package/src/components/ForestPlot/Readme.md +0 -0
  98. package/src/scss/LinearChart.scss +0 -0
  99. package/src/scss/editor-panel.scss +0 -745
  100. package/src/scss/legend.scss +0 -206
  101. package/src/scss/mixins.scss +0 -0
  102. package/src/scss/variables.scss +0 -1
  103. package/src/types/ChartProps.ts +0 -7
package/index.html CHANGED
@@ -34,12 +34,9 @@
34
34
  -->
35
35
 
36
36
  <!-- GENERIC CHART TYPES -->
37
- <div class="react-container" data-config="/examples/private/highlight.json"></div>
38
- <div class="react-container" data-config="/examples/private/aggregate.json"></div>
39
- <!-- <div class="react-container" data-config="/examples/private/missing-color.json"></div> -->
40
- <!-- <div class="react-container" data-config="/examples/private/combo.json"></div> -->
41
- <!-- <div class="react-container" data-config="/examples/feature/legend-highlights/highlights.json"></div> -->
42
- <!-- <div class="react-container" data-config="/examples/private/tooltip-issue.json"></div> -->
37
+ <!-- <div class="react-container" data-config="/examples/private/prod-line-config.json"></div> -->
38
+ <!-- <div class="react-container" data-config="/examples/private/chart-t.json"></div> -->
39
+ <!-- <div class="react-container" data-config="/examples/feature/bar/additional-column-tooltip.json"></div> -->
43
40
  <!-- <div class="react-container" data-config="https://cdc.gov/poxvirus/mpox/modules/data-viz/mpx-trends_1.json"></div> -->
44
41
  <!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date-city-temperature.json"></div> -->
45
42
  <!-- <div class="react-container" data-config="/examples/feature/area/area-chart-date-apple.json"></div> -->
@@ -50,6 +47,7 @@
50
47
  <!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Viz.json></div> -->
51
48
  <!-- <div class="react-container" data-config=/examples/feature/regions/index.json></div> -->
52
49
  <!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Regions_Viz.json></div> -->
50
+ <!-- <div class="react-container" data-config=https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Line_Chart_Regions_Viz.json></div> -->
53
51
  <!-- <div class="react-container" data-config="/examples/feature/forecasting/forecasting.json"></div> -->
54
52
  <!-- <div class="react-container" data-config="/examples/feature/forecasting/combo-forecasting.json"></div> -->
55
53
  <!-- <div class="react-container" data-config="/examples/feature/forecasting/effective_reproduction.json"></div> -->
@@ -125,6 +123,8 @@
125
123
 
126
124
  <!-- GENERIC CHART TYPES -->
127
125
  <!-- <div class="react-container" data-config="/examples/gallery/paired-bar/paired-bar-chart.json"></div> -->
126
+ <div class="react-container" data-config="/examples/feature/line/line-chart-preliminary.json"></div>
127
+
128
128
 
129
129
  <!-- HORIZONTAL BAR CHARTS -->
130
130
  <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-horizontal/horizontal-bar-chart-with-numbers-on-bar.json"></div> -->
@@ -134,7 +134,7 @@
134
134
  <!-- VERTICAL BAR CHARTS -->
135
135
  <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/combo-line-chart.json"></div> -->
136
136
  <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-categorical.json"></div> -->
137
- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json"></div>
137
+ <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json"></div> -->
138
138
  <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart-confidence.json"></div> -->
139
139
  <!-- <div class="react-container" data-config="/examples/gallery/bar-chart-vertical/vertical-bar-chart.json"></div> -->
140
140
  <!-- <div class="react-container" data-config="https://www.cdc.gov/respiratory-viruses/modules/respiratory-virus-activity/emergency-dept-visits_live.json"></div> -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/chart",
3
- "version": "4.23.11",
3
+ "version": "4.24.1",
4
4
  "description": "React component for visualizing tabular data in various types of charts",
5
5
  "moduleName": "CdcChart",
6
6
  "main": "dist/cdcchart",
@@ -59,7 +59,7 @@
59
59
  "react": "^18.2.0",
60
60
  "react-dom": "^18.2.0"
61
61
  },
62
- "gitHead": "ecad213667a3cb96c921eaddba43a31c84caaa08",
62
+ "gitHead": "a352a3f74f4b681191e3244061dbb3621f36eec3",
63
63
  "devDependencies": {
64
64
  "resize-observer-polyfill": "^1.5.1"
65
65
  }
package/src/CdcChart.tsx CHANGED
@@ -12,19 +12,27 @@ import { timeParse, timeFormat } from 'd3-time-format'
12
12
  import Papa from 'papaparse'
13
13
  import parse from 'html-react-parser'
14
14
  import 'react-tooltip/dist/react-tooltip.css'
15
- import chroma from 'chroma-js'
16
15
 
17
16
  // Primary Components
18
17
  import ConfigContext from './ConfigContext'
19
- import PieChart from './components/PieChart'
18
+ import PieChart from './components/PieChart/PieChart'
20
19
  import LinearChart from './components/LinearChart'
21
20
 
22
21
  import { colorPalettesChart as colorPalettes, twoColorPalette } from '@cdc/core/data/colorPalettes'
23
22
 
24
- import SparkLine from './components/SparkLine'
23
+ import SparkLine from './components/Sparkline'
25
24
  import Legend from './components/Legend'
26
25
  import defaults from './data/initial-state'
27
26
  import EditorPanel from './components/EditorPanel'
27
+ import { abbreviateNumber } from './helpers/abbreviateNumber'
28
+ import { getQuartiles } from './helpers/getQuartiles'
29
+ import { sortAsc, sortDesc } from './helpers/sort'
30
+ import { filterData } from './helpers/filterData'
31
+ import { handleChartAriaLabels } from './helpers/handleChartAriaLabels'
32
+ import { lineOptions } from './helpers/lineOptions'
33
+ import { handleLineType } from './helpers/handleLineType'
34
+ import { generateColorsArray } from './helpers/generateColorsArray'
35
+ import { computeMarginBottom } from './helpers/computeMarginBottom'
28
36
  import Loading from '@cdc/core/components/Loading'
29
37
  import Filters from '@cdc/core/components/Filters'
30
38
  import MediaControls from '@cdc/core/components/MediaControls'
@@ -45,13 +53,6 @@ import DataTable from '@cdc/core/components/DataTable'
45
53
  import { getFileExtension } from '@cdc/core/helpers/getFileExtension'
46
54
  import Title from '@cdc/core/components/ui/Title'
47
55
 
48
- const generateColorsArray = (color = '#000000', special = false) => {
49
- let colorObj = chroma(color)
50
- let hoverColor = special ? colorObj.brighten(0.5).hex() : colorObj.saturate(1.3).hex()
51
-
52
- return [color, hoverColor, colorObj.darken(0.3).hex()]
53
- }
54
-
55
56
  export default function CdcChart({ configUrl, config: configObj, isEditor = false, isDebug = false, isDashboard = false, setConfig: setParentConfig, setEditing, hostname, link, setSharedFilter, setSharedFilterValue, dashboardConfig }) {
56
57
  const transform = new DataTransform()
57
58
  const [loading, setLoading] = useState(true)
@@ -88,34 +89,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
88
89
 
89
90
  const handleChartTabbing = config.showSidebar ? `#legend` : config?.title ? `#dataTableSection__${config.title.replace(/\s/g, '')}` : `#dataTableSection`
90
91
 
91
- const sortAsc = (a, b) => {
92
- return a.toString().localeCompare(b.toString(), 'en', { numeric: true })
93
- }
94
-
95
- const sortDesc = (a, b) => {
96
- return b.toString().localeCompare(a.toString(), 'en', { numeric: true })
97
- }
98
-
99
- const handleChartAriaLabels = (state, testing = false) => {
100
- if (testing) console.log(`handleChartAriaLabels Testing On:`, state) // eslint-disable-line
101
- try {
102
- if (!state.visualizationType) throw Error('handleChartAriaLabels: no visualization type found in state')
103
- let ariaLabel = ''
104
-
105
- if (state.visualizationType) {
106
- ariaLabel += `${state.visualizationType} chart`
107
- }
108
-
109
- if (state.title && state.visualizationType) {
110
- ariaLabel += ` with the title: ${state.title}`
111
- }
112
-
113
- return ariaLabel
114
- } catch (e) {
115
- console.error('COVE: ', e.message) // eslint-disable-line
116
- }
117
- }
118
-
119
92
  const reloadURLData = async () => {
120
93
  if (config.dataUrl) {
121
94
  const dataUrl = new URL(config.runtimeDataUrl || config.dataUrl, window.location.origin)
@@ -143,7 +116,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
143
116
  let data: any[] = []
144
117
 
145
118
  try {
146
- const ext = getFileExtension(dataUrl.pathname)
119
+ const ext = getFileExtension(dataUrl.href)
147
120
  if ('csv' === ext) {
148
121
  data = await fetch(dataUrlFinal)
149
122
  .then(response => response.text())
@@ -182,44 +155,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
182
155
  }
183
156
  }
184
157
 
185
- const handleLineType = lineType => {
186
- switch (lineType) {
187
- case 'dashed-sm':
188
- return '5 5'
189
- case 'Dashed Small':
190
- return '5 5'
191
- case 'dashed-md':
192
- return '10 5'
193
- case 'Dashed Medium':
194
- return '10 5'
195
- case 'dashed-lg':
196
- return '15 5'
197
- case 'Dashed Large':
198
- return '15 5'
199
- default:
200
- return 0
201
- }
202
- }
203
-
204
- const lineOptions = [
205
- {
206
- value: 'Dashed Small',
207
- key: 'dashed-sm'
208
- },
209
- {
210
- value: 'Dashed Medium',
211
- key: 'dashed-md'
212
- },
213
- {
214
- value: 'Dashed Large',
215
- key: 'dashed-lg'
216
- },
217
- {
218
- value: 'Solid Line',
219
- key: 'solid-line'
220
- }
221
- ]
222
-
223
158
  const loadConfig = async () => {
224
159
  let response = configObj || (await (await fetch(configUrl)).json())
225
160
 
@@ -392,37 +327,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
392
327
  let tableData: any[] = []
393
328
  const plots: any[] = []
394
329
 
395
- /**
396
- * Calculates the first quartile (q1) and third quartile (q3) from an array of integers or decimals.
397
- *
398
- * @param {Array} arr - The array of integers or decimals.
399
- * @returns {Object} An object containing the q1 and q3 values.
400
- */
401
- const getQuartiles = arr => {
402
- arr.sort((a, b) => a - b)
403
-
404
- // Calculate the index of the median value of the array
405
- const medianIndex = Math.floor(arr.length / 2)
406
-
407
- // Check if the length of the array is even or odd
408
- const isEvenLength = arr.length % 2 === 0
409
-
410
- // Split the array into two subarrays based on the median index
411
- const q1Array = isEvenLength ? arr.slice(0, medianIndex) : arr.slice(0, medianIndex + 1)
412
- const q3Array = isEvenLength ? arr.slice(medianIndex) : arr.slice(medianIndex + 1)
413
-
414
- // Calculate the median of the first subarray to get the q1 value
415
- const q1Index = Math.floor(q1Array.length / 2)
416
- const q1 = isEvenLength ? (q1Array[q1Index - 1] + q1Array[q1Index]) / 2 : q1Array[q1Index]
417
-
418
- // Calculate the median of the second subarray to get the q3 value
419
- const q3Index = Math.floor(q3Array.length / 2)
420
- const q3 = isEvenLength ? (q3Array[q3Index - 1] + q3Array[q3Index]) / 2 : q3Array[q3Index]
421
-
422
- // Return an object containing the q1 and q3 values
423
- return { q1, q3 }
424
- }
425
-
426
330
  // group specific statistics
427
331
  // prevent re-renders
428
332
  if (!groups) return
@@ -547,11 +451,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
547
451
  newConfig.runtime.xAxis = newConfig.yAxis
548
452
  newConfig.runtime.yAxis = newConfig.xAxis
549
453
 
550
- if (newConfig.visualizationType === 'Forest Plot') {
551
- newConfig.runtime.xAxis.type = newConfig.forestPlot.type
552
- newConfig.runtime.xAxis.tickRotation = newConfig.xAxis.tickRotation
553
- }
554
- newConfig.runtime.horizontal = true
454
+ newConfig.runtime.horizontal = false
555
455
  newConfig.orientation = 'horizontal'
556
456
  } else if (['Box Plot', 'Scatter Plot', 'Area Chart', 'Line', 'Forecasting'].includes(newConfig.visualizationType)) {
557
457
  newConfig.runtime.xAxis = newConfig.xAxis
@@ -569,25 +469,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
569
469
  setConfig(newConfig)
570
470
  }
571
471
 
572
- const filterData = (filters, data) => {
573
- let filteredData: any[] = []
574
-
575
- data.forEach(row => {
576
- let add = true
577
- filters
578
- .filter(filter => filter.type !== 'url')
579
- .forEach(filter => {
580
- if (row[filter.columnName] != filter.active) {
581
- add = false
582
- }
583
- })
584
-
585
- if (add) filteredData.push(row)
586
- })
587
-
588
- return filteredData
589
- }
590
-
591
472
  // Gets filter values from dataset
592
473
  const generateValuesForFilter = (columnName, data = this.state.data) => {
593
474
  const values: any[] = []
@@ -845,24 +726,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
845
726
  return Math.ceil(context.measureText(text).width)
846
727
  }
847
728
 
848
- const abbreviateNumber = num => {
849
- let unit = ''
850
- let absNum = Math.abs(num)
851
-
852
- if (absNum >= 1e9) {
853
- unit = 'B'
854
- num = num / 1e9
855
- } else if (absNum >= 1e6) {
856
- unit = 'M'
857
- num = num / 1e6
858
- } else if (absNum >= 1e3) {
859
- unit = 'K'
860
- num = num / 1e3
861
- }
862
-
863
- return num + unit
864
- }
865
-
866
729
  // Format numeric data based on settings in config OR from passed in settings for Additional Columns
867
730
  // - use only for old horizontal data - newer formatNumber is in helper/formatNumber
868
731
  // TODO: we should combine various formatNumber functions across this project.
@@ -914,11 +777,17 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
914
777
  }
915
778
  }
916
779
 
780
+ const resolveBottomTickRounding = () => {
781
+ if (config.forestPlot.type === 'Logarithmic' && !bottomRoundTo) return 2
782
+ if (Number(bottomRoundTo)) return Number(bottomRoundTo)
783
+ return 0
784
+ }
785
+
917
786
  if (axis === 'bottom') {
918
787
  stringFormattingOptions = {
919
788
  useGrouping: config.dataFormat.bottomCommas ? true : false,
920
- minimumFractionDigits: bottomRoundTo ? Number(bottomRoundTo) : 0,
921
- maximumFractionDigits: bottomRoundTo ? Number(bottomRoundTo) : 0
789
+ minimumFractionDigits: resolveBottomTickRounding(),
790
+ maximumFractionDigits: resolveBottomTickRounding()
922
791
  }
923
792
  }
924
793
 
@@ -1136,61 +1005,6 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1136
1005
  return key
1137
1006
  }
1138
1007
 
1139
- const computeMarginBottom = (config: Config): string => {
1140
- const isLegendBottom = legend.position === 'bottom' || ['sm', 'xs', 'xxs'].includes(currentViewport)
1141
- const isHorizontal = config.orientation === 'horizontal'
1142
- const tickRotation = Number(config.xAxis.tickRotation) > 0 ? Number(config.xAxis.tickRotation) : 0
1143
- const isBrush = config.brush.active
1144
- const offset = 20
1145
- const brushHeight = config.brush.height
1146
- let bottom = 0
1147
- if (!isLegendBottom && isHorizontal && !config.yAxis.label) {
1148
- bottom = Number(config.xAxis.labelOffset)
1149
- }
1150
- if (!isLegendBottom && isHorizontal && config.yAxis.label && !config.isResponsiveTicks) {
1151
- bottom = Number(config.runtime.xAxis.size) + Number(config.xAxis.labelOffset)
1152
- }
1153
- if (!isLegendBottom && isHorizontal && config.yAxis.label && config.isResponsiveTicks) {
1154
- bottom = config.dynamicMarginTop + offset
1155
- }
1156
- if (!isLegendBottom && isHorizontal && !config.yAxis.label && config.isResponsiveTicks) {
1157
- bottom = config.dynamicMarginTop ? config.dynamicMarginTop - offset : Number(config.xAxis.labelOffset) - offset
1158
- }
1159
- if (!isLegendBottom && isHorizontal && config.yAxis.label && config.isResponsiveTicks) {
1160
- bottom = config.dynamicMarginTop ? config.dynamicMarginTop + offset : Number(config.xAxis.labelOffset)
1161
- }
1162
-
1163
- if (!isHorizontal && !isLegendBottom && config.xAxis.label && tickRotation && !config.isResponsiveTicks) {
1164
- bottom = isBrush ? brushHeight + config.xAxis.tickWidthMax + -config.xAxis.size + config.xAxis.labelOffset + offset : config.xAxis.tickWidthMax + offset + -config.xAxis.size + config.xAxis.labelOffset
1165
- }
1166
- if (!isHorizontal && !isLegendBottom && !config.xAxis.label && tickRotation && !config.isResponsiveTicks) {
1167
- }
1168
- if (!isHorizontal && !isLegendBottom && !config.xAxis.label && tickRotation && !config.dynamicMarginTop && !config.isResponsiveTicks) {
1169
- bottom = isBrush ? config.xAxis.tickWidthMax + brushHeight + offset + -config.xAxis.size : 0
1170
- }
1171
-
1172
- if (!isHorizontal && !isLegendBottom && config.xAxis.label && !tickRotation && !config.isResponsiveTicks) {
1173
- bottom = isBrush ? brushHeight + -config.xAxis.size + config.xAxis.labelOffset + offset : -config.xAxis.size + config.xAxis.labelOffset + offset
1174
- }
1175
- if (!isHorizontal && !isLegendBottom && config.xAxis.label && config.dynamicMarginTop && config.isResponsiveTicks) {
1176
- bottom = isBrush ? brushHeight + config.xAxis.labelOffset + -config.xAxis.size + config.xAxis.tickWidthMax : config.dynamicMarginTop + -config.xAxis.size + offset
1177
- }
1178
- if (!isHorizontal && !isLegendBottom && !config.xAxis.label && config.dynamicMarginTop && config.isResponsiveTicks) {
1179
- bottom = isBrush ? brushHeight + config.xAxis.labelOffset + -config.xAxis.size + config.xAxis.tickWidthMax : config.dynamicMarginTop + -config.xAxis.size - offset
1180
- }
1181
- if (!isHorizontal && !isLegendBottom && config.xAxis.label && !config.dynamicMarginTop && config.isResponsiveTicks) {
1182
- bottom = isBrush ? brushHeight + config.xAxis.labelOffset + -config.xAxis.size + 25 : config.xAxis.labelOffset + -config.xAxis.size + offset
1183
- }
1184
- if (!isHorizontal && !isLegendBottom && !config.xAxis.label && !config.dynamicMarginTop && config.isResponsiveTicks) {
1185
- bottom = -config.xAxis.size + offset + config.xAxis.labelOffset
1186
- }
1187
- if (!isHorizontal && !isLegendBottom && !config.xAxis.label && !tickRotation && !config.dynamicMarginTop && !config.isResponsiveTicks) {
1188
- bottom = isBrush ? brushHeight + -config.xAxis.size + config.xAxis.labelOffset : 0
1189
- }
1190
-
1191
- return `${bottom}px`
1192
- }
1193
-
1194
1008
  // Prevent render if loading
1195
1009
  let body = <Loading />
1196
1010
 
@@ -1214,7 +1028,10 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1214
1028
  {config.filters && !externalFilters && <Filters config={config} setConfig={setConfig} setFilteredData={setFilteredData} filteredData={filteredData} excludedData={excludedData} filterData={filterData} dimensions={dimensions} />}
1215
1029
  {/* Visualization */}
1216
1030
  {config?.introText && config.visualizationType !== 'Spark Line' && <section className='introText'>{parse(config.introText)}</section>}
1217
- <div style={{ marginBottom: computeMarginBottom(config) }} className={`chart-container p-relative ${config.legend.position === 'bottom' ? 'bottom' : ''}${config.legend.hide ? ' legend-hidden' : ''}${lineDatapointClass}${barBorderClass} ${contentClasses.join(' ')}`}>
1031
+ <div
1032
+ style={{ marginBottom: computeMarginBottom(config, legend, currentViewport) }}
1033
+ className={`chart-container p-relative ${config.legend.position === 'bottom' ? 'bottom' : ''}${config.legend.hide ? ' legend-hidden' : ''}${lineDatapointClass}${barBorderClass} ${contentClasses.join(' ')} ${isDebug ? 'debug' : ''}`}
1034
+ >
1218
1035
  {/* All charts except sparkline */}
1219
1036
  {config.visualizationType !== 'Spark Line' && chartComponents[config.visualizationType]}
1220
1037
 
@@ -1236,7 +1053,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1236
1053
  )}
1237
1054
  </>
1238
1055
  )}
1239
- {!config.legend.hide && config.visualizationType !== 'Spark Line' && <Legend />}
1056
+ {!config.legend.hide && config.visualizationType !== 'Spark Line' && config.visualizationType !== 'Forest Plot' && <Legend />}
1240
1057
  </div>
1241
1058
  {/* Link */}
1242
1059
  {isDashboard && config.table && config.table.show && config.table.showDataTableLink ? tableLink : link && link}
@@ -1286,6 +1103,7 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1286
1103
 
1287
1104
  const contextValues = {
1288
1105
  capitalize,
1106
+ computeMarginBottom,
1289
1107
  getXAxisData,
1290
1108
  getYAxisData,
1291
1109
  config,
@@ -1328,7 +1146,8 @@ export default function CdcChart({ configUrl, config: configObj, isEditor = fals
1328
1146
  isDebug,
1329
1147
  setSharedFilter,
1330
1148
  setSharedFilterValue,
1331
- dashboardConfig
1149
+ dashboardConfig,
1150
+ debugSvg: isDebug
1332
1151
  }
1333
1152
 
1334
1153
  const classes = ['cdc-open-viz-module', 'type-chart', `${currentViewport}`, `font-${config.fontSize}`, `${config.theme}`]
@@ -0,0 +1,6 @@
1
+ import { createContext } from 'react'
2
+ import { ChartContext } from './types/ChartContext'
3
+
4
+ const ConfigContext = createContext({} as ChartContext)
5
+
6
+ export default ConfigContext
@@ -0,0 +1,22 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+
3
+ import Chart from '../CdcChart'
4
+
5
+ import pieChartExample from './_mock/pie_config.json'
6
+ import pieData from './_mock/pie_data.json'
7
+
8
+ const meta: Meta<typeof Chart> = {
9
+ title: 'Components/Templates/Editor/Chart',
10
+ component: Chart
11
+ }
12
+
13
+ type Story = StoryObj<typeof Chart>
14
+
15
+ export const Primary: Story = {
16
+ args: {
17
+ config: { ...pieChartExample, data: pieData },
18
+ isEditor: true
19
+ }
20
+ }
21
+
22
+ export default meta
@@ -0,0 +1,19 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import chartLinepreliminary from './_mock/preliminary_mock.json'
3
+
4
+ import Chart from '../CdcChart'
5
+
6
+ const meta: Meta<typeof Chart> = {
7
+ title: 'Components/Templates/Chart/Line/Preliminary',
8
+ component: Chart
9
+ }
10
+
11
+ type Story = StoryObj<typeof Chart>
12
+
13
+ export const Line_Chart: Story = {
14
+ args: {
15
+ config: chartLinepreliminary
16
+ }
17
+ }
18
+
19
+ export default meta
@@ -0,0 +1,191 @@
1
+ {
2
+ "type": "chart",
3
+ "debugSvg": false,
4
+ "chartMessage": {
5
+ "noData": "No Data Available"
6
+ },
7
+ "title": "ARDI",
8
+ "showTitle": true,
9
+ "showDownloadMediaButton": false,
10
+ "theme": "theme-blue",
11
+ "animate": false,
12
+ "fontSize": "medium",
13
+ "lineDatapointStyle": "hover",
14
+ "lineDatapointColor": "Same as Line",
15
+ "barHasBorder": "false",
16
+ "isLollipopChart": false,
17
+ "lollipopShape": "circle",
18
+ "lollipopColorStyle": "two-tone",
19
+ "visualizationSubType": "regular",
20
+ "barStyle": "",
21
+ "roundingStyle": "standard",
22
+ "tipRounding": "top",
23
+ "isResponsiveTicks": false,
24
+ "general": {
25
+ "showDownloadButton": false
26
+ },
27
+ "padding": {
28
+ "left": 5,
29
+ "right": 5
30
+ },
31
+ "suppressedData": [],
32
+ "yAxis": {
33
+ "hideAxis": false,
34
+ "displayNumbersOnBar": false,
35
+ "hideLabel": false,
36
+ "hideTicks": false,
37
+ "size": 50,
38
+ "gridLines": false,
39
+ "enablePadding": false,
40
+ "min": "",
41
+ "max": "",
42
+ "labelColor": "#333",
43
+ "tickLabelColor": "#333",
44
+ "tickColor": "#333",
45
+ "rightHideAxis": true,
46
+ "rightAxisSize": 0,
47
+ "rightLabel": "",
48
+ "rightLabelOffsetSize": 0,
49
+ "rightAxisLabelColor": "#333",
50
+ "rightAxisTickLabelColor": "#333",
51
+ "rightAxisTickColor": "#333",
52
+ "numTicks": "",
53
+ "axisPadding": 0,
54
+ "tickRotation": 0,
55
+ "anchors": [],
56
+ "dataKey": "males"
57
+ },
58
+ "topAxis": {
59
+ "hasLine": false
60
+ },
61
+ "isLegendValue": false,
62
+ "barThickness": 0.35,
63
+ "barHeight": 25,
64
+ "barSpace": 15,
65
+ "heights": {
66
+ "vertical": 300,
67
+ "horizontal": 750
68
+ },
69
+ "xAxis": {
70
+ "sortDates": false,
71
+ "anchors": [],
72
+ "type": "categorical",
73
+ "showTargetLabel": true,
74
+ "targetLabel": "Target",
75
+ "hideAxis": false,
76
+ "hideLabel": false,
77
+ "hideTicks": false,
78
+ "size": 75,
79
+ "tickRotation": 0,
80
+ "min": "",
81
+ "max": "",
82
+ "labelColor": "#333",
83
+ "tickLabelColor": "#333",
84
+ "tickColor": "#333",
85
+ "numTicks": "",
86
+ "labelOffset": 65,
87
+ "axisPadding": 0,
88
+ "target": 0,
89
+ "maxTickRotation": 0,
90
+ "dataKey": "cause_type"
91
+ },
92
+ "table": {
93
+ "label": "Data Table",
94
+ "expanded": true,
95
+ "limitHeight": false,
96
+ "height": "",
97
+ "caption": "",
98
+ "showDownloadUrl": false,
99
+ "showDataTableLink": true,
100
+ "indexLabel": "",
101
+ "download": false,
102
+ "showVertical": true,
103
+ "show": true,
104
+ "customTableConfig": true
105
+ },
106
+ "orientation": "vertical",
107
+ "color": "pinkpurple",
108
+ "columns": {},
109
+ "legend": {
110
+ "hide": false,
111
+ "behavior": "isolate",
112
+ "singleRow": false,
113
+ "colorCode": "",
114
+ "reverseLabelOrder": false,
115
+ "description": "",
116
+ "dynamicLegend": false,
117
+ "dynamicLegendDefaultText": "Show All",
118
+ "dynamicLegendItemLimit": 5,
119
+ "dynamicLegendItemLimitMessage": "Dynamic Legend Item Limit Hit.",
120
+ "dynamicLegendChartMessage": "Select Options from the Legend",
121
+ "lineMode": false,
122
+ "verticalSorted": false,
123
+ "highlightOnHover": false
124
+ },
125
+ "brush": {
126
+ "height": 25,
127
+ "data": [],
128
+ "active": false
129
+ },
130
+ "exclusions": {
131
+ "active": true,
132
+ "keys": ["all_causes"]
133
+ },
134
+ "palette": "qualitative-soft",
135
+ "isPaletteReversed": false,
136
+ "twoColor": {
137
+ "palette": "monochrome-1",
138
+ "isPaletteReversed": false
139
+ },
140
+ "labels": false,
141
+ "dataFormat": {
142
+ "commas": false,
143
+ "prefix": "",
144
+ "suffix": "",
145
+ "abbreviated": false,
146
+ "bottomSuffix": "",
147
+ "bottomPrefix": "",
148
+ "bottomAbbreviated": false,
149
+ "roundTo": 1
150
+ },
151
+ "confidenceKeys": {},
152
+ "visual": {
153
+ "border": true,
154
+ "accent": true,
155
+ "background": true,
156
+ "verticalHoverLine": false,
157
+ "horizontalHoverLine": false
158
+ },
159
+ "useLogScale": false,
160
+ "filterBehavior": "Filter Change",
161
+ "highlightedBarValues": [],
162
+ "series": [
163
+ {
164
+ "dataKey": "males",
165
+ "axis": "Left",
166
+ "tooltip": true
167
+ }
168
+ ],
169
+ "tooltips": {
170
+ "opacity": 90,
171
+ "singleSeries": false
172
+ },
173
+ "dashboard": {
174
+ "theme": "theme-blue",
175
+ "title": "ARDI"
176
+ },
177
+ "animateReplay": true,
178
+ "aspectRatio": 1,
179
+ "validated": 4.23,
180
+ "visualizationType": "Pie",
181
+ "pieType": "Donut",
182
+ "filters": [
183
+ {
184
+ "values": ["age", "sex"],
185
+ "active": "age",
186
+ "filterStyle": "dropdown",
187
+ "order": "asc",
188
+ "columnName": "data_group"
189
+ }
190
+ ]
191
+ }