@cdc/chart 4.25.8 → 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 (145) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/dist/{cdcchart-1a1724a1.es.js → cdcchart-dgT_1dIT.es.js} +136 -151
  3. package/dist/cdcchart.js +44236 -40355
  4. package/examples/feature/__data__/planet-example-data.json +0 -30
  5. package/examples/feature/boxplot/valid-boxplot.csv +38 -17
  6. package/examples/grouped-bar-test.json +400 -0
  7. package/examples/private/DEV-11825.json +573 -0
  8. package/examples/private/d.json +382 -0
  9. package/examples/private/example-2.json +49784 -0
  10. package/examples/private/f2.json +1 -0
  11. package/examples/private/f4.json +1577 -0
  12. package/examples/private/forecast.json +1180 -0
  13. package/examples/private/lollipop.json +468 -0
  14. package/examples/private/na.json +913 -0
  15. package/examples/private/new.json +48756 -0
  16. package/examples/private/pie-chart-legend.json +904 -0
  17. package/examples/private/test-data.csv +28 -0
  18. package/examples/suppressed_tooltip.json +480 -0
  19. package/index.html +2 -133
  20. package/package.json +25 -7
  21. package/src/CdcChart.tsx +9 -13
  22. package/src/CdcChartComponent.tsx +403 -92
  23. package/src/_stories/Chart.Anchors.stories.tsx +2 -2
  24. package/src/_stories/Chart.BoxPlot.stories.tsx +1 -1
  25. package/src/_stories/Chart.CI.stories.tsx +1 -1
  26. package/src/_stories/Chart.Combo.stories.tsx +18 -0
  27. package/src/_stories/Chart.CustomColors.stories.tsx +1 -1
  28. package/src/_stories/Chart.DynamicSeries.stories.tsx +2 -2
  29. package/src/_stories/Chart.Filters.stories.tsx +2 -2
  30. package/src/_stories/Chart.Forecast.stories.tsx +36 -0
  31. package/src/_stories/Chart.HTMLInDataTable.stories.tsx +520 -0
  32. package/src/_stories/Chart.Legend.Gradient.stories.tsx +2 -2
  33. package/src/_stories/Chart.Patterns.stories.tsx +20 -0
  34. package/src/_stories/Chart.PreserveDecimals.stories.tsx +220 -0
  35. package/src/_stories/Chart.ScatterPlot.stories.tsx +1 -1
  36. package/src/_stories/Chart.SmallMultiples.stories.tsx +47 -0
  37. package/src/_stories/Chart.stories.tsx +8 -5
  38. package/src/_stories/Chart.tooltip.stories.tsx +1 -1
  39. package/src/_stories/ChartAnnotation.stories.tsx +7 -4
  40. package/src/_stories/ChartAxisLabels.stories.tsx +2 -2
  41. package/src/_stories/ChartAxisTitles.stories.tsx +2 -2
  42. package/src/_stories/ChartBar.Editor.stories.tsx +3580 -0
  43. package/src/_stories/ChartEditor.Editor.stories.tsx +658 -0
  44. package/src/_stories/ChartEditor.stories.tsx +59 -60
  45. package/src/_stories/ChartLine.Suppression.stories.tsx +1 -1
  46. package/src/_stories/ChartLine.Symbols.stories.tsx +1 -1
  47. package/src/_stories/ChartPrefixSuffix.stories.tsx +2 -2
  48. package/src/_stories/_mock/combo.json +451 -0
  49. package/src/_stories/_mock/editor-test-configs.json +376 -0
  50. package/src/_stories/_mock/editor-test-datasets.json +477 -0
  51. package/src/_stories/_mock/editor-tests/bar-chart-editor-test.json +255 -0
  52. package/src/_stories/_mock/editor-tests/bar-chart-general-test.json +267 -0
  53. package/src/_stories/_mock/editor-tests/bar-chart-test.json +237 -0
  54. package/src/_stories/_mock/forecast_combo_with_gaps.json +913 -0
  55. package/src/_stories/_mock/pie_config.json +257 -62
  56. package/src/_stories/_mock/small_multiples/small_multiples_bars.json +1944 -0
  57. package/src/_stories/_mock/small_multiples/small_multiples_big_data_bars.json +1114 -0
  58. package/src/_stories/_mock/small_multiples/small_multiples_lines.json +2646 -0
  59. package/src/_stories/_mock/small_multiples/small_multiples_lines_colors.json +1305 -0
  60. package/src/_stories/_mock/small_multiples/small_multiples_stacked_bars.json +1936 -0
  61. package/src/_stories/_mock/stacked-pattern-test.json +520 -0
  62. package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -0
  63. package/src/components/Annotations/components/AnnotationDropdown.tsx +1 -1
  64. package/src/components/Annotations/components/findNearestDatum.ts +6 -41
  65. package/src/components/AreaChart/components/AreaChart.Stacked.jsx +10 -6
  66. package/src/components/AreaChart/index.tsx +1 -2
  67. package/src/components/BarChart/components/BarChart.Horizontal.tsx +161 -22
  68. package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +138 -5
  69. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +215 -73
  70. package/src/components/BarChart/components/BarChart.Vertical.tsx +155 -22
  71. package/src/components/BarChart/helpers/index.ts +43 -4
  72. package/src/components/BarChart/helpers/lollipopColors.ts +27 -0
  73. package/src/components/BarChart/helpers/useBarChart.ts +25 -3
  74. package/src/components/BoxPlot/BoxPlot.Vertical.tsx +2 -1
  75. package/src/components/BoxPlot/helpers/index.ts +3 -3
  76. package/src/components/Brush/BrushChart.tsx +1 -1
  77. package/src/components/DeviationBar.jsx +9 -6
  78. package/src/components/EditorPanel/EditorPanel.tsx +563 -229
  79. package/src/components/EditorPanel/EditorPanelContext.ts +3 -0
  80. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +96 -111
  81. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +19 -1
  82. package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +461 -0
  83. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +80 -67
  84. package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +422 -0
  85. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +188 -139
  86. package/src/components/EditorPanel/components/Panels/index.tsx +5 -1
  87. package/src/components/EditorPanel/components/Panels/panelVisual.styles.css +0 -8
  88. package/src/components/EditorPanel/editor-panel.scss +0 -20
  89. package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +49 -48
  90. package/src/components/EditorPanel/useEditorPermissions.ts +7 -15
  91. package/src/components/Forecasting/Forecasting.tsx +175 -27
  92. package/src/components/ForestPlot/ForestPlot.tsx +11 -7
  93. package/src/components/ForestPlot/ForestPlotProps.ts +1 -1
  94. package/src/components/Legend/Legend.Component.tsx +114 -14
  95. package/src/components/Legend/helpers/createFormatLabels.tsx +230 -171
  96. package/src/components/Legend/helpers/getLegendClasses.ts +0 -1
  97. package/src/components/LegendWrapper.tsx +1 -1
  98. package/src/components/LineChart/LineChartProps.ts +0 -3
  99. package/src/components/LineChart/components/LineChart.Circle.tsx +2 -2
  100. package/src/components/LineChart/helpers.ts +1 -1
  101. package/src/components/LineChart/index.tsx +38 -15
  102. package/src/components/LinearChart.tsx +96 -84
  103. package/src/components/PairedBarChart.jsx +6 -4
  104. package/src/components/PieChart/PieChart.tsx +170 -54
  105. package/src/components/Regions/components/Regions.tsx +3 -24
  106. package/src/components/Sankey/components/Sankey.tsx +7 -1
  107. package/src/components/Sankey/types/index.ts +1 -1
  108. package/src/components/ScatterPlot/ScatterPlot.jsx +32 -4
  109. package/src/components/SmallMultiples/SmallMultipleTile.tsx +198 -0
  110. package/src/components/SmallMultiples/SmallMultiples.css +32 -0
  111. package/src/components/SmallMultiples/SmallMultiples.tsx +271 -0
  112. package/src/components/SmallMultiples/index.ts +2 -0
  113. package/src/data/initial-state.js +327 -293
  114. package/src/helpers/buildForecastPaletteMappings.ts +112 -0
  115. package/src/helpers/buildForecastPaletteOptions.ts +71 -0
  116. package/src/helpers/getColorScale.ts +82 -8
  117. package/src/{hooks/useMinMax.ts → helpers/getMinMax.ts} +14 -7
  118. package/src/helpers/getNewRuntime.ts +1 -1
  119. package/src/helpers/getTransformedData.ts +1 -1
  120. package/src/helpers/getYAxisAutoPadding.ts +53 -0
  121. package/src/helpers/smallMultiplesHelpers.ts +529 -0
  122. package/src/hooks/useChartHoverAnalytics.tsx +44 -0
  123. package/src/hooks/useProgrammaticTooltip.ts +96 -0
  124. package/src/hooks/useReduceData.ts +105 -70
  125. package/src/hooks/useScales.ts +88 -34
  126. package/src/hooks/useSmallMultipleSynchronization.ts +59 -0
  127. package/src/hooks/useTooltip.tsx +116 -29
  128. package/src/index.jsx +0 -2
  129. package/src/scss/main.scss +13 -80
  130. package/src/store/chart.actions.ts +2 -0
  131. package/src/store/chart.reducer.ts +5 -1
  132. package/src/test/CdcChart.test.jsx +8 -3
  133. package/src/types/ChartConfig.ts +53 -11
  134. package/src/types/ChartContext.ts +4 -0
  135. package/vite.config.js +1 -1
  136. package/vitest.config.ts +16 -0
  137. package/src/_stories/_mock/pie_data.json +0 -218
  138. package/src/components/AreaChart/components/AreaChart.jsx +0 -109
  139. package/src/coreStyles_chart.scss +0 -3
  140. package/src/helpers/configHelpers.ts +0 -28
  141. package/src/helpers/generateColorsArray.ts +0 -8
  142. package/src/helpers/sort.ts +0 -7
  143. package/src/hooks/useActiveElement.js +0 -19
  144. package/src/hooks/useChartClasses.js +0 -41
  145. package/src/hooks/useColorPalette.js +0 -76
@@ -1,10 +1,11 @@
1
- import React, { forwardRef, useContext, useEffect, useMemo, useRef, useState } from 'react'
1
+ import React, { forwardRef, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
2
2
 
3
3
  // Libraries
4
4
  import { AxisLeft, AxisBottom, AxisRight, AxisTop } from '@visx/axis'
5
5
  import { Group } from '@visx/group'
6
6
  import { Line, Bar } from '@visx/shape'
7
7
  import { Tooltip as ReactTooltip } from 'react-tooltip'
8
+ import 'react-tooltip/dist/react-tooltip.css'
8
9
  import { Text } from '@visx/text'
9
10
  import { useTooltip, TooltipWithBounds } from '@visx/tooltip'
10
11
  import _ from 'lodash'
@@ -35,18 +36,21 @@ import { calcInitialHeight, handleAutoPaddingRight } from '../helpers/sizeHelper
35
36
  import { filterAndShiftLinearDateTicks } from '../helpers/filterAndShiftLinearDateTicks'
36
37
 
37
38
  // Hooks
38
- import useMinMax from '../hooks/useMinMax'
39
39
  import useReduceData from '../hooks/useReduceData'
40
40
  import useRightAxis from '../hooks/useRightAxis'
41
41
  import useScales, { getTickValues } from '../hooks/useScales'
42
+ import { useProgrammaticTooltip } from '../hooks/useProgrammaticTooltip'
43
+ import { useSmallMultipleSynchronization } from '../hooks/useSmallMultipleSynchronization'
42
44
 
43
45
  import getTopAxis from '../helpers/getTopAxis'
44
46
  import { useTooltip as useCoveTooltip } from '../hooks/useTooltip'
47
+ import { useChartHoverAnalytics } from '../hooks/useChartHoverAnalytics'
45
48
  import { useEditorPermissions } from './EditorPanel/useEditorPermissions'
46
49
  import Annotation from './Annotations'
47
50
  import { BlurStrokeText } from '@cdc/core/components/BlurStrokeText'
48
51
  import { countNumOfTicks } from '../helpers/countNumOfTicks'
49
52
  import HoverLine from './HoverLine/HoverLine'
53
+ import { SmallMultiples } from './SmallMultiples'
50
54
 
51
55
  type LinearChartProps = {
52
56
  parentWidth: number
@@ -84,20 +88,21 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
84
88
  config,
85
89
  convertLineToBarGraph,
86
90
  currentViewport,
91
+ vizViewport,
87
92
  dimensions,
88
93
  formatDate,
89
94
  formatNumber,
90
95
  handleChartAriaLabels,
91
96
  handleLineType,
92
97
  handleDragStateChange,
98
+ interactionLabel,
93
99
  isDraggingAnnotation,
94
100
  legendRef,
95
101
  parseDate,
96
102
  parentRef,
97
103
  tableData,
98
104
  transformedData: data,
99
- seriesHighlight,
100
-
105
+ seriesHighlight
101
106
  } = useContext(ConfigContext)
102
107
 
103
108
  // CONFIG
@@ -116,6 +121,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
116
121
  dataFormat,
117
122
  debugSvg
118
123
  } = config
124
+
119
125
  const { labelsAboveGridlines, hideAxis, inlineLabel } = config.yAxis
120
126
 
121
127
  // HOOKS % STATES
@@ -126,7 +132,6 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
126
132
  const [showHoverLine, setShowHoverLine] = useState(false)
127
133
  const [point, setPoint] = useState({ x: 0, y: 0 })
128
134
  const [suffixWidth, setSuffixWidth] = useState(0)
129
- const [yAxisAutoPadding, setYAxisAutoPadding] = useState(0)
130
135
 
131
136
  // REFS
132
137
  const axisBottomRef = useRef(null)
@@ -136,7 +141,6 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
136
141
  const triggerRef = useRef()
137
142
  const xAxisLabelRefs = useRef([])
138
143
  const xAxisTitleRef = useRef(null)
139
- const lastMaxValue = useRef(maxValue)
140
144
  const gridLineRefs = useRef([])
141
145
  const tooltipRef = useRef(null)
142
146
 
@@ -151,11 +155,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
151
155
  const isForestPlot = visualizationType === 'Forest Plot'
152
156
  const isDateTime = config.xAxis.type === 'date-time'
153
157
  const inlineLabelHasNoSpace = !inlineLabel?.includes(' ')
154
- const labelsOverflow = inlineLabel && !inlineLabelHasNoSpace
158
+ const needsYAxisAutoPadding = inlineLabel && !inlineLabelHasNoSpace
155
159
  const padding = orientation === 'horizontal' ? Number(config.xAxis.size) : Number(config.yAxis.size)
156
160
  const yLabelOffset = isNaN(parseInt(`${runtime.yAxis.labelOffset}`)) ? 0 : parseInt(`${runtime.yAxis.labelOffset}`)
157
- const tickLabelFontSize = isMobileFontViewport(currentViewport) ? TICK_LABEL_FONT_SIZE_SMALL : TICK_LABEL_FONT_SIZE
158
- const axisLabelFontSize = isMobileFontViewport(currentViewport) ? AXIS_LABEL_FONT_SIZE_SMALL : AXIS_LABEL_FONT_SIZE
161
+ const tickLabelFontSize = isMobileFontViewport(vizViewport) ? TICK_LABEL_FONT_SIZE_SMALL : TICK_LABEL_FONT_SIZE
162
+ const axisLabelFontSize = isMobileFontViewport(vizViewport) ? AXIS_LABEL_FONT_SIZE_SMALL : AXIS_LABEL_FONT_SIZE
159
163
  const GET_TEXT_WIDTH_FONT = `normal ${tickLabelFontSize}px Nunito, sans-serif`
160
164
 
161
165
  // zero if not forest plot
@@ -204,7 +208,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
204
208
  const xMax = width - runtime.yAxis.size - (visualizationType === 'Combo' ? config.yAxis.rightAxisSize : 0)
205
209
  const yMax = initialHeight + forestRowsHeight
206
210
 
207
- const isNoDataAvailable = config.filters && config.filters.values.length === 0 && data.length === 0
211
+ const isNoDataAvailable = config.filters?.length > 0 && data.length === 0
208
212
 
209
213
  const getXAxisData = d =>
210
214
  isDateScale(config.runtime.xAxis)
@@ -212,39 +216,37 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
212
216
  : d[config.runtime.originalXAxis.dataKey]
213
217
  const getYAxisData = (d, seriesKey) => d[seriesKey]
214
218
  const xAxisDataMapped = data.map(d => getXAxisData(d))
215
- const section = config.orientation === 'horizontal' || config.visualizationType === 'Forest Plot' ? 'yAxis' : 'xAxis'
216
- const properties = {
219
+ const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data })
220
+
221
+ const {
222
+ xScale,
223
+ yScale,
224
+ seriesScale,
225
+ g1xScale,
226
+ g2xScale,
227
+ xScaleNoPadding,
228
+ xScaleAnnotation,
229
+ min,
230
+ max,
231
+ leftMax,
232
+ rightMax
233
+ } = useScales({
217
234
  data,
218
235
  tableData,
219
- config: {
220
- ...config,
221
- yAxis: {
222
- ...config.yAxis,
223
- scalePadding: labelsOverflow ? yAxisAutoPadding : config.yAxis.scalePadding,
224
- enablePadding: labelsOverflow || config.yAxis.enablePadding
225
- }
226
- },
236
+ config,
227
237
  minValue,
228
238
  maxValue,
229
239
  isAllLine,
230
240
  existPositiveValue,
231
241
  xAxisDataMapped,
232
- xMax,
233
- yMax
234
- }
235
- const { min, max, leftMax, rightMax } = useMinMax(properties)
236
- const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data })
237
- const { xScale, yScale, seriesScale, g1xScale, g2xScale, xScaleNoPadding, xScaleAnnotation } = useScales({
238
- ...properties,
239
- min,
240
- max,
241
- leftMax,
242
- rightMax,
242
+ yMax,
243
243
  dimensions,
244
244
  xMax:
245
245
  parentWidth -
246
246
  Number(config.orientation === 'horizontal' ? config.xAxis.size : config.yAxis.size) -
247
- (hasRightAxis ? config.yAxis.rightAxisSize : 0)
247
+ (hasRightAxis ? config.yAxis.rightAxisSize : 0),
248
+ needsYAxisAutoPadding,
249
+ currentViewport
248
250
  })
249
251
 
250
252
  const [yTickCount, xTickCount] = ['yAxis', 'xAxis'].map(axis =>
@@ -263,13 +265,23 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
263
265
  handleTooltipClick,
264
266
  handleTooltipMouseOff,
265
267
  TooltipListItem,
268
+ getXValueFromCoordinate,
269
+ getCoordinateFromXValue,
266
270
  } = useCoveTooltip({
267
271
  xScale,
268
272
  yScale,
269
273
  seriesScale,
270
274
  showTooltip,
271
- hideTooltip
275
+ hideTooltip,
276
+ interactionLabel
277
+ })
278
+
279
+ // Analytics tracking for chart hover
280
+ const { handleChartMouseEnter, handleChartMouseLeave } = useChartHoverAnalytics({
281
+ config,
282
+ interactionLabel
272
283
  })
284
+
273
285
  // get the number of months between the first and last date
274
286
  const { dataKey } = runtime.xAxis
275
287
  const dateSpanMonths =
@@ -339,6 +351,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
339
351
  return manualStep
340
352
  }
341
353
 
354
+ const smallMultiplesSync = useSmallMultipleSynchronization(xMax, yMax, getXValueFromCoordinate)
355
+
342
356
  const onMouseMove = event => {
343
357
  const svgRect = event.currentTarget.getBoundingClientRect()
344
358
  const x = event.clientX - svgRect.left
@@ -348,8 +362,25 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
348
362
  x,
349
363
  y
350
364
  })
365
+
366
+ smallMultiplesSync.onMouseMove?.(event)
351
367
  }
352
368
 
369
+ const onMouseLeave = () => {
370
+ smallMultiplesSync.onMouseLeave?.()
371
+ }
372
+
373
+ // Use custom hook to provide programmatic tooltip control for small multiples
374
+ const internalSvgRef = useProgrammaticTooltip({
375
+ svgRef,
376
+ getCoordinateFromXValue,
377
+ config,
378
+ setPoint,
379
+ setShowHoverLine,
380
+ handleTooltipMouseOver,
381
+ hideTooltip
382
+ })
383
+
353
384
  // EFFECTS
354
385
  // Adjust padding on the right side of the chart to accommodate for overflow
355
386
  useEffect(() => {
@@ -438,7 +469,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
438
469
  if (!topLabelOnGridlineHeight) return
439
470
 
440
471
  // Adjust the viewBox for the svg
441
- const svg = svgRef.current
472
+ const svg = internalSvgRef.current
442
473
  if (!svg) return
443
474
  const parentWidthFromRef = parentRef.current.getBoundingClientRect().width
444
475
  svg.setAttribute('viewBox', `0 ${-topLabelOnGridlineHeight} ${parentWidthFromRef} ${newHeight}`)
@@ -458,45 +489,6 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
458
489
  initialHeight
459
490
  ])
460
491
 
461
- useEffect(() => {
462
- if (lastMaxValue.current === maxValue) return
463
- lastMaxValue.current = maxValue
464
-
465
- if (!yAxisAutoPadding) return
466
- setYAxisAutoPadding(0)
467
- }, [maxValue])
468
-
469
- useEffect(() => {
470
- if (!yScale?.ticks) return
471
- const ticks = yScale.ticks(handleNumTicks)
472
- if (orientation === 'horizontal' || !labelsOverflow || config.yAxis?.max || ticks.length === 0) {
473
- setYAxisAutoPadding(0)
474
- return
475
- }
476
-
477
- // minimum percentage of the max value that the distance should be from the top grid line
478
- const MINIMUM_DISTANCE_PERCENTAGE = 0.025
479
-
480
- const topGridLine = Math.max(...ticks)
481
- const needsPaddingThreshold = topGridLine - maxValue * MINIMUM_DISTANCE_PERCENTAGE
482
- const maxValueIsGreaterThanThreshold = maxValue > needsPaddingThreshold
483
-
484
- if (!maxValueIsGreaterThanThreshold) return
485
-
486
- const tickGap = ticks.length === 1 ? ticks[0] : ticks[1] - ticks[0]
487
- const nextTick = Math.max(...yScale.ticks(handleNumTicks)) + tickGap
488
- const divideBy = minValue < 0 ? maxValue / 2 : maxValue
489
- const calculatedPadding = (nextTick - maxValue) / divideBy
490
-
491
- // if auto padding is too close to next tick, add one more ticks worth of padding
492
- const newPadding =
493
- calculatedPadding > MINIMUM_DISTANCE_PERCENTAGE ? calculatedPadding : calculatedPadding + tickGap / divideBy
494
-
495
- /* sometimes even though the padding is getting to the next tick exactly,
496
- d3 still doesn't show the tick. we add 0.1 to ensure to tip it over the edge */
497
- setYAxisAutoPadding(newPadding * 100 + 0.1)
498
- }, [maxValue, labelsOverflow, yScale, handleNumTicks])
499
-
500
492
  useEffect(() => {
501
493
  if (!tooltipOpen) return
502
494
  if (!tooltipRef.current) return
@@ -514,6 +506,19 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
514
506
  tooltipRef.current.node.style.maxWidth = `${maxWidth}px`
515
507
  }, [tooltipOpen, tooltipData])
516
508
 
509
+ // Check if small multiples are enabled - if so, render SmallMultiples instead
510
+ if (config.smallMultiples?.mode) {
511
+ return (
512
+ <SmallMultiples
513
+ config={config}
514
+ data={data}
515
+ svgRef={svgRef}
516
+ parentWidth={parentWidth}
517
+ parentHeight={parentHeight}
518
+ />
519
+ )
520
+ }
521
+
517
522
  // Render Functions
518
523
  const generatePairedBarAxis = () => {
519
524
  const axisMaxHeight = bottomLabelStart + BOTTOM_LABEL_PADDING
@@ -648,7 +653,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
648
653
  verticalAnchor='start'
649
654
  fontSize={axisLabelFontSize}
650
655
  >
651
- {runtime.xAxis.label}
656
+ {!config.hideXAxisLabel ? runtime.xAxis.label : null}
652
657
  </Text>
653
658
  </Group>
654
659
  </>
@@ -668,7 +673,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
668
673
  className='tooltip-boundary'
669
674
  >
670
675
  <svg
671
- ref={svgRef}
676
+ ref={internalSvgRef}
672
677
  onMouseMove={onMouseMove}
673
678
  width={parentWidth + config.yAxis.rightAxisSize}
674
679
  height={isNoDataAvailable ? 1 : parentHeight}
@@ -678,8 +683,15 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
678
683
  role='img'
679
684
  aria-label={handleChartAriaLabels(config)}
680
685
  style={{ overflow: 'visible' }}
681
- onMouseLeave={() => setShowHoverLine(false)}
682
- onMouseEnter={() => setShowHoverLine(true)}
686
+ onMouseLeave={() => {
687
+ setShowHoverLine(false)
688
+ handleChartMouseLeave()
689
+ onMouseLeave()
690
+ }}
691
+ onMouseEnter={() => {
692
+ setShowHoverLine(true)
693
+ handleChartMouseEnter()
694
+ }}
683
695
  >
684
696
  {!isDraggingAnnotation && <Bar width={parentWidth} height={initialHeight} fill={'transparent'}></Bar>}{' '}
685
697
  {/* GRID LINES */}
@@ -693,7 +705,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
693
705
  {props => {
694
706
  const axisCenter =
695
707
  config.orientation === 'horizontal'
696
- ? (props.axisToPoint.y - props.axisFromPoint.y) / 2
708
+ ? Math.abs(props.axisToPoint.y - props.axisFromPoint.y) / 2
697
709
  : (props.axisFromPoint.y - props.axisToPoint.y) / 2
698
710
  return (
699
711
  <Group className='left-axis'>
@@ -727,7 +739,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
727
739
  fill={config.yAxis.labelColor}
728
740
  fontSize={axisLabelFontSize}
729
741
  >
730
- {props.label}
742
+ {!config.hideYAxisLabel ? props.label : null}
731
743
  </Text>
732
744
  </Group>
733
745
  )
@@ -1027,7 +1039,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
1027
1039
  {props => {
1028
1040
  const axisCenter =
1029
1041
  config.orientation === 'horizontal'
1030
- ? (props.axisToPoint.y - props.axisFromPoint.y) / 2
1042
+ ? Math.abs(props.axisToPoint.y - props.axisFromPoint.y) / 2
1031
1043
  : (props.axisFromPoint.y - props.axisToPoint.y) / 2
1032
1044
  const horizontalTickOffset =
1033
1045
  yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
@@ -1289,7 +1301,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
1289
1301
  fill={config.yAxis.labelColor}
1290
1302
  fontSize={axisLabelFontSize}
1291
1303
  >
1292
- {props.label}
1304
+ {!config.hideYAxisLabel ? props.label : null}
1293
1305
  </Text>
1294
1306
  </Group>
1295
1307
  )
@@ -1403,7 +1415,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
1403
1415
  : yMax
1404
1416
  }
1405
1417
  left={config.visualizationType !== 'Forest Plot' ? Number(runtime.yAxis.size) : 0}
1406
- label={config[section].label}
1418
+ label={runtime.xAxis.label}
1407
1419
  tickFormat={handleBottomTickFormatting}
1408
1420
  scale={xScale}
1409
1421
  stroke='#333'
@@ -1537,7 +1549,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
1537
1549
  verticalAnchor={tickRotation < -50 ? 'middle' : 'start'}
1538
1550
  textAnchor={tickRotation ? 'end' : 'middle'}
1539
1551
  width={
1540
- areTicksTouching && !config.isResponsiveTicks && !Number(config[section].tickRotation)
1552
+ areTicksTouching && !config.isResponsiveTicks && !Number(config.xAxis.tickRotation)
1541
1553
  ? limitedWidth
1542
1554
  : undefined
1543
1555
  }
@@ -1562,7 +1574,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
1562
1574
  fill={config.xAxis.labelColor}
1563
1575
  fontSize={axisLabelFontSize}
1564
1576
  >
1565
- {props.label}
1577
+ {!config.hideXAxisLabel ? props.label : null}
1566
1578
  </Text>
1567
1579
  </Group>
1568
1580
  )
@@ -113,7 +113,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
113
113
  const textFits = textWidth < barWidth - 5 // minus padding dx(5)
114
114
 
115
115
  return (
116
- <>
116
+ <React.Fragment key={`fragment-group1-${groupOne.dataKey}-${index}`}>
117
117
  <Group key={`group-${groupOne.dataKey}-${d[config.xAxis.dataKey]}`} className='horizontal'>
118
118
  <Bar
119
119
  id={`bar-${groupOne.dataKey}-${d[config.dataDescription?.xKey]}`}
@@ -124,6 +124,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
124
124
  width={xScale(d[config.series[0].dataKey])}
125
125
  height={barHeight}
126
126
  fill={groupOne.color}
127
+ onMouseEnter={() => {}}
127
128
  data-tooltip-html={dataTipOne(d)}
128
129
  data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
129
130
  stroke='#333'
@@ -145,7 +146,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
145
146
  </Text>
146
147
  )}
147
148
  </Group>
148
- </>
149
+ </React.Fragment>
149
150
  )
150
151
  })}
151
152
  {data
@@ -171,7 +172,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
171
172
  const isTextFits = textWidth < barWidth - 5 // minus padding dx(5)
172
173
 
173
174
  return (
174
- <>
175
+ <React.Fragment key={`fragment-group2-${groupTwo.dataKey}-${index}`}>
175
176
  <style>
176
177
  {`
177
178
  .bar-${groupTwo.dataKey}-${d[config.xAxis.dataKey]} {
@@ -189,6 +190,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
189
190
  width={xScale(d[config.series[1].dataKey])}
190
191
  height={barHeight}
191
192
  fill={groupTwo.color}
193
+ onMouseEnter={() => {}}
192
194
  data-tooltip-html={dataTipTwo(d)}
193
195
  data-tooltip-id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}`}
194
196
  strokeWidth={borderWidth}
@@ -210,7 +212,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
210
212
  </Text>
211
213
  )}
212
214
  </Group>
213
- </>
215
+ </React.Fragment>
214
216
  )
215
217
  })}
216
218
  </Group>