@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
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Calculates the first quartile (q1) and third quartile (q3) from an array of integers or decimals.
3
+ *
4
+ * @param {Array} arr - The array of integers or decimals.
5
+ * @returns {Object} An object containing the q1 and q3 values.
6
+ */
7
+ export const getQuartiles = arr => {
8
+ arr.sort((a, b) => a - b)
9
+
10
+ // Calculate the index of the median value of the array
11
+ const medianIndex = Math.floor(arr.length / 2)
12
+
13
+ // Check if the length of the array is even or odd
14
+ const isEvenLength = arr.length % 2 === 0
15
+
16
+ // Split the array into two subarrays based on the median index
17
+ const q1Array = isEvenLength ? arr.slice(0, medianIndex) : arr.slice(0, medianIndex + 1)
18
+ const q3Array = isEvenLength ? arr.slice(medianIndex) : arr.slice(medianIndex + 1)
19
+
20
+ // Calculate the median of the first subarray to get the q1 value
21
+ const q1Index = Math.floor(q1Array.length / 2)
22
+ const q1 = isEvenLength ? (q1Array[q1Index - 1] + q1Array[q1Index]) / 2 : q1Array[q1Index]
23
+
24
+ // Calculate the median of the second subarray to get the q3 value
25
+ const q3Index = Math.floor(q3Array.length / 2)
26
+ const q3 = isEvenLength ? (q3Array[q3Index - 1] + q3Array[q3Index]) / 2 : q3Array[q3Index]
27
+
28
+ // Return an object containing the q1 and q3 values
29
+ return { q1, q3 }
30
+ }
@@ -0,0 +1,19 @@
1
+ export const handleChartAriaLabels = (state, testing = false) => {
2
+ if (testing) console.log(`handleChartAriaLabels Testing On:`, state) // eslint-disable-line
3
+ try {
4
+ if (!state.visualizationType) throw Error('handleChartAriaLabels: no visualization type found in state')
5
+ let ariaLabel = ''
6
+
7
+ if (state.visualizationType) {
8
+ ariaLabel += `${state.visualizationType} chart`
9
+ }
10
+
11
+ if (state.title && state.visualizationType) {
12
+ ariaLabel += ` with the title: ${state.title}`
13
+ }
14
+
15
+ return ariaLabel
16
+ } catch (e) {
17
+ console.error('COVE: ', e.message) // eslint-disable-line
18
+ }
19
+ }
@@ -0,0 +1,18 @@
1
+ export const handleLineType = lineType => {
2
+ switch (lineType) {
3
+ case 'dashed-sm':
4
+ return '5 5'
5
+ case 'Dashed Small':
6
+ return '5 5'
7
+ case 'dashed-md':
8
+ return '10 5'
9
+ case 'Dashed Medium':
10
+ return '10 5'
11
+ case 'dashed-lg':
12
+ return '15 5'
13
+ case 'Dashed Large':
14
+ return '15 5'
15
+ default:
16
+ return 0
17
+ }
18
+ }
@@ -0,0 +1,18 @@
1
+ export const lineOptions = [
2
+ {
3
+ value: 'Dashed Small',
4
+ key: 'dashed-sm'
5
+ },
6
+ {
7
+ value: 'Dashed Medium',
8
+ key: 'dashed-md'
9
+ },
10
+ {
11
+ value: 'Dashed Large',
12
+ key: 'dashed-lg'
13
+ },
14
+ {
15
+ value: 'Solid Line',
16
+ key: 'solid-line'
17
+ }
18
+ ]
@@ -0,0 +1,7 @@
1
+ export const sortAsc = (a, b) => {
2
+ return a.toString().localeCompare(b.toString(), 'en', { numeric: true })
3
+ }
4
+
5
+ export const sortDesc = (a, b) => {
6
+ return b.toString().localeCompare(a.toString(), 'en', { numeric: true })
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
  })
@@ -190,7 +190,7 @@ const useScales = (properties: useScaleProps) => {
190
190
  if (config.forestPlot.type === 'Linear') {
191
191
  xScale = scaleLinear({
192
192
  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]
193
+ range: [leftWidthOffset, dimensions[0] - rightWidthOffset]
194
194
  })
195
195
  xScale.type = scaleTypes.LINEAR
196
196
  }
@@ -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,9 +11,9 @@ 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, parseDate, setSharedFilter } = useContext<ChartContext>(ConfigContext)
15
15
  const { xScale, yScale, showTooltip, hideTooltip } = props
16
- const { xAxis, visualizationType, orientation, yAxis, runtime } = config
16
+ const { xAxis, visualizationType, orientation, yAxis, runtime, barWidth } = config
17
17
  const data = transform.applySuppression(tableData, config.suppressedData)
18
18
  /**
19
19
  * Provides the tooltip information based on the tooltip data array and svg cursor coordinates
@@ -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,11 +215,12 @@ 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
@@ -250,7 +251,6 @@ export const useTooltip = props => {
250
251
  const yPositionOnPlot = visualizationType !== 'Forest Plot' ? yScale(d[config.xAxis.dataKey]) : yScale(index)
251
252
 
252
253
  const distance = Math.abs(yPositionOnPlot - yPosition)
253
-
254
254
  if (distance < minDistance) {
255
255
  minDistance = distance
256
256
  closestYValue = key ? d[key] : d[config.xAxis.dataKey]
@@ -275,9 +275,14 @@ export const useTooltip = props => {
275
275
  const eventSvgCoords = localPoint(e)
276
276
  const { x } = eventSvgCoords
277
277
  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')
278
+ let closestXScaleValue = getXValueFromCoordinate(x, true)
280
279
  let datum = config.data?.filter(item => item[config.xAxis.dataKey] === closestXScaleValue)
280
+ if (!closestXScaleValue) throw new Error('COVE: no closest x scale value in handleTooltipClick')
281
+ if (xAxis.type === 'date' && closestXScaleValue) {
282
+ closestXScaleValue = new Date(closestXScaleValue)
283
+ closestXScaleValue = formatDate(closestXScaleValue)
284
+ datum = config.data?.filter(item => formatDate(new Date(item[config.xAxis.dataKey])) === closestXScaleValue)
285
+ }
281
286
 
282
287
  if (!datum[0]) {
283
288
  throw new Error(`COVE: no data found matching the closest xScale value: ${closestXScaleValue}`)
@@ -300,16 +305,13 @@ export const useTooltip = props => {
300
305
  */
301
306
  const getYScaleValues = (closestXScaleValue, includedSeries) => {
302
307
  try {
303
- const formattedDate = formatDate(closestXScaleValue)
304
-
305
308
  let dataToSearch
306
309
 
307
310
  if (xAxis.type === 'categorical') {
308
311
  dataToSearch = data.filter(d => d[xAxis.dataKey] === closestXScaleValue)
309
312
  } else {
310
- dataToSearch = data.filter(d => formatDate(parseDate(d[xAxis.dataKey])) === formattedDate)
313
+ dataToSearch = data.filter(d => d[xAxis.dataKey] === closestXScaleValue)
311
314
  }
312
-
313
315
  // Return an empty array if no matching data is found.
314
316
  if (!dataToSearch || dataToSearch.length === 0) {
315
317
  return []
@@ -1,8 +1,73 @@
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';
4
+ .dash-container {
5
+ display: flex;
6
+ align-items: center;
7
+ flex-direction: row;
8
+ }
9
+
10
+ .legend-dash-left {
11
+ margin-left: 8px !important;
12
+ display: flex;
13
+ flex-direction: column;
14
+ }
15
+
16
+ .dash-inner {
17
+ width: 20px;
18
+ margin-left: 0px !important;
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ }
23
+
24
+ .dashes {
25
+ display: inline-block;
26
+
27
+ &.open-circles {
28
+ width: 12px;
29
+ height: 12px;
30
+ border: 2px solid currentColor;
31
+ border-radius: 50%;
32
+ }
33
+
34
+ &.dashed-small {
35
+ margin: 0 0px;
36
+ font-size: 20px;
37
+ }
38
+
39
+ &.dashed-medium,
40
+ &.dashed-large {
41
+ span {
42
+ display: inline-block;
43
+ position: relative;
44
+ margin-right: 12px;
45
+ margin-left: 0 !important;
46
+
47
+ &::before {
48
+ content: '';
49
+ display: block;
50
+ height: 2px;
51
+ background-color: currentColor;
52
+ position: absolute;
53
+ top: 50%;
54
+ transform: translateY(-20%);
55
+ width: 10px;
56
+ }
57
+ }
58
+ }
59
+
60
+ &.dashed-large {
61
+ span {
62
+ margin-right: 12px;
63
+ margin-left: 0 !important;
64
+
65
+ &::before {
66
+ width: 13px;
67
+ }
68
+ }
69
+ }
70
+ }
6
71
 
7
72
  .form-container {
8
73
  overflow-y: auto;
@@ -17,7 +82,6 @@
17
82
 
18
83
  .cdc-open-viz-module.type-chart {
19
84
  @import 'DataTable';
20
- @import 'editor-panel';
21
85
 
22
86
  border-radius: 3px;
23
87
 
@@ -1,43 +1,178 @@
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'
2
8
 
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
- }
9
+ export type ChartColumns = Record<string, Column>
10
+
11
+ type Region = {
12
+ from: string
13
+ to: string
14
+ label: string
15
+ color: string
16
+ background: string
17
+ range: 'Custom' | string
15
18
  }
16
19
 
17
- type Series = {
18
- dataKey: string
19
- axis: string
20
+ type BoxPlot = {
21
+ firstQuartilePercentage: number
22
+ [key: string]: any
23
+ }
24
+
25
+ type DataFormat = {
26
+ abbreviated: boolean
27
+ bottomAbbreviated: boolean
28
+ bottomCommas: boolean
29
+ bottomPrefix: string
30
+ bottomRoundTo: number
31
+ bottomSuffix: string
32
+ commas: boolean
33
+ prefix: string
34
+ rightCommas: boolean
35
+ rightPrefix: string
36
+ rightRoundTo: number
37
+ rightSuffix: string
38
+ roundTo: number
39
+ suffix: string
40
+ }
41
+
42
+ type Exclusions = {
43
+ keys: string[]
44
+ active: boolean
45
+ dateStart: string
46
+ dateEnd: string
47
+ }
48
+
49
+ type Filter = {
50
+ type: 'url'
51
+ columnName: string
52
+ showDropdown: boolean
53
+ filterStyle: string
54
+ label: string
55
+ order: 'asc' | 'desc' | 'cust'
56
+ values: string[]
57
+ }
58
+
59
+ export type Legend = {
60
+ additionalCategories: string[]
61
+ // general legend onClick behavior
62
+ behavior: 'highlight' | 'isolate' | string
63
+ colorCode: string
64
+ description: string
65
+ // show or hide the legend
66
+ hide: boolean
67
+ highlightOnHover: boolean
68
+ label: string
69
+ lineMode: boolean
70
+ position: string
71
+ reverseLabelOrder: boolean
72
+ singleRow: boolean
73
+ type: string
74
+ verticalSorted: boolean
75
+ }
76
+
77
+ type Visual = {
78
+ border?: boolean
79
+ borderColorTheme?: boolean
80
+ accent?: boolean
81
+ background?: boolean
82
+ hideBackgroundColor?: boolean
83
+ verticalHoverLine?: boolean
84
+ horizontalHoverLine?: boolean
20
85
  }
21
86
 
22
87
  type AllChartsConfig = {
88
+ animate: boolean
89
+ general: {
90
+ boxplot: BoxPlot
91
+ }
92
+ barHasBorder: 'true' | 'false'
93
+ barHeight: number
94
+ barSpace: number
95
+ barStyle: string
96
+ barThickness: number
97
+ boxplot: BoxPlot
98
+ brush: {
99
+ active: boolean
100
+ height: number
101
+ }
102
+ chartMessage: { noData?: string }
103
+ colorMatchLineSeriesLabels: boolean
23
104
  columns: ChartColumns
105
+ confidenceKeys: Record<string, any>
106
+ data: Object[]
107
+ dataCutoff: number
108
+ dataFormat: DataFormat
109
+ dataKey: string
110
+ description: string
111
+ dynamicMarginTop: number
112
+ exclusions: Exclusions
113
+ filters: Filter[]
114
+ filterBehavior: FilterBehavior
115
+ fontSize: 'small' | 'medium' | 'large'
116
+ footnotes: string
24
117
  forestPlot: ForestPlotConfigSettings
25
- isLollipopChart: boolean
26
- legend: {
27
- behavior: 'highlight' | unknown
118
+ heights: {
119
+ vertical: number
28
120
  }
121
+ highlightedBarValues: { value: any; color: string; borderWidth: number; legendLabel: string }[]
122
+ introText: string
123
+ isLollipopChart: boolean
124
+ isLegendValue: boolean
125
+ isResponsiveTicks: boolean
126
+ isPaletteReversed: boolean
127
+ labels: boolean
128
+ legend: Legend
129
+ lineDatapointColor: 'Same as Line' | 'Lighter than Line'
130
+ lineDatapointStyle: 'hidden' | 'always show' | 'hover'
131
+ lollipopColorStyle: 'regular' | 'two-tone'
132
+ lollipopShape: string
133
+ lollipopSize: 'small' | 'medium' | 'large'
134
+ newViz: Object
29
135
  orientation: 'vertical' | 'horizontal'
30
- runtime: {}
31
- series: Series[]
136
+ palette: string
137
+ pieType?: string
138
+ roundingStyle: string
139
+ runtime: Runtime
140
+ series: Series
141
+ showLineSeriesLabels: boolean
142
+ showTitle: boolean
143
+ stackedAreaChartLineType: string
144
+ suppressedData?: { label: string; icon: string; value: string }[]
145
+ superTitle: string
146
+ theme: string
147
+ table: Table
148
+ tipRounding: string
149
+ title: string
150
+ tooltips: {
151
+ singleSeries: boolean
152
+ opacity: number
153
+ }
154
+ topAxis: { hasLine: boolean }
155
+ twoColor: { palette: string }
156
+ type: string
32
157
  useLogScale: boolean
33
- visualizationType: 'Area Chart' | 'Bar' | 'Deviation Bar' | 'Forest Plot' | 'Paired Bar' | 'Scatter Plot' | 'Spark Line'
158
+ visual: Visual
159
+ visualizationType: 'Area Chart' | 'Bar' | 'Box Plot' | 'Deviation Bar' | 'Forest Plot' | 'Line' | 'Paired Bar' | 'Pie' | 'Scatter Plot' | 'Spark Line' | 'Combo' | 'Forecasting'
160
+ visualizationSubType: string
161
+ xAxis: Axis
162
+ yAxis: Axis
34
163
  xScale: Function
35
164
  yScale: Function
165
+ regions: Region[]
36
166
  }
37
167
 
168
+ export type ForestPlotConfig = {
169
+ visualizationType: 'Forest Plot'
170
+ forestPlot: ForestPlotConfigSettings
171
+ } & AllChartsConfig
172
+
38
173
  export type LineChartConfig = {
39
174
  visualizationType: 'Line'
40
175
  lineDatapointStyle: 'hidden' | 'always show' | 'hover'
41
- } & AllCharts
176
+ } & AllChartsConfig
42
177
 
43
- export type ChartConfig = LineChartConfig | AllChartsConfig
178
+ export type ChartConfig = LineChartConfig | ForestPlotConfig | AllChartsConfig
@@ -1,38 +1,54 @@
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
+ type ColorScale = PickD3Scale<'ordinal', any, any>
5
+
6
+ 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
9
23
  formatNumber: Function
10
24
  handleLineType: Function
11
25
  isNumber: unknown
26
+ isDebug?: boolean
12
27
  parseDate: Function
13
28
  rawData: Object[]
14
29
  seriesHighlight: String[]
15
30
  tableData: Object[]
16
- transformedData: Object[]
31
+ transformedData: TransformedData[]
17
32
  updateConfig: Function
18
33
  visualizationType: 'Line'
19
34
  }
20
35
 
21
36
  export type ChartContext =
22
37
  | LineChartContext
23
- | {
24
- colorScale?: Function
25
- config?: ChartConfig
38
+ | (SharedChartContext & {
26
39
  dimensions: [screenWidth: number, screenHeight: number]
27
-
28
40
  formatDate?: Function
29
41
  formatNumber?: Function
30
42
  handleLineType?: Function
31
43
  isNumber?: boolean
44
+ // url param added to allow various console logs and chart helpers
45
+ isDebug?: boolean
32
46
  parseDate?: Function
33
47
  rawData?: Object[]
34
48
  seriesHighlight?: String[]
35
49
  tableData?: Object[]
36
- transformedData?: Object[]
50
+ transformedData?: TransformedData[]
51
+ setSharedFilter?: Function
52
+ sharedFilterValue?: string
37
53
  updateConfig?: Function
38
- }
54
+ })