@cdc/chart 4.24.3 → 4.24.5
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 +34377 -33726
- package/examples/feature/line/line-chart.json +361 -37
- package/examples/region-issue.json +2065 -0
- package/examples/test.json +5409 -0
- package/index.html +13 -11
- package/package.json +2 -2
- package/src/CdcChart.tsx +159 -89
- package/src/_stories/Chart.stories.tsx +8 -0
- package/src/_stories/_mock/bar-chart-suppressed.json +474 -0
- package/src/components/AreaChart/components/AreaChart.jsx +2 -2
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +61 -63
- package/src/components/BarChart/components/BarChart.Vertical.tsx +79 -94
- package/src/components/DeviationBar.jsx +4 -2
- package/src/components/EditorPanel/EditorPanel.tsx +1580 -1924
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +19 -2
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +0 -1
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +4 -5
- package/src/components/EditorPanel/editor-panel.scss +0 -724
- package/src/components/EditorPanel/useEditorPermissions.js +4 -1
- package/src/components/Legend/Legend.Component.tsx +82 -58
- package/src/components/Legend/Legend.tsx +5 -1
- package/src/components/LineChart/LineChartProps.ts +13 -6
- package/src/components/LineChart/components/LineChart.Circle.tsx +22 -11
- package/src/components/LineChart/helpers.ts +134 -10
- package/src/components/LineChart/index.tsx +69 -42
- package/src/components/LinearChart.jsx +156 -139
- package/src/components/ZoomBrush.tsx +40 -21
- package/src/data/initial-state.js +4 -4
- package/src/hooks/useBarChart.js +47 -22
- package/src/hooks/useMinMax.ts +21 -2
- package/src/hooks/useScales.ts +33 -1
- package/src/hooks/useTooltip.tsx +11 -11
- package/src/scss/main.scss +80 -5
- package/src/types/ChartConfig.ts +3 -13
- package/src/types/ChartContext.ts +4 -0
- package/src/_stories/ChartLine.preliminary.tsx +0 -19
- package/src/_stories/ChartSuppress.stories.tsx +0 -19
- package/src/_stories/_mock/suppress_mock.json +0 -911
- package/src/helpers/computeMarginBottom.ts +0 -56
|
@@ -14,10 +14,9 @@ interface Props {
|
|
|
14
14
|
yMax: number
|
|
15
15
|
}
|
|
16
16
|
const ZoomBrush: FC<Props> = props => {
|
|
17
|
-
const {
|
|
17
|
+
const { tableData, config, parseDate, formatDate, setBrushConfig } = useContext(ConfigContext)
|
|
18
18
|
const { fontSize } = useBarChart()
|
|
19
|
-
|
|
20
|
-
const [filteredData, setFilteredData] = useState([...data])
|
|
19
|
+
const [brushKey, setBrushKey] = useState(0)
|
|
21
20
|
const brushRef = useRef(null)
|
|
22
21
|
const radius = 15
|
|
23
22
|
|
|
@@ -34,7 +33,7 @@ const ZoomBrush: FC<Props> = props => {
|
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
const style = {
|
|
37
|
-
fill: '#
|
|
36
|
+
fill: '#AFA6A5 ',
|
|
38
37
|
stroke: 'blue',
|
|
39
38
|
fillOpacity: 0.8,
|
|
40
39
|
strokeOpacity: 0,
|
|
@@ -42,13 +41,12 @@ const ZoomBrush: FC<Props> = props => {
|
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
const onBrushChange = event => {
|
|
45
|
-
if (!event) return
|
|
46
|
-
|
|
44
|
+
if (!event || !event.xValues) return
|
|
47
45
|
const { xValues } = event
|
|
48
46
|
|
|
49
47
|
const dataKey = config.xAxis?.dataKey
|
|
50
48
|
|
|
51
|
-
const
|
|
49
|
+
const brushedData = tableData.filter(item => xValues.includes(item[dataKey]))
|
|
52
50
|
|
|
53
51
|
const endValue = xValues
|
|
54
52
|
.slice()
|
|
@@ -66,26 +64,45 @@ const ZoomBrush: FC<Props> = props => {
|
|
|
66
64
|
startValue: formatIfDate(startValue)
|
|
67
65
|
}))
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
...config,
|
|
75
|
-
brush: {
|
|
76
|
-
...config.brush,
|
|
77
|
-
data: filteredData
|
|
67
|
+
setBrushConfig(prev => {
|
|
68
|
+
return {
|
|
69
|
+
...prev,
|
|
70
|
+
isBrushing: brushRef.current?.state.isBrushing,
|
|
71
|
+
data: brushedData
|
|
78
72
|
}
|
|
79
73
|
})
|
|
80
|
-
}
|
|
74
|
+
}
|
|
81
75
|
|
|
82
|
-
//reset filters if brush is off
|
|
83
76
|
useEffect(() => {
|
|
84
77
|
if (!config.brush.active) {
|
|
85
|
-
|
|
78
|
+
setBrushKey(prevKey => prevKey + 1)
|
|
79
|
+
setBrushConfig({
|
|
80
|
+
data: [],
|
|
81
|
+
isActive: false,
|
|
82
|
+
isBrushing: false
|
|
83
|
+
})
|
|
86
84
|
}
|
|
87
85
|
}, [config.brush.active])
|
|
88
86
|
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (config.filters?.some(filter => filter.active)) {
|
|
89
|
+
setBrushKey(prevKey => prevKey + 1)
|
|
90
|
+
setBrushConfig(prev => {
|
|
91
|
+
return {
|
|
92
|
+
...prev,
|
|
93
|
+
data: tableData
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
return () =>
|
|
98
|
+
setBrushConfig(prev => {
|
|
99
|
+
return {
|
|
100
|
+
...prev,
|
|
101
|
+
data: []
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
}, [config.filters])
|
|
105
|
+
|
|
89
106
|
const calculateTop = (): number => {
|
|
90
107
|
const tickRotation = Number(config.xAxis.tickRotation) > 0 ? Number(config.xAxis.tickRotation) : 0
|
|
91
108
|
let top = 0
|
|
@@ -123,10 +140,12 @@ const ZoomBrush: FC<Props> = props => {
|
|
|
123
140
|
if (!['Line', 'Bar', 'Area Chart', 'Combo'].includes(config.visualizationType)) {
|
|
124
141
|
return
|
|
125
142
|
}
|
|
143
|
+
|
|
126
144
|
return (
|
|
127
145
|
<Group display={config.brush.active ? 'block' : 'none'} top={Number(props.yMax) + calculateTop()} left={Number(config.runtime.yAxis.size)} pointerEvents='fill'>
|
|
128
|
-
<rect fill='#
|
|
146
|
+
<rect fill='#F7F7F7 ' width={props.xMax} height={config.brush.height} rx={radius} />
|
|
129
147
|
<Brush
|
|
148
|
+
key={brushKey}
|
|
130
149
|
renderBrushHandle={props => <BrushHandle textProps={textProps} fontSize={fontSize[config.fontSize]} {...props} isBrushing={brushRef.current?.state.isBrushing} />}
|
|
131
150
|
innerRef={brushRef}
|
|
132
151
|
useWindowMoveEvents={true}
|
|
@@ -161,7 +180,7 @@ const BrushHandle = props => {
|
|
|
161
180
|
<Text pointerEvents='visiblePainted' dominantBaseline='hanging' x={0} verticalAnchor='start' textAnchor={textAnchor} fontSize={props.fontSize / 1.4} dy={10} y={15}>
|
|
162
181
|
{isLeft ? textProps.startValue : textProps.endValue}
|
|
163
182
|
</Text>
|
|
164
|
-
<path cursor='ew-resize' d='M0.5,10A6,6 0 0 1 6.5,16V14A6,6 0 0 1 0.5,20ZM2.5,18V12M4.5,18V12' fill={!isBrushing ? '#
|
|
183
|
+
<path cursor='ew-resize' d='M0.5,10A6,6 0 0 1 6.5,16V14A6,6 0 0 1 0.5,20ZM2.5,18V12M4.5,18V12' fill={!isBrushing ? '#000' : '#297EF1'} strokeWidth='1' transform={transform}></path>
|
|
165
184
|
</Group>
|
|
166
185
|
)
|
|
167
186
|
}
|
|
@@ -28,9 +28,7 @@ export default {
|
|
|
28
28
|
left: 5,
|
|
29
29
|
right: 5
|
|
30
30
|
},
|
|
31
|
-
suppressedData: [],
|
|
32
31
|
preliminaryData: [],
|
|
33
|
-
|
|
34
32
|
yAxis: {
|
|
35
33
|
hideAxis: false,
|
|
36
34
|
displayNumbersOnBar: false,
|
|
@@ -118,7 +116,9 @@ export default {
|
|
|
118
116
|
labelOffset: 65,
|
|
119
117
|
axisPadding: 200,
|
|
120
118
|
target: 0,
|
|
121
|
-
maxTickRotation: 0
|
|
119
|
+
maxTickRotation: 0,
|
|
120
|
+
showSuppressedSymbol: true,
|
|
121
|
+
showSuppressedLine: true
|
|
122
122
|
},
|
|
123
123
|
table: {
|
|
124
124
|
label: 'Data Table',
|
|
@@ -154,11 +154,11 @@ export default {
|
|
|
154
154
|
lineMode: false,
|
|
155
155
|
verticalSorted: false,
|
|
156
156
|
highlightOnHover: false,
|
|
157
|
+
hideSuppressedLabels: false,
|
|
157
158
|
seriesHighlight: []
|
|
158
159
|
},
|
|
159
160
|
brush: {
|
|
160
161
|
height: 25,
|
|
161
|
-
data: [],
|
|
162
162
|
active: false
|
|
163
163
|
},
|
|
164
164
|
exclusions: {
|
package/src/hooks/useBarChart.js
CHANGED
|
@@ -164,26 +164,13 @@ export const useBarChart = () => {
|
|
|
164
164
|
if (!match?.color) return false
|
|
165
165
|
return match
|
|
166
166
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return
|
|
173
|
-
}
|
|
174
|
-
if (barWidth < 10) {
|
|
175
|
-
return 6
|
|
176
|
-
}
|
|
177
|
-
if (barWidth < 15) {
|
|
178
|
-
return 7
|
|
179
|
-
}
|
|
180
|
-
if (barWidth < 20) {
|
|
181
|
-
return 8
|
|
182
|
-
}
|
|
183
|
-
if (barWidth < 90) {
|
|
184
|
-
return 8
|
|
185
|
-
}
|
|
186
|
-
return 0
|
|
167
|
+
|
|
168
|
+
const shouldSuppress = bar => {
|
|
169
|
+
return config.preliminaryData?.some(pd => {
|
|
170
|
+
const matchesColumn = pd.column ? pd.column === bar.key : true
|
|
171
|
+
const matchesValue = String(bar.value) === String(pd.value) && pd.value !== ''
|
|
172
|
+
return matchesColumn && matchesValue && pd.symbol && pd.type === 'suppression'
|
|
173
|
+
})
|
|
187
174
|
}
|
|
188
175
|
|
|
189
176
|
const getAdditionalColumn = (series, xAxisDataValue) => {
|
|
@@ -223,14 +210,51 @@ export const useBarChart = () => {
|
|
|
223
210
|
if (config.legend.highlightOnHover && config.legend.behavior === 'highlight') setSeriesHighlight([])
|
|
224
211
|
}
|
|
225
212
|
|
|
213
|
+
const composeSuppressionBars = ({ bar }) => {
|
|
214
|
+
const suppresedBarHeight = config.xAxis.showSuppressedLine ? 3 : 0
|
|
215
|
+
const ASTERISK = 'Asterisk'
|
|
216
|
+
const getIconPadding = symbol => (String(symbol).includes(ASTERISK) ? -5 : -suppresedBarHeight * 3)
|
|
217
|
+
const getVerticalAnchor = symbol => {
|
|
218
|
+
return String(symbol).includes(ASTERISK) ? 'middle' : 'end'
|
|
219
|
+
}
|
|
220
|
+
const getIconSize = (symbol, barWidth) => {
|
|
221
|
+
switch (symbol) {
|
|
222
|
+
case ASTERISK:
|
|
223
|
+
return barWidth * 1.2
|
|
224
|
+
case 'Double ' + ASTERISK:
|
|
225
|
+
return barWidth
|
|
226
|
+
default:
|
|
227
|
+
return barWidth / 1.5
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function shouldSuppressBar() {
|
|
232
|
+
const isSuppressed = config.preliminaryData.some(pd => {
|
|
233
|
+
const selectedSuppressionColumn = !pd.column || pd.column === bar.key
|
|
234
|
+
const isValueMatch = String(pd.value) === String(bar.value) && pd.value !== '' && pd.type === 'suppression'
|
|
235
|
+
|
|
236
|
+
return isValueMatch && selectedSuppressionColumn
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
return isSuppressed && config.xAxis.showSuppressedSymbol
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
suppresedBarHeight,
|
|
244
|
+
getIconSize,
|
|
245
|
+
getIconPadding,
|
|
246
|
+
getVerticalAnchor,
|
|
247
|
+
isSuppressed: shouldSuppressBar()
|
|
248
|
+
}
|
|
249
|
+
}
|
|
226
250
|
return {
|
|
227
|
-
generateIconSize,
|
|
228
251
|
isHorizontal,
|
|
229
252
|
barBorderWidth,
|
|
230
253
|
lollipopBarWidth,
|
|
231
254
|
lollipopShapeSize,
|
|
232
255
|
isLabelBelowBar,
|
|
233
256
|
displayNumbersOnBar,
|
|
257
|
+
shouldSuppress,
|
|
234
258
|
section,
|
|
235
259
|
isRounded,
|
|
236
260
|
isStacked,
|
|
@@ -249,6 +273,7 @@ export const useBarChart = () => {
|
|
|
249
273
|
hoveredBar,
|
|
250
274
|
setHoveredBar,
|
|
251
275
|
onMouseOverBar,
|
|
252
|
-
onMouseLeaveBar
|
|
276
|
+
onMouseLeaveBar,
|
|
277
|
+
composeSuppressionBars
|
|
253
278
|
}
|
|
254
279
|
}
|
package/src/hooks/useMinMax.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ChartConfig } from '../types/ChartConfig'
|
|
2
|
+
import _ from 'lodash'
|
|
2
3
|
|
|
3
4
|
type UseMinMaxProps = {
|
|
4
5
|
/** config - standard chart config */
|
|
@@ -11,11 +12,13 @@ type UseMinMaxProps = {
|
|
|
11
12
|
existPositiveValue: boolean
|
|
12
13
|
/** data - standard data array */
|
|
13
14
|
data: Object[]
|
|
15
|
+
/** Table data -data array Filtered & Excluded */
|
|
16
|
+
tableData: Object[]
|
|
14
17
|
/** isAllLine: if all series are line type including dashed lines */
|
|
15
18
|
isAllLine: boolean
|
|
16
19
|
}
|
|
17
20
|
|
|
18
|
-
const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAllLine }: UseMinMaxProps) => {
|
|
21
|
+
const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAllLine, tableData }: UseMinMaxProps) => {
|
|
19
22
|
let min = 0
|
|
20
23
|
let max = 0
|
|
21
24
|
|
|
@@ -147,7 +150,23 @@ const useMinMax = ({ config, minValue, maxValue, existPositiveValue, data, isAll
|
|
|
147
150
|
|
|
148
151
|
if (config.visualizationType === 'Line') {
|
|
149
152
|
const isMinValid = config.useLogScale ? enteredMinValue >= 0 && enteredMinValue < minValue : enteredMinValue < minValue
|
|
150
|
-
|
|
153
|
+
// update minValue for (0) Suppression points
|
|
154
|
+
const suppressedMinValue = tableData?.some((dataItem, index) => {
|
|
155
|
+
return config.preliminaryData?.some(pd => {
|
|
156
|
+
if (pd.type !== 'suppression' || !pd.style) return false
|
|
157
|
+
|
|
158
|
+
// Filter data item based on current series keys and check if pd.value is present
|
|
159
|
+
const relevantData = _.pick(dataItem, config.runtime?.seriesKeys)
|
|
160
|
+
const isValuePresent = _.values(relevantData).includes(pd.value)
|
|
161
|
+
|
|
162
|
+
// Check for value match condition
|
|
163
|
+
const valueMatch = pd.column ? dataItem[pd.column] === pd.value : isValuePresent
|
|
164
|
+
|
|
165
|
+
// Return true if the value matches and it's either the first or the last item
|
|
166
|
+
return valueMatch && (index === 0 || index === tableData.length - 1)
|
|
167
|
+
})
|
|
168
|
+
})
|
|
169
|
+
min = enteredMinValue && isMinValid ? enteredMinValue : suppressedMinValue ? 0 : minValue
|
|
151
170
|
}
|
|
152
171
|
//If data value max wasn't provided, calculate it
|
|
153
172
|
if (max === Number.MIN_VALUE) {
|
package/src/hooks/useScales.ts
CHANGED
|
@@ -72,7 +72,7 @@ const useScales = (properties: useScaleProps) => {
|
|
|
72
72
|
domain: [xAxisMin, xAxisMax],
|
|
73
73
|
range: [0, xMax]
|
|
74
74
|
})
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
xScale.type = scaleTypes.TIME
|
|
77
77
|
seriesScale = composeScaleBand(seriesDomain, [0, config.barThickness * xMax], 0)
|
|
78
78
|
}
|
|
@@ -238,6 +238,38 @@ const useScales = (properties: useScaleProps) => {
|
|
|
238
238
|
|
|
239
239
|
export default useScales
|
|
240
240
|
|
|
241
|
+
export const getTickValues = (xAxisDataMapped, xScale, num) => {
|
|
242
|
+
const xDomain = xScale.domain()
|
|
243
|
+
|
|
244
|
+
if (xScale.type === 'time') {
|
|
245
|
+
const xDomainMax = xAxisDataMapped[xAxisDataMapped.length - 1]
|
|
246
|
+
const xDomainMin = xAxisDataMapped[0]
|
|
247
|
+
const step = (xDomainMax - xDomainMin) / (num - 1)
|
|
248
|
+
const tickValues = []
|
|
249
|
+
for (let i = xDomainMax; i >= xDomainMin; i -= step) {
|
|
250
|
+
tickValues.push(i)
|
|
251
|
+
}
|
|
252
|
+
if (tickValues[tickValues.length - 1] !== xDomainMin) {
|
|
253
|
+
tickValues.push(xDomainMin)
|
|
254
|
+
}
|
|
255
|
+
tickValues.reverse()
|
|
256
|
+
|
|
257
|
+
return tickValues
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (xDomain.length > 2) {
|
|
261
|
+
const step = num || 1
|
|
262
|
+
const tickValues = []
|
|
263
|
+
for (let i = xDomain.length; i > 0; i -= step) {
|
|
264
|
+
const adjustedIndex = Math.max(Math.round(i) - 1, 0)
|
|
265
|
+
tickValues.push(xDomain[adjustedIndex])
|
|
266
|
+
}
|
|
267
|
+
tickValues.reverse()
|
|
268
|
+
|
|
269
|
+
return tickValues
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
241
273
|
/// helper functions
|
|
242
274
|
const composeXScale = ({ min, max, xMax, config }) => {
|
|
243
275
|
// Adjust min value if using logarithmic scale
|
package/src/hooks/useTooltip.tsx
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import { useContext } from 'react'
|
|
2
|
+
// Local imports
|
|
2
3
|
import ConfigContext from '../ConfigContext'
|
|
3
4
|
import { type ChartContext } from '../types/ChartContext'
|
|
4
|
-
|
|
5
|
-
// third party
|
|
6
|
-
import { localPoint } from '@visx/event'
|
|
7
|
-
import { bisector } from 'd3-array'
|
|
8
|
-
import { DataTransform } from '@cdc/core/helpers/DataTransform'
|
|
9
|
-
const transform = new DataTransform()
|
|
10
|
-
|
|
11
5
|
import { formatNumber as formatColNumber } from '@cdc/core/helpers/cove/number'
|
|
12
6
|
import { isDateScale } from '@cdc/core/helpers/cove/date'
|
|
7
|
+
// Third-party library imports
|
|
8
|
+
import { localPoint } from '@visx/event'
|
|
9
|
+
import { bisector } from 'd3-array'
|
|
13
10
|
|
|
14
11
|
export const useTooltip = props => {
|
|
15
|
-
const { tableData, config, formatNumber, capitalize, formatDate, formatTooltipsDate, parseDate, setSharedFilter } = useContext<ChartContext>(ConfigContext)
|
|
12
|
+
const { tableData: data, config, formatNumber, capitalize, formatDate, formatTooltipsDate, parseDate, setSharedFilter } = useContext<ChartContext>(ConfigContext)
|
|
16
13
|
const { xScale, yScale, showTooltip, hideTooltip } = props
|
|
17
14
|
const { xAxis, visualizationType, orientation, yAxis, runtime } = config
|
|
18
|
-
const data = transform.applySuppression(tableData, config.suppressedData)
|
|
19
15
|
/**
|
|
20
16
|
* Provides the tooltip information based on the tooltip data array and svg cursor coordinates
|
|
21
17
|
* @function getTooltipInformation
|
|
@@ -141,9 +137,13 @@ export const useTooltip = props => {
|
|
|
141
137
|
if (visualizationType !== 'Pie' && visualizationType !== 'Forest Plot') {
|
|
142
138
|
tooltipItems.push(
|
|
143
139
|
...getIncludedTooltipSeries()
|
|
144
|
-
?.filter(
|
|
140
|
+
?.filter(seriesKey => config.series?.find(item => item.dataKey === seriesKey && item?.tooltip) || config.xAxis?.dataKey == seriesKey)
|
|
145
141
|
?.flatMap(seriesKey => {
|
|
146
|
-
|
|
142
|
+
let formattedValue = seriesKey === config.xAxis.dataKey ? resolvedScaleValues[0]?.[seriesKey] : formatNumber(resolvedScaleValues[0]?.[seriesKey], getAxisPosition(seriesKey))
|
|
143
|
+
const suppressed = config.preliminaryData?.find(pd => pd.label && pd.type === 'suppression' && pd.displayTooltip && resolvedScaleValues[0]?.[seriesKey] === pd.value && (!pd.column || seriesKey === pd.column))
|
|
144
|
+
if (suppressed) {
|
|
145
|
+
formattedValue = suppressed.label
|
|
146
|
+
}
|
|
147
147
|
return resolvedScaleValues?.[0]?.[seriesKey] ? [[seriesKey, formattedValue, getAxisPosition(seriesKey)]] : []
|
|
148
148
|
})
|
|
149
149
|
)
|
package/src/scss/main.scss
CHANGED
|
@@ -13,9 +13,21 @@
|
|
|
13
13
|
flex-direction: column-reverse;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
.cdc-open-viz-module.type-dashboard {
|
|
17
|
+
.cdc-open-viz-module.type-chart.isEditor {
|
|
18
|
+
.cdc-chart-inner-container {
|
|
19
|
+
background: white;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
.cdc-open-viz-module.type-chart {
|
|
17
25
|
@import 'DataTable';
|
|
18
26
|
|
|
27
|
+
&.isEditor .cdc-chart-inner-container {
|
|
28
|
+
background: white;
|
|
29
|
+
}
|
|
30
|
+
|
|
19
31
|
border-radius: 3px;
|
|
20
32
|
|
|
21
33
|
.checkbox-group {
|
|
@@ -75,11 +87,10 @@
|
|
|
75
87
|
margin-bottom: 20px;
|
|
76
88
|
}
|
|
77
89
|
|
|
90
|
+
.subtext,
|
|
91
|
+
.subtext--responsive-ticks,
|
|
78
92
|
.section-subtext {
|
|
79
|
-
padding:
|
|
80
|
-
}
|
|
81
|
-
.subtext--responsive-ticks {
|
|
82
|
-
margin-top: 3em;
|
|
93
|
+
padding: 0 1rem;
|
|
83
94
|
}
|
|
84
95
|
|
|
85
96
|
.legend-container {
|
|
@@ -130,6 +141,9 @@
|
|
|
130
141
|
word-wrap: break-word;
|
|
131
142
|
white-space: pre-wrap;
|
|
132
143
|
word-break: break-word;
|
|
144
|
+
@include breakpoint(xs) {
|
|
145
|
+
font-size: $font-small;
|
|
146
|
+
}
|
|
133
147
|
}
|
|
134
148
|
}
|
|
135
149
|
|
|
@@ -145,12 +159,20 @@
|
|
|
145
159
|
|
|
146
160
|
h3 {
|
|
147
161
|
font-size: 1.3rem;
|
|
162
|
+
@include breakpoint(xs) {
|
|
163
|
+
font-size: $font-small + 0.4em;
|
|
164
|
+
}
|
|
148
165
|
}
|
|
149
166
|
|
|
150
167
|
h3,
|
|
151
168
|
p {
|
|
152
169
|
margin-bottom: 0.8em;
|
|
153
170
|
}
|
|
171
|
+
p {
|
|
172
|
+
@include breakpoint(xs) {
|
|
173
|
+
font-size: $font-small;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
154
176
|
& div.legend-item {
|
|
155
177
|
margin-bottom: 0.5em !important;
|
|
156
178
|
|
|
@@ -192,6 +214,52 @@
|
|
|
192
214
|
}
|
|
193
215
|
}
|
|
194
216
|
|
|
217
|
+
.div[class*='Asterisk'] {
|
|
218
|
+
transform: 0;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.legend-preliminary {
|
|
222
|
+
display: flex;
|
|
223
|
+
flex-direction: row;
|
|
224
|
+
align-items: center;
|
|
225
|
+
font-size: 1em;
|
|
226
|
+
vertical-align: middle;
|
|
227
|
+
margin-bottom: 0.5em;
|
|
228
|
+
|
|
229
|
+
@include breakpoint(xs) {
|
|
230
|
+
font-size: $font-small;
|
|
231
|
+
}
|
|
232
|
+
& > span {
|
|
233
|
+
display: flex;
|
|
234
|
+
justify-items: center;
|
|
235
|
+
align-items: center;
|
|
236
|
+
white-space: nowrap;
|
|
237
|
+
font-size: 1em;
|
|
238
|
+
margin-right: 8px;
|
|
239
|
+
max-height: 1px;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
& > span[class*='Asterisk'] {
|
|
243
|
+
transform: scale(1.8);
|
|
244
|
+
margin-top: 15px;
|
|
245
|
+
}
|
|
246
|
+
& > span[class*='Dagger'] {
|
|
247
|
+
margin-top: 2px;
|
|
248
|
+
}
|
|
249
|
+
& > span[class*='Sign'] {
|
|
250
|
+
margin-top: 1px;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
& > svg {
|
|
254
|
+
width: 50px;
|
|
255
|
+
height: 23px;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
& > p {
|
|
259
|
+
margin: 0;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
195
263
|
.visx-tooltip {
|
|
196
264
|
z-index: 100000;
|
|
197
265
|
}
|
|
@@ -599,6 +667,11 @@
|
|
|
599
667
|
}
|
|
600
668
|
}
|
|
601
669
|
|
|
670
|
+
.cdc-open-viz-module .is-editor .cdc-chart-inner-container {
|
|
671
|
+
overflow: hidden;
|
|
672
|
+
background-color: var(--white);
|
|
673
|
+
}
|
|
674
|
+
|
|
602
675
|
.isEditor.type-sparkline .cdc-chart-inner-container {
|
|
603
676
|
margin: 3em auto 0;
|
|
604
677
|
max-width: 60%;
|
|
@@ -626,8 +699,10 @@
|
|
|
626
699
|
padding: 1em;
|
|
627
700
|
}
|
|
628
701
|
|
|
629
|
-
.subtext
|
|
702
|
+
.subtext,
|
|
703
|
+
.subtext--responsive-ticks {
|
|
630
704
|
margin-top: 0px;
|
|
705
|
+
padding: 0 1rem;
|
|
631
706
|
}
|
|
632
707
|
|
|
633
708
|
.isEditor {
|
package/src/types/ChartConfig.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { Legend } from '@cdc/core/types/Legend'
|
|
|
12
12
|
import { ConfidenceInterval } from '@cdc/core/types/ConfidenceInterval'
|
|
13
13
|
import { Region } from '@cdc/core/types/Region'
|
|
14
14
|
import { type PreliminaryDataItem } from '../components/LineChart/LineChartProps'
|
|
15
|
+
import { VizFilter } from '@cdc/core/types/VizFilter'
|
|
15
16
|
|
|
16
17
|
export type ChartColumns = Record<string, Column>
|
|
17
18
|
|
|
@@ -39,18 +40,6 @@ type Exclusions = {
|
|
|
39
40
|
dateEnd: string
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
type Filter = {
|
|
43
|
-
active: string
|
|
44
|
-
type: 'url'
|
|
45
|
-
columnName: string
|
|
46
|
-
showDropdown: boolean
|
|
47
|
-
filterStyle: string
|
|
48
|
-
label: string
|
|
49
|
-
order: 'asc' | 'desc' | 'cust'
|
|
50
|
-
values: string[]
|
|
51
|
-
queryParameter: string
|
|
52
|
-
}
|
|
53
|
-
|
|
54
43
|
export type Legend = {
|
|
55
44
|
seriesHighlight: string[]
|
|
56
45
|
additionalCategories: string[]
|
|
@@ -109,7 +98,7 @@ type AllChartsConfig = {
|
|
|
109
98
|
description: string
|
|
110
99
|
dynamicMarginTop: number
|
|
111
100
|
exclusions: Exclusions
|
|
112
|
-
filters:
|
|
101
|
+
filters: VizFilter[]
|
|
113
102
|
filterBehavior: FilterBehavior
|
|
114
103
|
fontSize: 'small' | 'medium' | 'large'
|
|
115
104
|
footnotes: string
|
|
@@ -161,6 +150,7 @@ type AllChartsConfig = {
|
|
|
161
150
|
twoColor: { palette: string }
|
|
162
151
|
type: 'chart' | 'dashboard'
|
|
163
152
|
useLogScale: boolean
|
|
153
|
+
uid: string | number
|
|
164
154
|
visual: Visual
|
|
165
155
|
visualizationType: 'Area Chart' | 'Bar' | 'Box Plot' | 'Deviation Bar' | 'Forest Plot' | 'Line' | 'Paired Bar' | 'Pie' | 'Scatter Plot' | 'Spark Line' | 'Combo' | 'Forecasting' | 'Sankey'
|
|
166
156
|
visualizationSubType: string
|
|
@@ -21,6 +21,10 @@ type SharedChartContext = {
|
|
|
21
21
|
legendIsolateValues?: string[]
|
|
22
22
|
setLegendIsolateValues?: Function
|
|
23
23
|
getTextWidth?: () => string | number
|
|
24
|
+
brushConfig: { data: []; isBrushing: boolean; isActive: boolean }
|
|
25
|
+
setBrushConfig: Function
|
|
26
|
+
clean: Function
|
|
27
|
+
capitalize: (value: string) => string
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
// Line Chart Specific Context
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
-
import chartLinepreliminary from './_mock/preliminary_mock.json'
|
|
3
|
-
|
|
4
|
-
import Chart from '../CdcChart'
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof Chart> = {
|
|
7
|
-
title: 'Components/Templates/Chart/Line/Preliminary',
|
|
8
|
-
component: Chart
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
type Story = StoryObj<typeof Chart>
|
|
12
|
-
|
|
13
|
-
export const Line_Chart: Story = {
|
|
14
|
-
args: {
|
|
15
|
-
config: chartLinepreliminary
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default meta
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
-
import suppressMock from './_mock/suppress_mock.json'
|
|
3
|
-
|
|
4
|
-
import Chart from '../CdcChart'
|
|
5
|
-
|
|
6
|
-
const meta: Meta<typeof Chart> = {
|
|
7
|
-
title: 'Components/Templates/Chart/Suppress',
|
|
8
|
-
component: Chart
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
type Story = StoryObj<typeof Chart>
|
|
12
|
-
|
|
13
|
-
export const Horizontal_Chart: Story = {
|
|
14
|
-
args: {
|
|
15
|
-
config: suppressMock
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default meta
|