@cdc/chart 4.26.4 → 4.26.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/CONFIG.md +349 -29
- package/LICENSE +201 -0
- package/dist/cdcchart.js +34247 -32805
- package/examples/feature/heatmap/average-age-categorical.json +313 -0
- package/examples/feature/heatmap/calendar-heatmap.json +134 -0
- package/examples/feature/heatmap/cell-values-bottom-axis.json +181 -0
- package/examples/feature/heatmap/sparse-aggregation.json +158 -0
- package/examples/private/bump-chart.json +1116 -0
- package/examples/private/test-123.json +624 -0
- package/package.json +4 -3
- package/src/CdcChartComponent.tsx +135 -54
- package/src/_stories/Chart.AltText.stories.tsx +136 -0
- package/src/_stories/Chart.HeatMap.stories.tsx +187 -0
- package/src/_stories/Chart.Sankey.smoke.stories.tsx +62 -0
- package/src/_stories/Chart.SmallMultiples.smoke.stories.tsx +29 -0
- package/src/_stories/ChartAxisTitles.smoke.stories.tsx +13 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +63 -0
- package/src/_stories/ChartBrush.Interaction.stories.tsx +112 -0
- package/src/_stories/ChartBrush.smoke.stories.tsx +13 -4
- package/src/_stories/_mock/alt_text_metadata.json +38 -0
- package/src/_stories/_mock/heatmap-average-age-categorical.json +315 -0
- package/src/_stories/_mock/heatmap.json +156 -0
- package/src/_stories/_mock/reported_pertussis_cases.json +1643 -0
- package/src/_stories/_mock/sankey_mock.json +78 -0
- package/src/_stories/_mock/small_multiples/small_multiples_lines.json +1 -1
- package/src/components/Annotations/components/AnnotationDraggable.tsx +1 -1
- package/src/components/Annotations/components/AnnotationDropdown.tsx +5 -2
- package/src/components/Axis/LeftAxis.tsx +14 -11
- package/src/components/Axis/LeftAxisGridlines.tsx +14 -11
- package/src/components/Brush/BrushSelector.tsx +88 -187
- package/src/components/Brush/brushInteraction.ts +22 -0
- package/src/components/Brush/tests/brushInteraction.test.ts +38 -0
- package/src/components/EditorPanel/EditorPanel.tsx +310 -49
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +13 -0
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +105 -13
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +1 -0
- package/src/components/EditorPanel/components/Panels/Panel.Regions.tsx +5 -0
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +2 -2
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +1 -1
- package/src/components/EditorPanel/helpers/getVisualizationTypeConfigUpdate.ts +57 -0
- package/src/components/EditorPanel/helpers/tests/getVisualizationTypeConfigUpdate.test.ts +56 -0
- package/src/components/EditorPanel/useEditorPermissions.test.tsx +70 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +42 -22
- package/src/components/HeatMap/components/HeatMap.tsx +762 -0
- package/src/components/HeatMap/components/HeatMapGradientLegend.tsx +114 -0
- package/src/components/HeatMap/heatmap.constants.ts +13 -0
- package/src/components/HeatMap/heatmap.css +71 -0
- package/src/components/HeatMap/helpers/index.ts +261 -0
- package/src/components/HeatMap/index.tsx +5 -0
- package/src/components/HeatMap/tests/HeatMap.test.tsx +1040 -0
- package/src/components/HeatMap/tests/helpers.test.ts +167 -0
- package/src/components/LineChart/components/LineChart.BumpCircle.tsx +19 -22
- package/src/components/LineChart/helpers.test.ts +345 -0
- package/src/components/LineChart/helpers.ts +15 -5
- package/src/components/LineChart/index.tsx +7 -1
- package/src/components/LinearChart/tests/LinearChart.test.tsx +107 -33
- package/src/components/LinearChart/tests/mockConfigContext.ts +1 -0
- package/src/components/LinearChart.tsx +58 -37
- package/src/components/PieChart/PieChart.tsx +4 -1
- package/src/components/RadarChart/RadarChart.tsx +3 -1
- package/src/components/Regions/components/Regions.tsx +195 -41
- package/src/components/Sankey/components/Sankey.tsx +7 -3
- package/src/components/Sankey/helpers/getSankeyTooltip.tsx +7 -6
- package/src/components/SmallMultiples/SmallMultipleTile.tsx +30 -3
- package/src/components/SmallMultiples/SmallMultiples.css +12 -0
- package/src/components/SmallMultiples/SmallMultiples.tsx +15 -9
- package/src/components/SmallMultiples/tests/SmallMultipleTile.test.tsx +152 -0
- package/src/components/Sparkline/components/SparkLine.tsx +4 -9
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.css +1 -1
- package/src/components/WarmingStripes/WarmingStripesGradientLegend.tsx +2 -2
- package/src/data/initial-state.js +11 -0
- package/src/helpers/axisLabelFontSize.ts +8 -0
- package/src/helpers/bumpChartTooltip.ts +54 -0
- package/src/helpers/calculateLeftYAxisWidth.ts +4 -0
- package/src/helpers/ensureSpecialChartAxisTypes.ts +11 -0
- package/src/helpers/getMinMax.ts +2 -3
- package/src/helpers/getYAxisAutoPadding.ts +8 -6
- package/src/helpers/getYAxisAutoPaddingMode.ts +17 -0
- package/src/helpers/handleChartAriaLabels.ts +23 -10
- package/src/helpers/seriesHighlight.ts +26 -0
- package/src/helpers/tests/axisLabelFontSize.test.ts +15 -0
- package/src/helpers/tests/bumpChartTooltip.test.ts +75 -0
- package/src/helpers/tests/ensureSpecialChartAxisTypes.test.ts +30 -0
- package/src/helpers/tests/getYAxisAutoPadding.test.ts +37 -0
- package/src/helpers/tests/getYAxisAutoPaddingMode.test.ts +90 -0
- package/src/helpers/tests/handleChartAriaLabels.test.ts +71 -0
- package/src/helpers/tests/seriesHighlight.test.ts +61 -0
- package/src/hooks/tests/useScales.test.tsx +105 -0
- package/src/hooks/useScales.ts +19 -9
- package/src/index.jsx +5 -2
- package/src/scss/main.scss +32 -49
- package/src/types/ChartConfig.ts +18 -0
- package/src/types/ChartContext.ts +2 -0
|
@@ -72,6 +72,21 @@ const getLeftAxisLabelTransforms = container =>
|
|
|
72
72
|
.map(label => label.getAttribute('transform'))
|
|
73
73
|
.filter(Boolean)
|
|
74
74
|
|
|
75
|
+
const sidePlacementYAxis = {
|
|
76
|
+
hideAxis: false,
|
|
77
|
+
hideLabel: false,
|
|
78
|
+
hideTicks: false,
|
|
79
|
+
size: '50',
|
|
80
|
+
gridLines: true,
|
|
81
|
+
label: 'Y-Axis',
|
|
82
|
+
titlePlacement: 'side',
|
|
83
|
+
tickRotation: 0,
|
|
84
|
+
anchors: [],
|
|
85
|
+
axisPadding: 0,
|
|
86
|
+
labelPlacement: 'On Date/Category Axis',
|
|
87
|
+
rightAxisSize: 0
|
|
88
|
+
}
|
|
89
|
+
|
|
75
90
|
describe('LinearChart', () => {
|
|
76
91
|
describe('rendering', () => {
|
|
77
92
|
it('renders without crashing', () => {
|
|
@@ -238,26 +253,103 @@ describe('LinearChart', () => {
|
|
|
238
253
|
expect(leftAxis).toBeTruthy()
|
|
239
254
|
})
|
|
240
255
|
|
|
256
|
+
it('does not render the side y-axis title inside the svg when titlePlacement is top', () => {
|
|
257
|
+
const { container } = renderLinearChart()
|
|
258
|
+
|
|
259
|
+
expect(container.querySelector('.left-axis text.y-label')).toBeFalsy()
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
it('does not render the top y-axis title inside LinearChart when titlePlacement is top', () => {
|
|
263
|
+
const { container } = renderLinearChart()
|
|
264
|
+
|
|
265
|
+
expect(container.querySelector('.y-axis-top-title')).toBeFalsy()
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
it('renders the side y-axis title inside the svg when titlePlacement is side', () => {
|
|
269
|
+
const { container } = renderLinearChart({
|
|
270
|
+
yAxis: sidePlacementYAxis
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
expect(container.querySelector('.y-axis-top-title')).toBeFalsy()
|
|
274
|
+
expect(container.querySelector('.left-axis text.y-label')).toBeTruthy()
|
|
275
|
+
})
|
|
276
|
+
|
|
241
277
|
it('renders bottom axis group', () => {
|
|
242
278
|
const { container } = renderLinearChart()
|
|
243
279
|
const bottomAxis = container.querySelector('.bottom-axis')
|
|
244
280
|
expect(bottomAxis).toBeTruthy()
|
|
245
281
|
})
|
|
246
282
|
|
|
283
|
+
it('uses vizViewport for x-axis viewport tick overrides', () => {
|
|
284
|
+
const data = [
|
|
285
|
+
{ Date: '2024-01-01', Value: 1 },
|
|
286
|
+
{ Date: '2024-02-01', Value: 2 },
|
|
287
|
+
{ Date: '2024-03-01', Value: 3 },
|
|
288
|
+
{ Date: '2024-04-01', Value: 4 },
|
|
289
|
+
{ Date: '2024-05-01', Value: 5 },
|
|
290
|
+
{ Date: '2024-06-01', Value: 6 }
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
const { container } = renderLinearChart(
|
|
294
|
+
{
|
|
295
|
+
data,
|
|
296
|
+
preliminaryData: [],
|
|
297
|
+
series: [{ dataKey: 'Value', axis: 'Left' }],
|
|
298
|
+
xAxis: {
|
|
299
|
+
type: 'date',
|
|
300
|
+
dataKey: 'Date',
|
|
301
|
+
label: 'X-Axis',
|
|
302
|
+
hideAxis: false,
|
|
303
|
+
hideLabel: false,
|
|
304
|
+
hideTicks: false,
|
|
305
|
+
size: '50',
|
|
306
|
+
tickRotation: 0,
|
|
307
|
+
maxTickRotation: 90,
|
|
308
|
+
anchors: [],
|
|
309
|
+
axisPadding: 0,
|
|
310
|
+
dateParseFormat: '%Y-%m-%d',
|
|
311
|
+
dateDisplayFormat: '%b %Y'
|
|
312
|
+
},
|
|
313
|
+
runtime: {
|
|
314
|
+
xAxis: {
|
|
315
|
+
type: 'date',
|
|
316
|
+
dataKey: 'Date',
|
|
317
|
+
label: 'X-Axis',
|
|
318
|
+
numTicks: 6,
|
|
319
|
+
viewportNumTicks: { xxs: 2 }
|
|
320
|
+
},
|
|
321
|
+
yAxis: {
|
|
322
|
+
size: 50,
|
|
323
|
+
label: 'Y-Axis',
|
|
324
|
+
gridLines: true
|
|
325
|
+
},
|
|
326
|
+
originalXAxis: {
|
|
327
|
+
dataKey: 'Date'
|
|
328
|
+
},
|
|
329
|
+
series: [{ dataKey: 'Value', axis: 'Left' }],
|
|
330
|
+
seriesKeys: ['Value'],
|
|
331
|
+
seriesLabels: { Value: 'Value' },
|
|
332
|
+
seriesLabelsAll: ['Value'],
|
|
333
|
+
uniqueId: 'test-chart'
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
currentViewport: 'lg',
|
|
338
|
+
vizViewport: 'xxs',
|
|
339
|
+
colorScale: () => '#000',
|
|
340
|
+
transformedData: data,
|
|
341
|
+
tableData: data
|
|
342
|
+
}
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
expect(container.querySelectorAll('.bottom-axis .vx-axis-tick')).toHaveLength(2)
|
|
346
|
+
})
|
|
347
|
+
|
|
247
348
|
it('hides Y axis when hideAxis is true', () => {
|
|
248
349
|
const { container } = renderLinearChart({
|
|
249
350
|
yAxis: {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
hideTicks: false,
|
|
253
|
-
size: '50',
|
|
254
|
-
gridLines: true,
|
|
255
|
-
label: 'Y-Axis',
|
|
256
|
-
tickRotation: 0,
|
|
257
|
-
anchors: [],
|
|
258
|
-
axisPadding: 0,
|
|
259
|
-
labelPlacement: 'On Date/Category Axis',
|
|
260
|
-
rightAxisSize: 0
|
|
351
|
+
...sidePlacementYAxis,
|
|
352
|
+
hideAxis: true
|
|
261
353
|
}
|
|
262
354
|
})
|
|
263
355
|
// The axis line should be hidden, but grid lines may still render
|
|
@@ -288,34 +380,14 @@ describe('LinearChart', () => {
|
|
|
288
380
|
|
|
289
381
|
const baseRender = renderLinearChart({
|
|
290
382
|
yAxis: {
|
|
291
|
-
|
|
292
|
-
hideLabel: false,
|
|
293
|
-
hideTicks: false,
|
|
294
|
-
size: '50',
|
|
295
|
-
gridLines: true,
|
|
296
|
-
label: 'Y-Axis',
|
|
297
|
-
tickRotation: 0,
|
|
298
|
-
anchors: [],
|
|
299
|
-
axisPadding: 0,
|
|
300
|
-
labelPlacement: 'On Date/Category Axis',
|
|
301
|
-
rightAxisSize: 0,
|
|
383
|
+
...sidePlacementYAxis,
|
|
302
384
|
labelOffset: 0
|
|
303
385
|
},
|
|
304
386
|
runtime: baseRuntime
|
|
305
387
|
})
|
|
306
388
|
const offsetRender = renderLinearChart({
|
|
307
389
|
yAxis: {
|
|
308
|
-
|
|
309
|
-
hideLabel: false,
|
|
310
|
-
hideTicks: false,
|
|
311
|
-
size: '50',
|
|
312
|
-
gridLines: true,
|
|
313
|
-
label: 'Y-Axis',
|
|
314
|
-
tickRotation: 0,
|
|
315
|
-
anchors: [],
|
|
316
|
-
axisPadding: 0,
|
|
317
|
-
labelPlacement: 'On Date/Category Axis',
|
|
318
|
-
rightAxisSize: 0,
|
|
390
|
+
...sidePlacementYAxis,
|
|
319
391
|
labelOffset: 240
|
|
320
392
|
},
|
|
321
393
|
runtime: {
|
|
@@ -372,6 +444,7 @@ describe('LinearChart', () => {
|
|
|
372
444
|
axisPadding: 0,
|
|
373
445
|
labelOffset: 0
|
|
374
446
|
},
|
|
447
|
+
yAxis: sidePlacementYAxis,
|
|
375
448
|
runtime: baseRuntime
|
|
376
449
|
})
|
|
377
450
|
const offsetRender = renderLinearChart({
|
|
@@ -390,6 +463,7 @@ describe('LinearChart', () => {
|
|
|
390
463
|
axisPadding: 0,
|
|
391
464
|
labelOffset: 240
|
|
392
465
|
},
|
|
466
|
+
yAxis: sidePlacementYAxis,
|
|
393
467
|
runtime: {
|
|
394
468
|
...baseRuntime,
|
|
395
469
|
yAxis: {
|
|
@@ -36,6 +36,8 @@ import { isLegendWrapViewport, isMobileFontViewport } from '@cdc/core/helpers/vi
|
|
|
36
36
|
import { calcInitialHeight } from '../helpers/sizeHelpers'
|
|
37
37
|
import { calculateHorizontalBarCategoryLabelWidth } from '../helpers/calculateHorizontalBarCategoryLabelWidth'
|
|
38
38
|
import { calculateLeftYAxisWidth } from '../helpers/calculateLeftYAxisWidth'
|
|
39
|
+
import { getAxisLabelFontSize } from '../helpers/axisLabelFontSize'
|
|
40
|
+
import { getYAxisAutoPaddingMode } from '../helpers/getYAxisAutoPaddingMode'
|
|
39
41
|
|
|
40
42
|
// Hooks
|
|
41
43
|
import useReduceData from '../hooks/useReduceData'
|
|
@@ -69,9 +71,6 @@ const DEFAULT_LEFT_Y_AXIS_WIDTH = 50
|
|
|
69
71
|
// Font sizes
|
|
70
72
|
const TICK_LABEL_FONT_SIZE = 16
|
|
71
73
|
const TICK_LABEL_FONT_SIZE_SMALL = 13
|
|
72
|
-
const AXIS_LABEL_FONT_SIZE = 18
|
|
73
|
-
const AXIS_LABEL_FONT_SIZE_SMALL = 14
|
|
74
|
-
|
|
75
74
|
// Label positioning constants
|
|
76
75
|
const BELOW_BAR_TEXT_OFFSET = -6.5
|
|
77
76
|
const LABEL_PADDING_OFFSET = 8
|
|
@@ -122,6 +121,9 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
122
121
|
transformedData: data,
|
|
123
122
|
} = useContext(ConfigContext)
|
|
124
123
|
|
|
124
|
+
// SVG accessibility: title/desc pattern
|
|
125
|
+
const a11y = handleChartAriaLabels(config)
|
|
126
|
+
|
|
125
127
|
// CONFIG
|
|
126
128
|
// todo: start destructuring this file for conciseness
|
|
127
129
|
const { visualizationType, orientation, xAxis, yAxis, runtime, legend, forestPlot, debugSvg } = config
|
|
@@ -129,9 +131,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
129
131
|
const { inlineLabel } = config.yAxis
|
|
130
132
|
|
|
131
133
|
// HOOKS % STATES
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const dataForMinMax = config.xAxis.brushActive && tableData && tableData.length > 0 ? tableData : data
|
|
134
|
+
const useBrushFullRange = config.xAxis.brushActive && !config.xAxis.brushDynamicYAxis
|
|
135
|
+
const dataForMinMax = useBrushFullRange && tableData && tableData.length > 0 ? tableData : data
|
|
135
136
|
const { minValue, maxValue, existPositiveValue, isAllLine } = useReduceData(config, dataForMinMax)
|
|
136
137
|
|
|
137
138
|
const { visSupportsSmallMultiples } = useEditorPermissions()
|
|
@@ -163,6 +164,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
163
164
|
const xAxisLabelRefs = useRef([])
|
|
164
165
|
const xAxisTitleRef = useRef(null)
|
|
165
166
|
const tooltipRef = useRef(null)
|
|
167
|
+
const brushLayoutRef = useRef<{ yAxisWidth: number; xMax: number } | null>(null)
|
|
168
|
+
const brushLayoutDepsRef = useRef<{ parentWidth: number; tableData: any } | null>(null)
|
|
166
169
|
|
|
167
170
|
const dataRef = useIntersectionObserver(triggerRef, {
|
|
168
171
|
freezeOnceVisible: false
|
|
@@ -174,10 +177,9 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
174
177
|
const isLogarithmicAxis = config.yAxis.type === 'logarithmic'
|
|
175
178
|
const isForestPlot = visualizationType === 'Forest Plot'
|
|
176
179
|
const isDateTime = config.xAxis.type === 'date-time'
|
|
177
|
-
const
|
|
178
|
-
const needsYAxisAutoPadding = inlineLabel && !inlineLabelHasNoSpace
|
|
180
|
+
const yAxisAutoPaddingMode = getYAxisAutoPaddingMode(config)
|
|
179
181
|
const tickLabelFontSize = isMobileFontViewport(vizViewport) ? TICK_LABEL_FONT_SIZE_SMALL : TICK_LABEL_FONT_SIZE
|
|
180
|
-
const axisLabelFontSize =
|
|
182
|
+
const axisLabelFontSize = getAxisLabelFontSize(vizViewport)
|
|
181
183
|
const GET_TEXT_WIDTH_FONT = `normal ${tickLabelFontSize}px Nunito, sans-serif`
|
|
182
184
|
|
|
183
185
|
// zero if not forest plot
|
|
@@ -185,11 +187,10 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
185
187
|
|
|
186
188
|
// height before bottom axis
|
|
187
189
|
const initialHeight = useMemo(
|
|
188
|
-
() =>
|
|
189
|
-
visualizationType === 'Warming Stripes' ? WARMING_STRIPES_HEIGHT : calcInitialHeight(config, currentViewport),
|
|
190
|
+
() => (visualizationType === 'Warming Stripes' ? WARMING_STRIPES_HEIGHT : calcInitialHeight(config, vizViewport)),
|
|
190
191
|
[
|
|
191
192
|
visualizationType,
|
|
192
|
-
|
|
193
|
+
vizViewport,
|
|
193
194
|
config.heights?.vertical,
|
|
194
195
|
config.heights?.horizontal,
|
|
195
196
|
config.heights?.mobileVertical,
|
|
@@ -263,6 +264,21 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
263
264
|
// Chart width calculation using the current y-axis width
|
|
264
265
|
const xMax = parentWidth - yAxisWidth - (hasRightAxis ? config.yAxis.rightAxisSize : 0)
|
|
265
266
|
|
|
267
|
+
// Stabilize brush container dimensions when brushDynamicYAxis is enabled.
|
|
268
|
+
// Without this, y-axis rescaling on each brush change creates a feedback loop:
|
|
269
|
+
// brush drag → y-domain change → tick label width change → xMax shift → brush jumps.
|
|
270
|
+
// We freeze the brush coordinate system and only update on real layout changes.
|
|
271
|
+
const isDynamicBrushYAxis = config.xAxis.brushDynamicYAxis
|
|
272
|
+
const isFirstBrushLayout = !brushLayoutDepsRef.current
|
|
273
|
+
const viewportResized = brushLayoutDepsRef.current?.parentWidth !== parentWidth
|
|
274
|
+
const dataReloaded = brushLayoutDepsRef.current?.tableData !== tableData
|
|
275
|
+
if (!isDynamicBrushYAxis || isFirstBrushLayout || viewportResized || dataReloaded) {
|
|
276
|
+
brushLayoutRef.current = { yAxisWidth, xMax }
|
|
277
|
+
brushLayoutDepsRef.current = { parentWidth, tableData }
|
|
278
|
+
}
|
|
279
|
+
const stableBrushYAxisWidth = isDynamicBrushYAxis ? brushLayoutRef.current!.yAxisWidth : yAxisWidth
|
|
280
|
+
const stableBrushXMax = isDynamicBrushYAxis ? brushLayoutRef.current!.xMax : xMax
|
|
281
|
+
|
|
266
282
|
const {
|
|
267
283
|
xScale,
|
|
268
284
|
yScale,
|
|
@@ -285,8 +301,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
285
301
|
xAxisDataMapped,
|
|
286
302
|
yMax,
|
|
287
303
|
xMax,
|
|
288
|
-
|
|
289
|
-
currentViewport
|
|
304
|
+
yAxisAutoPaddingMode,
|
|
305
|
+
currentViewport: vizViewport
|
|
290
306
|
})
|
|
291
307
|
|
|
292
308
|
// Consolidated tick formatters
|
|
@@ -324,10 +340,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
324
340
|
runtime.xAxis?.type
|
|
325
341
|
])
|
|
326
342
|
|
|
327
|
-
const horizontalYAxisLabelSpace =
|
|
343
|
+
const horizontalYAxisLabelSpace =
|
|
344
|
+
runtime.yAxis.label && !config.hideYAxisLabel && config.yAxis.titlePlacement !== 'top' ? 30 : 0
|
|
328
345
|
|
|
329
346
|
const [yTickCount, xTickCount] = ['yAxis', 'xAxis'].map(axis =>
|
|
330
|
-
countNumOfTicks({ axis, max, runtime, currentViewport, isHorizontal, data, config, min })
|
|
347
|
+
countNumOfTicks({ axis, max, runtime, currentViewport: vizViewport, isHorizontal, data, config, min })
|
|
331
348
|
)
|
|
332
349
|
const handleNumTicks = isForestPlot ? config.data.length : yTickCount
|
|
333
350
|
|
|
@@ -416,11 +433,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
416
433
|
|
|
417
434
|
const getManualStep = useCallback(() => {
|
|
418
435
|
let manualStep = config.xAxis.manualStep
|
|
419
|
-
if (config.xAxis.viewportStepCount && config.xAxis.viewportStepCount[
|
|
420
|
-
manualStep = config.xAxis.viewportStepCount[
|
|
436
|
+
if (config.xAxis.viewportStepCount && config.xAxis.viewportStepCount[vizViewport]) {
|
|
437
|
+
manualStep = config.xAxis.viewportStepCount[vizViewport]
|
|
421
438
|
}
|
|
422
439
|
return manualStep
|
|
423
|
-
}, [config.xAxis.manualStep, config.xAxis.viewportStepCount,
|
|
440
|
+
}, [config.xAxis.manualStep, config.xAxis.viewportStepCount, vizViewport])
|
|
424
441
|
|
|
425
442
|
const smallMultiplesSync = useSmallMultipleSynchronization(xMax, yMax, yAxisWidth, getXValueFromCoordinate)
|
|
426
443
|
|
|
@@ -508,7 +525,6 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
508
525
|
|
|
509
526
|
const isForestPlot = visualizationType === 'Forest Plot'
|
|
510
527
|
const topLabelOnGridline = topYLabelRef.current && yAxis.labelsAboveGridlines
|
|
511
|
-
|
|
512
528
|
// Heights to add
|
|
513
529
|
const forestRowsHeight = isForestPlot ? config.data.length * forestPlot.rowHeight : 0
|
|
514
530
|
const topLabelOnGridlineHeight = topLabelOnGridline ? topYLabelRef.current.getBBox().height : 0
|
|
@@ -605,7 +621,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
605
621
|
debugSvg && 'debug'
|
|
606
622
|
} ${isDraggingAnnotation && 'dragging-annotation'}`}
|
|
607
623
|
role='img'
|
|
608
|
-
aria-label={
|
|
624
|
+
aria-label={a11y}
|
|
609
625
|
style={{ overflow: 'visible' }}
|
|
610
626
|
onMouseLeave={() => {
|
|
611
627
|
setShowHoverLine(false)
|
|
@@ -754,18 +770,19 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
754
770
|
{/* we are handling regions in bar charts differently, so that we can calculate the bar group into the region space. */}
|
|
755
771
|
{/* prettier-ignore */}
|
|
756
772
|
{config.visualizationType !== 'Bar' && config.visualizationType !== 'Combo' && (
|
|
757
|
-
<
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
773
|
+
<Group left={yAxisWidth}>
|
|
774
|
+
<Regions
|
|
775
|
+
xScale={xScale}
|
|
776
|
+
handleTooltipClick={handleTooltipClick}
|
|
777
|
+
handleTooltipMouseOff={handleTooltipMouseOff}
|
|
778
|
+
handleTooltipMouseOver={handleTooltipMouseOver}
|
|
779
|
+
showTooltip={showTooltip}
|
|
780
|
+
hideTooltip={hideTooltip}
|
|
781
|
+
tooltipData={tooltipData}
|
|
782
|
+
yMax={yMax}
|
|
783
|
+
xMax={xMax}
|
|
784
|
+
/>
|
|
785
|
+
</Group>
|
|
769
786
|
)}
|
|
770
787
|
{isNoDataAvailable && (
|
|
771
788
|
<Text
|
|
@@ -926,7 +943,7 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
926
943
|
)}
|
|
927
944
|
{config.visualizationType === 'Bump Chart' && (
|
|
928
945
|
<ReactTooltip
|
|
929
|
-
id={`bump
|
|
946
|
+
id={`cdc-open-viz-tooltip-${config.runtime.uniqueId}-bump`}
|
|
930
947
|
variant='light'
|
|
931
948
|
arrowColor='rgba(0,0,0,0)'
|
|
932
949
|
className='tooltip'
|
|
@@ -949,8 +966,8 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
949
966
|
style={{
|
|
950
967
|
position: 'relative',
|
|
951
968
|
marginTop: `${BRUSH_MARGIN}px`,
|
|
952
|
-
left: `${
|
|
953
|
-
width: `${Math.max(
|
|
969
|
+
left: `${stableBrushYAxisWidth}px`,
|
|
970
|
+
width: `${Math.max(stableBrushXMax, BRUSH_MIN_WIDTH)}px`,
|
|
954
971
|
height: `${BRUSH_HEIGHT}px`,
|
|
955
972
|
pointerEvents: 'auto',
|
|
956
973
|
zIndex: 15,
|
|
@@ -961,7 +978,11 @@ const LinearChart = forwardRef<SVGAElement, LinearChartProps>(({ parentHeight, p
|
|
|
961
978
|
}}
|
|
962
979
|
className='brush-overlay'
|
|
963
980
|
>
|
|
964
|
-
<BrushSelector
|
|
981
|
+
<BrushSelector
|
|
982
|
+
key={brushKeyRef.current}
|
|
983
|
+
xMax={Math.max(stableBrushXMax, BRUSH_MIN_WIDTH)}
|
|
984
|
+
yMax={BRUSH_HEIGHT}
|
|
985
|
+
/>
|
|
965
986
|
</div>
|
|
966
987
|
)}
|
|
967
988
|
</div>
|
|
@@ -44,6 +44,9 @@ const PieChart = React.forwardRef<SVGSVGElement, PieChartProps>((props, ref) =>
|
|
|
44
44
|
seriesHighlight,
|
|
45
45
|
isDraggingAnnotation
|
|
46
46
|
} = useContext(ConfigContext)
|
|
47
|
+
|
|
48
|
+
const a11y = handleChartAriaLabels(config)
|
|
49
|
+
|
|
47
50
|
const dispatch = useContext(ChartDispatchContext)
|
|
48
51
|
const { tooltipData, showTooltip, hideTooltip, tooltipOpen, tooltipLeft, tooltipTop } = useTooltip<TooltipData>()
|
|
49
52
|
const { handleTooltipMouseOver, handleTooltipMouseOff, TooltipListItem } = useCoveTooltip({
|
|
@@ -390,7 +393,7 @@ const PieChart = React.forwardRef<SVGSVGElement, PieChartProps>((props, ref) =>
|
|
|
390
393
|
height={height}
|
|
391
394
|
className={getSvgClasses()}
|
|
392
395
|
role='img'
|
|
393
|
-
aria-label={
|
|
396
|
+
aria-label={a11y}
|
|
394
397
|
onMouseEnter={handleChartMouseEnter}
|
|
395
398
|
onMouseLeave={() => {
|
|
396
399
|
handleTooltipMouseOff()
|
|
@@ -41,6 +41,8 @@ const RadarChart = React.forwardRef<SVGSVGElement, RadarChartProps>((props, ref)
|
|
|
41
41
|
formatNumber
|
|
42
42
|
} = useContext(ConfigContext)
|
|
43
43
|
|
|
44
|
+
const a11y = handleChartAriaLabels(config)
|
|
45
|
+
|
|
44
46
|
const dispatch = useContext(ChartDispatchContext)
|
|
45
47
|
|
|
46
48
|
const { tooltipData, showTooltip, hideTooltip, tooltipOpen, tooltipLeft, tooltipTop } = useTooltip<TooltipData>()
|
|
@@ -232,7 +234,7 @@ const RadarChart = React.forwardRef<SVGSVGElement, RadarChartProps>((props, ref)
|
|
|
232
234
|
height={height}
|
|
233
235
|
className='radar-chart'
|
|
234
236
|
role='img'
|
|
235
|
-
aria-label={
|
|
237
|
+
aria-label={a11y}
|
|
236
238
|
onMouseEnter={handleChartMouseEnter}
|
|
237
239
|
onMouseLeave={() => {
|
|
238
240
|
handleTooltipMouseOff()
|