@cdc/chart 4.23.11 → 4.24.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 (104) hide show
  1. package/dist/cdcchart.js +35740 -35027
  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 +393 -0
  9. package/examples/feature/regions/index.json +9 -5
  10. package/examples/feature/scatterplot/scatterplot.json +272 -33
  11. package/index.html +10 -8
  12. package/package.json +2 -2
  13. package/src/CdcChart.tsx +70 -234
  14. package/src/ConfigContext.tsx +6 -0
  15. package/src/_stories/ChartEditor.stories.tsx +22 -0
  16. package/src/_stories/ChartLine.preliminary.tsx +19 -0
  17. package/src/_stories/_mock/pie_config.json +192 -0
  18. package/src/_stories/_mock/pie_data.json +218 -0
  19. package/src/_stories/_mock/preliminary_mock.json +346 -0
  20. package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +2 -2
  21. package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +2 -26
  22. package/src/components/AreaChart/index.tsx +4 -0
  23. package/src/components/{BarChart.Horizontal.tsx → BarChart/components/BarChart.Horizontal.tsx} +8 -8
  24. package/src/components/{BarChart.StackedHorizontal.tsx → BarChart/components/BarChart.StackedHorizontal.tsx} +37 -7
  25. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +108 -0
  26. package/src/components/{BarChart.Vertical.tsx → BarChart/components/BarChart.Vertical.tsx} +53 -70
  27. package/src/components/BarChart/components/BarChart.jsx +39 -0
  28. package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
  29. package/src/components/BarChart/components/context.tsx +13 -0
  30. package/src/components/BarChart/index.tsx +3 -0
  31. package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +10 -9
  32. package/src/components/BoxPlot/index.tsx +3 -0
  33. package/src/components/EditorPanel/EditorPanel.tsx +2776 -0
  34. package/src/components/EditorPanel/EditorPanelContext.ts +40 -0
  35. package/src/components/EditorPanel/components/PanelProps.ts +3 -0
  36. package/src/components/EditorPanel/components/Panels/Panel.BoxPlot.tsx +148 -0
  37. package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx} +97 -167
  38. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +160 -0
  39. package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +168 -0
  40. package/src/components/{Series.jsx → EditorPanel/components/Panels/Panel.Series.tsx} +4 -4
  41. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +297 -0
  42. package/src/components/EditorPanel/components/Panels/index.tsx +17 -0
  43. package/src/components/EditorPanel/components/panels.scss +72 -0
  44. package/src/components/EditorPanel/editor-panel.scss +739 -0
  45. package/src/components/EditorPanel/index.tsx +3 -0
  46. package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +34 -2
  47. package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
  48. package/src/components/Forecasting/index.tsx +3 -0
  49. package/src/components/ForestPlot/ForestPlot.tsx +254 -0
  50. package/src/components/ForestPlot/ForestPlotProps.ts +7 -0
  51. package/src/components/ForestPlot/index.tsx +1 -209
  52. package/src/components/Legend/Legend.Component.tsx +199 -0
  53. package/src/components/Legend/Legend.tsx +28 -0
  54. package/src/components/Legend/helpers/createFormatLabels.tsx +140 -0
  55. package/src/components/Legend/index.tsx +3 -0
  56. package/src/components/LineChart/LineChartProps.ts +29 -0
  57. package/src/components/LineChart/components/LineChart.Circle.tsx +147 -0
  58. package/src/components/LineChart/helpers.ts +45 -0
  59. package/src/components/LineChart/index.tsx +111 -23
  60. package/src/components/LinearChart.jsx +55 -72
  61. package/src/components/PairedBarChart.jsx +4 -2
  62. package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +93 -31
  63. package/src/components/PieChart/index.tsx +3 -0
  64. package/src/components/Regions/components/Regions.tsx +144 -0
  65. package/src/components/Regions/index.tsx +3 -0
  66. package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
  67. package/src/components/ScatterPlot/index.tsx +3 -0
  68. package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
  69. package/src/components/Sparkline/index.tsx +3 -0
  70. package/src/data/initial-state.js +10 -8
  71. package/src/helpers/abbreviateNumber.ts +17 -0
  72. package/src/helpers/computeMarginBottom.ts +55 -0
  73. package/src/helpers/filterData.ts +18 -0
  74. package/src/helpers/generateColorsArray.ts +8 -0
  75. package/src/helpers/getQuartiles.ts +30 -0
  76. package/src/helpers/handleChartAriaLabels.ts +19 -0
  77. package/src/helpers/handleLineType.ts +18 -0
  78. package/src/helpers/lineOptions.ts +18 -0
  79. package/src/helpers/sort.ts +7 -0
  80. package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
  81. package/src/hooks/useBarChart.js +7 -6
  82. package/src/hooks/useHighlightedBars.js +1 -1
  83. package/src/hooks/useMinMax.ts +3 -3
  84. package/src/hooks/useScales.ts +19 -6
  85. package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +31 -25
  86. package/src/scss/main.scss +0 -3
  87. package/src/types/ChartConfig.ts +167 -23
  88. package/src/types/ChartContext.ts +34 -12
  89. package/src/types/ForestPlot.ts +7 -14
  90. package/src/types/Label.ts +7 -0
  91. package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
  92. package/src/ConfigContext.jsx +0 -5
  93. package/src/components/BarChart.StackedVertical.tsx +0 -91
  94. package/src/components/BarChart.jsx +0 -30
  95. package/src/components/EditorPanel.jsx +0 -3356
  96. package/src/components/ForestPlot/Readme.md +0 -0
  97. package/src/components/Legend.jsx +0 -310
  98. package/src/components/LineChart/LineChart.Circle.tsx +0 -105
  99. package/src/scss/LinearChart.scss +0 -0
  100. package/src/scss/editor-panel.scss +0 -745
  101. package/src/scss/legend.scss +0 -206
  102. package/src/scss/mixins.scss +0 -0
  103. package/src/scss/variables.scss +0 -1
  104. package/src/types/ChartProps.ts +0 -7
@@ -0,0 +1,20 @@
1
+ import { ChartConfig, Legend } from '../../types/ChartConfig'
2
+ import { computeMarginBottom } from '../computeMarginBottom'
3
+
4
+ describe('computeMarginBottom', () => {
5
+ it('should return correct value', () => {
6
+ const config = {
7
+ orientation: 'horizontal',
8
+ xAxis: { labelOffset: '10' },
9
+ yAxis: { label: null },
10
+ brush: { active: false },
11
+ isResponsiveTicks: true,
12
+ dynamicMarginTop: 20
13
+ }
14
+ const legend = { position: 'top' }
15
+ const currentViewport = 'md'
16
+ expect(computeMarginBottom(config as unknown as ChartConfig, legend as Legend, currentViewport)).toBe('0px')
17
+ config.yAxis.label = 'label'
18
+ expect(computeMarginBottom(config as unknown as ChartConfig, legend as Legend, currentViewport)).toBe('40px')
19
+ })
20
+ })
@@ -184,7 +184,7 @@ export const useBarChart = () => {
184
184
  return 0
185
185
  }
186
186
 
187
- const getAdditionalColumn = xAxisDataValue => {
187
+ const getAdditionalColumn = (series, xAxisDataValue) => {
188
188
  if (!xAxisDataValue) return ''
189
189
  const columns = config.columns
190
190
  const columnsWithTooltips = []
@@ -193,7 +193,8 @@ export const useBarChart = () => {
193
193
  tableData.find(d => {
194
194
  return d[config.xAxis.dataKey] === xAxisDataValue
195
195
  }) || {}
196
- for (const [colKeys, colVals] of Object.entries(columns)) {
196
+ Object.keys(columns).forEach(colKeys => {
197
+ if(series && config.columns[colKeys].series && config.columns[colKeys].series !== series) return
197
198
  const formattingParams = {
198
199
  addColPrefix: config.columns[colKeys].prefix,
199
200
  addColSuffix: config.columns[colKeys].suffix,
@@ -201,11 +202,11 @@ export const useBarChart = () => {
201
202
  addColCommas: config.columns[colKeys].commas
202
203
  }
203
204
 
204
- const formattedValue = formatColNumber(closestVal[colVals?.name], 'left', true, config, formattingParams)
205
- if (colVals.tooltips) {
206
- columnsWithTooltips.push([colVals.label, formattedValue])
205
+ const formattedValue = formatColNumber(closestVal[config.columns[colKeys].name], 'left', true, config, formattingParams)
206
+ if (config.columns[colKeys].tooltips) {
207
+ columnsWithTooltips.push([config.columns[colKeys].label, formattedValue])
207
208
  }
208
- }
209
+ })
209
210
  columnsWithTooltips.forEach(columnData => {
210
211
  additionalTooltipItems += `${columnData[0]} : ${columnData[1]} <br/>`
211
212
  })
@@ -127,7 +127,7 @@ export const useHighlightedBars = (config, updateConfig) => {
127
127
  */
128
128
  HighLightedBarUtils.findDuplicates = arr => {
129
129
  const duplicates = {}
130
- const result = arr.filter(obj => {
130
+ const result = arr?.filter(obj => {
131
131
  const { legendLabel } = obj
132
132
  if (!duplicates[legendLabel]) {
133
133
  duplicates[legendLabel] = true
@@ -181,10 +181,10 @@ const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAll
181
181
  if (config.yAxis.enablePadding) {
182
182
  if (min < 0) {
183
183
  // sets with negative data need more padding on the max
184
- max *= 1.2
185
- min *= 1.2
184
+ max *= 1 + (config.yAxis.scalePadding * 2) / 100
185
+ min *= 1 + (config.yAxis.scalePadding * 2) / 100
186
186
  } else {
187
- max *= 1.1
187
+ max *= 1 + config.yAxis.scalePadding / 100
188
188
  }
189
189
  }
190
190
 
@@ -56,21 +56,25 @@ const useScales = (properties: useScaleProps) => {
56
56
 
57
57
  // handle Vertical bars
58
58
  if (!isHorizontal) {
59
- xScaleBrush = composeScalePoint(xAxisDataKeysMapped, [0, xMax], 0.5)
60
- xScale = composeScalePoint(xAxisDataMapped, [0, xMax], 0.5)
61
- xScale.type = scaleTypes.POINT
59
+ xScaleBrush = composeScalePoint(xAxisDataKeysMapped, [0, xMax], .5)
60
+ xScale = composeScaleBand(xAxisDataMapped, [0, xMax], 1 - config.barThickness)
62
61
  yScale = composeYScale(properties)
63
- seriesScale = composeScalePoint(seriesDomain, [0, xMax])
62
+ seriesScale = composeScaleBand(seriesDomain, [0, xScale.bandwidth()], 0)
64
63
  }
65
64
 
66
65
  // handle Area chart
67
66
  if (config.xAxis.type === 'date' && config.xAxis.sortDates) {
67
+ let xAxisMin = Math.min(...xAxisDataMapped)
68
+ let xAxisMax = Math.max(...xAxisDataMapped)
69
+ xAxisMin -= (config.xAxis.padding ? config.xAxis.padding * 0.01 : 0) * (xAxisMax - xAxisMin)
70
+ xAxisMax += (config.xAxis.padding ? config.xAxis.padding * 0.01 : 0) * (xAxisMax - xAxisMin)
68
71
  xScale = scaleTime({
69
- domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)],
72
+ domain: [xAxisMin, xAxisMax],
70
73
  range: [0, xMax]
71
74
  })
72
75
  xScaleBrush = xScale
73
76
  xScale.type = scaleTypes.LINEAR
77
+ seriesScale = composeScaleBand(seriesDomain, [0, config.barThickness * (xMax)], 0)
74
78
  }
75
79
 
76
80
  // handle Deviation bar
@@ -190,7 +194,7 @@ const useScales = (properties: useScaleProps) => {
190
194
  if (config.forestPlot.type === 'Linear') {
191
195
  xScale = scaleLinear({
192
196
  domain: [Math.min(...data.map(d => parseFloat(d[config.forestPlot.lower]))) - xAxisPadding, Math.max(...data.map(d => parseFloat(d[config.forestPlot.upper]))) + xAxisPadding],
193
- range: [leftWidthOffset, xMax - rightWidthOffset]
197
+ range: [leftWidthOffset, dimensions[0] - rightWidthOffset]
194
198
  })
195
199
  xScale.type = scaleTypes.LINEAR
196
200
  }
@@ -284,3 +288,12 @@ const composeScalePoint = (domain, range, padding = 0) => {
284
288
  type: 'point'
285
289
  })
286
290
  }
291
+
292
+ const composeScaleBand = (domain, range, padding = 0) => {
293
+ return scaleBand({
294
+ domain: domain,
295
+ range: range,
296
+ padding: padding,
297
+ type: 'band'
298
+ })
299
+ }
@@ -1,6 +1,6 @@
1
1
  import { useContext } from 'react'
2
2
  import ConfigContext from '../ConfigContext'
3
- import { defaultStyles } from '@visx/tooltip'
3
+ import { type ChartContext } from '../types/ChartContext'
4
4
 
5
5
  // third party
6
6
  import { localPoint } from '@visx/event'
@@ -11,7 +11,7 @@ const transform = new DataTransform()
11
11
  import { formatNumber as formatColNumber } from '@cdc/core/helpers/cove/number'
12
12
 
13
13
  export const useTooltip = props => {
14
- const { tableData, config, formatNumber, capitalize, formatDate, parseDate, setSharedFilter } = useContext(ConfigContext)
14
+ const { tableData, config, formatNumber, capitalize, formatDate, formatTooltipsDate, parseDate, setSharedFilter } = useContext<ChartContext>(ConfigContext)
15
15
  const { xScale, yScale, showTooltip, hideTooltip } = props
16
16
  const { xAxis, visualizationType, orientation, yAxis, runtime } = config
17
17
  const data = transform.applySuppression(tableData, config.suppressedData)
@@ -82,13 +82,10 @@ export const useTooltip = props => {
82
82
  includedSeries.push(...getColumnNames(config.columns))
83
83
 
84
84
  const yScaleValues = getYScaleValues(closestXScaleValue, includedSeries)
85
-
86
85
  const xScaleValues = data.filter(d => d[xAxis.dataKey] === getClosestYValue(y))
87
86
 
88
87
  const resolvedScaleValues = orientation === 'vertical' ? yScaleValues : xScaleValues
89
88
 
90
- // const forestPlotXValue = visualizationType === 'Forest Plot' ? data?.filter(d => d[xAxis.dataKey] === getClosestYValue(y))?.[0]?.[config.forestPlot.estimateField] : null
91
-
92
89
  const getAxisPosition = seriesKey => {
93
90
  const seriesObj = config.series.filter(s => s.dataKey === seriesKey)[0]
94
91
  const position = seriesObj?.axis ? String(seriesObj.axis).toLowerCase() : 'left'
@@ -112,7 +109,7 @@ export const useTooltip = props => {
112
109
  if (config.visualizationType === 'Pie') {
113
110
  closestValue = arc?.data[colVals.name]
114
111
  } else {
115
- closestValue = resolvedScaleValues[0][colVals.name]
112
+ closestValue = resolvedScaleValues[0]?.[colVals.name]
116
113
  }
117
114
 
118
115
  const formattedValue = formatColNumber(closestValue, 'left', true, config, formattingParams)
@@ -135,6 +132,7 @@ export const useTooltip = props => {
135
132
  ['Percent', `${Math.round((((arc?.endAngle - arc?.startAngle) * 180) / Math.PI / 360) * 100) + '%'}`]
136
133
  )
137
134
  }
135
+
138
136
  if (visualizationType === 'Forest Plot') {
139
137
  tooltipItems.push([config.xAxis.dataKey, getClosestYValue(y)])
140
138
  }
@@ -143,9 +141,9 @@ export const useTooltip = props => {
143
141
  tooltipItems.push(
144
142
  ...getIncludedTooltipSeries()
145
143
  ?.filter(Boolean)
146
- .flatMap(seriesKey => {
147
- const formattedValue = seriesKey === config.xAxis.dataKey ? resolvedScaleValues[0][seriesKey] : formatNumber(resolvedScaleValues[0][seriesKey], getAxisPosition(seriesKey))
148
- return resolvedScaleValues[0][seriesKey] ? [[seriesKey, formattedValue]] : []
144
+ ?.flatMap(seriesKey => {
145
+ const formattedValue = seriesKey === config.xAxis.dataKey ? resolvedScaleValues[0]?.[seriesKey] : formatNumber(resolvedScaleValues[0]?.[seriesKey], getAxisPosition(seriesKey))
146
+ return resolvedScaleValues?.[0]?.[seriesKey] ? [[seriesKey, formattedValue, getAxisPosition(seriesKey)]] : []
149
147
  })
150
148
  )
151
149
  }
@@ -204,9 +202,11 @@ export const useTooltip = props => {
204
202
  * @function getXValueFromCoordinate
205
203
  * @returns {String} - the closest x value to the cursor position
206
204
  */
207
- const getXValueFromCoordinate = x => {
205
+ const getXValueFromCoordinate = (x, isClick = false) => {
208
206
  if (visualizationType === 'Pie') return
209
207
  if (orientation === 'horizontal') return
208
+
209
+ // Check the type of x equal to point or if the type of xAxis is equal to continuous or date
210
210
  if (xScale.type === 'point' || xAxis.type === 'continuous' || xAxis.type === 'date') {
211
211
  // Find the closest x value by calculating the minimum distance
212
212
  let closestX = null
@@ -215,21 +215,24 @@ export const useTooltip = props => {
215
215
 
216
216
  data.forEach(d => {
217
217
  const xPosition = xAxis.type === 'date' ? xScale(parseDate(d[xAxis.dataKey])) : xScale(d[xAxis.dataKey])
218
- const distance = Math.abs(Number(xPosition - offset))
218
+ let bwOffset = config.barHeight
219
+ const distance = Math.abs(Number(xPosition - offset + (isClick ? bwOffset * 2 : 0)))
219
220
 
220
- if (distance < minDistance) {
221
+ if (distance <= minDistance) {
221
222
  minDistance = distance
222
- closestX = xAxis.type === 'date' ? parseDate(d[xAxis.dataKey]) : d[xAxis.dataKey]
223
+ closestX = xAxis.type === 'date' ? d[xAxis.dataKey] : d[xAxis.dataKey]
223
224
  }
224
225
  })
225
226
  return closestX
226
227
  }
227
228
 
228
229
  if (config.xAxis.type === 'categorical' || (visualizationType === 'Combo' && orientation !== 'horizontal' && visualizationType !== 'Forest Plot')) {
229
- let eachBand = xScale.step()
230
+ let range = xScale.range()[1] - xScale.range()[0]
231
+ let eachBand = range / (xScale.domain().length + 1)
232
+
230
233
  let numerator = x
231
- const index = Math.floor(Number(numerator) / eachBand)
232
- return xScale.domain()[index - 1] // fixes off by 1 error
234
+ const index = Math.floor((Number(numerator) - eachBand / 2) / eachBand)
235
+ return xScale.domain()[index] // fixes off by 1 error
233
236
  }
234
237
 
235
238
  if (config.xAxis.type === 'date' && visualizationType !== 'Combo' && orientation !== 'horizontal') {
@@ -250,7 +253,6 @@ export const useTooltip = props => {
250
253
  const yPositionOnPlot = visualizationType !== 'Forest Plot' ? yScale(d[config.xAxis.dataKey]) : yScale(index)
251
254
 
252
255
  const distance = Math.abs(yPositionOnPlot - yPosition)
253
-
254
256
  if (distance < minDistance) {
255
257
  minDistance = distance
256
258
  closestYValue = key ? d[key] : d[config.xAxis.dataKey]
@@ -275,9 +277,14 @@ export const useTooltip = props => {
275
277
  const eventSvgCoords = localPoint(e)
276
278
  const { x } = eventSvgCoords
277
279
  if (!x) throw new Error('COVE: no x value in handleTooltipClick.')
278
- let closestXScaleValue = getXValueFromCoordinate(x)
279
- if (!closestXScaleValue) throw new Error('COVE: no closest x scale value in handleTooltipClick')
280
+ let closestXScaleValue = getXValueFromCoordinate(x, true)
280
281
  let datum = config.data?.filter(item => item[config.xAxis.dataKey] === closestXScaleValue)
282
+ if (!closestXScaleValue) throw new Error('COVE: no closest x scale value in handleTooltipClick')
283
+ if (xAxis.type === 'date' && closestXScaleValue) {
284
+ closestXScaleValue = new Date(closestXScaleValue)
285
+ closestXScaleValue = formatDate(closestXScaleValue)
286
+ datum = config.data?.filter(item => formatDate(new Date(item[config.xAxis.dataKey])) === closestXScaleValue)
287
+ }
281
288
 
282
289
  if (!datum[0]) {
283
290
  throw new Error(`COVE: no data found matching the closest xScale value: ${closestXScaleValue}`)
@@ -300,16 +307,13 @@ export const useTooltip = props => {
300
307
  */
301
308
  const getYScaleValues = (closestXScaleValue, includedSeries) => {
302
309
  try {
303
- const formattedDate = formatDate(closestXScaleValue)
304
-
305
310
  let dataToSearch
306
311
 
307
312
  if (xAxis.type === 'categorical') {
308
313
  dataToSearch = data.filter(d => d[xAxis.dataKey] === closestXScaleValue)
309
314
  } else {
310
- dataToSearch = data.filter(d => formatDate(parseDate(d[xAxis.dataKey])) === formattedDate)
315
+ dataToSearch = data.filter(d => d[xAxis.dataKey] === closestXScaleValue)
311
316
  }
312
-
313
317
  // Return an empty array if no matching data is found.
314
318
  if (!dataToSearch || dataToSearch.length === 0) {
315
319
  return []
@@ -424,10 +428,12 @@ export const useTooltip = props => {
424
428
  if (key === config.xAxis.dataKey) return <li className='tooltip-heading'>{`${capitalize(config.xAxis.dataKey ? `${config.xAxis.dataKey}: ` : '')} ${config.yAxis.type === 'date' ? formatDate(parseDate(key, false)) : value}`}</li>
425
429
  return <li className='tooltip-body'>{`${getSeriesNameFromLabel(key)}: ${formatNumber(value, 'left')}`}</li>
426
430
  }
431
+ const formattedDate = config.tooltips.dateDisplayFormat ? formatTooltipsDate(parseDate(value, false)) : formatDate(parseDate(value, false))
427
432
 
428
433
  // TOOLTIP HEADING
429
- if (visualizationType === 'Bar' && orientation === 'horizontal' && key === config.xAxis.dataKey) return <li className='tooltip-heading'>{`${capitalize(config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ` : '')} ${value}`}</li>
430
- if (key === config.xAxis.dataKey) return <li className='tooltip-heading'>{`${capitalize(config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ` : '')} ${config.xAxis.type === 'date' ? value : value}`}</li>
434
+ if (visualizationType === 'Bar' && orientation === 'horizontal' && key === config.xAxis.dataKey) return <li className='tooltip-heading'>{`${capitalize(config.runtime.yAxis.label ? `${config.runtime.yAxis.label}: ` : '')} ${config.xAxis.type === 'date' ? formattedDate : value}`}</li>
435
+
436
+ if (key === config.xAxis.dataKey) return <li className='tooltip-heading'>{`${capitalize(config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ` : '')} ${config.xAxis.type === 'date' ? formattedDate : value}`}</li>
431
437
 
432
438
  // TOOLTIP BODY
433
439
  return <li className='tooltip-body'>{`${getSeriesNameFromLabel(key)}: ${value}`}</li>
@@ -1,7 +1,5 @@
1
1
  @import '@cdc/core/styles/base';
2
2
  @import '@cdc/core/styles/heading-colors';
3
- @import 'mixins';
4
- @import 'variables';
5
3
  @import '@cdc/core/styles/v2/themes/color-definitions';
6
4
 
7
5
  .form-container {
@@ -17,7 +15,6 @@
17
15
 
18
16
  .cdc-open-viz-module.type-chart {
19
17
  @import 'DataTable';
20
- @import 'editor-panel';
21
18
 
22
19
  border-radius: 3px;
23
20
 
@@ -1,43 +1,187 @@
1
+ import { Axis } from '@cdc/core/types/Axis'
1
2
  import { type ForestPlotConfigSettings } from './ForestPlot'
3
+ import { type Column } from '@cdc/core/types/Column'
4
+ import { type Series } from '@cdc/core/types/Series'
5
+ import { Runtime } from '@cdc/core/types/Runtime'
6
+ import { FilterBehavior } from '@cdc/core/types/FilterBehavior'
7
+ import { Table } from '@cdc/core/types/Table'
8
+ import { BoxPlot } from '@cdc/core/types/BoxPlot'
9
+ import { General } from '@cdc/core/types/General'
2
10
 
3
- export type ChartColumns = {
4
- [key: string]: {
5
- label: string
6
- dataTable: boolean
7
- tooltips: boolean
8
- prefix: string
9
- suffix: string
10
- forestPlot: boolean
11
- startingPoint: string
12
- forestPlotAlignRight: boolean
13
- name?: string
14
- }
11
+ export type ChartColumns = Record<string, Column>
12
+
13
+ type Region = {
14
+ from: string
15
+ to: string
16
+ fromType: 'Previous Days' | 'Fixed Date'
17
+ toType: 'Last Date' | 'Fised Date'
18
+ label: string
19
+ color: string
20
+ background: string
21
+ range: 'Custom' | string
15
22
  }
16
23
 
17
- type Series = {
18
- dataKey: string
19
- axis: string
24
+ type DataFormat = {
25
+ abbreviated: boolean
26
+ bottomAbbreviated: boolean
27
+ bottomCommas: boolean
28
+ bottomPrefix: string
29
+ bottomRoundTo: number
30
+ bottomSuffix: string
31
+ commas: boolean
32
+ prefix: string
33
+ rightCommas: boolean
34
+ rightPrefix: string
35
+ rightRoundTo: number
36
+ rightSuffix: string
37
+ roundTo: number
38
+ suffix: string
39
+ }
40
+
41
+ type Exclusions = {
42
+ keys: string[]
43
+ active: boolean
44
+ dateStart: string
45
+ dateEnd: string
46
+ }
47
+
48
+ type Filter = {
49
+ active: string
50
+ type: 'url'
51
+ columnName: string
52
+ showDropdown: boolean
53
+ filterStyle: string
54
+ label: string
55
+ order: 'asc' | 'desc' | 'cust'
56
+ values: string[]
57
+ queryParameter: string
58
+ }
59
+
60
+ export type Legend = {
61
+ additionalCategories: string[]
62
+ // general legend onClick behavior
63
+ behavior: 'highlight' | 'isolate' | string
64
+ colorCode: string
65
+ description: string
66
+ // show or hide the legend
67
+ hide: boolean
68
+ highlightOnHover: boolean
69
+ label: string
70
+ lineMode: boolean
71
+ position: string
72
+ reverseLabelOrder: boolean
73
+ singleRow: boolean
74
+ type: string
75
+ verticalSorted: boolean
76
+ }
77
+
78
+ type Visual = {
79
+ border?: boolean
80
+ borderColorTheme?: boolean
81
+ accent?: boolean
82
+ background?: boolean
83
+ hideBackgroundColor?: boolean
84
+ verticalHoverLine?: boolean
85
+ horizontalHoverLine?: boolean
20
86
  }
21
87
 
22
88
  type AllChartsConfig = {
89
+ animate: boolean
90
+ general: General
91
+ barHasBorder: 'true' | 'false'
92
+ barHeight: number
93
+ barSpace: number
94
+ barStyle: string
95
+ barThickness: number
96
+ boxplot: BoxPlot
97
+ brush: {
98
+ active: boolean
99
+ height: number
100
+ }
101
+ chartMessage: { noData?: string }
102
+ color: string
103
+ colorMatchLineSeriesLabels: boolean
23
104
  columns: ChartColumns
105
+ confidenceKeys: Record<string, any>
106
+ customColors: string[]
107
+ data: Object[]
108
+ dataUrl: string
109
+ dataCutoff: number
110
+ dataDescription: string
111
+ dataFormat: DataFormat
112
+ dataKey: string
113
+ description: string
114
+ dynamicMarginTop: number
115
+ exclusions: Exclusions
116
+ filters: Filter[]
117
+ filterBehavior: FilterBehavior
118
+ fontSize: 'small' | 'medium' | 'large'
119
+ footnotes: string
24
120
  forestPlot: ForestPlotConfigSettings
25
- isLollipopChart: boolean
26
- legend: {
27
- behavior: 'highlight' | unknown
121
+ formattedData: Object[] & { urlFiltered: boolean }
122
+ heights: {
123
+ vertical: number
28
124
  }
125
+ highlightedBarValues: { value: any; color: string; borderWidth: number; legendLabel: string }[]
126
+ introText: string
127
+ isLollipopChart: boolean
128
+ isLegendValue: boolean
129
+ isResponsiveTicks: boolean
130
+ isPaletteReversed: boolean
131
+ labels: boolean
132
+ legend: Legend
133
+ lineDatapointColor: 'Same as Line' | 'Lighter than Line'
134
+ lineDatapointStyle: 'hidden' | 'always show' | 'hover'
135
+ lollipopColorStyle: 'regular' | 'two-tone'
136
+ lollipopShape: string
137
+ lollipopSize: 'small' | 'medium' | 'large'
138
+ newViz: Object
29
139
  orientation: 'vertical' | 'horizontal'
30
- runtime: {}
31
- series: Series[]
140
+ palette: string
141
+ pieType?: string
142
+ primary?: DataFormat
143
+ roundingStyle: string
144
+ runtime: Runtime
145
+ runtimeDataUrl: string
146
+ series: Series
147
+ showLineSeriesLabels: boolean
148
+ showSidebar: boolean
149
+ showTitle: boolean
150
+ sortData: 'ascending' | 'descending'
151
+ stackedAreaChartLineType: string
152
+ suppressedData?: { label: string; icon: string; value: string }[]
153
+ superTitle: string
154
+ theme: string
155
+ table: Table
156
+ tipRounding: string
157
+ title: string
158
+ tooltips: {
159
+ singleSeries: boolean
160
+ opacity: number
161
+ dateDisplayFormat: string
162
+ }
163
+ topAxis: { hasLine: boolean }
164
+ twoColor: { palette: string }
165
+ type: string
32
166
  useLogScale: boolean
33
- visualizationType: 'Area Chart' | 'Bar' | 'Deviation Bar' | 'Forest Plot' | 'Paired Bar' | 'Scatter Plot' | 'Spark Line'
167
+ visual: Visual
168
+ visualizationType: 'Area Chart' | 'Bar' | 'Box Plot' | 'Deviation Bar' | 'Forest Plot' | 'Line' | 'Paired Bar' | 'Pie' | 'Scatter Plot' | 'Spark Line' | 'Combo' | 'Forecasting'
169
+ visualizationSubType: string
170
+ xAxis: Axis
171
+ yAxis: Axis
34
172
  xScale: Function
35
173
  yScale: Function
174
+ regions: Region[]
36
175
  }
37
176
 
177
+ export type ForestPlotConfig = {
178
+ visualizationType: 'Forest Plot'
179
+ forestPlot: ForestPlotConfigSettings
180
+ } & AllChartsConfig
181
+
38
182
  export type LineChartConfig = {
39
183
  visualizationType: 'Line'
40
184
  lineDatapointStyle: 'hidden' | 'always show' | 'hover'
41
- } & AllCharts
185
+ } & AllChartsConfig
42
186
 
43
- export type ChartConfig = LineChartConfig | AllChartsConfig
187
+ export type ChartConfig = LineChartConfig | ForestPlotConfig | AllChartsConfig
@@ -1,38 +1,60 @@
1
1
  import { type ChartConfig } from './ChartConfig'
2
+ import { PickD3Scale } from '@visx/scale'
2
3
 
3
- // Line Chart Specific Context
4
- type LineChartContext = {
5
- colorScale: Function
4
+ export type ColorScale = PickD3Scale<'ordinal', any, any>
5
+
6
+ export type TransformedData = {
7
+ dataKey?: string
8
+ [key: string]: any
9
+ }
10
+
11
+ type SharedChartContext = {
12
+ colorScale?: ColorScale
6
13
  config: ChartConfig
14
+ currentViewport?: string
15
+ highlight?: Function
16
+ highlightReset?: Function
17
+ }
18
+
19
+ // Line Chart Specific Context
20
+ type LineChartContext = SharedChartContext & {
7
21
  dimensions: [screenWidth: number, screenHeight: number]
8
22
  formatDate: Function
23
+ formatTooltipsDate: Function
9
24
  formatNumber: Function
10
25
  handleLineType: Function
11
26
  isNumber: unknown
27
+ isDebug?: boolean
12
28
  parseDate: Function
13
29
  rawData: Object[]
14
- seriesHighlight: String[]
30
+ seriesHighlight: string[]
15
31
  tableData: Object[]
16
- transformedData: Object[]
32
+ transformedData: TransformedData[]
17
33
  updateConfig: Function
18
34
  visualizationType: 'Line'
35
+ colorPalettes: Record<string, string[]>
36
+ twoColorPalette: Record<string, string[]>
19
37
  }
20
38
 
21
39
  export type ChartContext =
22
40
  | LineChartContext
23
- | {
24
- colorScale?: Function
25
- config?: ChartConfig
41
+ | (SharedChartContext & {
26
42
  dimensions: [screenWidth: number, screenHeight: number]
27
-
28
43
  formatDate?: Function
44
+ formatTooltipsDate: Function
29
45
  formatNumber?: Function
30
46
  handleLineType?: Function
31
47
  isNumber?: boolean
48
+ // url param added to allow various console logs and chart helpers
49
+ isDebug?: boolean
32
50
  parseDate?: Function
33
51
  rawData?: Object[]
34
- seriesHighlight?: String[]
52
+ seriesHighlight?: string[]
35
53
  tableData?: Object[]
36
- transformedData?: Object[]
54
+ transformedData?: TransformedData[]
55
+ setSharedFilter?: Function
56
+ sharedFilterValue?: string
37
57
  updateConfig?: Function
38
- }
58
+ colorPalettes: any
59
+ twoColorPalette: any
60
+ })
@@ -2,8 +2,10 @@ import { type Color } from '@cdc/core/types/Color'
2
2
 
3
3
  export type ForestPlotConfigSettings = {
4
4
  colors: {
5
- line: Color // color of line of effect
6
- shape: Color // color for effect estimate shape
5
+ // color of line of no effect
6
+ line: Color
7
+ // color for effect estimate shape
8
+ shape: Color
7
9
  }
8
10
  // description - appears below the study column.
9
11
  description: {
@@ -11,8 +13,9 @@ export type ForestPlotConfigSettings = {
11
13
  text: string
12
14
  location: number
13
15
  }
14
- // effect estimates
15
- estimateField: string // column chose for the effect estimate
16
+ // column chose for the effect estimate
17
+ estimateField: string
18
+ // column chose for the esimate radius
16
19
  estimateRadius: string
17
20
  hideDateCategoryCol: boolean
18
21
  leftWidthOffset: number
@@ -33,15 +36,8 @@ export type ForestPlotConfigSettings = {
33
36
  radius: {
34
37
  min: number
35
38
  max: number
36
- /** @deprecated - moved to estimateField due to duplication */
37
39
  scalingColumn: string
38
40
  }
39
- /** @deprecated - moved to pooledResult */
40
- regression: {
41
- lower: number
42
- upper: number
43
- estimateField: number
44
- }
45
41
  result: {
46
42
  show: boolean
47
43
  text: string
@@ -51,9 +47,6 @@ export type ForestPlotConfigSettings = {
51
47
  shape: string
52
48
  startAt: number
53
49
  title: string // centered title above the chart
54
-
55
- /** @deprecated - moved to lineOfNoEffect*/
56
- showZeroLine: boolean
57
50
  // labels under chart
58
51
  leftLabel: string
59
52
  rightLabel: string
@@ -0,0 +1,7 @@
1
+ export type Label = {
2
+ datum: string
3
+ index: number
4
+ text: string
5
+ value: string
6
+ icon?: any
7
+ }
@@ -1,17 +0,0 @@
1
- x,y1,y2,y3,y4
2
- 1000,8,37,72,82
3
- 2000,2,30,75,83
4
- 3000,15,42,51,95
5
- 4,10,38,61,96
6
- 5,1,38,66,86
7
- 60,6,37,70,85
8
- 10,19,47,59,91
9
- 24,18,32,68,89
10
- 3,7,38,74,89
11
- 26,10,39,56,91
12
- 42,16,38,55,76
13
- 32,20,46,52,94
14
- 11,9,41,57,86
15
- 22,10,47,56,80
16
- 73,1,36,71,94
17
- 23,13,30,66,78