@cdc/chart 4.24.10 → 4.24.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 (53) hide show
  1. package/dist/cdcchart.js +34618 -33995
  2. package/examples/feature/boxplot/boxplot-data.json +88 -22
  3. package/examples/feature/boxplot/boxplot.json +540 -16
  4. package/examples/feature/boxplot/testing.csv +7 -7
  5. package/examples/feature/sankey/sankey-example-data.json +0 -1
  6. package/examples/private/test.json +20092 -0
  7. package/index.html +3 -3
  8. package/package.json +2 -2
  9. package/src/CdcChart.tsx +86 -86
  10. package/src/_stories/Chart.CustomColors.stories.tsx +19 -0
  11. package/src/_stories/Chart.DynamicSeries.stories.tsx +27 -0
  12. package/src/_stories/Chart.Legend.Gradient.stories.tsx +42 -1
  13. package/src/_stories/Chart.stories.tsx +7 -8
  14. package/src/_stories/ChartEditor.stories.tsx +27 -0
  15. package/src/_stories/ChartLine.Suppression.stories.tsx +25 -0
  16. package/src/_stories/ChartPrefixSuffix.stories.tsx +8 -0
  17. package/src/_stories/_mock/boxplot_multiseries.json +647 -0
  18. package/src/_stories/_mock/dynamic_series_bar_config.json +723 -0
  19. package/src/_stories/_mock/dynamic_series_config.json +979 -0
  20. package/{examples/feature/scatterplot/scatterplot.json → src/_stories/_mock/scatterplot_mock.json} +62 -92
  21. package/src/_stories/_mock/suppression_mock.json +1549 -0
  22. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +43 -9
  23. package/src/components/BarChart/components/BarChart.Vertical.tsx +60 -42
  24. package/src/components/BarChart/helpers/index.ts +1 -2
  25. package/src/components/BoxPlot/BoxPlot.tsx +189 -0
  26. package/src/components/EditorPanel/EditorPanel.tsx +64 -62
  27. package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +3 -3
  28. package/src/components/EditorPanel/components/Panels/Panel.BoxPlot.tsx +51 -6
  29. package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +40 -9
  30. package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +3 -3
  31. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +121 -56
  32. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +1 -2
  33. package/src/components/EditorPanel/useEditorPermissions.ts +15 -1
  34. package/src/components/Legend/Legend.Component.tsx +9 -10
  35. package/src/components/Legend/Legend.tsx +16 -16
  36. package/src/components/LineChart/helpers.ts +48 -43
  37. package/src/components/LineChart/index.tsx +88 -82
  38. package/src/components/LinearChart.tsx +17 -10
  39. package/src/components/Sankey/index.tsx +50 -32
  40. package/src/components/Sankey/sankey.scss +6 -5
  41. package/src/components/Sankey/useSankeyAlert.tsx +60 -0
  42. package/src/components/ScatterPlot/ScatterPlot.jsx +20 -4
  43. package/src/data/initial-state.js +3 -9
  44. package/src/hooks/useLegendClasses.ts +10 -23
  45. package/src/hooks/useMinMax.ts +27 -13
  46. package/src/hooks/useReduceData.ts +43 -10
  47. package/src/hooks/useScales.ts +56 -35
  48. package/src/hooks/useTooltip.tsx +54 -49
  49. package/src/scss/main.scss +0 -18
  50. package/src/types/ChartConfig.ts +6 -19
  51. package/src/types/ChartContext.ts +4 -1
  52. package/src/types/ForestPlot.ts +8 -0
  53. package/src/components/BoxPlot/BoxPlot.jsx +0 -111
@@ -13,32 +13,62 @@ import createBarElement from '@cdc/core/components/createBarElement'
13
13
  const BarChartStackedVertical = () => {
14
14
  const [barWidth, setBarWidth] = useState(0)
15
15
  const { xScale, yScale, seriesScale, xMax, yMax } = useContext(BarChartContext)
16
- const { transformedData, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter } = useContext(ConfigContext)
17
- const { isHorizontal, barBorderWidth, applyRadius, hoveredBar, getAdditionalColumn, onMouseLeaveBar, onMouseOverBar, barStackedSeriesKeys } = useBarChart()
16
+ const { transformedData, colorScale, seriesHighlight, config, formatNumber, formatDate, parseDate, setSharedFilter } =
17
+ useContext(ConfigContext)
18
+ const {
19
+ isHorizontal,
20
+ barBorderWidth,
21
+ applyRadius,
22
+ hoveredBar,
23
+ getAdditionalColumn,
24
+ onMouseLeaveBar,
25
+ onMouseOverBar,
26
+ barStackedSeriesKeys
27
+ } = useBarChart()
18
28
  const { orientation } = config
19
29
 
20
30
  const data = config.brush?.active && config.brush.data?.length ? config.brush.data : transformedData
21
31
  const isDateAxisType = config.runtime.xAxis.type === 'date-time' || config.runtime.xAxis.type === 'date'
32
+ const isDateTimeScaleAxisType = config.runtime.xAxis.type === 'date-time'
22
33
 
23
34
  return (
24
35
  config.visualizationSubType === 'stacked' &&
25
36
  !isHorizontal && (
26
37
  <>
27
- <BarStack data={data} keys={barStackedSeriesKeys} x={d => d[config.runtime.xAxis.dataKey]} xScale={xScale} yScale={yScale} color={colorScale}>
38
+ <BarStack
39
+ data={data}
40
+ keys={barStackedSeriesKeys}
41
+ x={d => d[config.runtime.xAxis.dataKey]}
42
+ xScale={xScale}
43
+ yScale={yScale}
44
+ color={colorScale}
45
+ >
28
46
  {barStacks =>
29
47
  barStacks.reverse().map(barStack =>
30
48
  barStack.bars.map(bar => {
31
- let transparentBar = config.legend.behavior === 'highlight' && seriesHighlight.length > 0 && seriesHighlight.indexOf(bar.key) === -1
32
- let displayBar = config.legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(bar.key) !== -1
33
- let barThickness = isDateAxisType ? seriesScale.range()[1] - seriesScale.range()[0] : xMax / barStack.bars.length
49
+ let transparentBar =
50
+ config.legend.behavior === 'highlight' &&
51
+ seriesHighlight.length > 0 &&
52
+ seriesHighlight.indexOf(bar.key) === -1
53
+ let displayBar =
54
+ config.legend.behavior === 'highlight' ||
55
+ seriesHighlight.length === 0 ||
56
+ seriesHighlight.indexOf(bar.key) !== -1
57
+ let barThickness = isDateAxisType
58
+ ? seriesScale.range()[1] - seriesScale.range()[0]
59
+ : xMax / barStack.bars.length
34
60
  if (config.runtime.xAxis.type !== 'date') barThickness = config.barThickness * barThickness
35
61
  // tooltips
36
62
  const rawXValue = bar.bar.data[config.runtime.xAxis.dataKey]
37
63
  const xAxisValue = isDateAxisType ? formatDate(parseDate(rawXValue)) : rawXValue
38
64
  const yAxisValue = formatNumber(bar.bar ? bar.bar.data[bar.key] : 0, 'left')
39
65
  if (!yAxisValue) return
40
- const barX = xScale(isDateAxisType ? parseDate(rawXValue) : rawXValue) - (isDateAxisType ? barThickness / 2 : 0)
41
- const xAxisTooltip = config.runtime.xAxis.label ? `${config.runtime.xAxis.label}: ${xAxisValue}` : xAxisValue
66
+ const barX =
67
+ xScale(isDateAxisType ? parseDate(rawXValue) : rawXValue) -
68
+ (isDateTimeScaleAxisType ? barThickness / 2 : 0)
69
+ const xAxisTooltip = config.runtime.xAxis.label
70
+ ? `${config.runtime.xAxis.label}: ${xAxisValue}`
71
+ : xAxisValue
42
72
  const additionalColTooltip = getAdditionalColumn(hoveredBar)
43
73
  const tooltipBody = `${config.runtime.seriesLabels[bar.key]}: ${yAxisValue}`
44
74
  const tooltip = `<ul>
@@ -51,7 +81,11 @@ const BarChartStackedVertical = () => {
51
81
 
52
82
  return (
53
83
  <Group key={`${barStack.index}--${bar.index}--${orientation}`}>
54
- <Group key={`bar-stack-${barStack.index}-${bar.index}`} id={`barStack${barStack.index}-${bar.index}`} className='stack vertical'>
84
+ <Group
85
+ key={`bar-stack-${barStack.index}-${bar.index}`}
86
+ id={`barStack${barStack.index}-${bar.index}`}
87
+ className='stack vertical'
88
+ >
55
89
  {createBarElement({
56
90
  config: config,
57
91
  seriesHighlight,
@@ -15,11 +15,13 @@ import { BarGroup } from '@visx/shape'
15
15
  import Regions from '../../Regions'
16
16
  // CDC core components and helpers
17
17
  import { isDateScale } from '@cdc/core/helpers/cove/date'
18
+ import isNumber from '@cdc/core/helpers/isNumber'
18
19
  import createBarElement from '@cdc/core/components/createBarElement'
19
20
  // Third party libraries
20
21
  import chroma from 'chroma-js'
21
22
  // Types
22
23
  import { type ChartContext } from '../../../types/ChartContext'
24
+ import _, { has } from 'lodash'
23
25
 
24
26
  export const BarChartVertical = () => {
25
27
  const { xScale, yScale, xMax, yMax, seriesScale } = useContext<BarChartContextValues>(BarChartContext)
@@ -42,7 +44,7 @@ export const BarChartVertical = () => {
42
44
  } = useBarChart()
43
45
 
44
46
  // prettier-ignore
45
- const { colorScale, config, dashboardConfig, tableData, formatDate, formatNumber, getXAxisData, getYAxisData, isNumber, parseDate, seriesHighlight, setSharedFilter, transformedData, brushConfig } = useContext<ChartContext>(ConfigContext)
47
+ const { colorScale, config, dashboardConfig, tableData, formatDate, formatNumber, getXAxisData, getYAxisData, parseDate, seriesHighlight, setSharedFilter, transformedData, brushConfig } = useContext<ChartContext>(ConfigContext)
46
48
  const { HighLightedBarUtils } = useHighlightedBars(config)
47
49
  let data = transformedData
48
50
  // check if user add suppression
@@ -56,6 +58,34 @@ export const BarChartVertical = () => {
56
58
  data = brushConfig.data
57
59
  }
58
60
 
61
+ const hasConfidenceInterval = Object.keys(config.confidenceKeys).length > 0
62
+
63
+ const getData = () => {
64
+ const dynamicSeries = config.series.find(s => s.dynamicCategory)
65
+ if (!dynamicSeries) return data
66
+ const { dynamicCategory, dataKey } = dynamicSeries
67
+ const xAxisKey = config.runtime.originalXAxis.dataKey
68
+ const xAxisGroupDataLookup = _.groupBy(data, xAxisKey)
69
+ return Object.values(xAxisGroupDataLookup).map(group => {
70
+ return group.reduce((acc, datum) => {
71
+ const dataValue = datum[dataKey]
72
+ const dataCategory = datum[dynamicCategory]
73
+ if (hasConfidenceInterval) {
74
+ const { lower, upper } = config.confidenceKeys
75
+ if (!acc.CI) acc.CI = {}
76
+ const lowerValue = datum[lower]
77
+ const upperValue = datum[upper]
78
+ acc.CI[dataCategory] = { lower: lowerValue, upper: upperValue }
79
+ }
80
+ acc[dataCategory] = dataValue
81
+ acc[xAxisKey] = datum[xAxisKey]
82
+ acc.dynamicData = true
83
+ return acc
84
+ }, {})
85
+ })
86
+ }
87
+
88
+ const _data = getData()
59
89
  return (
60
90
  config.visualizationSubType !== 'stacked' &&
61
91
  (config.visualizationType === 'Bar' ||
@@ -64,7 +94,7 @@ export const BarChartVertical = () => {
64
94
  config.orientation === 'vertical' && (
65
95
  <Group>
66
96
  <BarGroup
67
- data={data}
97
+ data={_data}
68
98
  keys={config.runtime.barSeriesKeys || config.runtime.seriesKeys}
69
99
  height={yMax}
70
100
  x0={d => {
@@ -87,6 +117,8 @@ export const BarChartVertical = () => {
87
117
  left={barGroup.x0}
88
118
  >
89
119
  {barGroup.bars.map((bar, index) => {
120
+ const datum = _data[barGroup.index]
121
+ const dataValue = datum[config.runtime.originalXAxis.dataKey]
90
122
  const scaleVal = config.yAxis.type === 'logarithmic' ? 0.1 : 0
91
123
  let highlightedBarValues = config.highlightedBarValues
92
124
  .map(item => item.value)
@@ -116,17 +148,12 @@ export const BarChartVertical = () => {
116
148
  setTotalBarsInGroup(barGroup.bars.length)
117
149
  const yAxisValue = formatNumber(/[a-zA-Z]/.test(String(bar.value)) ? '' : bar.value, 'left')
118
150
  const xAxisValue =
119
- config.runtime[section].type === 'date'
120
- ? formatDate(parseDate(data[barGroup.index][config.runtime.originalXAxis.dataKey]))
121
- : data[barGroup.index][config.runtime.originalXAxis.dataKey]
151
+ config.runtime[section].type === 'date' ? formatDate(parseDate(dataValue)) : dataValue
122
152
 
123
153
  // create new Index for bars with negative values
124
154
  const newIndex = bar.value < 0 ? -1 : index
125
155
  // tooltips
126
- const additionalColTooltip = getAdditionalColumn(
127
- bar.key,
128
- data[barGroup.index][config.runtime.originalXAxis.dataKey]
129
- )
156
+ const additionalColTooltip = getAdditionalColumn(bar.key, dataValue)
130
157
  let xAxisTooltip = config.runtime.xAxis.label
131
158
  ? `${config.runtime.xAxis.label}: ${xAxisValue}`
132
159
  : xAxisValue
@@ -141,10 +168,6 @@ export const BarChartVertical = () => {
141
168
  // configure colors
142
169
  let labelColor = '#000000'
143
170
  labelColor = HighLightedBarUtils.checkFontColor(yAxisValue, highlightedBarValues, labelColor) // Set if background is transparent'
144
- let barColor =
145
- config.runtime.seriesLabels && config.runtime.seriesLabels[bar.key]
146
- ? colorScale(config.runtime.seriesLabels[bar.key])
147
- : colorScale(bar.key)
148
171
  const isRegularLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'regular'
149
172
  const isTwoToneLollipopColor = config.isLollipopChart && config.lollipopColorStyle === 'two-tone'
150
173
  const isHighlightedBar = highlightedBarValues?.includes(xAxisValue)
@@ -167,10 +190,8 @@ export const BarChartVertical = () => {
167
190
  bar,
168
191
  defaultBarHeight,
169
192
  config,
170
- isNumber,
171
193
  barWidth,
172
- isVertical: true,
173
- yAxisValue
194
+ isVertical: true
174
195
  })
175
196
 
176
197
  const absentDataLabel = getAbsentDataLabel(yAxisValue)
@@ -225,6 +246,16 @@ export const BarChartVertical = () => {
225
246
  return _barColor
226
247
  }
227
248
 
249
+ // Confidence Interval Variables
250
+ const tickWidth = 5
251
+ const xPos = barX + (config.xAxis.type !== 'date-time' ? barWidth / 2 : 0)
252
+ const [upperPos, lowerPos] = ['upper', 'lower'].map(position => {
253
+ if (!hasConfidenceInterval) return
254
+ const d = datum.dynamicData ? datum.CI[bar.key][position] : datum[config.confidenceKeys[position]]
255
+ return yScale(d)
256
+ })
257
+ // End Confidence Interval Variables
258
+
228
259
  return (
229
260
  <Group key={`${barGroup.index}--${index}`}>
230
261
  <Group key={`bar-sub-group-${barGroup.index}-${barGroup.x0}-${barY}--${index}`}>
@@ -353,6 +384,19 @@ export const BarChartVertical = () => {
353
384
  <animate attributeName='height' values={`0, ${lollipopShapeSize}`} dur='2.5s' />
354
385
  </rect>
355
386
  )}
387
+ {hasConfidenceInterval && (
388
+ <path
389
+ key={`confidence-interval-v-${datum[config.runtime.originalXAxis.dataKey]}`}
390
+ stroke='#333'
391
+ strokeWidth='px'
392
+ d={`M${xPos - tickWidth} ${upperPos}
393
+ L${xPos + tickWidth} ${upperPos}
394
+ M${xPos} ${upperPos}
395
+ L${xPos} ${lowerPos}
396
+ M${xPos - tickWidth} ${lowerPos}
397
+ L${xPos + tickWidth} ${lowerPos}`}
398
+ />
399
+ )}
356
400
  </Group>
357
401
  </Group>
358
402
  )
@@ -362,32 +406,6 @@ export const BarChartVertical = () => {
362
406
  }}
363
407
  </BarGroup>
364
408
 
365
- {Object.keys(config.confidenceKeys).length > 0
366
- ? data.map(d => {
367
- let xPos, yPos
368
- let upperPos
369
- let lowerPos
370
- let tickWidth = 5
371
- xPos = xScale(getXAxisData(d)) + (config.xAxis.type !== 'date-time' ? seriesScale.range()[1] / 2 : 0)
372
- upperPos = yScale(getYAxisData(d, config.confidenceKeys.lower))
373
- lowerPos = yScale(getYAxisData(d, config.confidenceKeys.upper))
374
- return (
375
- <path
376
- key={`confidence-interval-v-${yPos}-${d[config.runtime.originalXAxis.dataKey]}`}
377
- stroke='#333'
378
- strokeWidth='px'
379
- d={`
380
- M${xPos - tickWidth} ${upperPos}
381
- L${xPos + tickWidth} ${upperPos}
382
- M${xPos} ${upperPos}
383
- L${xPos} ${lowerPos}
384
- M${xPos - tickWidth} ${lowerPos}
385
- L${xPos + tickWidth} ${lowerPos}`}
386
- />
387
- )
388
- })
389
- : ''}
390
-
391
409
  <Regions xScale={xScale} yMax={yMax} barWidth={barWidth} totalBarsInGroup={totalBarsInGroup} />
392
410
  </Group>
393
411
  )
@@ -1,11 +1,11 @@
1
1
  import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
2
+ import isNumber from '@cdc/core/helpers/isNumber'
2
3
 
3
4
  // Define an interface for the function's parameter
4
5
  interface BarConfigProps {
5
6
  defaultBarWidth?: number
6
7
  defaultBarHeight?: number
7
8
  bar?: { [key: string]: any }
8
- isNumber?: Function
9
9
  config: { [key: string]: any }
10
10
  barWidth: number
11
11
  isVertical: boolean
@@ -17,7 +17,6 @@ export const getBarConfig = ({
17
17
  defaultBarHeight,
18
18
  defaultBarWidth,
19
19
  config,
20
- isNumber,
21
20
  barWidth,
22
21
  isVertical
23
22
  }: BarConfigProps) => {
@@ -0,0 +1,189 @@
1
+ import React, { useContext } from 'react'
2
+ import { BoxPlot } from '@visx/stats'
3
+ import { Group } from '@visx/group'
4
+ import ConfigContext from '../../ConfigContext'
5
+ import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
6
+ import { colorPalettesChart } from '@cdc/core/data/colorPalettes'
7
+ import { scaleBand } from '@visx/scale'
8
+ import _ from 'lodash'
9
+ import { max, min, median, quantile } from 'd3-array'
10
+ const CoveBoxPlot = ({ xScale, yScale }) => {
11
+ const { config, colorScale, seriesHighlight, transformedData: data } = useContext(ConfigContext)
12
+ const { boxplot } = config
13
+
14
+ // tooltips
15
+ const tooltip_id = `cdc-open-viz-tooltip-${config.runtime.uniqueId}`
16
+
17
+ const handleTooltip = (d, key, q1, q3, median, iqr) => {
18
+ return `
19
+ <strong>${d.columnCategory}</strong></br>
20
+ <strong>Key:${key}</strong></br>
21
+ ${boxplot.labels.q1}: ${q1}<br/>
22
+ ${boxplot.labels.q3}: ${q3}<br/>
23
+ ${boxplot.labels.iqr}: ${iqr}<br/>
24
+ ${boxplot.labels.median}: ${median}
25
+ `
26
+ }
27
+
28
+ const boxWidth = xScale.bandwidth()
29
+ const constrainedWidth = Math.min(40, boxWidth)
30
+ const color_0 = colorPalettesChart[config?.palette][0] ? colorPalettesChart[config?.palette][0] : '#000'
31
+ const seriesScale = scaleBand({
32
+ range: [0, config.barThickness * 100 || 1],
33
+ domain: config.series?.map(item => item?.dataKey)
34
+ })
35
+
36
+ const calculateBoxPlotStats = values => {
37
+ if (!values || !values.length) return {}
38
+ const sortedValues = values.sort((a, b) => a - b)
39
+ return {
40
+ min: min(values),
41
+ max: max(values),
42
+ median: median(values),
43
+ firstQuartile: quantile(sortedValues, 0.25),
44
+ thirdQuartile: quantile(sortedValues, 0.75)
45
+ }
46
+ }
47
+
48
+ const getValuesBySeriesKey = (group: string) => {
49
+ const allSeriesKeys = config.series.map(item => item?.dataKey)
50
+ const result = {}
51
+ const filteredData = data.filter(item => item[config.xAxis.dataKey] === group)
52
+ allSeriesKeys.forEach(key => {
53
+ result[key] = filteredData.map(item => item[key])
54
+ })
55
+
56
+ return result
57
+ }
58
+
59
+ interface Plot {
60
+ columnCategory: string
61
+ keyValues: { [key: string]: number[] }
62
+ }
63
+ const createPlots = data => {
64
+ const dataKeys = data.map(d => d[config.xAxis.dataKey])
65
+ const plots: Plot[] = []
66
+ const groups: string[] = _.uniq(dataKeys)
67
+ if (groups && groups.length > 0) {
68
+ groups.forEach(group => {
69
+ plots.push({
70
+ columnCategory: group,
71
+ keyValues: getValuesBySeriesKey(group)
72
+ })
73
+ })
74
+ }
75
+ return plots
76
+ }
77
+
78
+ return (
79
+ <ErrorBoundary component='BoxPlot'>
80
+ <Group left={Number(config.yAxis.size)} className='boxplot' key={`boxplot-group`}>
81
+ {createPlots(data).map((d, i) => {
82
+ const offset = boxWidth - constrainedWidth
83
+ const radius = 4
84
+
85
+ return (
86
+ <Group
87
+ key={`boxplotplot-${d.columnCategory}`}
88
+ left={xScale(d.columnCategory) + (xScale.bandwidth() - seriesScale.bandwidth()) / 2}
89
+ >
90
+ {config.series.map(item => {
91
+ const valuesByKey = d.keyValues[item.dataKey]
92
+ const { min, max, median, firstQuartile, thirdQuartile } = calculateBoxPlotStats(valuesByKey)
93
+ let iqr = Number(thirdQuartile - firstQuartile).toFixed(config.dataFormat.roundTo)
94
+
95
+ const transparentPlot =
96
+ config.legend.behavior === 'highlight' &&
97
+ seriesHighlight.length > 0 &&
98
+ seriesHighlight.indexOf(item.dataKey) === -1
99
+ const displayPlot =
100
+ config.legend.behavior === 'highlight' ||
101
+ seriesHighlight.length === 0 ||
102
+ seriesHighlight.indexOf(item.dataKey) !== -1
103
+ const fillOpacity = transparentPlot ? 0.3 : 0.5
104
+
105
+ return (
106
+ <Group key={`boxplotplot-${item}`}>
107
+ {boxplot.plotNonOutlierValues &&
108
+ valuesByKey.map((value, index) => {
109
+ return (
110
+ <circle
111
+ display={displayPlot ? 'block' : 'none'}
112
+ cx={seriesScale(item.dataKey) + seriesScale.bandwidth() / 2}
113
+ cy={yScale(value)}
114
+ r={radius}
115
+ fill={'#ccc'}
116
+ style={{ opacity: fillOpacity, fillOpacity: 1, stroke: 'black' }}
117
+ key={`boxplot-${i}--circle-${index}`}
118
+ />
119
+ )
120
+ })}
121
+ {displayPlot && (
122
+ <BoxPlot
123
+ display={displayPlot ? 'block' : 'none'}
124
+ data-left={xScale(d.columnCategory) + config.yAxis.size + offset / 2 + 0.5}
125
+ key={`box-plot-${i}-${item}`}
126
+ min={min}
127
+ max={max}
128
+ left={seriesScale(item.dataKey)}
129
+ firstQuartile={firstQuartile}
130
+ thirdQuartile={thirdQuartile}
131
+ median={median}
132
+ boxWidth={seriesScale.bandwidth()}
133
+ fill={colorScale(item.dataKey)}
134
+ fillOpacity={fillOpacity}
135
+ stroke={fillOpacity ? 'rgba(0,0,0,0.2)' : 'rgba(0,0,0,0.1)'}
136
+ valueScale={yScale}
137
+ outliers={boxplot.plotOutlierValues ? d.columnOutliers : []}
138
+ outlierProps={{
139
+ style: {
140
+ fill: `${color_0}`,
141
+ opacity: fillOpacity
142
+ }
143
+ }}
144
+ medianProps={{
145
+ style: {
146
+ stroke: 'black',
147
+ opacity: fillOpacity
148
+ }
149
+ }}
150
+ boxProps={{
151
+ style: {
152
+ stroke: 'black',
153
+ strokeWidth: boxplot.borders === 'true' ? 1 : 0,
154
+ opacity: fillOpacity
155
+ }
156
+ }}
157
+ maxProps={{
158
+ style: {
159
+ stroke: 'black',
160
+ opacity: fillOpacity
161
+ }
162
+ }}
163
+ container
164
+ containerProps={{
165
+ 'data-tooltip-html': handleTooltip(
166
+ d,
167
+ item.dataKey,
168
+ firstQuartile,
169
+ thirdQuartile,
170
+ median,
171
+ iqr
172
+ ),
173
+ 'data-tooltip-id': tooltip_id,
174
+ tabIndex: -1
175
+ }}
176
+ />
177
+ )}
178
+ </Group>
179
+ )
180
+ })}
181
+ </Group>
182
+ )
183
+ })}
184
+ </Group>
185
+ </ErrorBoundary>
186
+ )
187
+ }
188
+
189
+ export default CoveBoxPlot