@cdc/chart 4.24.5 → 4.24.9-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.js +50526 -42181
- package/examples/cases-year.json +13379 -0
- package/examples/feature/annotations/index.json +542 -0
- package/examples/gallery/bar-chart-vertical/combo-line-chart.json +76 -15
- package/examples/gallery/bar-chart-vertical/vertical-bar-chart-stacked.json +5 -5
- package/examples/xaxis.json +493 -0
- package/index.html +20 -10
- package/package.json +5 -4
- package/src/CdcChart.tsx +461 -172
- package/src/_stories/Chart.Legend.Gradient.tsx +19 -0
- package/src/_stories/Chart.stories.tsx +18 -171
- package/src/_stories/ChartAnnotation.stories.tsx +32 -0
- package/src/_stories/_mock/annotation_category_mock.json +473 -0
- package/src/_stories/_mock/annotation_date-linear_mock.json +530 -0
- package/{examples/feature/line/line-chart.json → src/_stories/_mock/annotation_date-time_mock.json} +150 -69
- package/src/_stories/_mock/legend.gradient_mock.json +236 -0
- package/src/_stories/_mock/line_chart_two_points_new_chart.json +128 -0
- package/src/_stories/_mock/line_chart_two_points_regression_test.json +127 -0
- package/src/_stories/_mock/lollipop.json +171 -0
- package/src/components/Annotations/components/AnnotationDraggable.styles.css +31 -0
- package/src/components/Annotations/components/AnnotationDraggable.tsx +207 -0
- package/src/components/Annotations/components/AnnotationDropdown.styles.css +14 -0
- package/src/components/Annotations/components/AnnotationDropdown.tsx +72 -0
- package/src/components/Annotations/components/AnnotationList.styles.css +45 -0
- package/src/components/Annotations/components/AnnotationList.tsx +42 -0
- package/src/components/Annotations/components/findNearestDatum.ts +138 -0
- package/src/components/Annotations/components/helpers/index.tsx +46 -0
- package/src/components/Annotations/index.tsx +13 -0
- package/src/components/AreaChart/components/AreaChart.Stacked.jsx +1 -1
- package/src/components/AreaChart/components/AreaChart.jsx +1 -1
- package/src/components/Axis/Categorical.Axis.tsx +145 -0
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +47 -44
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +0 -1
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +11 -14
- package/src/components/BarChart/components/BarChart.Vertical.tsx +67 -30
- package/src/components/BarChart/helpers/index.ts +91 -0
- package/src/components/BrushChart.tsx +205 -0
- package/src/components/EditorPanel/EditorPanel.tsx +1794 -403
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +320 -0
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +282 -18
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +43 -8
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +4 -4
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +4 -13
- package/src/components/EditorPanel/components/Panels/index.tsx +3 -1
- package/src/components/EditorPanel/components/panels.scss +4 -0
- package/src/components/EditorPanel/editor-panel.scss +35 -3
- package/src/components/EditorPanel/{useEditorPermissions.js → useEditorPermissions.ts} +105 -17
- package/src/components/Legend/Legend.Component.tsx +185 -194
- package/src/components/Legend/Legend.Suppression.tsx +146 -0
- package/src/components/Legend/Legend.tsx +21 -5
- package/src/components/Legend/helpers/createFormatLabels.tsx +1 -1
- package/src/components/Legend/helpers/index.ts +35 -0
- package/src/components/LegendWrapper.tsx +26 -0
- package/src/components/LineChart/LineChartProps.ts +1 -15
- package/src/components/LineChart/components/LineChart.BumpCircle.tsx +103 -0
- package/src/components/LineChart/components/LineChart.Circle.tsx +57 -8
- package/src/components/LineChart/helpers.ts +72 -14
- package/src/components/LineChart/index.tsx +117 -42
- package/src/components/LinearChart.tsx +1366 -0
- package/src/components/PairedBarChart.jsx +9 -9
- package/src/components/PieChart/PieChart.tsx +75 -18
- package/src/components/Sankey/index.tsx +89 -30
- package/src/components/ScatterPlot/ScatterPlot.jsx +22 -8
- package/src/components/Sparkline/components/SparkLine.tsx +2 -2
- package/src/components/ZoomBrush.tsx +90 -44
- package/src/data/initial-state.js +25 -7
- package/src/helpers/handleChartTabbing.ts +8 -0
- package/src/helpers/isConvertLineToBarGraph.ts +4 -0
- package/src/hooks/{useBarChart.js → useBarChart.ts} +2 -40
- package/src/hooks/useColorScale.ts +1 -1
- package/src/hooks/useLegendClasses.ts +68 -0
- package/src/hooks/useMinMax.ts +12 -7
- package/src/hooks/useScales.ts +58 -26
- package/src/hooks/useTooltip.tsx +135 -25
- package/src/scss/DataTable.scss +2 -1
- package/src/scss/main.scss +128 -28
- package/src/types/ChartConfig.ts +83 -10
- package/src/types/ChartContext.ts +14 -4
- package/tests-examples/helpers/testZeroValue.test.ts +30 -0
- package/src/components/BrushHandle.jsx +0 -17
- package/src/components/LineChart/index.scss +0 -1
- package/src/components/LinearChart.jsx +0 -774
- package/src/helpers/filterData.ts +0 -18
- package/src/helpers/tests/computeMarginBottom.test.ts +0 -21
- package/src/hooks/useLegendClasses.js +0 -31
- /package/src/hooks/{useReduceData.js → useReduceData.ts} +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React, { useContext } from 'react'
|
|
2
|
+
import ConfigContext from '../ConfigContext'
|
|
3
|
+
|
|
4
|
+
type LegendWrapperProps = {
|
|
5
|
+
children: React.ReactNode
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const LegendWrapper: React.FC<LegendWrapperProps> = props => {
|
|
9
|
+
const { children } = props
|
|
10
|
+
|
|
11
|
+
const { config, currentViewport } = useContext(ConfigContext)
|
|
12
|
+
|
|
13
|
+
const getLegendWrappingClasses = () => {
|
|
14
|
+
let classes = ['legend-wrapper', 'd-flex', 'flex-nowrap', 'w-100']
|
|
15
|
+
const { legend } = config
|
|
16
|
+
if (legend.position === 'bottom' || legend.position === 'top' || ['xxs', 'xs', 'sm'].includes(currentViewport)) {
|
|
17
|
+
classes = classes.filter(item => item !== 'flex-nowrap')
|
|
18
|
+
classes.push('flex-wrap')
|
|
19
|
+
}
|
|
20
|
+
return classes.join(' ')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return <div className={getLegendWrappingClasses()}>{...children}</div>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default LegendWrapper
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// todo: review tooltipData type
|
|
2
2
|
// todo: review svgRef type
|
|
3
|
+
import { type PreliminaryDataItem } from '../../types/ChartConfig'
|
|
3
4
|
export type LineChartProps = {
|
|
4
5
|
xScale: Function
|
|
5
6
|
yScale: Function
|
|
@@ -16,21 +17,6 @@ export type LineChartProps = {
|
|
|
16
17
|
tooltipData: any
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export interface PreliminaryDataItem {
|
|
20
|
-
column: string
|
|
21
|
-
displayLegend: boolean
|
|
22
|
-
displayTable: boolean
|
|
23
|
-
displayTooltip: boolean
|
|
24
|
-
iconCode: string
|
|
25
|
-
label: string
|
|
26
|
-
lineCode: string
|
|
27
|
-
seriesKey: string
|
|
28
|
-
style: string
|
|
29
|
-
symbol: string
|
|
30
|
-
type: 'effect' | 'suppression'
|
|
31
|
-
value: string
|
|
32
|
-
}
|
|
33
|
-
|
|
34
20
|
export interface DataItem {
|
|
35
21
|
[key: string]: any
|
|
36
22
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { Group } from '@visx/group'
|
|
3
|
+
import { type Column } from '@cdc/core/types/Column'
|
|
4
|
+
import React from 'react'
|
|
5
|
+
import { type ChartConfig } from '../../../types/ChartConfig'
|
|
6
|
+
|
|
7
|
+
type LineChartBumpCircleProp = {
|
|
8
|
+
config: ChartConfig,
|
|
9
|
+
xScale: any,
|
|
10
|
+
yScale: any,
|
|
11
|
+
parseDate: any
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const LineChartBumpCircle = (props: LineChartBumpCircleProp) => {
|
|
15
|
+
const { config, xScale, yScale, parseDate } = props
|
|
16
|
+
|
|
17
|
+
// get xScale and yScale...
|
|
18
|
+
if (!config?.runtime?.series) return
|
|
19
|
+
|
|
20
|
+
const handleX = xValue => {
|
|
21
|
+
if (config.xAxis.type === 'date') {
|
|
22
|
+
return parseDate(xValue).getTime()
|
|
23
|
+
}
|
|
24
|
+
if (config.xAxis.type === 'date-time') {
|
|
25
|
+
return new Date(xValue)
|
|
26
|
+
}
|
|
27
|
+
if (config.xAxis.type === 'categorical') {
|
|
28
|
+
return xValue
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const checkBandScale = xValue => {
|
|
33
|
+
return xScale.bandwidth ? xScale.bandwidth() / 2 + Number(xValue) : Number(xValue)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
const getListItems = dataRow => {
|
|
38
|
+
return Object.values(config.columns)
|
|
39
|
+
?.filter(column => column.tooltips).map(column => {
|
|
40
|
+
const label = column.label || column.name;
|
|
41
|
+
return `
|
|
42
|
+
<li className='tooltip-body'>
|
|
43
|
+
<strong>${label}</strong>: ${dataRow[column.name]}
|
|
44
|
+
</li>`;
|
|
45
|
+
})
|
|
46
|
+
.join(' ');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const getTooltip = dataRow => `<ul> ${getListItems(dataRow)} </ul>`
|
|
50
|
+
|
|
51
|
+
const circles = config.runtime?.series.map((series) => {
|
|
52
|
+
return config.data.map((d, dataIndex) => {
|
|
53
|
+
let series_dataKey = d[series.dataKey]
|
|
54
|
+
let axis_dataKey = d[config.xAxis.dataKey]
|
|
55
|
+
return (
|
|
56
|
+
<React.Fragment key={`bump-circle-${series_dataKey}-${dataIndex}`}>
|
|
57
|
+
<Group left={Number(config.runtime.yAxis.size)}>
|
|
58
|
+
{series_dataKey && (
|
|
59
|
+
<>
|
|
60
|
+
<circle
|
|
61
|
+
key={`bump-circle-${series_dataKey}-${dataIndex}`}
|
|
62
|
+
data-tooltip-html={getTooltip(d)}
|
|
63
|
+
data-tooltip-id={`bump-chart`}
|
|
64
|
+
r={10}
|
|
65
|
+
cx={Number(checkBandScale(xScale(handleX(axis_dataKey))))}
|
|
66
|
+
cy={Number(yScale(series_dataKey))}
|
|
67
|
+
stroke='#CACACA'
|
|
68
|
+
strokeWidth={1}
|
|
69
|
+
fill='#E5E4E2'
|
|
70
|
+
/>
|
|
71
|
+
{series_dataKey.toString().length === 2 ? (
|
|
72
|
+
// prettier-ignore
|
|
73
|
+
<text
|
|
74
|
+
x={Number(checkBandScale(xScale(handleX(axis_dataKey)))) - 7}
|
|
75
|
+
y={Number(yScale(series_dataKey)) + 4}
|
|
76
|
+
fill='#000000'
|
|
77
|
+
fontSize={11.5}
|
|
78
|
+
>
|
|
79
|
+
{series_dataKey}
|
|
80
|
+
</text>
|
|
81
|
+
) : (
|
|
82
|
+
// prettier-ignore
|
|
83
|
+
<text
|
|
84
|
+
x={Number(checkBandScale(xScale(handleX(axis_dataKey)))) - 4}
|
|
85
|
+
y={Number(yScale(series_dataKey)) + 4}
|
|
86
|
+
fill='#000000'
|
|
87
|
+
fontSize={11.5}
|
|
88
|
+
>
|
|
89
|
+
{series_dataKey}
|
|
90
|
+
</text>
|
|
91
|
+
)}
|
|
92
|
+
</>
|
|
93
|
+
)}
|
|
94
|
+
</Group>
|
|
95
|
+
</React.Fragment>
|
|
96
|
+
)
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
return <>{circles}</>
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export default LineChartBumpCircle
|
|
@@ -27,11 +27,33 @@ type LineChartCircleProps = {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const LineChartCircle = (props: LineChartCircleProps) => {
|
|
30
|
-
const {
|
|
30
|
+
const {
|
|
31
|
+
config,
|
|
32
|
+
d,
|
|
33
|
+
tableData,
|
|
34
|
+
displayArea,
|
|
35
|
+
seriesKey,
|
|
36
|
+
tooltipData,
|
|
37
|
+
xScale,
|
|
38
|
+
yScale,
|
|
39
|
+
colorScale,
|
|
40
|
+
parseDate,
|
|
41
|
+
yScaleRight,
|
|
42
|
+
data,
|
|
43
|
+
circleData,
|
|
44
|
+
dataIndex,
|
|
45
|
+
mode
|
|
46
|
+
} = props
|
|
31
47
|
const { lineDatapointStyle } = config
|
|
32
|
-
const filtered = config?.series.filter(s => s.dataKey === seriesKey)?.[0]
|
|
48
|
+
const filtered = config?.runtime?.series.filter(s => s.dataKey === seriesKey)?.[0]
|
|
33
49
|
// If we're not showing the circle, simply return
|
|
34
|
-
const getColor = (
|
|
50
|
+
const getColor = (
|
|
51
|
+
displayArea: boolean,
|
|
52
|
+
colorScale: Function,
|
|
53
|
+
config: ChartConfig,
|
|
54
|
+
hoveredKey: string,
|
|
55
|
+
seriesKey: string
|
|
56
|
+
) => {
|
|
35
57
|
const seriesLabels = config.runtime.seriesLabels || []
|
|
36
58
|
let color
|
|
37
59
|
|
|
@@ -47,14 +69,19 @@ const LineChartCircle = (props: LineChartCircleProps) => {
|
|
|
47
69
|
return color
|
|
48
70
|
}
|
|
49
71
|
const getXPos = hoveredXValue => {
|
|
50
|
-
return (
|
|
72
|
+
return (
|
|
73
|
+
(config.xAxis.type === 'categorical' ? xScale(hoveredXValue) : xScale(parseDate(hoveredXValue))) +
|
|
74
|
+
(xScale.bandwidth ? xScale.bandwidth() / 2 : 0)
|
|
75
|
+
)
|
|
51
76
|
}
|
|
52
77
|
if (mode === 'ALWAYS_SHOW_POINTS') {
|
|
53
78
|
if (lineDatapointStyle === 'hidden') return <></>
|
|
54
79
|
const getIndex = seriesKey => config.runtime.seriesLabelsAll.indexOf(seriesKey)
|
|
55
80
|
|
|
56
81
|
if (lineDatapointStyle === 'always show') {
|
|
57
|
-
const isMatch = circleData?.some(
|
|
82
|
+
const isMatch = circleData?.some(
|
|
83
|
+
cd => cd[config.xAxis.dataKey] === d[config.xAxis.dataKey] && cd[seriesKey] === d[seriesKey]
|
|
84
|
+
)
|
|
58
85
|
if (isMatch) {
|
|
59
86
|
return <></>
|
|
60
87
|
}
|
|
@@ -98,7 +125,7 @@ const LineChartCircle = (props: LineChartCircleProps) => {
|
|
|
98
125
|
if (isNaN(hoveredSeriesValue)) return <></>
|
|
99
126
|
const isMatch = circleData?.some(cd => cd[config.xAxis.dataKey] === hoveredXValue)
|
|
100
127
|
|
|
101
|
-
if (isMatch) {
|
|
128
|
+
if (isMatch || !hoveredSeriesValue) {
|
|
102
129
|
return <></>
|
|
103
130
|
}
|
|
104
131
|
|
|
@@ -120,10 +147,17 @@ const LineChartCircle = (props: LineChartCircleProps) => {
|
|
|
120
147
|
|
|
121
148
|
if (mode === 'ISOLATED_POINTS') {
|
|
122
149
|
const drawIsolatedPoints = (currentIndex, seriesKey) => {
|
|
150
|
+
let isMatch = false
|
|
123
151
|
const currentPoint = data[currentIndex]
|
|
124
152
|
const previousPoint = currentIndex > 0 ? data[currentIndex - 1] : null
|
|
125
153
|
const nextPoint = currentIndex < data.length - 1 ? data[currentIndex + 1] : null
|
|
126
154
|
let res = false
|
|
155
|
+
// check if isolated points has overlap with circle effect
|
|
156
|
+
circleData.forEach(item => {
|
|
157
|
+
if (item?.data[seriesKey] === currentPoint[seriesKey]) {
|
|
158
|
+
isMatch = true
|
|
159
|
+
}
|
|
160
|
+
})
|
|
127
161
|
|
|
128
162
|
// Handle the first point in the array
|
|
129
163
|
if (currentIndex === 0 && nextPoint && !nextPoint[seriesKey]) {
|
|
@@ -135,10 +169,18 @@ const LineChartCircle = (props: LineChartCircleProps) => {
|
|
|
135
169
|
}
|
|
136
170
|
// Handle points in the middle
|
|
137
171
|
if (currentIndex > 0 && currentIndex < data.length - 1) {
|
|
138
|
-
if (
|
|
172
|
+
if (
|
|
173
|
+
currentPoint &&
|
|
174
|
+
currentPoint[seriesKey] &&
|
|
175
|
+
(!previousPoint || !previousPoint[seriesKey]) &&
|
|
176
|
+
(!nextPoint || !nextPoint[seriesKey])
|
|
177
|
+
) {
|
|
139
178
|
res = true
|
|
140
179
|
}
|
|
141
180
|
}
|
|
181
|
+
if (isMatch) {
|
|
182
|
+
res = false
|
|
183
|
+
}
|
|
142
184
|
|
|
143
185
|
return res
|
|
144
186
|
}
|
|
@@ -146,7 +188,14 @@ const LineChartCircle = (props: LineChartCircleProps) => {
|
|
|
146
188
|
if (mode) {
|
|
147
189
|
if (drawIsolatedPoints(dataIndex, seriesKey)) {
|
|
148
190
|
return (
|
|
149
|
-
<circle
|
|
191
|
+
<circle
|
|
192
|
+
cx={getXPos(d[config.xAxis?.dataKey])}
|
|
193
|
+
cy={filtered?.axis === 'Right' ? yScaleRight(d[filtered?.dataKey]) : yScale(d[filtered?.dataKey])}
|
|
194
|
+
r={5.3}
|
|
195
|
+
strokeWidth={2}
|
|
196
|
+
stroke={colorScale(config.runtime.seriesLabels[seriesKey])}
|
|
197
|
+
fill={colorScale(config.runtime?.seriesLabels[seriesKey])}
|
|
198
|
+
/>
|
|
150
199
|
)
|
|
151
200
|
}
|
|
152
201
|
}
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DataItem, StyleProps, Style } from './LineChartProps'
|
|
2
|
+
import { PreliminaryDataItem } from '../../types/ChartConfig'
|
|
2
3
|
import _ from 'lodash'
|
|
3
4
|
export const createStyles = (props: StyleProps): Style[] => {
|
|
4
5
|
const { preliminaryData, data, stroke, strokeWidth, handleLineType, lineType, seriesKey } = props
|
|
5
6
|
|
|
6
|
-
const validPreliminaryData: PreliminaryDataItem[] = preliminaryData.filter(
|
|
7
|
-
|
|
7
|
+
const validPreliminaryData: PreliminaryDataItem[] = preliminaryData.filter(
|
|
8
|
+
pd => pd.seriesKey && pd.column && pd.value && pd.type && pd.style && pd.type === 'effect'
|
|
9
|
+
)
|
|
10
|
+
const getMatchingPd = (point: DataItem): PreliminaryDataItem =>
|
|
11
|
+
validPreliminaryData.find(
|
|
12
|
+
pd =>
|
|
13
|
+
pd.seriesKey === seriesKey &&
|
|
14
|
+
point[pd.column] === pd.value &&
|
|
15
|
+
pd.type === 'effect' &&
|
|
16
|
+
pd.style !== 'Open Circles'
|
|
17
|
+
)
|
|
8
18
|
|
|
9
19
|
let styles: Style[] = []
|
|
10
20
|
const createStyle = (lineStyle): Style => ({
|
|
@@ -15,7 +25,9 @@ export const createStyles = (props: StyleProps): Style[] => {
|
|
|
15
25
|
|
|
16
26
|
data.forEach((d, index) => {
|
|
17
27
|
let matchingPd: PreliminaryDataItem = getMatchingPd(d)
|
|
18
|
-
let style: Style = matchingPd
|
|
28
|
+
let style: Style = matchingPd
|
|
29
|
+
? createStyle(handleLineType(matchingPd.style))
|
|
30
|
+
: createStyle(handleLineType(lineType))
|
|
19
31
|
|
|
20
32
|
styles.push(style)
|
|
21
33
|
|
|
@@ -27,18 +39,54 @@ export const createStyles = (props: StyleProps): Style[] => {
|
|
|
27
39
|
return styles as Style[]
|
|
28
40
|
}
|
|
29
41
|
|
|
30
|
-
export const filterCircles = (
|
|
42
|
+
export const filterCircles = (
|
|
43
|
+
preliminaryData: PreliminaryDataItem[],
|
|
44
|
+
data: DataItem[],
|
|
45
|
+
seriesKey: string
|
|
46
|
+
): DataItem[] => {
|
|
31
47
|
// Filter and map preliminaryData to get circlesFiltered
|
|
32
|
-
const circlesFiltered = preliminaryData
|
|
33
|
-
|
|
48
|
+
const circlesFiltered = preliminaryData
|
|
49
|
+
?.filter(item => item.style.includes('Circles') && item.type === 'effect')
|
|
50
|
+
.map(item => ({
|
|
51
|
+
column: item.column,
|
|
52
|
+
value: item.value,
|
|
53
|
+
seriesKey: item.seriesKey,
|
|
54
|
+
circleSize: item.circleSize,
|
|
55
|
+
style: item.style
|
|
56
|
+
}))
|
|
57
|
+
const filteredData = []
|
|
34
58
|
// Process data to find matching items
|
|
35
59
|
data.forEach(item => {
|
|
36
60
|
circlesFiltered.forEach(fc => {
|
|
37
|
-
if (
|
|
38
|
-
|
|
61
|
+
if (
|
|
62
|
+
item[fc.column] === fc.value &&
|
|
63
|
+
fc.seriesKey === seriesKey &&
|
|
64
|
+
item[seriesKey] &&
|
|
65
|
+
fc.style === 'Open Circles'
|
|
66
|
+
) {
|
|
67
|
+
const result = {
|
|
68
|
+
data: item,
|
|
69
|
+
size: fc.circleSize,
|
|
70
|
+
isFilled: false
|
|
71
|
+
}
|
|
72
|
+
filteredData.push(result)
|
|
73
|
+
}
|
|
74
|
+
if (
|
|
75
|
+
(!fc.value || item[fc.column] === fc.value) &&
|
|
76
|
+
fc.seriesKey === seriesKey &&
|
|
77
|
+
item[seriesKey] &&
|
|
78
|
+
fc.style === 'Filled Circles'
|
|
79
|
+
) {
|
|
80
|
+
const result = {
|
|
81
|
+
data: item,
|
|
82
|
+
size: fc.circleSize,
|
|
83
|
+
isFilled: true
|
|
84
|
+
}
|
|
85
|
+
filteredData.push(result)
|
|
39
86
|
}
|
|
40
87
|
})
|
|
41
88
|
})
|
|
89
|
+
|
|
42
90
|
return filteredData
|
|
43
91
|
}
|
|
44
92
|
|
|
@@ -56,8 +104,10 @@ const handleFirstIndex = (data, seriesKey, preliminaryData) => {
|
|
|
56
104
|
|
|
57
105
|
// Function to check if a data item matches the suppression criteria
|
|
58
106
|
const isSuppressed = pd => {
|
|
59
|
-
if (pd.type === 'effect') return
|
|
60
|
-
return
|
|
107
|
+
if (pd.type === 'effect' || pd.hideLineStyle) return
|
|
108
|
+
return (
|
|
109
|
+
pd.type == 'suppression' && pd.value === firstIndexDataItem[seriesKey] && (!pd.column || pd.column === seriesKey)
|
|
110
|
+
)
|
|
61
111
|
}
|
|
62
112
|
|
|
63
113
|
// Find applicable suppression data for the first item
|
|
@@ -93,7 +143,13 @@ const handleLastIndex = (data, seriesKey, preliminaryData) => {
|
|
|
93
143
|
let lastAddedIndex = -1 // Tracks the last index added to the result
|
|
94
144
|
preliminaryData?.forEach(pd => {
|
|
95
145
|
if (pd.type === 'effect') return
|
|
96
|
-
if (
|
|
146
|
+
if (
|
|
147
|
+
data[data.length - 1][seriesKey] === pd.value &&
|
|
148
|
+
pd.style &&
|
|
149
|
+
(!pd.column || pd.column === seriesKey) &&
|
|
150
|
+
pd.type == 'suppression' &&
|
|
151
|
+
!pd.hideLineStyle
|
|
152
|
+
) {
|
|
97
153
|
const lastIndex = data.length - 1
|
|
98
154
|
const modifiedItem = { ...data[lastIndex], [seriesKey]: 0 }
|
|
99
155
|
result.data.push(modifiedItem)
|
|
@@ -123,7 +179,7 @@ function handleMiddleIndices(data, seriesKey, dataKey, preliminaryData) {
|
|
|
123
179
|
const isValidMiddleIndex = index => index > 0 && index < data.length - 1
|
|
124
180
|
|
|
125
181
|
preliminaryData?.forEach(pd => {
|
|
126
|
-
if (pd.type === 'effect') return
|
|
182
|
+
if (pd.type === 'effect' || pd.hideLineStyle) return
|
|
127
183
|
const targetValue = pd.value
|
|
128
184
|
|
|
129
185
|
// Find all indices
|
|
@@ -143,7 +199,9 @@ function handleMiddleIndices(data, seriesKey, dataKey, preliminaryData) {
|
|
|
143
199
|
}
|
|
144
200
|
|
|
145
201
|
// Find and add the next calculable object
|
|
146
|
-
const nextIndex = data
|
|
202
|
+
const nextIndex = data
|
|
203
|
+
.slice(i + 1)
|
|
204
|
+
.findIndex(item => item[seriesKey] !== targetValue && isCalculable(item[seriesKey]))
|
|
147
205
|
if (nextIndex !== -1) {
|
|
148
206
|
result.data.push(data[i + 1 + nextIndex])
|
|
149
207
|
}
|