@cdc/chart 4.25.3-6 → 4.25.5-1
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-1a1724a1.es.js +4886 -0
- package/dist/cdcchart.js +50347 -75521
- package/index.html +1 -0
- package/package.json +22 -27
- package/src/CdcChart.tsx +1 -22
- package/src/CdcChartComponent.tsx +35 -21
- package/src/_stories/Chart.CI.stories.tsx +43 -0
- package/src/_stories/Chart.DynamicSeries.stories.tsx +68 -49
- package/src/_stories/Chart.Legend.Gradient.stories.tsx +6 -0
- package/src/_stories/Chart.stories.tsx +7 -16
- package/src/_stories/_mock/bar_chart_ci_labels.json +620 -0
- package/src/_stories/_mock/barchart_labels.mock.json +612 -0
- package/src/_stories/_mock/dynamic_series_bar_config.json +1 -1
- package/src/_stories/_mock/dynamic_series_suppression_mock.json +610 -0
- package/{examples/private/line-issue.json → src/_stories/_mock/legend_groupBy_mock.json} +46 -69
- package/src/components/Annotations/components/AnnotationDropdown.tsx +2 -2
- package/src/components/AreaChart/components/AreaChart.jsx +33 -5
- package/src/components/Axis/Categorical.Axis.tsx +2 -2
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +51 -41
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +19 -9
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +20 -9
- package/src/components/BarChart/components/BarChart.Vertical.tsx +48 -31
- package/src/components/BarChart/components/{BarChart.jsx → BarChart.tsx} +23 -5
- package/src/components/BarChart/components/context.tsx +20 -2
- package/src/components/BarChart/helpers/getBarHeights.ts +47 -0
- package/src/components/BarChart/helpers/index.ts +5 -2
- package/src/components/BarChart/helpers/tests/getBarHeights.test.ts +83 -0
- package/src/{hooks → components/BarChart/helpers}/useBarChart.ts +11 -47
- package/src/components/BoxPlot/BoxPlot.tsx +2 -1
- package/src/components/DeviationBar.jsx +2 -1
- package/src/components/EditorPanel/EditorPanel.tsx +60 -24
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +34 -34
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +51 -25
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +10 -3
- package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +4 -3
- package/src/components/EditorPanel/useEditorPermissions.ts +1 -4
- package/src/components/ForestPlot/ForestPlot.tsx +2 -2
- package/src/components/Legend/Legend.Component.tsx +69 -58
- package/src/components/Legend/Legend.Suppression.tsx +12 -22
- package/src/components/Legend/Legend.tsx +3 -1
- package/src/components/Legend/LegendGroup/LegendGroup.styles.css +40 -0
- package/src/components/Legend/LegendGroup/LegendGroup.tsx +103 -0
- package/src/components/Legend/LegendGroup/index.tsx +3 -0
- package/src/components/Legend/helpers/createFormatLabels.tsx +28 -0
- package/src/components/LineChart/LineChartProps.ts +3 -1
- package/src/components/LineChart/components/LineChart.Circle.tsx +77 -119
- package/src/components/LineChart/helpers.ts +133 -56
- package/src/components/LineChart/index.tsx +125 -60
- package/src/components/LinearChart.tsx +74 -115
- package/src/components/PairedBarChart.jsx +3 -2
- package/src/components/PieChart/PieChart.tsx +71 -91
- package/src/components/ScatterPlot/ScatterPlot.jsx +5 -0
- package/src/components/Sparkline/components/SparkLine.tsx +80 -18
- package/src/components/ZoomBrush.tsx +4 -4
- package/src/data/initial-state.js +4 -2
- package/src/helpers/countNumOfTicks.ts +1 -1
- package/src/helpers/dataHelpers.ts +31 -0
- package/src/helpers/sizeHelpers.ts +23 -0
- package/src/hooks/useMinMax.ts +21 -28
- package/src/hooks/useRightAxis.ts +4 -2
- package/src/hooks/useScales.ts +12 -14
- package/src/hooks/useTooltip.tsx +204 -203
- package/src/index.jsx +2 -2
- package/src/scss/main.scss +13 -6
- package/src/store/chart.actions.ts +1 -1
- package/src/types/ChartConfig.ts +7 -1
- package/LICENSE +0 -201
- package/examples/private/DEV-8850-2.json +0 -493
- package/examples/private/DEV-9822.json +0 -574
- package/examples/private/DEV-9840.json +0 -553
- package/examples/private/DEV-9850-3.json +0 -461
- package/examples/private/chart.json +0 -1084
- package/examples/private/ci_formatted.json +0 -202
- package/examples/private/ci_issue.json +0 -3016
- package/examples/private/completed.json +0 -634
- package/examples/private/dem-data-long.csv +0 -20
- package/examples/private/dem-data-long.json +0 -36
- package/examples/private/demographic_data.csv +0 -157
- package/examples/private/demographic_data.json +0 -2654
- package/examples/private/demographic_dynamic.json +0 -443
- package/examples/private/demographic_standard.json +0 -560
- package/examples/private/ehdi.json +0 -29939
- package/examples/private/not-loading.json +0 -360
- package/examples/private/test.json +0 -493
|
@@ -18,17 +18,29 @@ type SparkLineProps = {
|
|
|
18
18
|
|
|
19
19
|
const SparkLine: React.FC<SparkLineProps> = props => {
|
|
20
20
|
const { width: parentWidth, height: parentHeight } = props
|
|
21
|
-
const {
|
|
21
|
+
const {
|
|
22
|
+
transformedData: data,
|
|
23
|
+
config,
|
|
24
|
+
parseDate,
|
|
25
|
+
formatDate,
|
|
26
|
+
seriesHighlight,
|
|
27
|
+
formatNumber,
|
|
28
|
+
colorScale,
|
|
29
|
+
handleChartAriaLabels
|
|
30
|
+
} = useContext(ConfigContext)
|
|
22
31
|
let width = Number(parentWidth)
|
|
23
32
|
const { minValue, maxValue } = useReduceData(config, data, ConfigContext)
|
|
24
33
|
|
|
25
|
-
const margin = { top: 5, right:
|
|
34
|
+
const margin = { top: 5, right: 20, bottom: 10, left: 10 }
|
|
26
35
|
const height = Number(parentHeight)
|
|
27
36
|
|
|
28
37
|
const xMax = width - config.runtime.yAxis.size
|
|
29
38
|
const yMax = height - margin.top - 20
|
|
30
39
|
|
|
31
|
-
const getXAxisData = d =>
|
|
40
|
+
const getXAxisData = d =>
|
|
41
|
+
config.runtime.xAxis.type === 'date'
|
|
42
|
+
? parseDate(d[config.runtime.originalXAxis.dataKey]).getTime()
|
|
43
|
+
: d[config.runtime.originalXAxis.dataKey]
|
|
32
44
|
const getYAxisData = (d, seriesKey) => d[seriesKey]
|
|
33
45
|
|
|
34
46
|
let xScale
|
|
@@ -61,7 +73,10 @@ const SparkLine: React.FC<SparkLineProps> = props => {
|
|
|
61
73
|
range: [0, xMax]
|
|
62
74
|
})
|
|
63
75
|
|
|
64
|
-
yScale =
|
|
76
|
+
yScale =
|
|
77
|
+
config.runtime.xAxis.type === 'date'
|
|
78
|
+
? scaleLinear({ domain: [Math.min(...xAxisDataMapped), Math.max(...xAxisDataMapped)] })
|
|
79
|
+
: scalePoint({ domain: xAxisDataMapped, padding: 0.5 })
|
|
65
80
|
|
|
66
81
|
seriesScale = scalePoint({
|
|
67
82
|
domain: config.runtime.barSeriesKeys || config.runtime.seriesKeys,
|
|
@@ -94,7 +109,14 @@ const SparkLine: React.FC<SparkLineProps> = props => {
|
|
|
94
109
|
|
|
95
110
|
return (
|
|
96
111
|
<ErrorBoundary component='SparkLine'>
|
|
97
|
-
<svg
|
|
112
|
+
<svg
|
|
113
|
+
role='img'
|
|
114
|
+
aria-label={handleChartAriaLabels(config)}
|
|
115
|
+
width={parentWidth}
|
|
116
|
+
height={100}
|
|
117
|
+
className={'sparkline'}
|
|
118
|
+
tabIndex={0}
|
|
119
|
+
>
|
|
98
120
|
<title>{`Spark line graphic with the title ${config.title ? config.title : 'No Title Found'}`}</title>
|
|
99
121
|
{config.runtime.lineSeriesKeys?.length > 0
|
|
100
122
|
? config.runtime.lineSeriesKeys
|
|
@@ -104,30 +126,70 @@ const SparkLine: React.FC<SparkLineProps> = props => {
|
|
|
104
126
|
style={{ width }}
|
|
105
127
|
className='sparkline-group'
|
|
106
128
|
key={`series-${seriesKey}`}
|
|
107
|
-
opacity={
|
|
108
|
-
|
|
129
|
+
opacity={
|
|
130
|
+
config.legend.behavior === 'highlight' &&
|
|
131
|
+
seriesHighlight.length > 0 &&
|
|
132
|
+
seriesHighlight.indexOf(seriesKey) === -1
|
|
133
|
+
? 0.5
|
|
134
|
+
: 1
|
|
135
|
+
}
|
|
136
|
+
display={
|
|
137
|
+
config.legend.behavior === 'highlight' ||
|
|
138
|
+
seriesHighlight.length === 0 ||
|
|
139
|
+
seriesHighlight.indexOf(seriesKey) !== -1
|
|
140
|
+
? 'block'
|
|
141
|
+
: 'none'
|
|
142
|
+
}
|
|
109
143
|
>
|
|
110
|
-
{config.labels &&
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
144
|
+
{config.labels &&
|
|
145
|
+
data.map((d, dataIndex) => {
|
|
146
|
+
return (
|
|
147
|
+
<Group key={`series-${seriesKey}-point-${dataIndex}`}>
|
|
148
|
+
<Text
|
|
149
|
+
x={xScale(getXAxisData(d))}
|
|
150
|
+
y={yScale(getYAxisData(d, seriesKey))}
|
|
151
|
+
fill={
|
|
152
|
+
colorScale
|
|
153
|
+
? colorScale(
|
|
154
|
+
config.runtime.seriesLabels ? config.runtime.seriesLabels[seriesKey] : seriesKey
|
|
155
|
+
)
|
|
156
|
+
: '#000'
|
|
157
|
+
}
|
|
158
|
+
textAnchor='middle'
|
|
159
|
+
>
|
|
160
|
+
{formatNumber(d[seriesKey])}
|
|
161
|
+
</Text>
|
|
162
|
+
</Group>
|
|
163
|
+
)
|
|
164
|
+
})}
|
|
119
165
|
<LinePath
|
|
120
166
|
curve={allCurves.curveLinear}
|
|
121
167
|
data={data}
|
|
122
168
|
x={d => xScale(getXAxisData(d))}
|
|
123
169
|
y={d => yScale(getYAxisData(d, seriesKey))}
|
|
124
|
-
stroke={
|
|
170
|
+
stroke={
|
|
171
|
+
colorScale
|
|
172
|
+
? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[seriesKey] : seriesKey)
|
|
173
|
+
: '#000'
|
|
174
|
+
}
|
|
125
175
|
strokeWidth={2}
|
|
126
176
|
strokeOpacity={1}
|
|
127
177
|
shapeRendering='geometricPrecision'
|
|
128
178
|
markerEnd={`url(#${'arrow'}--${index})`}
|
|
129
179
|
/>
|
|
130
|
-
<MarkerArrow
|
|
180
|
+
<MarkerArrow
|
|
181
|
+
id={`arrow--${index}`}
|
|
182
|
+
refX={2}
|
|
183
|
+
size={6}
|
|
184
|
+
markerEnd={`url(#${'arrow'}--${index})`}
|
|
185
|
+
strokeOpacity={1}
|
|
186
|
+
fillOpacity={1}
|
|
187
|
+
fill={
|
|
188
|
+
colorScale
|
|
189
|
+
? colorScale(config.runtime.seriesLabels ? config.runtime.seriesLabels[seriesKey] : seriesKey)
|
|
190
|
+
: '#000'
|
|
191
|
+
}
|
|
192
|
+
/>
|
|
131
193
|
</Group>
|
|
132
194
|
<AxisBottom
|
|
133
195
|
top={yMax + margin.top}
|
|
@@ -7,7 +7,7 @@ import { ScaleLinear, ScaleBand } from 'd3-scale'
|
|
|
7
7
|
import { isDateScale } from '@cdc/core/helpers/cove/date'
|
|
8
8
|
import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
|
|
9
9
|
import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
|
|
10
|
-
import {
|
|
10
|
+
import { APP_FONT_SIZE } from '@cdc/core/helpers/constants'
|
|
11
11
|
|
|
12
12
|
interface Props {
|
|
13
13
|
xScaleBrush: ScaleLinear<number, number>
|
|
@@ -210,7 +210,7 @@ const BrushHandle = props => {
|
|
|
210
210
|
const transform = isLeft ? 'scale(-1, 1)' : 'translate(0,0)'
|
|
211
211
|
const textAnchor = isLeft ? 'end' : 'start'
|
|
212
212
|
const tooltipText = isLeft ? ` Drag edges to focus on a specific segment ` : ''
|
|
213
|
-
const textWidth = getTextWidth(tooltipText, `${
|
|
213
|
+
const textWidth = getTextWidth(tooltipText, `${APP_FONT_SIZE / 1.1}px`)
|
|
214
214
|
|
|
215
215
|
return (
|
|
216
216
|
<>
|
|
@@ -219,7 +219,7 @@ const BrushHandle = props => {
|
|
|
219
219
|
x={(Number(textProps.xMax) - textWidth) / 2}
|
|
220
220
|
dy={-12}
|
|
221
221
|
pointerEvents='visiblePainted'
|
|
222
|
-
fontSize={
|
|
222
|
+
fontSize={APP_FONT_SIZE / 1.1}
|
|
223
223
|
>
|
|
224
224
|
{tooltipText}
|
|
225
225
|
</Text>
|
|
@@ -232,7 +232,7 @@ const BrushHandle = props => {
|
|
|
232
232
|
y={25}
|
|
233
233
|
verticalAnchor='start'
|
|
234
234
|
textAnchor={textAnchor}
|
|
235
|
-
fontSize={
|
|
235
|
+
fontSize={APP_FONT_SIZE / 1.4}
|
|
236
236
|
>
|
|
237
237
|
{isLeft ? textProps.startValue : textProps.endValue}
|
|
238
238
|
</Text>
|
|
@@ -24,7 +24,6 @@ export default {
|
|
|
24
24
|
isResponsiveTicks: false,
|
|
25
25
|
general: {
|
|
26
26
|
annotationDropdownText: 'Annotations',
|
|
27
|
-
showDownloadButton: false,
|
|
28
27
|
showMissingDataLabel: true,
|
|
29
28
|
showSuppressedSymbol: true,
|
|
30
29
|
showZeroValueData: true,
|
|
@@ -166,13 +165,16 @@ export default {
|
|
|
166
165
|
seriesHighlight: [],
|
|
167
166
|
style: 'circles',
|
|
168
167
|
subStyle: 'linear blocks',
|
|
168
|
+
groupBy: '',
|
|
169
169
|
shape: 'circle',
|
|
170
170
|
tickRotation: '',
|
|
171
|
+
order: 'dataColumn',
|
|
171
172
|
hideBorder: {
|
|
172
173
|
side: false,
|
|
173
174
|
topBottom: true
|
|
174
175
|
},
|
|
175
|
-
position: 'right'
|
|
176
|
+
position: 'right',
|
|
177
|
+
orderedValues: []
|
|
176
178
|
},
|
|
177
179
|
brush: {
|
|
178
180
|
height: 45,
|
|
@@ -25,7 +25,7 @@ export const countNumOfTicks = ({ axis, max, runtime, currentViewport, isHorizon
|
|
|
25
25
|
}
|
|
26
26
|
if (Number(tickCount) > Number(max) && !isHorizontal) {
|
|
27
27
|
// cap it and round it so its an integer
|
|
28
|
-
tickCount = Number(min) < 0 ? Math.round(max) * 2 : Math.round(max)
|
|
28
|
+
tickCount = Math.max(2, Number(min) < 0 ? Math.round(max) * 2 : Math.round(max))
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Series } from '@cdc/core/types/Series'
|
|
2
|
+
import { ChartConfig } from '../types/ChartConfig'
|
|
3
|
+
|
|
4
|
+
export const getSeriesWithData = (config: ChartConfig) => {
|
|
5
|
+
const { filters, data, runtime, legend } = config
|
|
6
|
+
const { colorCode } = legend
|
|
7
|
+
const { series } = runtime
|
|
8
|
+
|
|
9
|
+
const filteredData = data.filter(d => filters.every(f => d[f.columnName] === f.active))
|
|
10
|
+
const colorCodeSeries = colorCode && Array.from(new Set(filteredData.map(d => d[colorCode])))
|
|
11
|
+
|
|
12
|
+
const result = series
|
|
13
|
+
.flatMap(s => {
|
|
14
|
+
if (!colorCode || s.type !== 'Bar') return s
|
|
15
|
+
return colorCodeSeries.map(c => ({ ...s, colorCodeSeries: c }))
|
|
16
|
+
})
|
|
17
|
+
.map(s => ({
|
|
18
|
+
...s,
|
|
19
|
+
data: filteredData
|
|
20
|
+
.filter(d => !s.dynamicCategory || d[s.dynamicCategory] === s.dataKey)
|
|
21
|
+
.filter(d => !s.colorCodeSeries || d[colorCode] === s.colorCodeSeries)
|
|
22
|
+
.filter(d => {
|
|
23
|
+
const key = s.dynamicCategory ? s.originalDataKey : s.dataKey
|
|
24
|
+
return d[key] || d[key] === 0
|
|
25
|
+
})
|
|
26
|
+
}))
|
|
27
|
+
.filter(s => s.data.length)
|
|
28
|
+
.map(s => s.colorCodeSeries || s.name || s.dataKey)
|
|
29
|
+
|
|
30
|
+
return result
|
|
31
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { clamp } from 'lodash'
|
|
2
|
+
|
|
1
3
|
import { isMobileHeightViewport } from '@cdc/core/helpers/viewports'
|
|
2
4
|
import { ChartConfig, ViewportSize } from '../types/ChartConfig'
|
|
5
|
+
import { EDITOR_WIDTH } from '@cdc/core/helpers/constants'
|
|
3
6
|
|
|
4
7
|
export function getOrientation(
|
|
5
8
|
{ orientation, heights, visualizationType }: Pick<ChartConfig, 'orientation' | 'heights' | 'visualizationType'>,
|
|
@@ -23,3 +26,23 @@ export function calcInitialHeight(
|
|
|
23
26
|
const height = Number(heights?.[renderedOrientation])
|
|
24
27
|
return isNaN(height) ? 0 : height
|
|
25
28
|
}
|
|
29
|
+
|
|
30
|
+
export function handleAutoPaddingRight(parentRef, xAxisLabelRefs, parentWidth): [boolean, number] {
|
|
31
|
+
const parentX = parentRef.current.getBoundingClientRect().x
|
|
32
|
+
const editorIsOpen = !!document.querySelector('.editor-panel:not(.hidden)')
|
|
33
|
+
const lastTickRect = xAxisLabelRefs.current?.[xAxisLabelRefs.current.length - 1]?.getBoundingClientRect()
|
|
34
|
+
const lastBottomTickEnd = lastTickRect ? lastTickRect.x + lastTickRect.width : 0
|
|
35
|
+
const editorWidth = editorIsOpen ? EDITOR_WIDTH : 0
|
|
36
|
+
const calculatedOverhang = lastBottomTickEnd - parentX - editorWidth - parentWidth
|
|
37
|
+
|
|
38
|
+
const paddingToAdd = clamp(calculatedOverhang, 0, 20)
|
|
39
|
+
const currentPadding = Number(parentRef.current.style.paddingRight.replace('px', ''))
|
|
40
|
+
const paddingDiff = Math.abs(currentPadding - paddingToAdd)
|
|
41
|
+
const DIFF_THRESHOLD = 5
|
|
42
|
+
|
|
43
|
+
const noChange = currentPadding === calculatedOverhang
|
|
44
|
+
const insufficientDiff = (paddingDiff < DIFF_THRESHOLD && calculatedOverhang > 0) || Math.abs(calculatedOverhang) < 1
|
|
45
|
+
const updatePadding = !noChange && !insufficientDiff
|
|
46
|
+
|
|
47
|
+
return [updatePadding, paddingToAdd]
|
|
48
|
+
}
|
package/src/hooks/useMinMax.ts
CHANGED
|
@@ -46,7 +46,6 @@ const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAll
|
|
|
46
46
|
|
|
47
47
|
min = enteredMinValue && isMinValid ? Number(enteredMinValue) : minValue
|
|
48
48
|
max = enteredMaxValue && isMaxValid ? Number(enteredMaxValue) : Number.MIN_VALUE
|
|
49
|
-
|
|
50
49
|
const { lower, upper } = config?.confidenceKeys || {}
|
|
51
50
|
|
|
52
51
|
if (lower && upper && config.visualizationType === 'Bar') {
|
|
@@ -167,35 +166,28 @@ const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAll
|
|
|
167
166
|
}
|
|
168
167
|
|
|
169
168
|
if (config.visualizationType === 'Line' && !convertLineToBarGraph) {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
// Return true if the value matches and it's either the first or the last item
|
|
186
|
-
return valueMatch && (index === 0 || index === tableData.length - 1)
|
|
169
|
+
const numEnteredMin = Number(enteredMinValue)
|
|
170
|
+
const isMinValid = isLogarithmicAxis ? numEnteredMin >= 0 && numEnteredMin < minValue : numEnteredMin < minValue
|
|
171
|
+
|
|
172
|
+
const suppressedMinValue = tableData?.some((item, i, arr) =>
|
|
173
|
+
config.preliminaryData?.some(({ type, style, column, value }) => {
|
|
174
|
+
if (type !== 'suppression' || !style) return false
|
|
175
|
+
|
|
176
|
+
const values = _.values(_.pick(item, config.runtime?.seriesKeys))
|
|
177
|
+
const dynamicCategory = config.series[0].dynamicCategory
|
|
178
|
+
|
|
179
|
+
const match = column ? item[column] === value : values.includes(value)
|
|
180
|
+
const dynamic = dynamicCategory && (item[dynamicCategory] === column || !column)
|
|
181
|
+
|
|
182
|
+
return (match || dynamic) && (i === 0 || i === arr.length - 1)
|
|
187
183
|
})
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
: suppressedMinValue
|
|
194
|
-
? 0
|
|
195
|
-
: isCategoricalAxis
|
|
196
|
-
? 0
|
|
197
|
-
: minValue
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
const isCategorical = config.yAxis.type === 'categorical'
|
|
187
|
+
|
|
188
|
+
min = enteredMinValue !== '' && isMinValid ? numEnteredMin : suppressedMinValue ? 0 : isCategorical ? 0 : minValue
|
|
198
189
|
}
|
|
190
|
+
|
|
199
191
|
//If data value max wasn't provided, calculate it
|
|
200
192
|
if (max === Number.MIN_VALUE) {
|
|
201
193
|
// if all values in data are negative set max = 0
|
|
@@ -241,6 +233,7 @@ const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAll
|
|
|
241
233
|
|
|
242
234
|
if (config.visualizationType === 'Scatter Plot') {
|
|
243
235
|
max = max * 1.1
|
|
236
|
+
min = min / 1.1
|
|
244
237
|
}
|
|
245
238
|
|
|
246
239
|
return { min, max, leftMax, rightMax }
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { scaleLinear } from '@visx/scale'
|
|
2
2
|
import useReduceData from './useReduceData'
|
|
3
|
+
import { TOP_PADDING } from './useScales'
|
|
3
4
|
|
|
4
5
|
export default function useRightAxis({ config, yMax = 0, data = [], updateConfig }) {
|
|
5
6
|
const hasRightAxis = config.visualizationType === 'Combo' && config.orientation === 'vertical'
|
|
6
|
-
const rightSeriesKeys =
|
|
7
|
+
const rightSeriesKeys =
|
|
8
|
+
config.series && config.series.filter(series => series.axis === 'Right').map(key => key.dataKey)
|
|
7
9
|
let { minValue } = useReduceData(config, data)
|
|
8
10
|
|
|
9
11
|
const allRightAxisData = rightSeriesKeys => {
|
|
@@ -35,7 +37,7 @@ export default function useRightAxis({ config, yMax = 0, data = [], updateConfig
|
|
|
35
37
|
|
|
36
38
|
const yScaleRight = scaleLinear({
|
|
37
39
|
domain: [minValue, max],
|
|
38
|
-
range: [yMax,
|
|
40
|
+
range: [yMax, TOP_PADDING]
|
|
39
41
|
})
|
|
40
42
|
|
|
41
43
|
return { yScaleRight, hasRightAxis }
|
package/src/hooks/useScales.ts
CHANGED
|
@@ -22,6 +22,8 @@ const scaleTypes = {
|
|
|
22
22
|
BAND: 'band'
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
export const TOP_PADDING = 10
|
|
26
|
+
|
|
25
27
|
type useScaleProps = {
|
|
26
28
|
config: ChartConfig // standard chart config
|
|
27
29
|
data: Object[] // standard data array
|
|
@@ -80,11 +82,13 @@ const useScales = (properties: useScaleProps) => {
|
|
|
80
82
|
if (xAxis.type === 'date-time' || xAxis.type === 'continuous') {
|
|
81
83
|
let xAxisMin = Math.min(...xAxisDataMapped.map(Number))
|
|
82
84
|
let xAxisMax = Math.max(...xAxisDataMapped.map(Number))
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
let paddingRatio = config.xAxis.padding ? config.xAxis.padding * 0.01 : 0
|
|
86
|
+
if (config.brush.active) {
|
|
87
|
+
paddingRatio = config.barThickness * 0.2
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
xAxisMin -= paddingRatio * (xAxisMax - xAxisMin)
|
|
91
|
+
xAxisMax += visualizationType === 'Line' ? 0 : paddingRatio * (xAxisMax - xAxisMin)
|
|
88
92
|
const range = config.xAxis.sortByRecentDate ? [xMax, 0] : [0, xMax]
|
|
89
93
|
xScale = scaleTime({
|
|
90
94
|
domain: [xAxisMin, xAxisMax],
|
|
@@ -137,14 +141,8 @@ const useScales = (properties: useScaleProps) => {
|
|
|
137
141
|
xScale.type = scaleTypes.LINEAR
|
|
138
142
|
}
|
|
139
143
|
if (xAxis.type === 'categorical') {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const strItem = String(item)
|
|
143
|
-
const parsed = parseFloat(strItem)
|
|
144
|
-
return !isNaN(parsed) ? Math.round(parsed).toString() : strItem
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
xScale = composeScaleBand(xAxisDataMappedRoundedItems, [0, xMax], 1 - config.barThickness)
|
|
144
|
+
xScale = composeScaleBand(xAxisDataMapped, [0, xMax], 1)
|
|
145
|
+
xScale.type = scaleTypes.BAND
|
|
148
146
|
}
|
|
149
147
|
}
|
|
150
148
|
|
|
@@ -398,7 +396,7 @@ const composeYScale = ({ min, max, yMax, config, leftMax }) => {
|
|
|
398
396
|
|
|
399
397
|
// If the visualization type is a bump chart then the domain and range need different values
|
|
400
398
|
const domainSet = config.visualizationType === 'Bump Chart' ? [1, max] : [min, max]
|
|
401
|
-
const yRange = config.visualizationType === 'Bump Chart' ? [30, yMax] : [yMax,
|
|
399
|
+
const yRange = config.visualizationType === 'Bump Chart' ? [30, yMax] : [yMax, TOP_PADDING]
|
|
402
400
|
// Return the configured scale function
|
|
403
401
|
return scaleFunc({
|
|
404
402
|
domain: domainSet,
|