carbon-react 144.9.9 → 144.9.11
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/esm/components/multi-action-button/multi-action-button.component.js +1 -2
- package/esm/components/split-button/split-button.component.js +1 -2
- package/esm/components/split-button/split-button.style.js +1 -1
- package/esm/components/switch/switch.style.js +1 -1
- package/esm/hooks/__internal__/useChildButtons/useChildButtons.js +10 -8
- package/esm/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.js +23 -23
- package/lib/components/multi-action-button/multi-action-button.component.js +1 -2
- package/lib/components/split-button/split-button.component.js +1 -2
- package/lib/components/split-button/split-button.style.js +1 -1
- package/lib/components/switch/switch.style.js +1 -1
- package/lib/hooks/__internal__/useChildButtons/useChildButtons.js +9 -7
- package/lib/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.js +22 -22
- package/package.json +1 -1
|
@@ -36,8 +36,6 @@ export const MultiActionButton = ({
|
|
|
36
36
|
} = useChildButtons(buttonRef);
|
|
37
37
|
const handleInsideClick = useClickAwayListener(hideButtons);
|
|
38
38
|
const handleClick = ev => {
|
|
39
|
-
// ensure button is focused when clicked (Safari)
|
|
40
|
-
buttonRef.current?.focus();
|
|
41
39
|
showButtons();
|
|
42
40
|
handleInsideClick();
|
|
43
41
|
if (onClick) {
|
|
@@ -56,6 +54,7 @@ export const MultiActionButton = ({
|
|
|
56
54
|
...filterOutStyledSystemSpacingProps(rest)
|
|
57
55
|
};
|
|
58
56
|
const renderAdditionalButtons = () => /*#__PURE__*/React.createElement(Popover, {
|
|
57
|
+
disablePortal: true,
|
|
59
58
|
placement: position === "left" ? "bottom-start" : /* istanbul ignore next */"bottom-end",
|
|
60
59
|
reference: buttonNode,
|
|
61
60
|
middleware: [offset(6), flip({
|
|
@@ -68,8 +68,6 @@ export const SplitButton = ({
|
|
|
68
68
|
...filterOutStyledSystemSpacingProps(rest)
|
|
69
69
|
};
|
|
70
70
|
const handleToggleClick = () => {
|
|
71
|
-
// ensure button is focused when clicked (Safari)
|
|
72
|
-
toggleButton.current?.focus();
|
|
73
71
|
showButtons();
|
|
74
72
|
};
|
|
75
73
|
const toggleButtonProps = {
|
|
@@ -119,6 +117,7 @@ export const SplitButton = ({
|
|
|
119
117
|
function renderAdditionalButtons() {
|
|
120
118
|
if (!showAdditionalButtons) return null;
|
|
121
119
|
return /*#__PURE__*/React.createElement(Popover, {
|
|
120
|
+
disablePortal: true,
|
|
122
121
|
placement: position === "left" ? /* istanbul ignore next */"bottom-start" : "bottom-end",
|
|
123
122
|
reference: buttonNode,
|
|
124
123
|
middleware: [offset(6), flip({
|
|
@@ -7,7 +7,7 @@ const StyledSplitButton = styled.div`
|
|
|
7
7
|
display: inline-block;
|
|
8
8
|
position: relative;
|
|
9
9
|
|
|
10
|
-
${StyledButton}:first-of-type {
|
|
10
|
+
& > ${StyledButton}:first-of-type {
|
|
11
11
|
border-top-right-radius: var(--borderRadius000);
|
|
12
12
|
border-bottom-right-radius: var(--borderRadius000);
|
|
13
13
|
}
|
|
@@ -39,7 +39,7 @@ export const StyledHintText = styled.div`
|
|
|
39
39
|
${({
|
|
40
40
|
isDarkBackground
|
|
41
41
|
}) => css`
|
|
42
|
-
color: ${isDarkBackground ? "var(--
|
|
42
|
+
color: ${isDarkBackground ? "var(--colorsUtilityYang080)" : "var(--colorsUtilityYin055)"};
|
|
43
43
|
`}
|
|
44
44
|
`;
|
|
45
45
|
const StyledSwitch = styled.div`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useRef, useCallback } from "react";
|
|
1
|
+
import { useState, useRef, useCallback, useEffect } from "react";
|
|
2
2
|
import Events from "../../../__internal__/utils/helpers/events";
|
|
3
3
|
import useMenuKeyboardNavigation from "../useMenuKeyboardNavigation";
|
|
4
4
|
const useChildButtons = (toggleButtonRef, widthRatio = 1) => {
|
|
@@ -18,16 +18,18 @@ const useChildButtons = (toggleButtonRef, widthRatio = 1) => {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
const getButtonChildren = useCallback(() => childrenContainer.current?.querySelectorAll('[data-component="button"]'), []);
|
|
21
|
+
|
|
22
|
+
// focus first child button when opened
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (showAdditionalButtons) {
|
|
25
|
+
getButtonChildren()?.[0]?.focus();
|
|
26
|
+
}
|
|
27
|
+
}, [showAdditionalButtons, getButtonChildren]);
|
|
21
28
|
const handleToggleButtonKeyDown = ev => {
|
|
22
|
-
const isToggleKey = Events.isEnterKey(ev) || Events.isSpaceKey(ev) || Events.isDownKey(ev) || Events.isUpKey(ev)
|
|
29
|
+
const isToggleKey = Events.isEnterKey(ev) || Events.isSpaceKey(ev) || Events.isDownKey(ev) || Events.isUpKey(ev);
|
|
23
30
|
if (isToggleKey) {
|
|
24
31
|
ev.preventDefault();
|
|
25
|
-
|
|
26
|
-
showButtons();
|
|
27
|
-
}
|
|
28
|
-
setTimeout(() => {
|
|
29
|
-
getButtonChildren()?.[0]?.focus();
|
|
30
|
-
});
|
|
32
|
+
showButtons();
|
|
31
33
|
}
|
|
32
34
|
};
|
|
33
35
|
const handleKeyDown = useMenuKeyboardNavigation(toggleButtonRef, getButtonChildren, hideButtons, showAdditionalButtons);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { useCallback } from "react";
|
|
1
|
+
import { useCallback, useEffect } from "react";
|
|
2
2
|
import Events from "../../../__internal__/utils/helpers/events";
|
|
3
|
-
import { defaultFocusableSelectors } from "../../../__internal__/focus-trap/focus-trap-utils";
|
|
4
3
|
import useModalManager from "../useModalManager";
|
|
5
4
|
export default (mainControlRef, getButtonChildren, hide, isOpen) => {
|
|
6
5
|
const refocusMainControl = useCallback(() => {
|
|
@@ -22,7 +21,7 @@ export default (mainControlRef, getButtonChildren, hide, isOpen) => {
|
|
|
22
21
|
modalRef: mainControlRef
|
|
23
22
|
});
|
|
24
23
|
const handleKeyDown = useCallback(ev => {
|
|
25
|
-
if (!(Events.isEnterKey(ev) || Events.isSpaceKey(ev))) {
|
|
24
|
+
if (!(Events.isEnterKey(ev) || Events.isSpaceKey(ev) || Events.isTabKey(ev))) {
|
|
26
25
|
ev.preventDefault();
|
|
27
26
|
}
|
|
28
27
|
const buttonChildren = getButtonChildren();
|
|
@@ -42,28 +41,29 @@ export default (mainControlRef, getButtonChildren, hide, isOpen) => {
|
|
|
42
41
|
if (!arrowModifierPressed && Events.isDownKey(ev) && currentIndex < childrenLength - 1) {
|
|
43
42
|
nextIndex = currentIndex + 1;
|
|
44
43
|
}
|
|
45
|
-
const tabPressed = Events.isTabKey(ev);
|
|
46
|
-
const tabShiftPressed = tabPressed && Events.isShiftKey(ev);
|
|
47
|
-
if (tabShiftPressed) {
|
|
48
|
-
if (currentIndex === 0) {
|
|
49
|
-
refocusMainControl();
|
|
50
|
-
} else {
|
|
51
|
-
nextIndex = currentIndex - 1;
|
|
52
|
-
}
|
|
53
|
-
} else if (tabPressed) {
|
|
54
|
-
if (currentIndex === childrenLength - 1) {
|
|
55
|
-
const elements = Array.from(document.querySelectorAll(defaultFocusableSelectors)).filter(el => Number(el.tabIndex) !== -1);
|
|
56
|
-
const indexOf = elements.indexOf(mainControlRef.current);
|
|
57
|
-
elements[indexOf + 1]?.focus();
|
|
58
|
-
// timeout enforces that the "hide" method will be run after browser focuses on the next element
|
|
59
|
-
setTimeout(hide, 0);
|
|
60
|
-
} else {
|
|
61
|
-
nextIndex = currentIndex + 1;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
44
|
if (nextIndex > -1) {
|
|
65
45
|
buttonChildren?.[nextIndex]?.focus();
|
|
66
46
|
}
|
|
67
|
-
}, [
|
|
47
|
+
}, [getButtonChildren]);
|
|
48
|
+
|
|
49
|
+
// check if a child button is focused, if not hide the menu
|
|
50
|
+
const checkFocus = useCallback(() => {
|
|
51
|
+
const buttonChildren = getButtonChildren();
|
|
52
|
+
if (!buttonChildren) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const buttonChildrenFocused = Array.from(buttonChildren).some(button => button === document.activeElement);
|
|
56
|
+
if (!buttonChildrenFocused) {
|
|
57
|
+
hide();
|
|
58
|
+
}
|
|
59
|
+
}, [getButtonChildren, hide]);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
document.addEventListener("focusin", checkFocus);
|
|
62
|
+
window.addEventListener("blur", hide);
|
|
63
|
+
return () => {
|
|
64
|
+
document.removeEventListener("focusin", checkFocus);
|
|
65
|
+
window.removeEventListener("blur", hide);
|
|
66
|
+
};
|
|
67
|
+
}, [checkFocus, hide]);
|
|
68
68
|
return handleKeyDown;
|
|
69
69
|
};
|
|
@@ -45,8 +45,6 @@ const MultiActionButton = ({
|
|
|
45
45
|
} = (0, _useChildButtons.default)(buttonRef);
|
|
46
46
|
const handleInsideClick = (0, _useClickAwayListener.default)(hideButtons);
|
|
47
47
|
const handleClick = ev => {
|
|
48
|
-
// ensure button is focused when clicked (Safari)
|
|
49
|
-
buttonRef.current?.focus();
|
|
50
48
|
showButtons();
|
|
51
49
|
handleInsideClick();
|
|
52
50
|
if (onClick) {
|
|
@@ -65,6 +63,7 @@ const MultiActionButton = ({
|
|
|
65
63
|
...(0, _utils.filterOutStyledSystemSpacingProps)(rest)
|
|
66
64
|
};
|
|
67
65
|
const renderAdditionalButtons = () => /*#__PURE__*/_react.default.createElement(_popover.default, {
|
|
66
|
+
disablePortal: true,
|
|
68
67
|
placement: position === "left" ? "bottom-start" : /* istanbul ignore next */"bottom-end",
|
|
69
68
|
reference: buttonNode,
|
|
70
69
|
middleware: [(0, _dom.offset)(6), (0, _dom.flip)({
|
|
@@ -77,8 +77,6 @@ const SplitButton = ({
|
|
|
77
77
|
...(0, _utils.filterOutStyledSystemSpacingProps)(rest)
|
|
78
78
|
};
|
|
79
79
|
const handleToggleClick = () => {
|
|
80
|
-
// ensure button is focused when clicked (Safari)
|
|
81
|
-
toggleButton.current?.focus();
|
|
82
80
|
showButtons();
|
|
83
81
|
};
|
|
84
82
|
const toggleButtonProps = {
|
|
@@ -128,6 +126,7 @@ const SplitButton = ({
|
|
|
128
126
|
function renderAdditionalButtons() {
|
|
129
127
|
if (!showAdditionalButtons) return null;
|
|
130
128
|
return /*#__PURE__*/_react.default.createElement(_popover.default, {
|
|
129
|
+
disablePortal: true,
|
|
131
130
|
placement: position === "left" ? /* istanbul ignore next */"bottom-start" : "bottom-end",
|
|
132
131
|
reference: buttonNode,
|
|
133
132
|
middleware: [(0, _dom.offset)(6), (0, _dom.flip)({
|
|
@@ -16,7 +16,7 @@ const StyledSplitButton = _styledComponents.default.div`
|
|
|
16
16
|
display: inline-block;
|
|
17
17
|
position: relative;
|
|
18
18
|
|
|
19
|
-
${_button.default}:first-of-type {
|
|
19
|
+
& > ${_button.default}:first-of-type {
|
|
20
20
|
border-top-right-radius: var(--borderRadius000);
|
|
21
21
|
border-bottom-right-radius: var(--borderRadius000);
|
|
22
22
|
}
|
|
@@ -48,7 +48,7 @@ const StyledHintText = exports.StyledHintText = _styledComponents.default.div`
|
|
|
48
48
|
${({
|
|
49
49
|
isDarkBackground
|
|
50
50
|
}) => (0, _styledComponents.css)`
|
|
51
|
-
color: ${isDarkBackground ? "var(--
|
|
51
|
+
color: ${isDarkBackground ? "var(--colorsUtilityYang080)" : "var(--colorsUtilityYin055)"};
|
|
52
52
|
`}
|
|
53
53
|
`;
|
|
54
54
|
const StyledSwitch = _styledComponents.default.div`
|
|
@@ -25,16 +25,18 @@ const useChildButtons = (toggleButtonRef, widthRatio = 1) => {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
const getButtonChildren = (0, _react.useCallback)(() => childrenContainer.current?.querySelectorAll('[data-component="button"]'), []);
|
|
28
|
+
|
|
29
|
+
// focus first child button when opened
|
|
30
|
+
(0, _react.useEffect)(() => {
|
|
31
|
+
if (showAdditionalButtons) {
|
|
32
|
+
getButtonChildren()?.[0]?.focus();
|
|
33
|
+
}
|
|
34
|
+
}, [showAdditionalButtons, getButtonChildren]);
|
|
28
35
|
const handleToggleButtonKeyDown = ev => {
|
|
29
|
-
const isToggleKey = _events.default.isEnterKey(ev) || _events.default.isSpaceKey(ev) || _events.default.isDownKey(ev) || _events.default.isUpKey(ev)
|
|
36
|
+
const isToggleKey = _events.default.isEnterKey(ev) || _events.default.isSpaceKey(ev) || _events.default.isDownKey(ev) || _events.default.isUpKey(ev);
|
|
30
37
|
if (isToggleKey) {
|
|
31
38
|
ev.preventDefault();
|
|
32
|
-
|
|
33
|
-
showButtons();
|
|
34
|
-
}
|
|
35
|
-
setTimeout(() => {
|
|
36
|
-
getButtonChildren()?.[0]?.focus();
|
|
37
|
-
});
|
|
39
|
+
showButtons();
|
|
38
40
|
}
|
|
39
41
|
};
|
|
40
42
|
const handleKeyDown = (0, _useMenuKeyboardNavigation.default)(toggleButtonRef, getButtonChildren, hideButtons, showAdditionalButtons);
|
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _events = _interopRequireDefault(require("../../../__internal__/utils/helpers/events"));
|
|
9
|
-
var _focusTrapUtils = require("../../../__internal__/focus-trap/focus-trap-utils");
|
|
10
9
|
var _useModalManager = _interopRequireDefault(require("../useModalManager"));
|
|
11
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
11
|
var _default = (mainControlRef, getButtonChildren, hide, isOpen) => {
|
|
@@ -29,7 +28,7 @@ var _default = (mainControlRef, getButtonChildren, hide, isOpen) => {
|
|
|
29
28
|
modalRef: mainControlRef
|
|
30
29
|
});
|
|
31
30
|
const handleKeyDown = (0, _react.useCallback)(ev => {
|
|
32
|
-
if (!(_events.default.isEnterKey(ev) || _events.default.isSpaceKey(ev))) {
|
|
31
|
+
if (!(_events.default.isEnterKey(ev) || _events.default.isSpaceKey(ev) || _events.default.isTabKey(ev))) {
|
|
33
32
|
ev.preventDefault();
|
|
34
33
|
}
|
|
35
34
|
const buttonChildren = getButtonChildren();
|
|
@@ -49,29 +48,30 @@ var _default = (mainControlRef, getButtonChildren, hide, isOpen) => {
|
|
|
49
48
|
if (!arrowModifierPressed && _events.default.isDownKey(ev) && currentIndex < childrenLength - 1) {
|
|
50
49
|
nextIndex = currentIndex + 1;
|
|
51
50
|
}
|
|
52
|
-
const tabPressed = _events.default.isTabKey(ev);
|
|
53
|
-
const tabShiftPressed = tabPressed && _events.default.isShiftKey(ev);
|
|
54
|
-
if (tabShiftPressed) {
|
|
55
|
-
if (currentIndex === 0) {
|
|
56
|
-
refocusMainControl();
|
|
57
|
-
} else {
|
|
58
|
-
nextIndex = currentIndex - 1;
|
|
59
|
-
}
|
|
60
|
-
} else if (tabPressed) {
|
|
61
|
-
if (currentIndex === childrenLength - 1) {
|
|
62
|
-
const elements = Array.from(document.querySelectorAll(_focusTrapUtils.defaultFocusableSelectors)).filter(el => Number(el.tabIndex) !== -1);
|
|
63
|
-
const indexOf = elements.indexOf(mainControlRef.current);
|
|
64
|
-
elements[indexOf + 1]?.focus();
|
|
65
|
-
// timeout enforces that the "hide" method will be run after browser focuses on the next element
|
|
66
|
-
setTimeout(hide, 0);
|
|
67
|
-
} else {
|
|
68
|
-
nextIndex = currentIndex + 1;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
51
|
if (nextIndex > -1) {
|
|
72
52
|
buttonChildren?.[nextIndex]?.focus();
|
|
73
53
|
}
|
|
74
|
-
}, [
|
|
54
|
+
}, [getButtonChildren]);
|
|
55
|
+
|
|
56
|
+
// check if a child button is focused, if not hide the menu
|
|
57
|
+
const checkFocus = (0, _react.useCallback)(() => {
|
|
58
|
+
const buttonChildren = getButtonChildren();
|
|
59
|
+
if (!buttonChildren) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const buttonChildrenFocused = Array.from(buttonChildren).some(button => button === document.activeElement);
|
|
63
|
+
if (!buttonChildrenFocused) {
|
|
64
|
+
hide();
|
|
65
|
+
}
|
|
66
|
+
}, [getButtonChildren, hide]);
|
|
67
|
+
(0, _react.useEffect)(() => {
|
|
68
|
+
document.addEventListener("focusin", checkFocus);
|
|
69
|
+
window.addEventListener("blur", hide);
|
|
70
|
+
return () => {
|
|
71
|
+
document.removeEventListener("focusin", checkFocus);
|
|
72
|
+
window.removeEventListener("blur", hide);
|
|
73
|
+
};
|
|
74
|
+
}, [checkFocus, hide]);
|
|
75
75
|
return handleKeyDown;
|
|
76
76
|
};
|
|
77
77
|
exports.default = _default;
|