@cdc/chart 4.25.5-1 → 4.25.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +201 -0
  2. package/dist/cdcchart.js +32848 -27824
  3. package/index.html +130 -130
  4. package/package.json +2 -2
  5. package/src/CdcChartComponent.tsx +66 -26
  6. package/src/_stories/Chart.stories.tsx +99 -93
  7. package/src/_stories/ChartPrefixSuffix.stories.tsx +29 -32
  8. package/src/_stories/_mock/pie_calculated_area.json +417 -0
  9. package/src/components/BarChart/components/BarChart.Horizontal.tsx +4 -13
  10. package/src/components/BarChart/components/BarChart.StackedVertical.tsx +3 -14
  11. package/src/components/BarChart/components/BarChart.Vertical.tsx +2 -8
  12. package/src/components/Brush/BrushChart.tsx +73 -0
  13. package/src/components/Brush/BrushController..tsx +39 -0
  14. package/src/components/DeviationBar.jsx +0 -1
  15. package/src/components/EditorPanel/EditorPanel.tsx +232 -147
  16. package/src/components/EditorPanel/components/Panels/Panel.General.tsx +2 -2
  17. package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +3 -2
  18. package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +2 -1
  19. package/src/components/EditorPanel/components/Panels/panelVisual.styles.css +8 -0
  20. package/src/components/EditorPanel/useEditorPermissions.ts +7 -4
  21. package/src/components/HoverLine/HoverLine.tsx +74 -0
  22. package/src/components/Legend/Legend.Suppression.tsx +47 -3
  23. package/src/components/Legend/helpers/index.ts +1 -1
  24. package/src/components/LineChart/index.tsx +3 -6
  25. package/src/components/LinearChart.tsx +161 -132
  26. package/src/components/PieChart/PieChart.tsx +58 -13
  27. package/src/data/initial-state.js +8 -5
  28. package/src/helpers/getNewRuntime.ts +35 -0
  29. package/src/helpers/getPiePercent.ts +22 -0
  30. package/src/helpers/getTransformedData.ts +22 -0
  31. package/src/helpers/tests/getNewRuntime.test.ts +82 -0
  32. package/src/helpers/tests/getPiePercent.test.ts +38 -0
  33. package/src/hooks/useRightAxis.ts +1 -1
  34. package/src/hooks/useScales.ts +8 -3
  35. package/src/hooks/useTooltip.tsx +24 -10
  36. package/src/store/chart.actions.ts +2 -6
  37. package/src/store/chart.reducer.ts +23 -23
  38. package/src/types/ChartConfig.ts +6 -3
  39. package/src/types/ChartContext.ts +0 -2
  40. package/src/components/ZoomBrush.tsx +0 -251
@@ -1,251 +0,0 @@
1
- import { Brush } from '@visx/brush'
2
- import { Group } from '@visx/group'
3
- import { Text } from '@visx/text'
4
- import { FC, useContext, useEffect, useRef, useState } from 'react'
5
- import ConfigContext from '../ConfigContext'
6
- import { ScaleLinear, ScaleBand } from 'd3-scale'
7
- import { isDateScale } from '@cdc/core/helpers/cove/date'
8
- import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
9
- import { getTextWidth } from '@cdc/core/helpers/getTextWidth'
10
- import { APP_FONT_SIZE } from '@cdc/core/helpers/constants'
11
-
12
- interface Props {
13
- xScaleBrush: ScaleLinear<number, number>
14
- yScale: ScaleBand<string>
15
- xMax: number
16
- yMax: number
17
- }
18
- const ZoomBrush: FC<Props> = props => {
19
- const { tableData, config, parseDate, formatDate, setBrushConfig, dashboardConfig } = useContext(ConfigContext)
20
- const sharedFilters = dashboardConfig?.dashboard?.sharedFilters ?? []
21
- const isDashboardFilters = sharedFilters?.length > 0
22
- const [showTooltip, setShowTooltip] = useState(false)
23
- const [brushKey, setBrushKey] = useState(0)
24
- const brushRef = useRef(null)
25
- const radius = 15
26
-
27
- const [textProps, setTextProps] = useState({
28
- startPosition: 0,
29
- endPosition: 0,
30
- startValue: '',
31
- endValue: '',
32
- xMax: props.xMax
33
- })
34
-
35
- const initialPosition = {
36
- start: { x: 0 },
37
- end: { x: props.xMax }
38
- }
39
- const style = {
40
- fill: '#474747',
41
- stroke: 'blue',
42
- fillOpacity: 0.8,
43
- strokeOpacity: 0,
44
- rx: radius
45
- }
46
-
47
- const onBrushChange = event => {
48
- setShowTooltip(false)
49
- const filteredValues = event?.xValues?.filter(val => val !== undefined)
50
- if (filteredValues?.length === 0) return
51
-
52
- const dataKey = config.xAxis?.dataKey
53
-
54
- const brushedData = tableData.filter(item => filteredValues.includes(item[dataKey]))
55
-
56
- const endValue = filteredValues
57
- .slice()
58
- .reverse()
59
- .find(item => item !== undefined)
60
- const startValue = filteredValues.find(item => item !== undefined)
61
-
62
- const formatIfDate = value => (isDateScale(config.runtime.xAxis) ? formatDate(parseDate(value)) : value)
63
-
64
- setTextProps(prev => ({
65
- ...prev,
66
- startPosition: brushRef.current?.state.start.x,
67
- endPosition: brushRef.current?.state.end.x,
68
- endValue: formatIfDate(endValue),
69
- startValue: formatIfDate(startValue),
70
- xMax: props.xMax
71
- }))
72
-
73
- setBrushConfig(prev => {
74
- return {
75
- ...prev,
76
- isBrushing: brushRef.current?.state.isBrushing,
77
- data: brushedData
78
- }
79
- })
80
- }
81
- // reset brush if brush is off.
82
- useEffect(() => {
83
- if (!config.brush?.active) {
84
- setBrushKey(prevKey => prevKey + 1)
85
- setBrushConfig({
86
- data: [],
87
- isActive: false,
88
- isBrushing: false
89
- })
90
- }
91
- }, [config.brush?.active])
92
-
93
- // reset brush if filters or exclusions are ON each time
94
-
95
- useEffect(() => {
96
- const isFiltersActive = config.filters?.some(filter => filter.active)
97
- const isExclusionsActive = config.exclusions?.active
98
-
99
- if ((isFiltersActive || isExclusionsActive || isDashboardFilters) && config.brush?.active) {
100
- setBrushKey(prevKey => prevKey + 1)
101
- setBrushConfig(prev => {
102
- return {
103
- ...prev,
104
- data: tableData
105
- }
106
- })
107
- }
108
- return () =>
109
- setBrushConfig(prev => {
110
- return {
111
- ...prev,
112
- data: []
113
- }
114
- })
115
- }, [config.filters, config.exclusions, config.brush?.active, isDashboardFilters])
116
-
117
- const calculateTop = (): number => {
118
- const tickRotation = Number(config.xAxis.tickRotation) > 0 ? Number(config.xAxis.tickRotation) : 0
119
- let top = 0
120
- const offSet = 30
121
- if (!config.xAxis.label) {
122
- if (!config.isResponsiveTicks && tickRotation) {
123
- top = Number(tickRotation + config.xAxis.tickWidthMax) / 1.6
124
- }
125
- if (!config.isResponsiveTicks && !tickRotation) {
126
- top = Number(config.xAxis.labelOffset) - offSet
127
- }
128
- if (config.isResponsiveTicks && config.dynamicMarginTop) {
129
- top = Number(config.xAxis.labelOffset + config.xAxis.tickWidthMax / 1.6)
130
- }
131
- if (config.isResponsiveTicks && !config.dynamicMarginTop) {
132
- top = Number(config.xAxis.labelOffset - offSet)
133
- }
134
- }
135
- if (config.xAxis.label) {
136
- if (!config.isResponsiveTicks && tickRotation) {
137
- top = Number(config.xAxis.tickWidthMax + tickRotation) + offSet
138
- }
139
-
140
- if (!config.isResponsiveTicks && !tickRotation) {
141
- top = config.xAxis.labelOffset + offSet
142
- }
143
-
144
- if (config.isResponsiveTicks && !tickRotation) {
145
- top = Number(config.dynamicMarginTop ? config.dynamicMarginTop : config.xAxis.labelOffset) + offSet * 2
146
- }
147
- }
148
-
149
- return top
150
- }
151
- if (!['Line', 'Bar', 'Area Chart', 'Combo'].includes(config.visualizationType)) {
152
- return
153
- }
154
-
155
- return (
156
- <ErrorBoundary component='Brush Chart'>
157
- <Group
158
- onMouseMove={() => {
159
- // show tooltip only once before brush started
160
- if (textProps.startPosition === 0 && (textProps.endPosition === 0 || textProps.endPosition === props.xMax)) {
161
- setShowTooltip(true)
162
- }
163
- }}
164
- onMouseLeave={() => setShowTooltip(false)}
165
- display={config.brush?.active ? 'block' : 'none'}
166
- top={Number(props.yMax) + calculateTop()}
167
- left={Number(config.runtime.yAxis.size)}
168
- pointerEvents='fill'
169
- >
170
- <rect fill='#949494' width={props.xMax} height={config.brush.height} rx={radius} />
171
- <Brush
172
- key={brushKey}
173
- disableDraggingOverlay={true}
174
- renderBrushHandle={props => (
175
- <BrushHandle
176
- left={Number(config.runtime.yAxis.size)}
177
- showTooltip={showTooltip}
178
- pixelDistance={textProps.endPosition - textProps.startPosition}
179
- textProps={textProps}
180
- {...props}
181
- isBrushing={brushRef.current?.state.isBrushing}
182
- />
183
- )}
184
- innerRef={brushRef}
185
- useWindowMoveEvents={true}
186
- selectedBoxStyle={style}
187
- xScale={props.xScaleBrush}
188
- yScale={props.yScale}
189
- width={props.xMax}
190
- resizeTriggerAreas={['left', 'right']}
191
- height={config.brush.height}
192
- handleSize={8}
193
- brushDirection='horizontal'
194
- initialBrushPosition={initialPosition}
195
- onChange={onBrushChange}
196
- />
197
- </Group>
198
- </ErrorBoundary>
199
- )
200
- }
201
-
202
- const BrushHandle = props => {
203
- const { x, isBrushActive, isBrushing, className, textProps, showTooltip, left } = props
204
- const pathWidth = 8
205
- if (!isBrushActive) {
206
- return null
207
- }
208
- // Flip the SVG path horizontally for the left handle
209
- const isLeft = className.includes('left')
210
- const transform = isLeft ? 'scale(-1, 1)' : 'translate(0,0)'
211
- const textAnchor = isLeft ? 'end' : 'start'
212
- const tooltipText = isLeft ? ` Drag edges to focus on a specific segment ` : ''
213
- const textWidth = getTextWidth(tooltipText, `${APP_FONT_SIZE / 1.1}px`)
214
-
215
- return (
216
- <>
217
- {showTooltip && (
218
- <Text
219
- x={(Number(textProps.xMax) - textWidth) / 2}
220
- dy={-12}
221
- pointerEvents='visiblePainted'
222
- fontSize={APP_FONT_SIZE / 1.1}
223
- >
224
- {tooltipText}
225
- </Text>
226
- )}
227
- <Group left={x + pathWidth / 2} top={-2}>
228
- <Text
229
- pointerEvents='visiblePainted'
230
- dominantBaseline='hanging'
231
- x={isLeft ? 55 : -50}
232
- y={25}
233
- verticalAnchor='start'
234
- textAnchor={textAnchor}
235
- fontSize={APP_FONT_SIZE / 1.4}
236
- >
237
- {isLeft ? textProps.startValue : textProps.endValue}
238
- </Text>
239
- <path
240
- cursor='ew-resize'
241
- d='M0.5,10A6,6 0 0 1 6.5,16V14A6,6 0 0 1 0.5,20ZM2.5,18V12M4.5,18V12'
242
- fill={'#297EF1'}
243
- strokeWidth='1'
244
- transform={transform}
245
- ></path>
246
- </Group>
247
- </>
248
- )
249
- }
250
-
251
- export default ZoomBrush