carbon-react 109.2.4 → 109.3.2
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/__internal__/field-help/field-help.component.d.ts +10 -0
- package/esm/__internal__/field-help/field-help.component.js +12 -16
- package/esm/__internal__/field-help/field-help.style.d.ts +8 -0
- package/esm/__internal__/field-help/field-help.style.js +2 -10
- package/esm/__internal__/field-help/index.d.ts +2 -1
- package/esm/__internal__/focus-trap/focus-trap-utils.d.ts +1 -2
- package/esm/__internal__/focus-trap/focus-trap-utils.js +57 -8
- package/esm/__internal__/focus-trap/focus-trap.component.js +35 -25
- package/esm/__spec_helper__/index.d.ts +1 -0
- package/esm/__spec_helper__/index.js +4 -10
- package/esm/__spec_helper__/mock-match-media.d.ts +2 -2
- package/esm/__spec_helper__/mock-match-media.js +2 -2
- package/esm/__spec_helper__/mock-resize-observer.d.ts +2 -0
- package/esm/components/alert/alert.component.js +9 -0
- package/esm/components/dialog/dialog.component.js +9 -2
- package/esm/components/dialog/dialog.d.ts +2 -0
- package/esm/components/dialog-full-screen/dialog-full-screen.component.js +9 -2
- package/esm/components/dialog-full-screen/dialog-full-screen.d.ts +2 -0
- package/esm/components/grid/grid-container/grid-container.component.d.ts +8 -0
- package/esm/components/grid/grid-container/grid-container.component.js +1821 -21
- package/esm/components/grid/grid-container/grid-container.style.d.ts +3 -0
- package/esm/components/grid/grid-container/grid-container.style.js +2 -2
- package/esm/components/grid/grid-container/index.d.ts +2 -1
- package/esm/components/grid/grid-item/grid-item.component.d.ts +11 -0
- package/esm/components/grid/grid-item/grid-item.component.js +1221 -45
- package/esm/components/grid/grid-item/grid-item.style.d.ts +17 -0
- package/esm/components/grid/grid-item/grid-item.style.js +38 -62
- package/esm/components/grid/grid-item/index.d.ts +2 -1
- package/esm/components/grid/index.d.ts +2 -0
- package/esm/components/grid/index.js +2 -3
- package/esm/components/multi-action-button/multi-action-button.component.js +14 -84
- package/esm/components/select/utils/highlight-part-of-text.js +13 -1
- package/esm/components/select/utils/with-filter.hoc.js +3 -2
- package/esm/components/sidebar/sidebar.component.js +9 -2
- package/esm/components/sidebar/sidebar.d.ts +2 -0
- package/esm/components/split-button/split-button.component.js +15 -82
- package/esm/components/toast/toast.component.js +35 -9
- package/esm/components/toast/toast.d.ts +5 -1
- package/esm/hooks/__internal__/useMenuKeyboardNavigation/index.d.ts +1 -0
- package/esm/hooks/__internal__/useMenuKeyboardNavigation/index.js +1 -0
- package/esm/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.d.ts +2 -0
- package/esm/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.js +70 -0
- package/lib/__internal__/field-help/field-help.component.d.ts +10 -0
- package/lib/__internal__/field-help/field-help.component.js +12 -16
- package/lib/__internal__/field-help/field-help.style.d.ts +8 -0
- package/lib/__internal__/field-help/field-help.style.js +2 -13
- package/lib/__internal__/field-help/index.d.ts +2 -1
- package/lib/__internal__/focus-trap/focus-trap-utils.d.ts +1 -2
- package/lib/__internal__/focus-trap/focus-trap-utils.js +57 -10
- package/lib/__internal__/focus-trap/focus-trap.component.js +34 -24
- package/lib/__spec_helper__/index.d.ts +1 -0
- package/lib/__spec_helper__/index.js +3 -10
- package/lib/__spec_helper__/mock-match-media.d.ts +2 -2
- package/lib/__spec_helper__/mock-match-media.js +4 -4
- package/lib/__spec_helper__/mock-resize-observer.d.ts +2 -0
- package/lib/components/alert/alert.component.js +9 -0
- package/lib/components/dialog/dialog.component.js +9 -2
- package/lib/components/dialog/dialog.d.ts +2 -0
- package/lib/components/dialog-full-screen/dialog-full-screen.component.js +9 -2
- package/lib/components/dialog-full-screen/dialog-full-screen.d.ts +2 -0
- package/lib/components/grid/grid-container/grid-container.component.d.ts +8 -0
- package/lib/components/grid/grid-container/grid-container.component.js +1826 -22
- package/lib/components/grid/grid-container/grid-container.style.d.ts +3 -0
- package/lib/components/grid/grid-container/grid-container.style.js +2 -2
- package/lib/components/grid/grid-container/index.d.ts +2 -1
- package/lib/components/grid/grid-item/grid-item.component.d.ts +11 -0
- package/lib/components/grid/grid-item/grid-item.component.js +1221 -46
- package/lib/components/grid/grid-item/grid-item.style.d.ts +17 -0
- package/lib/components/grid/grid-item/grid-item.style.js +37 -67
- package/lib/components/grid/grid-item/index.d.ts +2 -1
- package/lib/components/grid/index.d.ts +2 -0
- package/lib/components/multi-action-button/multi-action-button.component.js +13 -83
- package/lib/components/select/utils/highlight-part-of-text.js +13 -1
- package/lib/components/select/utils/with-filter.hoc.js +3 -2
- package/lib/components/sidebar/sidebar.component.js +9 -2
- package/lib/components/sidebar/sidebar.d.ts +2 -0
- package/lib/components/split-button/split-button.component.js +14 -83
- package/lib/components/toast/toast.component.js +35 -7
- package/lib/components/toast/toast.d.ts +5 -1
- package/lib/hooks/__internal__/useMenuKeyboardNavigation/index.d.ts +1 -0
- package/lib/hooks/__internal__/useMenuKeyboardNavigation/index.js +15 -0
- package/lib/hooks/__internal__/useMenuKeyboardNavigation/package.json +6 -0
- package/lib/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.d.ts +2 -0
- package/lib/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.js +85 -0
- package/package.json +3 -4
- package/esm/__internal__/field-help/field-help.d.ts +0 -14
- package/esm/components/grid/grid-container/grid-container.d.ts +0 -18
- package/esm/components/grid/grid-item/grid-item.d.ts +0 -42
- package/lib/__internal__/field-help/field-help.d.ts +0 -14
- package/lib/components/grid/grid-container/grid-container.d.ts +0 -18
- package/lib/components/grid/grid-item/grid-item.d.ts +0 -42
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PaddingProps, GridAreaProps, GridColumnProps, GridRowProps } from "styled-system";
|
|
2
|
+
export declare function getSpacing(prop?: PaddingProps[keyof PaddingProps]): string;
|
|
3
|
+
interface GridProperties extends PaddingProps {
|
|
4
|
+
alignSelf?: string;
|
|
5
|
+
justifySelf?: string;
|
|
6
|
+
gridColumn?: GridColumnProps["gridColumn"];
|
|
7
|
+
gridRow?: GridRowProps["gridRow"];
|
|
8
|
+
gridArea?: GridAreaProps["gridArea"];
|
|
9
|
+
}
|
|
10
|
+
interface ResponsiveSettings extends GridProperties {
|
|
11
|
+
maxWidth?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface StyledGridItemProps extends GridProperties {
|
|
14
|
+
responsiveSettings?: ResponsiveSettings[];
|
|
15
|
+
}
|
|
16
|
+
declare const StyledGridItem: import("styled-components").StyledComponent<"div", any, StyledGridItemProps, never>;
|
|
17
|
+
export default StyledGridItem;
|
|
@@ -1,42 +1,5 @@
|
|
|
1
1
|
import styled, { css } from "styled-components";
|
|
2
|
-
import { grid, flexbox } from "styled-system";
|
|
3
|
-
import styledSystemPropTypes from "@styled-system/prop-types";
|
|
4
|
-
import { padding } from "@styled-system/space";
|
|
5
|
-
import PropTypes from "prop-types";
|
|
6
|
-
import { filterStyledSystemPaddingProps } from "../../../style/utils";
|
|
7
|
-
|
|
8
|
-
function responsiveGridItem(responsiveSettings) {
|
|
9
|
-
return responsiveSettings.map(setting => {
|
|
10
|
-
const {
|
|
11
|
-
alignSelf,
|
|
12
|
-
gridArea,
|
|
13
|
-
gridColumn,
|
|
14
|
-
gridRow,
|
|
15
|
-
maxWidth,
|
|
16
|
-
justifySelf,
|
|
17
|
-
p,
|
|
18
|
-
pl,
|
|
19
|
-
pr,
|
|
20
|
-
pt,
|
|
21
|
-
pb
|
|
22
|
-
} = setting;
|
|
23
|
-
return css`
|
|
24
|
-
@media screen and (max-width: ${maxWidth}) {
|
|
25
|
-
align-self: ${alignSelf || "stretch"};
|
|
26
|
-
justify-self: ${justifySelf || "stretch"};
|
|
27
|
-
grid-area: ${gridArea};
|
|
28
|
-
grid-column: ${gridColumn};
|
|
29
|
-
grid-row: ${gridRow};
|
|
30
|
-
padding: ${getSpacing(p)};
|
|
31
|
-
padding-left: ${getSpacing(pl)};
|
|
32
|
-
padding-right: ${getSpacing(pr)};
|
|
33
|
-
padding-top: ${getSpacing(pt)};
|
|
34
|
-
padding-bottom: ${getSpacing(pb)};
|
|
35
|
-
}
|
|
36
|
-
`;
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
2
|
+
import { grid, flexbox, padding } from "styled-system";
|
|
40
3
|
export function getSpacing(prop) {
|
|
41
4
|
if (typeof prop === "number") {
|
|
42
5
|
switch (prop) {
|
|
@@ -78,17 +41,49 @@ export function getSpacing(prop) {
|
|
|
78
41
|
}
|
|
79
42
|
}
|
|
80
43
|
|
|
81
|
-
return prop;
|
|
44
|
+
return String(prop);
|
|
82
45
|
}
|
|
83
|
-
|
|
84
|
-
|
|
46
|
+
|
|
47
|
+
function responsiveGridItem(responsiveSettings) {
|
|
48
|
+
return responsiveSettings.map(setting => {
|
|
49
|
+
const {
|
|
50
|
+
alignSelf,
|
|
51
|
+
gridArea,
|
|
52
|
+
gridColumn,
|
|
53
|
+
gridRow,
|
|
54
|
+
maxWidth,
|
|
55
|
+
justifySelf,
|
|
56
|
+
p,
|
|
57
|
+
pl,
|
|
58
|
+
pr,
|
|
59
|
+
pt,
|
|
60
|
+
pb
|
|
61
|
+
} = setting;
|
|
62
|
+
return css`
|
|
63
|
+
@media screen and (max-width: ${maxWidth}) {
|
|
64
|
+
align-self: ${alignSelf || "stretch"};
|
|
65
|
+
justify-self: ${justifySelf || "stretch"};
|
|
66
|
+
grid-area: ${gridArea};
|
|
67
|
+
grid-column: ${gridColumn};
|
|
68
|
+
grid-row: ${gridRow};
|
|
69
|
+
padding: ${getSpacing(p)};
|
|
70
|
+
padding-left: ${getSpacing(pl)};
|
|
71
|
+
padding-right: ${getSpacing(pr)};
|
|
72
|
+
padding-top: ${getSpacing(pt)};
|
|
73
|
+
padding-bottom: ${getSpacing(pb)};
|
|
74
|
+
}
|
|
75
|
+
`;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const StyledGridItem = styled.div`
|
|
85
80
|
margin: 0;
|
|
86
81
|
${padding}
|
|
87
82
|
|
|
88
83
|
${({
|
|
89
84
|
alignSelf,
|
|
90
85
|
justifySelf,
|
|
91
|
-
gridArea,
|
|
86
|
+
gridArea = "auto / 1 / auto / 13",
|
|
92
87
|
gridColumn,
|
|
93
88
|
gridRow,
|
|
94
89
|
responsiveSettings
|
|
@@ -108,23 +103,4 @@ const GridItemStyle = styled.div`
|
|
|
108
103
|
`}
|
|
109
104
|
`}
|
|
110
105
|
`;
|
|
111
|
-
|
|
112
|
-
alignSelf: PropTypes.string,
|
|
113
|
-
gridColumn: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
114
|
-
gridRow: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
115
|
-
justifySelf: PropTypes.string,
|
|
116
|
-
...paddingPropTypes,
|
|
117
|
-
responsiveSettings: PropTypes.arrayOf(PropTypes.shape({
|
|
118
|
-
alignSelf: PropTypes.string,
|
|
119
|
-
gridArea: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
120
|
-
gridColumn: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
121
|
-
gridRow: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
122
|
-
justifySelf: PropTypes.string,
|
|
123
|
-
maxWidth: PropTypes.string,
|
|
124
|
-
...paddingPropTypes
|
|
125
|
-
}))
|
|
126
|
-
};
|
|
127
|
-
GridItemStyle.defaultProps = {
|
|
128
|
-
gridArea: "auto / 1 / auto / 13"
|
|
129
|
-
};
|
|
130
|
-
export default GridItemStyle;
|
|
106
|
+
export default StyledGridItem;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { default } from "./grid-item";
|
|
1
|
+
export { default } from "./grid-item.component";
|
|
2
|
+
export type { GridItemProps } from "./grid-item.component";
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export { GridContainer, GridItem };
|
|
1
|
+
export { default as GridContainer } from "./grid-container";
|
|
2
|
+
export { default as GridItem } from "./grid-item";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
2
|
|
|
3
|
-
import React, { useCallback,
|
|
3
|
+
import React, { useCallback, useState, useRef, useMemo } from "react";
|
|
4
4
|
import PropTypes from "prop-types";
|
|
5
5
|
import useClickAwayListener from "../../hooks/__internal__/useClickAwayListener";
|
|
6
6
|
import { StyledMultiActionButton, StyledButtonChildrenContainer } from "./multi-action-button.style";
|
|
@@ -8,7 +8,7 @@ import Button from "../button";
|
|
|
8
8
|
import Events from "../../__internal__/utils/helpers/events";
|
|
9
9
|
import Popover from "../../__internal__/popover";
|
|
10
10
|
import { filterStyledSystemMarginProps, filterOutStyledSystemSpacingProps } from "../../style/utils";
|
|
11
|
-
import
|
|
11
|
+
import useMenuKeyboardNavigation from "../../hooks/__internal__/useMenuKeyboardNavigation";
|
|
12
12
|
|
|
13
13
|
const MultiActionButton = ({
|
|
14
14
|
align = "left",
|
|
@@ -26,14 +26,11 @@ const MultiActionButton = ({
|
|
|
26
26
|
const buttonRef = useRef(null);
|
|
27
27
|
const buttonContainer = useRef(null);
|
|
28
28
|
const buttonChildren = useMemo(() => React.Children.toArray(children), [children]);
|
|
29
|
-
const
|
|
30
|
-
const listening = useRef(false);
|
|
31
|
-
const isMainButtonFocused = useRef(false);
|
|
32
|
-
const isFocusedAfterClosing = useRef(false);
|
|
29
|
+
const buttonChildrenRefs = useMemo(() => buttonChildren.map(() => /*#__PURE__*/React.createRef()), [buttonChildren]);
|
|
33
30
|
const [showAdditionalButtons, setShowAdditionalButtons] = useState(false);
|
|
34
31
|
const [minWidth, setMinWidth] = useState(0);
|
|
35
32
|
const hideButtons = useCallback(() => {
|
|
36
|
-
if (
|
|
33
|
+
if (buttonRef.current === document.activeElement) return;
|
|
37
34
|
setShowAdditionalButtons(false);
|
|
38
35
|
}, []);
|
|
39
36
|
|
|
@@ -55,15 +52,13 @@ const MultiActionButton = ({
|
|
|
55
52
|
const props = {
|
|
56
53
|
key: index.toString(),
|
|
57
54
|
role: "menuitem",
|
|
58
|
-
ref:
|
|
55
|
+
ref: buttonChildrenRefs[index],
|
|
59
56
|
tabIndex: -1,
|
|
60
57
|
onClick: ev => {
|
|
61
58
|
var _buttonRef$current;
|
|
62
59
|
|
|
63
60
|
if (child.props.onClick) child.props.onClick(ev);
|
|
64
|
-
isMainButtonFocused.current = false;
|
|
65
61
|
hideButtons();
|
|
66
|
-
isFocusedAfterClosing.current = true;
|
|
67
62
|
(_buttonRef$current = buttonRef.current) === null || _buttonRef$current === void 0 ? void 0 : _buttonRef$current.focus();
|
|
68
63
|
}
|
|
69
64
|
};
|
|
@@ -71,62 +66,10 @@ const MultiActionButton = ({
|
|
|
71
66
|
});
|
|
72
67
|
};
|
|
73
68
|
|
|
74
|
-
const handleKeyDown =
|
|
75
|
-
const currentIndex = additionalButtons.current.findIndex(node => node.current === document.activeElement);
|
|
76
|
-
let nextIndex = -1;
|
|
77
|
-
|
|
78
|
-
if (Events.isUpKey(ev)) {
|
|
79
|
-
nextIndex = currentIndex > 0 ? currentIndex - 1 : buttonChildren.length - 1;
|
|
80
|
-
ev.preventDefault();
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (Events.isDownKey(ev)) {
|
|
84
|
-
nextIndex = currentIndex < buttonChildren.length - 1 ? currentIndex + 1 : 0;
|
|
85
|
-
ev.preventDefault();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (Events.isTabKey(ev)) {
|
|
89
|
-
var _elements$indexOf;
|
|
90
|
-
|
|
91
|
-
const elements = Array.from(document.querySelectorAll(defaultFocusableSelectors)).filter(el => Number(el.tabIndex) !== -1);
|
|
92
|
-
const indexOf = elements.indexOf(buttonRef.current);
|
|
93
|
-
(_elements$indexOf = elements[indexOf]) === null || _elements$indexOf === void 0 ? void 0 : _elements$indexOf.focus(); // timeout enforces that the "hideButtons" method will be run after browser focuses on the next element
|
|
94
|
-
|
|
95
|
-
setTimeout(hideButtons, 0);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (nextIndex > -1) {
|
|
99
|
-
var _additionalButtons$cu;
|
|
100
|
-
|
|
101
|
-
(_additionalButtons$cu = additionalButtons.current[nextIndex].current) === null || _additionalButtons$cu === void 0 ? void 0 : _additionalButtons$cu.focus();
|
|
102
|
-
}
|
|
103
|
-
}, [buttonChildren, hideButtons]);
|
|
104
|
-
const addListeners = useCallback(() => {
|
|
105
|
-
/* istanbul ignore else */
|
|
106
|
-
if (!listening.current) {
|
|
107
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
108
|
-
listening.current = true;
|
|
109
|
-
}
|
|
110
|
-
}, [handleKeyDown]);
|
|
111
|
-
const removeListeners = useCallback(() => {
|
|
112
|
-
/* istanbul ignore else */
|
|
113
|
-
if (listening.current) {
|
|
114
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
115
|
-
listening.current = false;
|
|
116
|
-
}
|
|
117
|
-
}, [handleKeyDown]);
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
if (showAdditionalButtons) {
|
|
120
|
-
addListeners();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return () => {
|
|
124
|
-
removeListeners();
|
|
125
|
-
};
|
|
126
|
-
}, [showAdditionalButtons, addListeners, removeListeners]);
|
|
69
|
+
const handleKeyDown = useMenuKeyboardNavigation(buttonRef, buttonChildrenRefs, hideButtons);
|
|
127
70
|
|
|
128
71
|
const handleMainButtonKeyDown = ev => {
|
|
129
|
-
if (Events.isEnterKey(ev) || Events.isSpaceKey(ev) || Events.isDownKey(ev)) {
|
|
72
|
+
if (Events.isEnterKey(ev) || Events.isSpaceKey(ev) || Events.isDownKey(ev) || Events.isUpKey(ev)) {
|
|
130
73
|
ev.preventDefault();
|
|
131
74
|
|
|
132
75
|
if (!showAdditionalButtons) {
|
|
@@ -135,34 +78,20 @@ const MultiActionButton = ({
|
|
|
135
78
|
|
|
136
79
|
|
|
137
80
|
setTimeout(() => {
|
|
138
|
-
var
|
|
81
|
+
var _buttonChildrenRefs$, _buttonChildrenRefs$$;
|
|
139
82
|
|
|
140
|
-
(
|
|
83
|
+
(_buttonChildrenRefs$ = buttonChildrenRefs[0]) === null || _buttonChildrenRefs$ === void 0 ? void 0 : (_buttonChildrenRefs$$ = _buttonChildrenRefs$.current) === null || _buttonChildrenRefs$$ === void 0 ? void 0 : _buttonChildrenRefs$$.focus();
|
|
141
84
|
}, 0);
|
|
85
|
+
} else if (Events.isEscKey(ev)) {
|
|
86
|
+
ev.preventDefault();
|
|
87
|
+
setShowAdditionalButtons(false);
|
|
142
88
|
}
|
|
143
89
|
};
|
|
144
90
|
|
|
145
|
-
const focusMainButton = () => {
|
|
146
|
-
isMainButtonFocused.current = true;
|
|
147
|
-
|
|
148
|
-
if (isFocusedAfterClosing.current) {
|
|
149
|
-
isFocusedAfterClosing.current = false;
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
showButtons();
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const blurMainButton = () => {
|
|
157
|
-
isMainButtonFocused.current = false;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
91
|
const mainButtonProps = {
|
|
161
92
|
disabled,
|
|
162
93
|
displayed: showAdditionalButtons,
|
|
163
94
|
onTouchStart: showButtons,
|
|
164
|
-
onFocus: focusMainButton,
|
|
165
|
-
onBlur: blurMainButton,
|
|
166
95
|
onKeyDown: handleMainButtonKeyDown,
|
|
167
96
|
buttonType,
|
|
168
97
|
size,
|
|
@@ -182,7 +111,8 @@ const MultiActionButton = ({
|
|
|
182
111
|
"data-element": "additional-buttons",
|
|
183
112
|
align: align,
|
|
184
113
|
minWidth: minWidth,
|
|
185
|
-
ref: buttonContainer
|
|
114
|
+
ref: buttonContainer,
|
|
115
|
+
onKeyDown: handleKeyDown
|
|
186
116
|
}, childrenWithProps()));
|
|
187
117
|
|
|
188
118
|
useClickAwayListener([ref], hideButtons);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import MatchingText from "./matching-text.style";
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
function highlightPartOfText(text, partToHighlight) {
|
|
4
5
|
if (!partToHighlight || !partToHighlight.length || !text) return text;
|
|
5
6
|
const lowercaseText = text.toLowerCase();
|
|
6
7
|
const lowercasePart = partToHighlight.toLowerCase();
|
|
@@ -26,4 +27,15 @@ export default function highlightPartOfText(text, partToHighlight) {
|
|
|
26
27
|
key: "following"
|
|
27
28
|
}, followingText)];
|
|
28
29
|
return newValue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default function highlightPartOfTextRecursive(child, partToHighlight) {
|
|
33
|
+
if (typeof child === "string") {
|
|
34
|
+
return highlightPartOfText(child, partToHighlight);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const highlightedChildren = React.Children.map(child.props.children, grandChild => highlightPartOfTextRecursive(grandChild, partToHighlight));
|
|
38
|
+
return /*#__PURE__*/React.cloneElement(child, {
|
|
39
|
+
children: highlightedChildren
|
|
40
|
+
});
|
|
29
41
|
}
|
|
@@ -29,9 +29,10 @@ const filterOptionRows = (optionRow, filterText) => {
|
|
|
29
29
|
const processedText = cell.props.children.toLowerCase();
|
|
30
30
|
const processedValue = filterText.toLowerCase();
|
|
31
31
|
return processedText.includes(processedValue);
|
|
32
|
-
}
|
|
32
|
+
} // filter recursively based on children
|
|
33
|
+
|
|
33
34
|
|
|
34
|
-
return
|
|
35
|
+
return filterOptionRows(cell, filterText);
|
|
35
36
|
});
|
|
36
37
|
|
|
37
38
|
if (hasText) {
|
|
@@ -26,6 +26,7 @@ const Sidebar = /*#__PURE__*/React.forwardRef(({
|
|
|
26
26
|
children,
|
|
27
27
|
onCancel,
|
|
28
28
|
role = "dialog",
|
|
29
|
+
focusableContainers,
|
|
29
30
|
...rest
|
|
30
31
|
}, ref) => {
|
|
31
32
|
const locale = useLocale();
|
|
@@ -84,7 +85,8 @@ const Sidebar = /*#__PURE__*/React.forwardRef(({
|
|
|
84
85
|
className: "carbon-sidebar"
|
|
85
86
|
}, componentTags), enableBackgroundUI ? sidebar : /*#__PURE__*/React.createElement(FocusTrap, {
|
|
86
87
|
wrapperRef: sidebarRef,
|
|
87
|
-
isOpen: open
|
|
88
|
+
isOpen: open,
|
|
89
|
+
additionalWrapperRefs: focusableContainers
|
|
88
90
|
}, sidebar));
|
|
89
91
|
});
|
|
90
92
|
Sidebar.propTypes = {
|
|
@@ -122,7 +124,12 @@ Sidebar.propTypes = {
|
|
|
122
124
|
header: PropTypes.node,
|
|
123
125
|
|
|
124
126
|
/** The ARIA role to be applied to the container */
|
|
125
|
-
role: PropTypes.string
|
|
127
|
+
role: PropTypes.string,
|
|
128
|
+
|
|
129
|
+
/** an optional array of refs to containers whose content should also be reachable by tabbing from the sidebar */
|
|
130
|
+
focusableContainers: PropTypes.arrayOf(PropTypes.shape({
|
|
131
|
+
current: PropTypes.any
|
|
132
|
+
}))
|
|
126
133
|
};
|
|
127
134
|
Sidebar.defaultProps = {
|
|
128
135
|
position: "right",
|
|
@@ -42,6 +42,8 @@ export interface SidebarProps {
|
|
|
42
42
|
| "medium-large"
|
|
43
43
|
| "large"
|
|
44
44
|
| "extra-large";
|
|
45
|
+
/** an optional array of refs to containers whose content should also be reachable by tabbing from the sidebar */
|
|
46
|
+
focusableContainers?: React.MutableRefObject<HTMLElement>[];
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
declare const SidebarContext: React.Context<SidebarContextProps>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
2
|
|
|
3
|
-
import React, {
|
|
3
|
+
import React, { useContext, useCallback, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { ThemeContext } from "styled-components";
|
|
5
5
|
import PropTypes from "prop-types";
|
|
6
6
|
import styledSystemPropTypes from "@styled-system/prop-types";
|
|
@@ -15,7 +15,7 @@ import guid from "../../__internal__/utils/helpers/guid";
|
|
|
15
15
|
import Popover from "../../__internal__/popover";
|
|
16
16
|
import { filterStyledSystemMarginProps, filterOutStyledSystemSpacingProps } from "../../style/utils";
|
|
17
17
|
import { baseTheme } from "../../style/themes";
|
|
18
|
-
import
|
|
18
|
+
import useMenuKeyboardNavigation from "../../hooks/__internal__/useMenuKeyboardNavigation";
|
|
19
19
|
const marginPropTypes = filterStyledSystemMarginProps(styledSystemPropTypes.space);
|
|
20
20
|
const CONTENT_WIDTH_RATIO = 0.75;
|
|
21
21
|
|
|
@@ -35,73 +35,19 @@ const SplitButton = ({
|
|
|
35
35
|
...rest
|
|
36
36
|
}) => {
|
|
37
37
|
const theme = useContext(ThemeContext) || baseTheme;
|
|
38
|
-
const isToggleButtonFocused = useRef(false);
|
|
39
|
-
const isFocusedAfterClosing = useRef(false);
|
|
40
38
|
const buttonLabelId = useRef(guid());
|
|
41
|
-
const buttonChildren = React.Children.toArray(children);
|
|
42
|
-
const
|
|
39
|
+
const buttonChildren = useMemo(() => React.Children.toArray(children), [children]);
|
|
40
|
+
const buttonChildrenRefs = useMemo(() => buttonChildren.map(() => /*#__PURE__*/React.createRef()), [buttonChildren]);
|
|
43
41
|
const splitButtonNode = useRef();
|
|
44
42
|
const toggleButton = useRef();
|
|
45
43
|
const buttonContainer = useRef();
|
|
46
44
|
const [showAdditionalButtons, setShowAdditionalButtons] = useState(false);
|
|
47
45
|
const [minWidth, setMinWidth] = useState(0);
|
|
48
|
-
const listening = useRef(false);
|
|
49
46
|
const hideButtons = useCallback(() => {
|
|
50
|
-
if (
|
|
47
|
+
if (toggleButton.current === document.activeElement) return;
|
|
51
48
|
setShowAdditionalButtons(false);
|
|
52
49
|
}, []);
|
|
53
|
-
const handleKeyDown =
|
|
54
|
-
const numOfChildren = children.length - 1;
|
|
55
|
-
const currentIndex = additionalButtons.current.findIndex(node => node.current === document.activeElement);
|
|
56
|
-
let nextIndex = -1;
|
|
57
|
-
|
|
58
|
-
if (Events.isUpKey(ev)) {
|
|
59
|
-
nextIndex = currentIndex > 0 ? currentIndex - 1 : numOfChildren;
|
|
60
|
-
ev.preventDefault();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (Events.isDownKey(ev)) {
|
|
64
|
-
nextIndex = currentIndex < numOfChildren ? currentIndex + 1 : 0;
|
|
65
|
-
ev.preventDefault();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (Events.isTabKey(ev)) {
|
|
69
|
-
var _elements$indexOf;
|
|
70
|
-
|
|
71
|
-
const elements = Array.from(document.querySelectorAll(defaultFocusableSelectors)).filter(el => Number(el.tabIndex) !== -1);
|
|
72
|
-
const indexOf = elements.indexOf(toggleButton.current);
|
|
73
|
-
(_elements$indexOf = elements[indexOf]) === null || _elements$indexOf === void 0 ? void 0 : _elements$indexOf.focus(); // timeout enforces that the "hideButtons" method will be run after browser focuses on the next element
|
|
74
|
-
|
|
75
|
-
setTimeout(hideButtons, 0);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (nextIndex > -1) {
|
|
79
|
-
additionalButtons.current[nextIndex].current.focus();
|
|
80
|
-
}
|
|
81
|
-
}, [hideButtons, children]);
|
|
82
|
-
const addListeners = useCallback(() => {
|
|
83
|
-
/* istanbul ignore else */
|
|
84
|
-
if (!listening.current) {
|
|
85
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
86
|
-
listening.current = true;
|
|
87
|
-
}
|
|
88
|
-
}, [handleKeyDown]);
|
|
89
|
-
const removeListeners = useCallback(() => {
|
|
90
|
-
/* istanbul ignore else */
|
|
91
|
-
if (listening.current) {
|
|
92
|
-
document.removeEventListener("keydown", handleKeyDown);
|
|
93
|
-
listening.current = false;
|
|
94
|
-
}
|
|
95
|
-
}, [handleKeyDown]);
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
if (showAdditionalButtons) {
|
|
98
|
-
addListeners();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return () => {
|
|
102
|
-
removeListeners();
|
|
103
|
-
};
|
|
104
|
-
}, [showAdditionalButtons, addListeners, removeListeners]);
|
|
50
|
+
const handleKeyDown = useMenuKeyboardNavigation(toggleButton, buttonChildrenRefs, hideButtons);
|
|
105
51
|
|
|
106
52
|
function mainButtonProps() {
|
|
107
53
|
return {
|
|
@@ -124,10 +70,6 @@ const SplitButton = ({
|
|
|
124
70
|
disabled,
|
|
125
71
|
displayed: showAdditionalButtons,
|
|
126
72
|
onTouchStart: showButtons,
|
|
127
|
-
onFocus: focusToggleButton,
|
|
128
|
-
onBlur: () => {
|
|
129
|
-
isToggleButtonFocused.current = false;
|
|
130
|
-
},
|
|
131
73
|
onKeyDown: handleToggleButtonKeyDown,
|
|
132
74
|
buttonType,
|
|
133
75
|
size
|
|
@@ -184,7 +126,7 @@ const SplitButton = ({
|
|
|
184
126
|
}
|
|
185
127
|
|
|
186
128
|
function handleToggleButtonKeyDown(ev) {
|
|
187
|
-
if (Events.isEnterKey(ev) || Events.isSpaceKey(ev) || Events.isDownKey(ev)) {
|
|
129
|
+
if (Events.isEnterKey(ev) || Events.isSpaceKey(ev) || Events.isDownKey(ev) || Events.isUpKey(ev)) {
|
|
188
130
|
ev.preventDefault();
|
|
189
131
|
|
|
190
132
|
if (!showAdditionalButtons) {
|
|
@@ -192,10 +134,13 @@ const SplitButton = ({
|
|
|
192
134
|
}
|
|
193
135
|
|
|
194
136
|
setTimeout(() => {
|
|
195
|
-
var
|
|
137
|
+
var _buttonChildrenRefs$, _buttonChildrenRefs$$;
|
|
196
138
|
|
|
197
|
-
(
|
|
139
|
+
(_buttonChildrenRefs$ = buttonChildrenRefs[0]) === null || _buttonChildrenRefs$ === void 0 ? void 0 : (_buttonChildrenRefs$$ = _buttonChildrenRefs$.current) === null || _buttonChildrenRefs$$ === void 0 ? void 0 : _buttonChildrenRefs$$.focus();
|
|
198
140
|
}, 0);
|
|
141
|
+
} else if (Events.isEscKey(ev)) {
|
|
142
|
+
setShowAdditionalButtons(false);
|
|
143
|
+
ev.preventDefault();
|
|
199
144
|
}
|
|
200
145
|
}
|
|
201
146
|
|
|
@@ -205,15 +150,13 @@ const SplitButton = ({
|
|
|
205
150
|
const childProps = {
|
|
206
151
|
key: index.toString(),
|
|
207
152
|
role: "menuitem",
|
|
208
|
-
ref:
|
|
153
|
+
ref: buttonChildrenRefs[index],
|
|
209
154
|
tabIndex: -1,
|
|
210
155
|
onClick: ev => {
|
|
211
156
|
var _toggleButton$current;
|
|
212
157
|
|
|
213
158
|
if (child.props.onClick) child.props.onClick(ev);
|
|
214
|
-
isToggleButtonFocused.current = false;
|
|
215
159
|
hideButtons();
|
|
216
|
-
isFocusedAfterClosing.current = true;
|
|
217
160
|
(_toggleButton$current = toggleButton.current) === null || _toggleButton$current === void 0 ? void 0 : _toggleButton$current.focus();
|
|
218
161
|
}
|
|
219
162
|
};
|
|
@@ -221,17 +164,6 @@ const SplitButton = ({
|
|
|
221
164
|
});
|
|
222
165
|
}
|
|
223
166
|
|
|
224
|
-
function focusToggleButton() {
|
|
225
|
-
isToggleButtonFocused.current = true;
|
|
226
|
-
|
|
227
|
-
if (isFocusedAfterClosing.current) {
|
|
228
|
-
isFocusedAfterClosing.current = false;
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
showButtons();
|
|
233
|
-
}
|
|
234
|
-
|
|
235
167
|
function renderAdditionalButtons() {
|
|
236
168
|
if (!showAdditionalButtons) return null;
|
|
237
169
|
return /*#__PURE__*/React.createElement(Popover, {
|
|
@@ -243,7 +175,8 @@ const SplitButton = ({
|
|
|
243
175
|
"data-element": "additional-buttons",
|
|
244
176
|
align: align,
|
|
245
177
|
minWidth: minWidth,
|
|
246
|
-
ref: buttonContainer
|
|
178
|
+
ref: buttonContainer,
|
|
179
|
+
onKeyDown: handleKeyDown
|
|
247
180
|
}, childrenWithProps()));
|
|
248
181
|
}
|
|
249
182
|
|
|
@@ -11,8 +11,7 @@ import IconButton from "../icon-button";
|
|
|
11
11
|
import Events from "../../__internal__/utils/helpers/events";
|
|
12
12
|
import useLocale from "../../hooks/__internal__/useLocale";
|
|
13
13
|
import useModalManager from "../../hooks/__internal__/useModalManager";
|
|
14
|
-
|
|
15
|
-
const Toast = ({
|
|
14
|
+
const Toast = /*#__PURE__*/React.forwardRef(({
|
|
16
15
|
children,
|
|
17
16
|
className,
|
|
18
17
|
id,
|
|
@@ -23,12 +22,16 @@ const Toast = ({
|
|
|
23
22
|
targetPortalId,
|
|
24
23
|
timeout,
|
|
25
24
|
variant,
|
|
25
|
+
disableAutoFocus,
|
|
26
26
|
...restProps
|
|
27
|
-
}) => {
|
|
27
|
+
}, ref) => {
|
|
28
28
|
const locale = useLocale();
|
|
29
29
|
const toastRef = useRef();
|
|
30
30
|
const timer = useRef();
|
|
31
31
|
const toastContentNodeRef = useRef();
|
|
32
|
+
const closeIconRef = useRef();
|
|
33
|
+
const focusedElementBeforeOpening = useRef();
|
|
34
|
+
const refToPass = ref || toastRef;
|
|
32
35
|
const componentClasses = useMemo(() => {
|
|
33
36
|
return classNames(className);
|
|
34
37
|
}, [className]);
|
|
@@ -38,7 +41,7 @@ const Toast = ({
|
|
|
38
41
|
onDismiss(ev);
|
|
39
42
|
}
|
|
40
43
|
}, [onDismiss]);
|
|
41
|
-
useModalManager(open, dismissToast,
|
|
44
|
+
useModalManager(open, dismissToast, refToPass);
|
|
42
45
|
useEffect(() => {
|
|
43
46
|
clearTimeout(timer.current);
|
|
44
47
|
|
|
@@ -48,13 +51,34 @@ const Toast = ({
|
|
|
48
51
|
|
|
49
52
|
timer.current = setTimeout(() => onDismiss(), timeout);
|
|
50
53
|
}, [onDismiss, open, timeout]);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (onDismiss && !disableAutoFocus) {
|
|
56
|
+
if (open) {
|
|
57
|
+
var _closeIconRef$current;
|
|
58
|
+
|
|
59
|
+
focusedElementBeforeOpening.current = document.activeElement;
|
|
60
|
+
(_closeIconRef$current = closeIconRef.current) === null || _closeIconRef$current === void 0 ? void 0 : _closeIconRef$current.focus();
|
|
61
|
+
} else if (focusedElementBeforeOpening.current) {
|
|
62
|
+
focusedElementBeforeOpening.current.focus();
|
|
63
|
+
focusedElementBeforeOpening.current = undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}, [open, onDismiss, disableAutoFocus]);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
return () => {
|
|
69
|
+
if (focusedElementBeforeOpening.current) {
|
|
70
|
+
focusedElementBeforeOpening.current.focus();
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}, []);
|
|
51
74
|
|
|
52
75
|
function renderCloseIcon() {
|
|
53
76
|
if (!onDismiss) return null;
|
|
54
77
|
return /*#__PURE__*/React.createElement(IconButton, {
|
|
55
78
|
"aria-label": locale.toast.ariaLabels.close(),
|
|
56
79
|
"data-element": "close",
|
|
57
|
-
onAction: onDismiss
|
|
80
|
+
onAction: onDismiss,
|
|
81
|
+
ref: closeIconRef
|
|
58
82
|
}, /*#__PURE__*/React.createElement(Icon, {
|
|
59
83
|
type: "close"
|
|
60
84
|
}));
|
|
@@ -96,10 +120,9 @@ const Toast = ({
|
|
|
96
120
|
isCenter: isCenter
|
|
97
121
|
}, /*#__PURE__*/React.createElement(ToastWrapper, {
|
|
98
122
|
isCenter: isCenter,
|
|
99
|
-
ref:
|
|
123
|
+
ref: refToPass
|
|
100
124
|
}, /*#__PURE__*/React.createElement(TransitionGroup, null, renderToastContent())));
|
|
101
|
-
};
|
|
102
|
-
|
|
125
|
+
});
|
|
103
126
|
Toast.propTypes = {
|
|
104
127
|
/** Customizes the appearance in the DLS theme */
|
|
105
128
|
variant: PropTypes.oneOf(["error", "info", "success", "warning"]),
|
|
@@ -132,6 +155,9 @@ Toast.propTypes = {
|
|
|
132
155
|
targetPortalId: PropTypes.string,
|
|
133
156
|
|
|
134
157
|
/** Maximum toast width */
|
|
135
|
-
maxWidth: PropTypes.string
|
|
158
|
+
maxWidth: PropTypes.string,
|
|
159
|
+
|
|
160
|
+
/** Disables auto focus functionality when the Toast has a close icon */
|
|
161
|
+
disableAutoFocus: PropTypes.bool
|
|
136
162
|
};
|
|
137
163
|
export default Toast;
|