@cdc/chart 4.23.11 → 4.24.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/cdcchart.js +35740 -35027
  2. package/examples/feature/bar/additional-column-tooltip.json +446 -0
  3. package/examples/feature/bar/tall-data.json +98 -0
  4. package/examples/feature/forest-plot/forest-plot.json +63 -19
  5. package/examples/feature/forest-plot/linear.json +52 -3
  6. package/examples/feature/forest-plot/log.json +26 -0
  7. package/examples/feature/forest-plot/logarithmic.json +0 -35
  8. package/examples/feature/line/line-chart-preliminary.json +393 -0
  9. package/examples/feature/regions/index.json +9 -5
  10. package/examples/feature/scatterplot/scatterplot.json +272 -33
  11. package/index.html +10 -8
  12. package/package.json +2 -2
  13. package/src/CdcChart.tsx +70 -234
  14. package/src/ConfigContext.tsx +6 -0
  15. package/src/_stories/ChartEditor.stories.tsx +22 -0
  16. package/src/_stories/ChartLine.preliminary.tsx +19 -0
  17. package/src/_stories/_mock/pie_config.json +192 -0
  18. package/src/_stories/_mock/pie_data.json +218 -0
  19. package/src/_stories/_mock/preliminary_mock.json +346 -0
  20. package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +2 -2
  21. package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +2 -26
  22. package/src/components/AreaChart/index.tsx +4 -0
  23. package/src/components/{BarChart.Horizontal.tsx → BarChart/components/BarChart.Horizontal.tsx} +8 -8
  24. package/src/components/{BarChart.StackedHorizontal.tsx → BarChart/components/BarChart.StackedHorizontal.tsx} +37 -7
  25. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +108 -0
  26. package/src/components/{BarChart.Vertical.tsx → BarChart/components/BarChart.Vertical.tsx} +53 -70
  27. package/src/components/BarChart/components/BarChart.jsx +39 -0
  28. package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
  29. package/src/components/BarChart/components/context.tsx +13 -0
  30. package/src/components/BarChart/index.tsx +3 -0
  31. package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +10 -9
  32. package/src/components/BoxPlot/index.tsx +3 -0
  33. package/src/components/EditorPanel/EditorPanel.tsx +2776 -0
  34. package/src/components/EditorPanel/EditorPanelContext.ts +40 -0
  35. package/src/components/EditorPanel/components/PanelProps.ts +3 -0
  36. package/src/components/EditorPanel/components/Panels/Panel.BoxPlot.tsx +148 -0
  37. package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx} +97 -167
  38. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +160 -0
  39. package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +168 -0
  40. package/src/components/{Series.jsx → EditorPanel/components/Panels/Panel.Series.tsx} +4 -4
  41. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +297 -0
  42. package/src/components/EditorPanel/components/Panels/index.tsx +17 -0
  43. package/src/components/EditorPanel/components/panels.scss +72 -0
  44. package/src/components/EditorPanel/editor-panel.scss +739 -0
  45. package/src/components/EditorPanel/index.tsx +3 -0
  46. package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +34 -2
  47. package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
  48. package/src/components/Forecasting/index.tsx +3 -0
  49. package/src/components/ForestPlot/ForestPlot.tsx +254 -0
  50. package/src/components/ForestPlot/ForestPlotProps.ts +7 -0
  51. package/src/components/ForestPlot/index.tsx +1 -209
  52. package/src/components/Legend/Legend.Component.tsx +199 -0
  53. package/src/components/Legend/Legend.tsx +28 -0
  54. package/src/components/Legend/helpers/createFormatLabels.tsx +140 -0
  55. package/src/components/Legend/index.tsx +3 -0
  56. package/src/components/LineChart/LineChartProps.ts +29 -0
  57. package/src/components/LineChart/components/LineChart.Circle.tsx +147 -0
  58. package/src/components/LineChart/helpers.ts +45 -0
  59. package/src/components/LineChart/index.tsx +111 -23
  60. package/src/components/LinearChart.jsx +55 -72
  61. package/src/components/PairedBarChart.jsx +4 -2
  62. package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +93 -31
  63. package/src/components/PieChart/index.tsx +3 -0
  64. package/src/components/Regions/components/Regions.tsx +144 -0
  65. package/src/components/Regions/index.tsx +3 -0
  66. package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
  67. package/src/components/ScatterPlot/index.tsx +3 -0
  68. package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
  69. package/src/components/Sparkline/index.tsx +3 -0
  70. package/src/data/initial-state.js +10 -8
  71. package/src/helpers/abbreviateNumber.ts +17 -0
  72. package/src/helpers/computeMarginBottom.ts +55 -0
  73. package/src/helpers/filterData.ts +18 -0
  74. package/src/helpers/generateColorsArray.ts +8 -0
  75. package/src/helpers/getQuartiles.ts +30 -0
  76. package/src/helpers/handleChartAriaLabels.ts +19 -0
  77. package/src/helpers/handleLineType.ts +18 -0
  78. package/src/helpers/lineOptions.ts +18 -0
  79. package/src/helpers/sort.ts +7 -0
  80. package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
  81. package/src/hooks/useBarChart.js +7 -6
  82. package/src/hooks/useHighlightedBars.js +1 -1
  83. package/src/hooks/useMinMax.ts +3 -3
  84. package/src/hooks/useScales.ts +19 -6
  85. package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +31 -25
  86. package/src/scss/main.scss +0 -3
  87. package/src/types/ChartConfig.ts +167 -23
  88. package/src/types/ChartContext.ts +34 -12
  89. package/src/types/ForestPlot.ts +7 -14
  90. package/src/types/Label.ts +7 -0
  91. package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
  92. package/src/ConfigContext.jsx +0 -5
  93. package/src/components/BarChart.StackedVertical.tsx +0 -91
  94. package/src/components/BarChart.jsx +0 -30
  95. package/src/components/EditorPanel.jsx +0 -3356
  96. package/src/components/ForestPlot/Readme.md +0 -0
  97. package/src/components/Legend.jsx +0 -310
  98. package/src/components/LineChart/LineChart.Circle.tsx +0 -105
  99. package/src/scss/LinearChart.scss +0 -0
  100. package/src/scss/editor-panel.scss +0 -745
  101. package/src/scss/legend.scss +0 -206
  102. package/src/scss/mixins.scss +0 -0
  103. package/src/scss/variables.scss +0 -1
  104. package/src/types/ChartProps.ts +0 -7
@@ -2,13 +2,14 @@ import React, { useContext } from 'react'
2
2
 
3
3
  import * as allCurves from '@visx/curve'
4
4
  import { Group } from '@visx/group'
5
- import { LinePath, Bar } from '@visx/shape'
5
+ import { LinePath, Bar, SplitLinePath } from '@visx/shape'
6
6
  import { Text } from '@visx/text'
7
7
 
8
8
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
9
9
  import ConfigContext from '../../ConfigContext'
10
10
  import useRightAxis from '../../hooks/useRightAxis'
11
- import LineChartCircle from './LineChart.Circle'
11
+ import { filterCircles, createStyles } from './helpers'
12
+ import LineChartCircle from './components/LineChart.Circle'
12
13
 
13
14
  // types
14
15
  import { type ChartContext } from '../../types/ChartContext'
@@ -41,6 +42,7 @@ const LineChart = (props: LineChartProps) => {
41
42
  tableData,
42
43
  transformedData: data,
43
44
  updateConfig,
45
+ rawData
44
46
  } = useContext<ChartContext>(ConfigContext)
45
47
  const { yScaleRight } = useRightAxis({ config, yMax, data, updateConfig })
46
48
  if (!handleTooltipMouseOver) return
@@ -57,8 +59,14 @@ const LineChart = (props: LineChartProps) => {
57
59
  let lineType = config.series.filter(item => item.dataKey === seriesKey)[0].type
58
60
  const seriesData = config.series.filter(item => item.dataKey === seriesKey)
59
61
  const seriesAxis = seriesData[0].axis ? seriesData[0].axis : 'left'
60
-
61
62
  let displayArea = legend.behavior === 'highlight' || seriesHighlight.length === 0 || seriesHighlight.indexOf(seriesKey) !== -1
63
+ const circleData = filterCircles(config.preliminaryData, rawData, seriesKey)
64
+ // styles for preliminary Data items
65
+ let styles = createStyles({ preliminaryData: config.preliminaryData, data: tableData, stroke: colorScale(config.runtime.seriesLabels[seriesKey]), handleLineType, lineType, seriesKey })
66
+
67
+ let xPos = d => {
68
+ return xScale(getXAxisData(d)) + (xScale.bandwidth ? xScale.bandwidth() / 2 : 0)
69
+ }
62
70
 
63
71
  return (
64
72
  <Group
@@ -87,12 +95,15 @@ const LineChart = (props: LineChartProps) => {
87
95
  <Bar key={'bars'} width={Number(xMax)} height={Number(yMax)} fill={DEBUG ? 'red' : 'transparent'} fillOpacity={0.05} onMouseMove={e => handleTooltipMouseOver(e, tableData)} onMouseOut={handleTooltipMouseOff} onClick={e => handleTooltipClick(e, data)} />
88
96
 
89
97
  {/* Render legend */}
90
- <Text display={config.labels ? 'block' : 'none'} x={xScale(getXAxisData(d))} y={seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey))} fill={'#000'} textAnchor='middle'>
98
+ <Text display={config.labels ? 'block' : 'none'} x={xPos(d)} y={seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey))} fill={'#000'} textAnchor='middle'>
91
99
  {formatNumber(d[seriesKey], 'left')}
92
100
  </Text>
93
101
 
94
102
  {(lineDatapointStyle === 'hidden' || lineDatapointStyle === 'always show') && (
95
103
  <LineChartCircle
104
+ mode='ALWAYS_SHOW_POINTS'
105
+ dataIndex={dataIndex}
106
+ circleData={circleData}
96
107
  data={data}
97
108
  d={d}
98
109
  config={config}
@@ -108,44 +119,121 @@ const LineChart = (props: LineChartProps) => {
108
119
  key={`line-circle--${dataIndex}`}
109
120
  />
110
121
  )}
122
+
123
+ <LineChartCircle
124
+ mode='ISOLATED_POINTS'
125
+ dataIndex={dataIndex}
126
+ circleData={circleData}
127
+ data={data}
128
+ d={d}
129
+ config={config}
130
+ seriesKey={seriesKey}
131
+ displayArea={displayArea}
132
+ tooltipData={tooltipData}
133
+ xScale={xScale}
134
+ yScale={yScale}
135
+ colorScale={colorScale}
136
+ parseDate={parseDate}
137
+ yScaleRight={yScaleRight}
138
+ seriesAxis={seriesAxis}
139
+ key={`isolated-circle-${dataIndex}`}
140
+ />
111
141
  </Group>
112
142
  )
113
143
  )
114
144
  })}
115
145
  <>
116
146
  {lineDatapointStyle === 'hover' && (
117
- <LineChartCircle data={data} config={config} seriesKey={seriesKey} displayArea={displayArea} tooltipData={tooltipData} xScale={xScale} yScale={yScale} colorScale={colorScale} parseDate={parseDate} yScaleRight={yScaleRight} seriesAxis={seriesAxis} />
147
+ <LineChartCircle
148
+ dataIndex={0}
149
+ mode='HOVER_POINTS'
150
+ circleData={circleData}
151
+ data={data}
152
+ config={config}
153
+ seriesKey={seriesKey}
154
+ displayArea={displayArea}
155
+ tooltipData={tooltipData}
156
+ xScale={xScale}
157
+ yScale={yScale}
158
+ colorScale={colorScale}
159
+ parseDate={parseDate}
160
+ yScaleRight={yScaleRight}
161
+ seriesAxis={seriesAxis}
162
+ />
118
163
  )}
119
164
  </>
120
- {/* STANDARD LINE */}
121
- <LinePath
122
- curve={allCurves[seriesData[0].lineType]}
123
- data={data}
124
- x={d => xScale(getXAxisData(d))}
125
- y={d => (seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey)))}
126
- stroke={colorScale ? colorScale(config.runtime.seriesLabels[seriesKey]) : '#000'}
127
- strokeWidth={2}
128
- strokeOpacity={1}
129
- strokeDasharray={lineType ? handleLineType(lineType) : 0}
130
- defined={(item, i) => {
131
- return item[seriesKey] !== '' && item[seriesKey] !== null && item[seriesKey] !== undefined
132
- }}
133
- />
165
+ {/* SPLIT LINE */}
166
+ {config?.preliminaryData?.some(d => d.value && d.column) ? (
167
+ <SplitLinePath
168
+ curve={allCurves[seriesData[0].lineType]}
169
+ segments={(config.xAxis.type === 'date' && config.xAxis.sortDates
170
+ ? data.sort((d1, d2) => {
171
+ let x1 = getXAxisData(d1)
172
+ let x2 = getXAxisData(d2)
173
+ if (x1 < x2) return -1
174
+ if (x2 < x1) return 1
175
+ return 0
176
+ })
177
+ : data
178
+ ).map(d => [d])}
179
+ segmentation='x'
180
+ x={d => xPos(d)}
181
+ y={d => (seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(Number(getYAxisData(d, seriesKey))))}
182
+ styles={styles}
183
+ defined={(item, i) => {
184
+ return item[seriesKey] !== '' && item[seriesKey] !== null && item[seriesKey] !== undefined
185
+ }}
186
+ />
187
+ ) : (
188
+ <>
189
+ {/* STANDARD LINE */}
190
+ <LinePath
191
+ curve={allCurves[seriesData[0].lineType]}
192
+ data={
193
+ config.xAxis.type === 'date' && config.xAxis.sortDates
194
+ ? data.sort((d1, d2) => {
195
+ let x1 = getXAxisData(d1)
196
+ let x2 = getXAxisData(d2)
197
+ if (x1 < x2) return -1
198
+ if (x2 < x1) return 1
199
+ return 0
200
+ })
201
+ : data
202
+ }
203
+ x={d => xPos(d)}
204
+ y={d => (seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(Number(getYAxisData(d, seriesKey))))}
205
+ stroke={colorScale(config.runtime.seriesLabels[seriesKey])}
206
+ strokeWidth={2}
207
+ strokeOpacity={1}
208
+ shapeRendering='geometricPrecision'
209
+ strokeDasharray={lineType ? handleLineType(lineType) : 0}
210
+ defined={(item, i) => {
211
+ return item[seriesKey] !== '' && item[seriesKey] !== null && item[seriesKey] !== undefined
212
+ }}
213
+ />
214
+ </>
215
+ )}
216
+
217
+ {/* circles for preliminaryData data */}
218
+ {circleData.map((d, i) => {
219
+ return <circle key={i} cx={xPos(d)} cy={yScale(Number(getYAxisData(d, seriesKey)))} r={6} strokeWidth={2} stroke={colorScale ? colorScale(config.runtime.seriesLabels[seriesKey]) : '#000'} fill='#fff' />
220
+ })}
221
+
134
222
  {/* ANIMATED LINE */}
135
223
  {config.animate && (
136
224
  <LinePath
137
225
  className='animation'
138
226
  curve={seriesData.lineType}
139
227
  data={data}
140
- x={d => xScale(getXAxisData(d))}
141
- y={d => (seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(getYAxisData(d, seriesKey)))}
228
+ x={d => xPos(d)}
229
+ y={d => (seriesAxis === 'Right' ? yScaleRight(getYAxisData(d, seriesKey)) : yScale(Number(getYAxisData(d, seriesKey))))}
142
230
  stroke='#fff'
143
231
  strokeWidth={3}
144
232
  strokeOpacity={1}
145
233
  shapeRendering='geometricPrecision'
146
234
  strokeDasharray={lineType ? handleLineType(lineType) : 0}
147
235
  defined={(item, i) => {
148
- return isNumber(item[config.runtime.seriesLabels[seriesKey]])
236
+ return item[seriesKey] !== '' && item[seriesKey] !== null && item[seriesKey] !== undefined
149
237
  }}
150
238
  />
151
239
  )}
@@ -163,7 +251,7 @@ const LineChart = (props: LineChartProps) => {
163
251
  return <></>
164
252
  }
165
253
  return (
166
- <text x={xScale(getXAxisData(lastDatum)) + 5} y={yScale(getYAxisData(lastDatum, seriesKey))} alignmentBaseline='middle' fill={config.colorMatchLineSeriesLabels && colorScale ? colorScale(config.runtime.seriesLabels[seriesKey] || seriesKey) : 'black'}>
254
+ <text x={xPos(lastDatum) + 5} y={yScale(getYAxisData(lastDatum, seriesKey))} alignmentBaseline='middle' fill={config.colorMatchLineSeriesLabels && colorScale ? colorScale(config.runtime.seriesLabels[seriesKey] || seriesKey) : 'black'}>
167
255
  {config.runtime.seriesLabels[seriesKey] || seriesKey}
168
256
  </text>
169
257
  )
@@ -9,11 +9,10 @@ import { Tooltip as ReactTooltip } from 'react-tooltip'
9
9
  import { useTooltip, TooltipWithBounds } from '@visx/tooltip'
10
10
 
11
11
  // CDC Components
12
- import AreaChart from './AreaChart'
13
- import AreaChartStacked from './AreaChart.Stacked'
12
+ import { AreaChart, AreaChartStacked } from './AreaChart'
14
13
  import BarChart from './BarChart'
15
14
  import ConfigContext from '../ConfigContext'
16
- import CoveBoxPlot from './BoxPlot'
15
+ import BoxPlot from './BoxPlot'
17
16
  import ScatterPlot from './ScatterPlot'
18
17
  import DeviationBar from './DeviationBar'
19
18
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
@@ -22,6 +21,7 @@ import LineChart from './LineChart'
22
21
  import ForestPlot from './ForestPlot'
23
22
  import PairedBarChart from './PairedBarChart'
24
23
  import useIntersectionObserver from './../hooks/useIntersectionObserver'
24
+ import Regions from './Regions'
25
25
 
26
26
  // Hooks
27
27
  import useMinMax from '../hooks/useMinMax'
@@ -30,14 +30,33 @@ import useRightAxis from '../hooks/useRightAxis'
30
30
  import useScales from '../hooks/useScales'
31
31
  import useTopAxis from '../hooks/useTopAxis'
32
32
  import { useTooltip as useCoveTooltip } from '../hooks/useTooltip'
33
- import { useEditorPermissions } from '../hooks/useEditorPermissions'
33
+ import { useEditorPermissions } from './EditorPanel/useEditorPermissions'
34
34
 
35
35
  // styles
36
- import '../scss/LinearChart.scss'
37
36
  import ZoomBrush from './ZoomBrush'
38
37
 
39
38
  const LinearChart = props => {
40
- const { isEditor, isDashboard, transformedData: data, dimensions, config, parseDate, formatDate, currentViewport, formatNumber, handleChartAriaLabels, updateConfig, handleLineType, rawData, capitalize, setSharedFilter, setSharedFilterValue, getTextWidth, isDebug } = useContext(ConfigContext)
39
+ const {
40
+ isEditor,
41
+ isDashboard,
42
+ computeMarginBottom,
43
+ transformedData: data,
44
+ dimensions,
45
+ config,
46
+ parseDate,
47
+ formatDate,
48
+ currentViewport,
49
+ formatNumber,
50
+ handleChartAriaLabels,
51
+ updateConfig,
52
+ handleLineType,
53
+ rawData,
54
+ capitalize,
55
+ setSharedFilter,
56
+ setSharedFilterValue,
57
+ getTextWidth,
58
+ isDebug
59
+ } = useContext(ConfigContext)
41
60
  // todo: start destructuring this file for conciseness
42
61
  const { visualizationType, visualizationSubType, orientation, xAxis, yAxis, runtime, debugSvg } = config
43
62
 
@@ -50,7 +69,7 @@ const LinearChart = props => {
50
69
  }
51
70
  // configure height , yMax, xMax
52
71
  const { horizontal: heightHorizontal } = config.heights
53
- const isHorizontal = orientation === 'horizontal'
72
+ const isHorizontal = orientation === 'horizontal' || config.visualizationType === 'Forest Plot'
54
73
  const shouldAbbreviate = true
55
74
  let height = config.aspectRatio ? width * config.aspectRatio : config.visualizationType === 'Forest Plot' ? config.heights['vertical'] : config.heights[orientation]
56
75
  const xMax = width - runtime.yAxis.size - (visualizationType === 'Combo' ? config.yAxis.rightAxisSize : 0)
@@ -59,9 +78,10 @@ const LinearChart = props => {
59
78
  if (config.visualizationType === 'Forest Plot') {
60
79
  height = height + config.data.length * config.forestPlot.rowHeight
61
80
  yMax = yMax + config.data.length * config.forestPlot.rowHeight
81
+ width = dimensions[0]
62
82
  }
63
- if (config.brush.active) {
64
- height = height + config.brush.height
83
+ if (config.brush?.active) {
84
+ height = height + config.brush?.height
65
85
  }
66
86
 
67
87
  // hooks % states
@@ -82,11 +102,11 @@ const LinearChart = props => {
82
102
  const getXAxisData = d => (config.runtime.xAxis.type === 'date' ? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime() : d[config.runtime.originalXAxis.dataKey])
83
103
  const getYAxisData = (d, seriesKey) => d[seriesKey]
84
104
  const xAxisDataMapped = config.brush.active && config.brush.data?.length ? config.brush.data.map(d => getXAxisData(d)) : data.map(d => getXAxisData(d))
85
- const section = config.orientation === 'horizontal' ? 'yAxis' : 'xAxis'
105
+ const section = config.orientation === 'horizontal' || config.visualizationType === 'Forest Plot' ? 'yAxis' : 'xAxis'
86
106
  const properties = { data, config, minValue, maxValue, isAllLine, existPositiveValue, xAxisDataMapped, xMax, yMax }
87
107
  const { min, max, leftMax, rightMax } = useMinMax(properties)
88
108
  const { yScaleRight, hasRightAxis } = useRightAxis({ config, yMax, data, updateConfig })
89
- const { xScale, yScale, seriesScale, g1xScale, g2xScale, xScaleNoPadding, xScaleBrush } = useScales({ ...properties, min, max, leftMax, rightMax })
109
+ const { xScale, yScale, seriesScale, g1xScale, g2xScale, xScaleNoPadding, xScaleBrush } = useScales({ ...properties, min, max, leftMax, rightMax, dimensions })
90
110
 
91
111
  // sets the portal x/y for where tooltips should appear on the page.
92
112
  const [chartPosition, setChartPosition] = useState(null)
@@ -113,10 +133,10 @@ const LinearChart = props => {
113
133
  tick = 0
114
134
  }
115
135
 
116
- if (config.visualizationType === 'Forest Plot') return formatNumber(tick, 'bottom', false, false, false, true)
117
- if (runtime.xAxis.type === 'date') return formatDate(tick)
118
- if (orientation === 'horizontal') return formatNumber(tick, 'left', shouldAbbreviate)
119
- if (config.xAxis.type === 'continuous') return formatNumber(tick, 'bottom', shouldAbbreviate)
136
+ if (runtime.xAxis.type === 'date' && config.visualizationType !== 'Forest Plot') return formatDate(tick)
137
+ if (orientation === 'horizontal' && config.visualizationType !== 'Forest Plot') return formatNumber(tick, 'left', shouldAbbreviate)
138
+ if (config.xAxis.type === 'continuous' && config.visualizationType !== 'Forest Plot') return formatNumber(tick, 'bottom', shouldAbbreviate)
139
+ if (config.visualizationType === 'Forest Plot') return formatNumber(tick, 'left', config.dataFormat.abbreviated, config.runtime.xAxis.prefix, config.runtime.xAxis.suffix, Number(config.dataFormat.roundTo))
120
140
  return tick
121
141
  }
122
142
 
@@ -154,7 +174,7 @@ const LinearChart = props => {
154
174
  }
155
175
 
156
176
  if (config.visualizationType === 'Forest Plot') {
157
- tickCount = config.xAxis.numTicks !== '' ? config.xAxis.numTicks : 4
177
+ tickCount = config.yAxis.numTicks !== '' ? config.yAxis.numTicks : 4
158
178
  }
159
179
  }
160
180
 
@@ -247,9 +267,9 @@ const LinearChart = props => {
247
267
  <Bar width={width} height={height} fill={'transparent'}></Bar> {/* Highlighted regions */}
248
268
  {/* Y axis */}
249
269
  {!['Spark Line', 'Forest Plot'].includes(visualizationType) && (
250
- <AxisLeft scale={yScale} tickLength={config.useLogScale ? 6 : 8} left={Number(runtime.yAxis.size) - config.yAxis.axisPadding} label={runtime.yAxis.label} stroke='#333' tickFormat={(tick, i) => handleLeftTickFormatting(tick, i)} numTicks={handleNumTicks()}>
270
+ <AxisLeft scale={yScale} tickLength={config.useLogScale ? 6 : 8} left={Number(runtime.yAxis.size) - config.yAxis.axisPadding} label={runtime.yAxis.yAxis?.label || runtime.yAxis.label} stroke='#333' tickFormat={(tick, i) => handleLeftTickFormatting(tick, i)} numTicks={handleNumTicks()}>
251
271
  {props => {
252
- const axisCenter = runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
272
+ const axisCenter = config.orientation === 'horizontal' ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
253
273
  const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
254
274
  return (
255
275
  <Group className='left-axis'>
@@ -262,7 +282,7 @@ const LinearChart = props => {
262
282
 
263
283
  return (
264
284
  <Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
265
- {!runtime.yAxis.hideTicks && <Line key={`${tick.value}--hide-hideTicks`} from={tick.from} to={config.useLogScale ? to : tick.to} stroke={config.yAxis.tickColor} display={runtime.horizontal ? 'none' : 'block'} />}
285
+ {!runtime.yAxis.hideTicks && <Line key={`${tick.value}--hide-hideTicks`} from={tick.from} to={config.useLogScale ? to : tick.to} stroke={config.yAxis.tickColor} display={orientation === 'horizontal' ? 'none' : 'block'} />}
266
286
 
267
287
  {runtime.yAxis.gridLines ? <Line key={`${tick.value}--hide-hideGridLines`} display={(config.useLogScale && showTicks).toString()} from={{ x: tick.from.x + xMax, y: tick.from.y }} to={tick.from} stroke='rgba(0,0,0,0.3)' /> : ''}
268
288
 
@@ -325,7 +345,7 @@ const LinearChart = props => {
325
345
  {hasRightAxis && (
326
346
  <AxisRight scale={yScaleRight} left={Number(width - config.yAxis.rightAxisSize)} label={config.yAxis.rightLabel} tickFormat={tick => formatNumber(tick, 'right')} numTicks={runtime.yAxis.rightNumTicks || undefined} labelOffset={45}>
327
347
  {props => {
328
- const axisCenter = runtime.horizontal ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
348
+ const axisCenter = config.orientation === 'horizontal' ? (props.axisToPoint.y - props.axisFromPoint.y) / 2 : (props.axisFromPoint.y - props.axisToPoint.y) / 2
329
349
  const horizontalTickOffset = yMax / props.ticks.length / 2 - (yMax / props.ticks.length) * (1 - config.barThickness) + 5
330
350
  return (
331
351
  <Group className='right-axis'>
@@ -369,7 +389,7 @@ const LinearChart = props => {
369
389
  {visualizationType !== 'Paired Bar' && visualizationType !== 'Spark Line' && (
370
390
  <AxisBottom
371
391
  top={runtime.horizontal && config.visualizationType !== 'Forest Plot' ? Number(heightHorizontal) + Number(config.xAxis.axisPadding) : config.visualizationType === 'Forest Plot' ? yMax + Number(config.xAxis.axisPadding) : yMax + Number(config.xAxis.axisPadding)}
372
- left={Number(runtime.yAxis.size)}
392
+ left={config.visualizationType !== 'Forest Plot' ? Number(runtime.yAxis.size) : 0}
373
393
  label={runtime.xAxis.label}
374
394
  tickFormat={handleBottomTickFormatting}
375
395
  scale={xScale}
@@ -378,7 +398,7 @@ const LinearChart = props => {
378
398
  tickStroke='#333'
379
399
  >
380
400
  {props => {
381
- const axisCenter = config.visualizationType !== 'Forest Plot' ? (props.axisToPoint.x - props.axisFromPoint.x) / 2 : width / 2
401
+ const axisCenter = config.visualizationType !== 'Forest Plot' ? (props.axisToPoint.x - props.axisFromPoint.x) / 2 : dimensions[0] / 2
382
402
  const containsMultipleWords = inputString => /\s/.test(inputString)
383
403
  const ismultiLabel = props.ticks.some(tick => containsMultipleWords(tick.value))
384
404
 
@@ -418,7 +438,7 @@ const LinearChart = props => {
418
438
  config.xAxis.tickWidthMax = tickWidthMax
419
439
 
420
440
  return (
421
- <Group className='bottom-axis'>
441
+ <Group className='bottom-axis' width={dimensions[0]}>
422
442
  {props.ticks.map((tick, i, propsTicks) => {
423
443
  // when using LogScale show major ticks values only
424
444
  const showTick = String(tick.value).startsWith('1') || tick.value === 0.1 ? 'block' : 'none'
@@ -435,7 +455,7 @@ const LinearChart = props => {
435
455
 
436
456
  return (
437
457
  <Group key={`vx-tick-${tick.value}-${i}`} className={'vx-axis-tick'}>
438
- {!config.xAxis.hideTicks && <Line from={tick.from} to={orientation === 'horizontal' && config.useLogScale ? to : tick.to} stroke={config.xAxis.tickColor} strokeWidth={showTick === 'block' ? 1.3 : 1} />}
458
+ {!config.xAxis.hideTicks && <Line from={tick.from} to={orientation === 'horizontal' && config.useLogScale ? to : tick.to} stroke={config.xAxis.tickColor} strokeWidth={showTick === 'block' && config.useLogScale ? 1.3 : 1} />}
439
459
  {!config.xAxis.hideLabel && (
440
460
  <Text
441
461
  dy={config.orientation === 'horizontal' && config.useLogScale ? 8 : 0}
@@ -458,7 +478,9 @@ const LinearChart = props => {
458
478
  <Text
459
479
  x={axisCenter}
460
480
  y={
461
- config.orientation === 'horizontal'
481
+ config.visualizationType === 'Forest Plot'
482
+ ? config.xAxis.tickWidthMax + 40
483
+ : config.orientation === 'horizontal'
462
484
  ? dynamicMarginTop || config.xAxis.labelOffset
463
485
  : config.isResponsiveTicks && dynamicMarginTop && !isHorizontal
464
486
  ? dynamicMarginTop
@@ -467,6 +489,7 @@ const LinearChart = props => {
467
489
  : Number(config.xAxis.labelOffset)
468
490
  }
469
491
  textAnchor='middle'
492
+ verticalAnchor='start'
470
493
  fontWeight='bold'
471
494
  fill={config.xAxis.labelColor}
472
495
  >
@@ -560,7 +583,7 @@ const LinearChart = props => {
560
583
  showTooltip={showTooltip}
561
584
  />
562
585
  )}
563
- {visualizationType === 'Box Plot' && <CoveBoxPlot xScale={xScale} yScale={yScale} />}
586
+ {visualizationType === 'Box Plot' && <BoxPlot xScale={xScale} yScale={yScale} />}
564
587
  {((visualizationType === 'Area Chart' && config.visualizationSubType === 'regular') || visualizationType === 'Combo') && (
565
588
  <AreaChart xScale={xScale} yScale={yScale} yMax={yMax} xMax={xMax} chartRef={svgRef} width={xMax} height={yMax} handleTooltipMouseOver={handleTooltipMouseOver} handleTooltipMouseOff={handleTooltipMouseOff} tooltipData={tooltipData} showTooltip={showTooltip} />
566
589
  )}
@@ -630,10 +653,8 @@ const LinearChart = props => {
630
653
  xScale={xScale}
631
654
  yScale={yScale}
632
655
  seriesScale={seriesScale}
633
- width={xMax}
634
- height={yMax}
635
- maxWidth={width}
636
- maxHeight={height}
656
+ width={width}
657
+ height={height}
637
658
  getXAxisData={getXAxisData}
638
659
  getYAxisData={getYAxisData}
639
660
  animatedChart={animatedChart}
@@ -708,48 +729,10 @@ const LinearChart = props => {
708
729
  )
709
730
  })}
710
731
  {/* we are handling regions in bar charts differently, so that we can calculate the bar group into the region space. */}
711
- {config.regions && config.visualizationType !== 'Bar' && config.orientation === 'vertical'
712
- ? config.regions.map(region => {
713
- if (!Object.keys(region).includes('from') || !Object.keys(region).includes('to')) return null
714
-
715
- let from
716
- let to
717
- let width
718
-
719
- if (config.xAxis.type === 'date') {
720
- from = xScale(parseDate(region.from).getTime())
721
- to = xScale(parseDate(region.to).getTime())
722
- width = to - from
723
- }
724
-
725
- if (config.xAxis.type === 'categorical') {
726
- from = xScale(region.from)
727
- to = xScale(region.to)
728
- width = to - from
729
- }
730
-
731
- if (!from) return null
732
- if (!to) return null
733
-
734
- return (
735
- <Group className='regions' left={Number(runtime.yAxis.size)} key={region.label} onMouseMove={handleTooltipMouseOver} onMouseLeave={handleTooltipMouseOff} handleTooltipClick={handleTooltipClick} tooltipData={JSON.stringify(tooltipData)} showTooltip={showTooltip}>
736
- <path
737
- stroke='#333'
738
- d={`M${from} -5
739
- L${from} 5
740
- M${from} 0
741
- L${to} 0
742
- M${to} -5
743
- L${to} 5`}
744
- />
745
- <rect x={from} y={0} width={width} height={yMax} fill={region.background} opacity={0.3} />
746
- <Text x={from + width / 2} y={5} fill={region.color} verticalAnchor='start' textAnchor='middle'>
747
- {region.label}
748
- </Text>
749
- </Group>
750
- )
751
- })
752
- : ''}
732
+ {/* prettier-ignore */}
733
+ {config.visualizationType !== 'Bar' && config.visualizationType !== 'Combo' && (
734
+ <Regions xScale={xScale} handleTooltipClick={handleTooltipClick} handleTooltipMouseOff={handleTooltipMouseOff} handleTooltipMouseOver={handleTooltipMouseOver} showTooltip={showTooltip} hideTooltip={hideTooltip} tooltipData={tooltipData} yMax={yMax} width={width} />
735
+ )}
753
736
  {chartHasTooltipGuides && showTooltip && tooltipData && config.visual.verticalHoverLine && (
754
737
  <Group key='tooltipLine-vertical' className='vertical-tooltip-line'>
755
738
  <Line from={{ x: tooltipData.dataXPosition - 10, y: 0 }} to={{ x: tooltipData.dataXPosition - 10, y: yMax }} stroke={'black'} strokeWidth={1} pointerEvents='none' strokeDasharray='5,5' className='vertical-tooltip-line' />
@@ -20,6 +20,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
20
20
  const groupOne = {
21
21
  parentKey: config.dataDescription.seriesKey,
22
22
  dataKey: config.series[0].dataKey,
23
+ dataKeyLabel: config.runtime.seriesLabels[config.series[0].dataKey] || config.series[0].dataKey,
23
24
  color: colorScale(config.runtime.seriesLabels[config.series[0].dataKey]),
24
25
  max: Math.max.apply(
25
26
  Math,
@@ -31,6 +32,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
31
32
  const groupTwo = {
32
33
  parentKey: config.dataDescription.seriesKey,
33
34
  dataKey: config.series[1].dataKey,
35
+ dataKeyLabel: config.runtime.seriesLabels[config.series[1].dataKey] || config.series[1].dataKey,
34
36
  color: colorScale(config.runtime.seriesLabels[config.series[1].dataKey]),
35
37
  max: Math.max.apply(
36
38
  Math,
@@ -59,7 +61,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
59
61
 
60
62
  const dataTipOne = d => {
61
63
  return `<p>
62
- ${config.dataDescription.seriesKey}: ${groupOne.dataKey}<br/>
64
+ ${config.dataDescription.seriesKey}: ${groupOne.dataKeyLabel}<br/>
63
65
  ${config.xAxis.dataKey}: ${d[config.xAxis.dataKey]}<br/>
64
66
  ${label}${formatNumber(d[groupOne.dataKey], 'left')}
65
67
  </p>`
@@ -67,7 +69,7 @@ const PairedBarChart = ({ width, height, originalWidth }) => {
67
69
 
68
70
  const dataTipTwo = d => {
69
71
  return `<p>
70
- ${config.dataDescription.seriesKey}: ${groupTwo.dataKey}<br/>
72
+ ${config.dataDescription.seriesKey}: ${groupTwo.dataKeyLabel}<br/>
71
73
  ${config.xAxis.dataKey}: ${d[config.xAxis.dataKey]}<br/>
72
74
  ${label}${formatNumber(d[groupTwo.dataKey], 'left')}
73
75
  </p>`