@react-magma/charts 15.0.0-rc.2 → 15.0.0-rc.3
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/charts.js +45 -1
- package/dist/charts.js.map +1 -1
- package/dist/charts.modern.module.js +46 -2
- package/dist/charts.modern.module.js.map +1 -1
- package/dist/charts.umd.js +207 -6
- package/dist/charts.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CarbonChart/CarbonChart.test.js +8 -3
- package/src/components/CarbonChart/CarbonChart.tsx +56 -1
package/package.json
CHANGED
|
@@ -17,10 +17,14 @@ global.ResizeObserver = jest.fn().mockImplementation(() => ({
|
|
|
17
17
|
disconnect: jest.fn(),
|
|
18
18
|
}));
|
|
19
19
|
|
|
20
|
-
// Capture MutationObserver callbacks so we can trigger them manually
|
|
21
|
-
|
|
20
|
+
// Capture MutationObserver callbacks so we can trigger them manually.
|
|
21
|
+
// Multiple observers may be created per component; we collect all of them and
|
|
22
|
+
// call each one so that no observer is silently skipped.
|
|
23
|
+
let mutationObserverCallbacks = [];
|
|
24
|
+
const mutationObserverCallback = mutations =>
|
|
25
|
+
mutationObserverCallbacks.forEach(cb => cb(mutations));
|
|
22
26
|
global.MutationObserver = jest.fn().mockImplementation(callback => {
|
|
23
|
-
|
|
27
|
+
mutationObserverCallbacks.push(callback);
|
|
24
28
|
return {
|
|
25
29
|
observe: jest.fn(),
|
|
26
30
|
disconnect: jest.fn(),
|
|
@@ -603,6 +607,7 @@ describe('CarbonChart', () => {
|
|
|
603
607
|
let otherButton;
|
|
604
608
|
|
|
605
609
|
beforeEach(() => {
|
|
610
|
+
mutationObserverCallbacks = [];
|
|
606
611
|
jest.useFakeTimers();
|
|
607
612
|
jest.spyOn(window, 'requestAnimationFrame').mockImplementation(cb => {
|
|
608
613
|
cb(0);
|
|
@@ -24,11 +24,13 @@ import {
|
|
|
24
24
|
import styled from '@emotion/styled';
|
|
25
25
|
import { transparentize } from 'polished';
|
|
26
26
|
import {
|
|
27
|
+
Announce,
|
|
27
28
|
DropdownDivider,
|
|
28
29
|
DropdownMenuItem,
|
|
29
30
|
ThemeInterface,
|
|
30
31
|
ThemeContext,
|
|
31
32
|
useIsInverse,
|
|
33
|
+
VisuallyHidden,
|
|
32
34
|
} from 'react-magma-dom';
|
|
33
35
|
import {
|
|
34
36
|
FullscreenExitIcon,
|
|
@@ -1075,7 +1077,9 @@ export const CarbonChart = React.forwardRef<HTMLDivElement, CarbonChartProps>(
|
|
|
1075
1077
|
|
|
1076
1078
|
const [isTableOpen, setIsTableOpen] = React.useState(false);
|
|
1077
1079
|
const [isFullscreen, setIsFullscreen] = React.useState(false);
|
|
1080
|
+
const [legendAnnouncement, setLegendAnnouncement] = React.useState('');
|
|
1078
1081
|
const lastTableTriggerRef = React.useRef<HTMLButtonElement | null>(null);
|
|
1082
|
+
const legendAnnouncedRef = React.useRef(false);
|
|
1079
1083
|
|
|
1080
1084
|
const mergedRef = React.useCallback(
|
|
1081
1085
|
(node: HTMLDivElement | null) => {
|
|
@@ -1179,7 +1183,9 @@ export const CarbonChart = React.forwardRef<HTMLDivElement, CarbonChartProps>(
|
|
|
1179
1183
|
if (parent?.tagName === 'FIELDSET') {
|
|
1180
1184
|
const existingCaption = parent.querySelector('legend');
|
|
1181
1185
|
|
|
1182
|
-
if (existingCaption
|
|
1186
|
+
if (existingCaption && existingCaption.textContent !== legendLabel) {
|
|
1187
|
+
existingCaption.textContent = legendLabel;
|
|
1188
|
+
}
|
|
1183
1189
|
|
|
1184
1190
|
return;
|
|
1185
1191
|
}
|
|
@@ -1290,12 +1296,61 @@ export const CarbonChart = React.forwardRef<HTMLDivElement, CarbonChartProps>(
|
|
|
1290
1296
|
return () => clearTimeout(timer);
|
|
1291
1297
|
}, [type, dataSet]);
|
|
1292
1298
|
|
|
1299
|
+
React.useEffect(() => {
|
|
1300
|
+
const wrapper = internalRef.current;
|
|
1301
|
+
|
|
1302
|
+
if (!wrapper) return;
|
|
1303
|
+
|
|
1304
|
+
const observer = new MutationObserver(() => {
|
|
1305
|
+
const allItems = wrapper.querySelectorAll<HTMLElement>(
|
|
1306
|
+
'.legend-item:not(.additional)'
|
|
1307
|
+
);
|
|
1308
|
+
|
|
1309
|
+
if (allItems.length <= 1) return;
|
|
1310
|
+
|
|
1311
|
+
const activeLabels: string[] = [];
|
|
1312
|
+
|
|
1313
|
+
allItems.forEach(el => {
|
|
1314
|
+
const checkbox = el.querySelector<HTMLElement>('.checkbox');
|
|
1315
|
+
const label = el.querySelector('p');
|
|
1316
|
+
|
|
1317
|
+
if (checkbox?.getAttribute('aria-checked') === 'true' && label) {
|
|
1318
|
+
activeLabels.push(label.textContent?.trim() || '');
|
|
1319
|
+
}
|
|
1320
|
+
});
|
|
1321
|
+
|
|
1322
|
+
if (activeLabels.length === 1) {
|
|
1323
|
+
if (!legendAnnouncedRef.current) {
|
|
1324
|
+
legendAnnouncedRef.current = true;
|
|
1325
|
+
setLegendAnnouncement(`Only ${activeLabels[0]} is selected`);
|
|
1326
|
+
}
|
|
1327
|
+
} else if (activeLabels.length === allItems.length) {
|
|
1328
|
+
legendAnnouncedRef.current = false;
|
|
1329
|
+
setLegendAnnouncement('All items selected');
|
|
1330
|
+
} else {
|
|
1331
|
+
legendAnnouncedRef.current = false;
|
|
1332
|
+
setLegendAnnouncement('');
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
|
|
1336
|
+
observer.observe(wrapper, {
|
|
1337
|
+
subtree: true,
|
|
1338
|
+
attributes: true,
|
|
1339
|
+
attributeFilter: ['aria-checked'],
|
|
1340
|
+
});
|
|
1341
|
+
|
|
1342
|
+
return () => observer.disconnect();
|
|
1343
|
+
}, [type, dataSet]);
|
|
1344
|
+
|
|
1293
1345
|
const groupsLength = Object.keys(buildColors()).length;
|
|
1294
1346
|
|
|
1295
1347
|
const showTable = chartToolbar?.showAsTable !== false;
|
|
1296
1348
|
|
|
1297
1349
|
return (
|
|
1298
1350
|
<FullscreenRoot ref={mergedRef} isInverse={isInverse} theme={theme}>
|
|
1351
|
+
<VisuallyHidden>
|
|
1352
|
+
<Announce>{legendAnnouncement}</Announce>
|
|
1353
|
+
</VisuallyHidden>
|
|
1299
1354
|
<CarbonChartWrapper
|
|
1300
1355
|
data-testid={testId}
|
|
1301
1356
|
isInverse={isInverse}
|