@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.
- package/dist/cdcchart.js +35740 -35027
- package/examples/feature/bar/additional-column-tooltip.json +446 -0
- package/examples/feature/bar/tall-data.json +98 -0
- package/examples/feature/forest-plot/forest-plot.json +63 -19
- package/examples/feature/forest-plot/linear.json +52 -3
- package/examples/feature/forest-plot/log.json +26 -0
- package/examples/feature/forest-plot/logarithmic.json +0 -35
- package/examples/feature/line/line-chart-preliminary.json +393 -0
- package/examples/feature/regions/index.json +9 -5
- package/examples/feature/scatterplot/scatterplot.json +272 -33
- package/index.html +10 -8
- package/package.json +2 -2
- package/src/CdcChart.tsx +70 -234
- package/src/ConfigContext.tsx +6 -0
- package/src/_stories/ChartEditor.stories.tsx +22 -0
- package/src/_stories/ChartLine.preliminary.tsx +19 -0
- package/src/_stories/_mock/pie_config.json +192 -0
- package/src/_stories/_mock/pie_data.json +218 -0
- package/src/_stories/_mock/preliminary_mock.json +346 -0
- package/src/components/{AreaChart.Stacked.jsx → AreaChart/components/AreaChart.Stacked.jsx} +2 -2
- package/src/components/{AreaChart.jsx → AreaChart/components/AreaChart.jsx} +2 -26
- package/src/components/AreaChart/index.tsx +4 -0
- package/src/components/{BarChart.Horizontal.tsx → BarChart/components/BarChart.Horizontal.tsx} +8 -8
- package/src/components/{BarChart.StackedHorizontal.tsx → BarChart/components/BarChart.StackedHorizontal.tsx} +37 -7
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +108 -0
- package/src/components/{BarChart.Vertical.tsx → BarChart/components/BarChart.Vertical.tsx} +53 -70
- package/src/components/BarChart/components/BarChart.jsx +39 -0
- package/src/components/{BarChartType.jsx → BarChart/components/BarChartType.jsx} +0 -2
- package/src/components/BarChart/components/context.tsx +13 -0
- package/src/components/BarChart/index.tsx +3 -0
- package/src/components/{BoxPlot.jsx → BoxPlot/BoxPlot.jsx} +10 -9
- package/src/components/BoxPlot/index.tsx +3 -0
- package/src/components/EditorPanel/EditorPanel.tsx +2776 -0
- package/src/components/EditorPanel/EditorPanelContext.ts +40 -0
- package/src/components/EditorPanel/components/PanelProps.ts +3 -0
- package/src/components/EditorPanel/components/Panels/Panel.BoxPlot.tsx +148 -0
- package/src/components/{ForestPlotSettings.jsx → EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx} +97 -167
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +160 -0
- package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +168 -0
- package/src/components/{Series.jsx → EditorPanel/components/Panels/Panel.Series.tsx} +4 -4
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +297 -0
- package/src/components/EditorPanel/components/Panels/index.tsx +17 -0
- package/src/components/EditorPanel/components/panels.scss +72 -0
- package/src/components/EditorPanel/editor-panel.scss +739 -0
- package/src/components/EditorPanel/index.tsx +3 -0
- package/src/{hooks → components/EditorPanel}/useEditorPermissions.js +34 -2
- package/src/components/{Forecasting.jsx → Forecasting/Forecasting.jsx} +1 -1
- package/src/components/Forecasting/index.tsx +3 -0
- package/src/components/ForestPlot/ForestPlot.tsx +254 -0
- package/src/components/ForestPlot/ForestPlotProps.ts +7 -0
- package/src/components/ForestPlot/index.tsx +1 -209
- package/src/components/Legend/Legend.Component.tsx +199 -0
- package/src/components/Legend/Legend.tsx +28 -0
- package/src/components/Legend/helpers/createFormatLabels.tsx +140 -0
- package/src/components/Legend/index.tsx +3 -0
- package/src/components/LineChart/LineChartProps.ts +29 -0
- package/src/components/LineChart/components/LineChart.Circle.tsx +147 -0
- package/src/components/LineChart/helpers.ts +45 -0
- package/src/components/LineChart/index.tsx +111 -23
- package/src/components/LinearChart.jsx +55 -72
- package/src/components/PairedBarChart.jsx +4 -2
- package/src/components/{PieChart.jsx → PieChart/PieChart.tsx} +93 -31
- package/src/components/PieChart/index.tsx +3 -0
- package/src/components/Regions/components/Regions.tsx +144 -0
- package/src/components/Regions/index.tsx +3 -0
- package/src/components/{ScatterPlot.jsx → ScatterPlot/ScatterPlot.jsx} +3 -3
- package/src/components/ScatterPlot/index.tsx +3 -0
- package/src/components/{SparkLine.jsx → Sparkline/SparkLine.jsx} +2 -2
- package/src/components/Sparkline/index.tsx +3 -0
- package/src/data/initial-state.js +10 -8
- package/src/helpers/abbreviateNumber.ts +17 -0
- package/src/helpers/computeMarginBottom.ts +55 -0
- package/src/helpers/filterData.ts +18 -0
- package/src/helpers/generateColorsArray.ts +8 -0
- package/src/helpers/getQuartiles.ts +30 -0
- package/src/helpers/handleChartAriaLabels.ts +19 -0
- package/src/helpers/handleLineType.ts +18 -0
- package/src/helpers/lineOptions.ts +18 -0
- package/src/helpers/sort.ts +7 -0
- package/src/helpers/tests/computeMarginBottom.test.ts +20 -0
- package/src/hooks/useBarChart.js +7 -6
- package/src/hooks/useHighlightedBars.js +1 -1
- package/src/hooks/useMinMax.ts +3 -3
- package/src/hooks/useScales.ts +19 -6
- package/src/hooks/{useTooltip.jsx → useTooltip.tsx} +31 -25
- package/src/scss/main.scss +0 -3
- package/src/types/ChartConfig.ts +167 -23
- package/src/types/ChartContext.ts +34 -12
- package/src/types/ForestPlot.ts +7 -14
- package/src/types/Label.ts +7 -0
- package/examples/feature/scatterplot/scatterplot-continuous.csv +0 -17
- package/src/ConfigContext.jsx +0 -5
- package/src/components/BarChart.StackedVertical.tsx +0 -91
- package/src/components/BarChart.jsx +0 -30
- package/src/components/EditorPanel.jsx +0 -3356
- package/src/components/ForestPlot/Readme.md +0 -0
- package/src/components/Legend.jsx +0 -310
- package/src/components/LineChart/LineChart.Circle.tsx +0 -105
- package/src/scss/LinearChart.scss +0 -0
- package/src/scss/editor-panel.scss +0 -745
- package/src/scss/legend.scss +0 -206
- package/src/scss/mixins.scss +0 -0
- package/src/scss/variables.scss +0 -1
- 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
|
|
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={
|
|
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
|
|
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
|
-
{/*
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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 =>
|
|
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
|
|
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={
|
|
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
|
|
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 '
|
|
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 {
|
|
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
|
|
64
|
-
height = height + config.brush
|
|
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
|
|
117
|
-
if (
|
|
118
|
-
if (
|
|
119
|
-
if (config.
|
|
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.
|
|
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 =
|
|
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={
|
|
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 =
|
|
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 :
|
|
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.
|
|
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' && <
|
|
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={
|
|
634
|
-
height={
|
|
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
|
-
{
|
|
712
|
-
|
|
713
|
-
|
|
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.
|
|
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.
|
|
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>`
|