@cdc/chart 4.25.10 → 4.25.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/{cdcchart-1a1724a1.es.js → cdcchart-dgT_1dIT.es.js} +136 -151
  2. package/dist/cdcchart.js +36258 -34658
  3. package/examples/feature/__data__/planet-example-data.json +1 -1
  4. package/examples/feature/boxplot/valid-boxplot.csv +38 -17
  5. package/examples/private/DEV-11825.json +573 -0
  6. package/examples/private/na.json +913 -0
  7. package/examples/private/test-data.csv +28 -0
  8. package/index.html +2 -121
  9. package/package.json +4 -4
  10. package/src/CdcChart.tsx +8 -11
  11. package/src/CdcChartComponent.tsx +256 -87
  12. package/src/_stories/Chart.Combo.stories.tsx +18 -0
  13. package/src/_stories/Chart.Forecast.stories.tsx +36 -0
  14. package/src/_stories/Chart.HTMLInDataTable.stories.tsx +520 -0
  15. package/src/_stories/Chart.Patterns.stories.tsx +2 -1
  16. package/src/_stories/Chart.PreserveDecimals.stories.tsx +220 -0
  17. package/src/_stories/Chart.SmallMultiples.stories.tsx +47 -0
  18. package/src/_stories/ChartAnnotation.stories.tsx +6 -3
  19. package/src/_stories/ChartBar.Editor.stories.tsx +3580 -0
  20. package/src/_stories/ChartEditor.Editor.stories.tsx +658 -0
  21. package/src/_stories/ChartEditor.stories.tsx +1 -2
  22. package/src/_stories/_mock/combo.json +451 -0
  23. package/src/_stories/_mock/editor-test-configs.json +376 -0
  24. package/src/_stories/_mock/editor-test-datasets.json +477 -0
  25. package/src/_stories/_mock/editor-tests/bar-chart-editor-test.json +255 -0
  26. package/src/_stories/_mock/editor-tests/bar-chart-general-test.json +267 -0
  27. package/src/_stories/_mock/editor-tests/bar-chart-test.json +237 -0
  28. package/src/_stories/_mock/forecast_combo_with_gaps.json +913 -0
  29. package/src/_stories/_mock/pie_config.json +257 -62
  30. package/src/_stories/_mock/small_multiples/small_multiples_bars.json +1944 -0
  31. package/src/_stories/_mock/small_multiples/small_multiples_big_data_bars.json +1114 -0
  32. package/src/_stories/_mock/small_multiples/small_multiples_lines.json +2646 -0
  33. package/src/_stories/_mock/small_multiples/small_multiples_lines_colors.json +1305 -0
  34. package/src/_stories/_mock/small_multiples/small_multiples_stacked_bars.json +1936 -0
  35. package/src/components/Annotations/components/findNearestDatum.ts +6 -41
  36. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -6
  37. package/src/components/AreaChart/index.tsx +1 -2
  38. package/src/components/BarChart/components/BarChart.Horizontal.tsx +4 -4
  39. package/src/components/BarChart/components/BarChart.Vertical.tsx +3 -2
  40. package/src/components/BoxPlot/helpers/index.ts +3 -3
  41. package/src/components/Brush/BrushChart.tsx +1 -1
  42. package/src/components/EditorPanel/EditorPanel.tsx +199 -190
  43. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +96 -111
  44. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +19 -1
  45. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +102 -55
  46. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +54 -49
  47. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +422 -0
  48. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +75 -21
  49. package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
  50. package/src/components/EditorPanel/editor-panel.scss +0 -20
  51. package/src/components/EditorPanel/useEditorPermissions.ts +7 -15
  52. package/src/components/Forecasting/Forecasting.tsx +139 -21
  53. package/src/components/Legend/Legend.Component.tsx +16 -9
  54. package/src/components/Legend/helpers/createFormatLabels.tsx +181 -181
  55. package/src/components/Legend/helpers/getLegendClasses.ts +0 -1
  56. package/src/components/LineChart/LineChartProps.ts +0 -3
  57. package/src/components/LineChart/helpers.ts +1 -1
  58. package/src/components/LineChart/index.tsx +36 -13
  59. package/src/components/LinearChart.tsx +75 -80
  60. package/src/components/Regions/components/Regions.tsx +3 -24
  61. package/src/components/Sankey/types/index.ts +1 -1
  62. package/src/components/SmallMultiples/SmallMultipleTile.tsx +198 -0
  63. package/src/components/SmallMultiples/SmallMultiples.css +32 -0
  64. package/src/components/SmallMultiples/SmallMultiples.tsx +271 -0
  65. package/src/components/SmallMultiples/index.ts +2 -0
  66. package/src/data/initial-state.js +13 -1
  67. package/src/helpers/buildForecastPaletteOptions.ts +0 -38
  68. package/src/helpers/getColorScale.ts +10 -0
  69. package/src/{hooks/useMinMax.ts → helpers/getMinMax.ts} +14 -7
  70. package/src/helpers/getYAxisAutoPadding.ts +53 -0
  71. package/src/helpers/smallMultiplesHelpers.ts +529 -0
  72. package/src/hooks/useProgrammaticTooltip.ts +96 -0
  73. package/src/hooks/useScales.ts +88 -34
  74. package/src/hooks/useSmallMultipleSynchronization.ts +59 -0
  75. package/src/hooks/useTooltip.tsx +60 -15
  76. package/src/scss/main.scss +1 -80
  77. package/src/store/chart.actions.ts +2 -0
  78. package/src/store/chart.reducer.ts +4 -0
  79. package/src/types/ChartConfig.ts +24 -6
  80. package/src/types/ChartContext.ts +3 -0
  81. package/src/_stories/_mock/pie_data.json +0 -218
  82. package/src/components/AreaChart/components/AreaChart.jsx +0 -109
  83. package/src/helpers/sort.ts +0 -7
  84. package/src/hooks/useActiveElement.js +0 -19
  85. package/src/hooks/useChartClasses.js +0 -41
@@ -1,41 +1,3 @@
1
- import { timeParse } from 'd3-time-format'
2
-
3
- const getXValueFromCoordinate = (x, isClick = false) => {
4
- if (visualizationType === 'Pie') return
5
- if (orientation === 'horizontal') return
6
-
7
- // Check the type of x equal to point or if the type of xAxis is equal to continuous or date
8
- if (config.xAxis.type === 'categorical' || (visualizationType === 'Combo' && orientation !== 'horizontal' && visualizationType !== 'Forest Plot')) {
9
- let range = xScale.range()[1] - xScale.range()[0]
10
- let eachBand = range / (xScale.domain().length + 1)
11
-
12
- let numerator = x
13
- const index = Math.floor((Number(numerator) - eachBand / 2) / eachBand)
14
- return xScale.domain()[index] // fixes off by 1 error
15
- }
16
-
17
- if (config.xAxis.type === 'date') {
18
- const xValue = x // Assuming x is the coordinate on the chart
19
- const xTimestamp = convertXValueToTimestamp(x, 0, xMax, xScale.domain())
20
-
21
- // Calculate the closest date to the x coordinate
22
- let closestDate = null
23
- let minDistance = Number.MAX_VALUE
24
-
25
- xScale.domain().forEach(timestamp => {
26
- const distance = Math.abs(xTimestamp - timestamp)
27
- if (distance < minDistance) {
28
- minDistance = distance
29
- closestDate = timestamp
30
- }
31
- })
32
-
33
- return closestDate
34
- }
35
-
36
- return x
37
- }
38
-
39
1
  const findNearestDatum = ({ data, xScale, yScale, config, xMax, annotationSeriesKey }, xPosition) => {
40
2
  const { xAxis, visualizationType, orientation } = config
41
3
 
@@ -62,7 +24,7 @@ const findNearestDatum = ({ data, xScale, yScale, config, xMax, annotationSeries
62
24
  return domain[index]
63
25
  }
64
26
 
65
- const getXValueFromCoordinate = (x, isClick = false) => {
27
+ const getXValueFromCoordinate = x => {
66
28
  if (visualizationType === 'Pie') return
67
29
  if (orientation === 'horizontal') return
68
30
 
@@ -85,7 +47,10 @@ const findNearestDatum = ({ data, xScale, yScale, config, xMax, annotationSeries
85
47
  }
86
48
 
87
49
  // Check the type of x equal to point or if the type of xAxis is equal to continuous or date
88
- if (config.xAxis.type === 'categorical' || (visualizationType === 'Combo' && orientation !== 'horizontal' && visualizationType !== 'Forest Plot')) {
50
+ if (
51
+ config.xAxis.type === 'categorical' ||
52
+ (visualizationType === 'Combo' && orientation !== 'horizontal' && visualizationType !== 'Forest Plot')
53
+ ) {
89
54
  const range = xScale.range()[1] - xScale.range()[0]
90
55
  const eachBand = range / (xScale.domain().length + 1)
91
56
 
@@ -135,4 +100,4 @@ const findNearestDatum = ({ data, xScale, yScale, config, xMax, annotationSeries
135
100
  return { x, y }
136
101
  }
137
102
 
138
- export { findNearestDatum, getXValueFromCoordinate }
103
+ export { findNearestDatum }
@@ -13,17 +13,21 @@ import { approvedCurveTypes } from '@cdc/core/helpers/lineChartHelpers'
13
13
 
14
14
  const AreaChartStacked = ({ xScale, yScale, yMax, xMax, handleTooltipMouseOver, handleTooltipMouseOff }) => {
15
15
  // import data from context
16
- let { transformedData, config, seriesHighlight, colorScale, rawData } = useContext(ConfigContext)
16
+ let { transformedData, config, seriesHighlight, colorScale, rawData, parseDate } = useContext(ConfigContext)
17
17
  const data = config.brush?.active && config.brush.data?.length ? config.brush.data : transformedData
18
18
  // Draw transparent bars over the chart to get tooltip data
19
19
  // Turn DEBUG on for additional context.
20
20
  if (!data) return
21
21
 
22
22
  const handleDateCategory = value => {
23
- if (config.xAxis.type === 'categorical') return xScale(value)
23
+ if (config.xAxis.type === 'categorical') {
24
+ return xScale(value) + (xScale.bandwidth ? xScale.bandwidth() / 2 : 0)
25
+ }
24
26
  if (isDateScale(config.xAxis)) {
25
- let date = new Date(value)
26
- return xScale(date)
27
+ const scaledValue = xScale(parseDate(value, false))
28
+ // Add bandwidth offset to center on band scales (date type)
29
+ // For date-time (time scale), bandwidth doesn't exist so no offset added
30
+ return scaledValue + (xScale.bandwidth ? xScale.bandwidth() / 2 : 0)
27
31
  }
28
32
  }
29
33
 
@@ -65,7 +69,7 @@ const AreaChartStacked = ({ xScale, yScale, yMax, xMax, handleTooltipMouseOver,
65
69
  key={stack.key}
66
70
  d={path(stack) || ''}
67
71
  strokeWidth={2}
68
- stroke={displayArea ? colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[stack.key] : stack.key) : '#000' : 'transparent'}
72
+ stroke={displayArea ? colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[stack.key] : stack.key) : '#000' : 'transparent'}
69
73
  fillOpacity={transparentArea ? 0.2 : 1}
70
74
  fill={displayArea ? colorScale ? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[stack.key] : stack.key) : '#000' : 'transparent'}
71
75
  />
@@ -74,7 +78,7 @@ const AreaChartStacked = ({ xScale, yScale, yMax, xMax, handleTooltipMouseOver,
74
78
  }}
75
79
  </AreaStack>
76
80
  {/* prettier-ignore */}
77
- <Bar width={Number(xMax)} height={Number(yMax)} fill={'transparent'} onMouseMove={e => handleTooltipMouseOver(e, rawData)} onMouseLeave={handleTooltipMouseOff} />
81
+ <Bar width={Number(xMax)} height={Number(yMax)} fill={'transparent'} onMouseMove={e => handleTooltipMouseOver(e, rawData)} onMouseLeave={handleTooltipMouseOff} />
78
82
  </Group>
79
83
  </ErrorBoundary>
80
84
  </svg>
@@ -1,4 +1,3 @@
1
- import AreaChart from './components/AreaChart'
2
1
  import AreaChartStacked from './components/AreaChart.Stacked'
3
2
 
4
- export { AreaChart, AreaChartStacked }
3
+ export { AreaChartStacked }
@@ -1,4 +1,4 @@
1
- import React, { useContext } from 'react'
1
+ import { useContext } from 'react'
2
2
 
3
3
  // Local context and hooks
4
4
  import ConfigContext from '../../../ConfigContext'
@@ -26,7 +26,7 @@ import _ from 'lodash'
26
26
  import { getBarData } from '../helpers/getBarData'
27
27
  import { getHorizontalBarHeights } from '../helpers/getBarHeights'
28
28
 
29
- export const BarChartHorizontal = () => {
29
+ const BarChartHorizontal = () => {
30
30
  const { xScale, yScale, yMax, seriesScale, barChart } = useContext<BarChartContextValues>(BarChartContext)
31
31
  const {
32
32
  isHorizontal,
@@ -54,12 +54,12 @@ export const BarChartHorizontal = () => {
54
54
  formatDate,
55
55
  parseDate,
56
56
  setSharedFilter,
57
- currentViewport
57
+ vizViewport
58
58
  } = useContext<ChartContext>(ConfigContext)
59
59
 
60
60
  const { HighLightedBarUtils } = useHighlightedBars(config)
61
61
 
62
- const LABEL_FONT_SIZE = isMobileFontViewport(currentViewport) ? 13 : 16
62
+ const LABEL_FONT_SIZE = isMobileFontViewport(vizViewport) ? 13 : 16
63
63
 
64
64
  const hasConfidenceInterval = [config.confidenceKeys?.upper, config.confidenceKeys?.lower].every(
65
65
  v => v != null && String(v).trim() !== ''
@@ -23,7 +23,7 @@ import { type ChartContext } from '../../../types/ChartContext'
23
23
  import _ from 'lodash'
24
24
  import { getBarData } from '../helpers/getBarData'
25
25
 
26
- export const BarChartVertical = () => {
26
+ const BarChartVertical = () => {
27
27
  const { xScale, yScale, xMax, yMax, seriesScale, convertLineToBarGraph, barChart } =
28
28
  useContext<BarChartContextValues>(BarChartContext)
29
29
  const {
@@ -46,6 +46,7 @@ export const BarChartVertical = () => {
46
46
  colorScale,
47
47
  config,
48
48
  currentViewport,
49
+ vizViewport,
49
50
  dashboardConfig,
50
51
  tableData,
51
52
  formatDate,
@@ -58,7 +59,7 @@ export const BarChartVertical = () => {
58
59
 
59
60
  const { HighLightedBarUtils } = useHighlightedBars(config)
60
61
 
61
- const LABEL_FONT_SIZE = isMobileFontViewport(currentViewport) ? 13 : 16
62
+ const LABEL_FONT_SIZE = isMobileFontViewport(vizViewport) ? 13 : 16
62
63
 
63
64
  const root = document.documentElement
64
65
 
@@ -29,7 +29,7 @@ export const handleTooltip = (boxplot, columnCategory, key, q1, q3, median, iqr,
29
29
  `
30
30
  }
31
31
 
32
- export const calculateBoxPlotStats = (values: number[]) => {
32
+ const calculateBoxPlotStats = (values: number[]) => {
33
33
  if (!values || values.length === 0) return {}
34
34
 
35
35
  // Sort the values
@@ -82,7 +82,7 @@ const getValuesBySeriesKey = (group: string, config, data) => {
82
82
  }
83
83
 
84
84
  // Helper to calculate outliers based on IQR
85
- export const calculateOutliers = (values: number[], firstQuartile: number, thirdQuartile: number) => {
85
+ const calculateOutliers = (values: number[], firstQuartile: number, thirdQuartile: number) => {
86
86
  const iqr = thirdQuartile - firstQuartile
87
87
  const lowerBound = firstQuartile - 1.5 * iqr
88
88
  const upperBound = thirdQuartile + 1.5 * iqr
@@ -90,7 +90,7 @@ export const calculateOutliers = (values: number[], firstQuartile: number, third
90
90
  }
91
91
 
92
92
  // Helper to calculate non-outliers based on IQR
93
- export const calculateNonOutliers = (values: number[], firstQuartile: number, thirdQuartile: number): number[] => {
93
+ const calculateNonOutliers = (values: number[], firstQuartile: number, thirdQuartile: number): number[] => {
94
94
  const iqr = thirdQuartile - firstQuartile
95
95
  const lowerBound = firstQuartile - 1.5 * iqr
96
96
  const upperBound = thirdQuartile + 1.5 * iqr
@@ -6,7 +6,7 @@ import ConfigContext from '../../ConfigContext'
6
6
  import { Text } from '@visx/text'
7
7
  import { APP_FONT_SIZE } from '@cdc/core/helpers/constants'
8
8
  import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
9
- export interface BrushChartProps {
9
+ interface BrushChartProps {
10
10
  xMax: number
11
11
  yMax: number
12
12
  brushPosition: { start: { x: number }; end: { x: number } }