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.
Files changed (91) hide show
  1. package/esm/__internal__/field-help/field-help.component.d.ts +10 -0
  2. package/esm/__internal__/field-help/field-help.component.js +12 -16
  3. package/esm/__internal__/field-help/field-help.style.d.ts +8 -0
  4. package/esm/__internal__/field-help/field-help.style.js +2 -10
  5. package/esm/__internal__/field-help/index.d.ts +2 -1
  6. package/esm/__internal__/focus-trap/focus-trap-utils.d.ts +1 -2
  7. package/esm/__internal__/focus-trap/focus-trap-utils.js +57 -8
  8. package/esm/__internal__/focus-trap/focus-trap.component.js +35 -25
  9. package/esm/__spec_helper__/index.d.ts +1 -0
  10. package/esm/__spec_helper__/index.js +4 -10
  11. package/esm/__spec_helper__/mock-match-media.d.ts +2 -2
  12. package/esm/__spec_helper__/mock-match-media.js +2 -2
  13. package/esm/__spec_helper__/mock-resize-observer.d.ts +2 -0
  14. package/esm/components/alert/alert.component.js +9 -0
  15. package/esm/components/dialog/dialog.component.js +9 -2
  16. package/esm/components/dialog/dialog.d.ts +2 -0
  17. package/esm/components/dialog-full-screen/dialog-full-screen.component.js +9 -2
  18. package/esm/components/dialog-full-screen/dialog-full-screen.d.ts +2 -0
  19. package/esm/components/grid/grid-container/grid-container.component.d.ts +8 -0
  20. package/esm/components/grid/grid-container/grid-container.component.js +1821 -21
  21. package/esm/components/grid/grid-container/grid-container.style.d.ts +3 -0
  22. package/esm/components/grid/grid-container/grid-container.style.js +2 -2
  23. package/esm/components/grid/grid-container/index.d.ts +2 -1
  24. package/esm/components/grid/grid-item/grid-item.component.d.ts +11 -0
  25. package/esm/components/grid/grid-item/grid-item.component.js +1221 -45
  26. package/esm/components/grid/grid-item/grid-item.style.d.ts +17 -0
  27. package/esm/components/grid/grid-item/grid-item.style.js +38 -62
  28. package/esm/components/grid/grid-item/index.d.ts +2 -1
  29. package/esm/components/grid/index.d.ts +2 -0
  30. package/esm/components/grid/index.js +2 -3
  31. package/esm/components/multi-action-button/multi-action-button.component.js +14 -84
  32. package/esm/components/select/utils/highlight-part-of-text.js +13 -1
  33. package/esm/components/select/utils/with-filter.hoc.js +3 -2
  34. package/esm/components/sidebar/sidebar.component.js +9 -2
  35. package/esm/components/sidebar/sidebar.d.ts +2 -0
  36. package/esm/components/split-button/split-button.component.js +15 -82
  37. package/esm/components/toast/toast.component.js +35 -9
  38. package/esm/components/toast/toast.d.ts +5 -1
  39. package/esm/hooks/__internal__/useMenuKeyboardNavigation/index.d.ts +1 -0
  40. package/esm/hooks/__internal__/useMenuKeyboardNavigation/index.js +1 -0
  41. package/esm/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.d.ts +2 -0
  42. package/esm/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.js +70 -0
  43. package/lib/__internal__/field-help/field-help.component.d.ts +10 -0
  44. package/lib/__internal__/field-help/field-help.component.js +12 -16
  45. package/lib/__internal__/field-help/field-help.style.d.ts +8 -0
  46. package/lib/__internal__/field-help/field-help.style.js +2 -13
  47. package/lib/__internal__/field-help/index.d.ts +2 -1
  48. package/lib/__internal__/focus-trap/focus-trap-utils.d.ts +1 -2
  49. package/lib/__internal__/focus-trap/focus-trap-utils.js +57 -10
  50. package/lib/__internal__/focus-trap/focus-trap.component.js +34 -24
  51. package/lib/__spec_helper__/index.d.ts +1 -0
  52. package/lib/__spec_helper__/index.js +3 -10
  53. package/lib/__spec_helper__/mock-match-media.d.ts +2 -2
  54. package/lib/__spec_helper__/mock-match-media.js +4 -4
  55. package/lib/__spec_helper__/mock-resize-observer.d.ts +2 -0
  56. package/lib/components/alert/alert.component.js +9 -0
  57. package/lib/components/dialog/dialog.component.js +9 -2
  58. package/lib/components/dialog/dialog.d.ts +2 -0
  59. package/lib/components/dialog-full-screen/dialog-full-screen.component.js +9 -2
  60. package/lib/components/dialog-full-screen/dialog-full-screen.d.ts +2 -0
  61. package/lib/components/grid/grid-container/grid-container.component.d.ts +8 -0
  62. package/lib/components/grid/grid-container/grid-container.component.js +1826 -22
  63. package/lib/components/grid/grid-container/grid-container.style.d.ts +3 -0
  64. package/lib/components/grid/grid-container/grid-container.style.js +2 -2
  65. package/lib/components/grid/grid-container/index.d.ts +2 -1
  66. package/lib/components/grid/grid-item/grid-item.component.d.ts +11 -0
  67. package/lib/components/grid/grid-item/grid-item.component.js +1221 -46
  68. package/lib/components/grid/grid-item/grid-item.style.d.ts +17 -0
  69. package/lib/components/grid/grid-item/grid-item.style.js +37 -67
  70. package/lib/components/grid/grid-item/index.d.ts +2 -1
  71. package/lib/components/grid/index.d.ts +2 -0
  72. package/lib/components/multi-action-button/multi-action-button.component.js +13 -83
  73. package/lib/components/select/utils/highlight-part-of-text.js +13 -1
  74. package/lib/components/select/utils/with-filter.hoc.js +3 -2
  75. package/lib/components/sidebar/sidebar.component.js +9 -2
  76. package/lib/components/sidebar/sidebar.d.ts +2 -0
  77. package/lib/components/split-button/split-button.component.js +14 -83
  78. package/lib/components/toast/toast.component.js +35 -7
  79. package/lib/components/toast/toast.d.ts +5 -1
  80. package/lib/hooks/__internal__/useMenuKeyboardNavigation/index.d.ts +1 -0
  81. package/lib/hooks/__internal__/useMenuKeyboardNavigation/index.js +15 -0
  82. package/lib/hooks/__internal__/useMenuKeyboardNavigation/package.json +6 -0
  83. package/lib/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.d.ts +2 -0
  84. package/lib/hooks/__internal__/useMenuKeyboardNavigation/useMenuKeyboardNavigation.js +85 -0
  85. package/package.json +3 -4
  86. package/esm/__internal__/field-help/field-help.d.ts +0 -14
  87. package/esm/components/grid/grid-container/grid-container.d.ts +0 -18
  88. package/esm/components/grid/grid-item/grid-item.d.ts +0 -42
  89. package/lib/__internal__/field-help/field-help.d.ts +0 -14
  90. package/lib/components/grid/grid-container/grid-container.d.ts +0 -18
  91. 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;
@@ -10,52 +10,10 @@ var _styledComponents = _interopRequireWildcard(require("styled-components"));
10
10
 
11
11
  var _styledSystem = require("styled-system");
12
12
 
13
- var _propTypes = _interopRequireDefault(require("@styled-system/prop-types"));
14
-
15
- var _space = require("@styled-system/space");
16
-
17
- var _propTypes2 = _interopRequireDefault(require("prop-types"));
18
-
19
- var _utils = require("../../../style/utils");
20
-
21
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22
-
23
13
  function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
24
14
 
25
15
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
26
16
 
27
- function responsiveGridItem(responsiveSettings) {
28
- return responsiveSettings.map(setting => {
29
- const {
30
- alignSelf,
31
- gridArea,
32
- gridColumn,
33
- gridRow,
34
- maxWidth,
35
- justifySelf,
36
- p,
37
- pl,
38
- pr,
39
- pt,
40
- pb
41
- } = setting;
42
- return (0, _styledComponents.css)`
43
- @media screen and (max-width: ${maxWidth}) {
44
- align-self: ${alignSelf || "stretch"};
45
- justify-self: ${justifySelf || "stretch"};
46
- grid-area: ${gridArea};
47
- grid-column: ${gridColumn};
48
- grid-row: ${gridRow};
49
- padding: ${getSpacing(p)};
50
- padding-left: ${getSpacing(pl)};
51
- padding-right: ${getSpacing(pr)};
52
- padding-top: ${getSpacing(pt)};
53
- padding-bottom: ${getSpacing(pb)};
54
- }
55
- `;
56
- });
57
- }
58
-
59
17
  function getSpacing(prop) {
60
18
  if (typeof prop === "number") {
61
19
  switch (prop) {
@@ -97,18 +55,49 @@ function getSpacing(prop) {
97
55
  }
98
56
  }
99
57
 
100
- return prop;
58
+ return String(prop);
101
59
  }
102
60
 
103
- const paddingPropTypes = (0, _utils.filterStyledSystemPaddingProps)(_propTypes.default.space);
104
- const GridItemStyle = _styledComponents.default.div`
61
+ function responsiveGridItem(responsiveSettings) {
62
+ return responsiveSettings.map(setting => {
63
+ const {
64
+ alignSelf,
65
+ gridArea,
66
+ gridColumn,
67
+ gridRow,
68
+ maxWidth,
69
+ justifySelf,
70
+ p,
71
+ pl,
72
+ pr,
73
+ pt,
74
+ pb
75
+ } = setting;
76
+ return (0, _styledComponents.css)`
77
+ @media screen and (max-width: ${maxWidth}) {
78
+ align-self: ${alignSelf || "stretch"};
79
+ justify-self: ${justifySelf || "stretch"};
80
+ grid-area: ${gridArea};
81
+ grid-column: ${gridColumn};
82
+ grid-row: ${gridRow};
83
+ padding: ${getSpacing(p)};
84
+ padding-left: ${getSpacing(pl)};
85
+ padding-right: ${getSpacing(pr)};
86
+ padding-top: ${getSpacing(pt)};
87
+ padding-bottom: ${getSpacing(pb)};
88
+ }
89
+ `;
90
+ });
91
+ }
92
+
93
+ const StyledGridItem = _styledComponents.default.div`
105
94
  margin: 0;
106
- ${_space.padding}
95
+ ${_styledSystem.padding}
107
96
 
108
97
  ${({
109
98
  alignSelf,
110
99
  justifySelf,
111
- gridArea,
100
+ gridArea = "auto / 1 / auto / 13",
112
101
  gridColumn,
113
102
  gridRow,
114
103
  responsiveSettings
@@ -128,24 +117,5 @@ const GridItemStyle = _styledComponents.default.div`
128
117
  `}
129
118
  `}
130
119
  `;
131
- GridItemStyle.propTypes = {
132
- alignSelf: _propTypes2.default.string,
133
- gridColumn: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
134
- gridRow: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
135
- justifySelf: _propTypes2.default.string,
136
- ...paddingPropTypes,
137
- responsiveSettings: _propTypes2.default.arrayOf(_propTypes2.default.shape({
138
- alignSelf: _propTypes2.default.string,
139
- gridArea: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
140
- gridColumn: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
141
- gridRow: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
142
- justifySelf: _propTypes2.default.string,
143
- maxWidth: _propTypes2.default.string,
144
- ...paddingPropTypes
145
- }))
146
- };
147
- GridItemStyle.defaultProps = {
148
- gridArea: "auto / 1 / auto / 13"
149
- };
150
- var _default = GridItemStyle;
120
+ var _default = StyledGridItem;
151
121
  exports.default = _default;
@@ -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,2 +1,4 @@
1
1
  export { default as GridContainer } from "./grid-container";
2
+ export type { GridContainerProps } from "./grid-container";
2
3
  export { default as GridItem } from "./grid-item";
4
+ export type { GridItemProps } from "./grid-item";
@@ -21,7 +21,7 @@ var _popover = _interopRequireDefault(require("../../__internal__/popover"));
21
21
 
22
22
  var _utils = require("../../style/utils");
23
23
 
24
- var _focusTrapUtils = require("../../__internal__/focus-trap/focus-trap-utils");
24
+ var _useMenuKeyboardNavigation = _interopRequireDefault(require("../../hooks/__internal__/useMenuKeyboardNavigation"));
25
25
 
26
26
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
27
 
@@ -47,14 +47,11 @@ const MultiActionButton = ({
47
47
  const buttonRef = (0, _react.useRef)(null);
48
48
  const buttonContainer = (0, _react.useRef)(null);
49
49
  const buttonChildren = (0, _react.useMemo)(() => _react.default.Children.toArray(children), [children]);
50
- const additionalButtons = (0, _react.useRef)(buttonChildren.map(() => /*#__PURE__*/_react.default.createRef()));
51
- const listening = (0, _react.useRef)(false);
52
- const isMainButtonFocused = (0, _react.useRef)(false);
53
- const isFocusedAfterClosing = (0, _react.useRef)(false);
50
+ const buttonChildrenRefs = (0, _react.useMemo)(() => buttonChildren.map(() => /*#__PURE__*/_react.default.createRef()), [buttonChildren]);
54
51
  const [showAdditionalButtons, setShowAdditionalButtons] = (0, _react.useState)(false);
55
52
  const [minWidth, setMinWidth] = (0, _react.useState)(0);
56
53
  const hideButtons = (0, _react.useCallback)(() => {
57
- if (isMainButtonFocused.current) return;
54
+ if (buttonRef.current === document.activeElement) return;
58
55
  setShowAdditionalButtons(false);
59
56
  }, []);
60
57
 
@@ -76,15 +73,13 @@ const MultiActionButton = ({
76
73
  const props = {
77
74
  key: index.toString(),
78
75
  role: "menuitem",
79
- ref: additionalButtons.current[index],
76
+ ref: buttonChildrenRefs[index],
80
77
  tabIndex: -1,
81
78
  onClick: ev => {
82
79
  var _buttonRef$current;
83
80
 
84
81
  if (child.props.onClick) child.props.onClick(ev);
85
- isMainButtonFocused.current = false;
86
82
  hideButtons();
87
- isFocusedAfterClosing.current = true;
88
83
  (_buttonRef$current = buttonRef.current) === null || _buttonRef$current === void 0 ? void 0 : _buttonRef$current.focus();
89
84
  }
90
85
  };
@@ -92,62 +87,10 @@ const MultiActionButton = ({
92
87
  });
93
88
  };
94
89
 
95
- const handleKeyDown = (0, _react.useCallback)(ev => {
96
- const currentIndex = additionalButtons.current.findIndex(node => node.current === document.activeElement);
97
- let nextIndex = -1;
98
-
99
- if (_events.default.isUpKey(ev)) {
100
- nextIndex = currentIndex > 0 ? currentIndex - 1 : buttonChildren.length - 1;
101
- ev.preventDefault();
102
- }
103
-
104
- if (_events.default.isDownKey(ev)) {
105
- nextIndex = currentIndex < buttonChildren.length - 1 ? currentIndex + 1 : 0;
106
- ev.preventDefault();
107
- }
108
-
109
- if (_events.default.isTabKey(ev)) {
110
- var _elements$indexOf;
111
-
112
- const elements = Array.from(document.querySelectorAll(_focusTrapUtils.defaultFocusableSelectors)).filter(el => Number(el.tabIndex) !== -1);
113
- const indexOf = elements.indexOf(buttonRef.current);
114
- (_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
115
-
116
- setTimeout(hideButtons, 0);
117
- }
118
-
119
- if (nextIndex > -1) {
120
- var _additionalButtons$cu;
121
-
122
- (_additionalButtons$cu = additionalButtons.current[nextIndex].current) === null || _additionalButtons$cu === void 0 ? void 0 : _additionalButtons$cu.focus();
123
- }
124
- }, [buttonChildren, hideButtons]);
125
- const addListeners = (0, _react.useCallback)(() => {
126
- /* istanbul ignore else */
127
- if (!listening.current) {
128
- document.addEventListener("keydown", handleKeyDown);
129
- listening.current = true;
130
- }
131
- }, [handleKeyDown]);
132
- const removeListeners = (0, _react.useCallback)(() => {
133
- /* istanbul ignore else */
134
- if (listening.current) {
135
- document.removeEventListener("keydown", handleKeyDown);
136
- listening.current = false;
137
- }
138
- }, [handleKeyDown]);
139
- (0, _react.useEffect)(() => {
140
- if (showAdditionalButtons) {
141
- addListeners();
142
- }
143
-
144
- return () => {
145
- removeListeners();
146
- };
147
- }, [showAdditionalButtons, addListeners, removeListeners]);
90
+ const handleKeyDown = (0, _useMenuKeyboardNavigation.default)(buttonRef, buttonChildrenRefs, hideButtons);
148
91
 
149
92
  const handleMainButtonKeyDown = ev => {
150
- if (_events.default.isEnterKey(ev) || _events.default.isSpaceKey(ev) || _events.default.isDownKey(ev)) {
93
+ if (_events.default.isEnterKey(ev) || _events.default.isSpaceKey(ev) || _events.default.isDownKey(ev) || _events.default.isUpKey(ev)) {
151
94
  ev.preventDefault();
152
95
 
153
96
  if (!showAdditionalButtons) {
@@ -156,34 +99,20 @@ const MultiActionButton = ({
156
99
 
157
100
 
158
101
  setTimeout(() => {
159
- var _additionalButtons$cu2, _additionalButtons$cu3;
102
+ var _buttonChildrenRefs$, _buttonChildrenRefs$$;
160
103
 
161
- (_additionalButtons$cu2 = additionalButtons.current[0]) === null || _additionalButtons$cu2 === void 0 ? void 0 : (_additionalButtons$cu3 = _additionalButtons$cu2.current) === null || _additionalButtons$cu3 === void 0 ? void 0 : _additionalButtons$cu3.focus();
104
+ (_buttonChildrenRefs$ = buttonChildrenRefs[0]) === null || _buttonChildrenRefs$ === void 0 ? void 0 : (_buttonChildrenRefs$$ = _buttonChildrenRefs$.current) === null || _buttonChildrenRefs$$ === void 0 ? void 0 : _buttonChildrenRefs$$.focus();
162
105
  }, 0);
106
+ } else if (_events.default.isEscKey(ev)) {
107
+ ev.preventDefault();
108
+ setShowAdditionalButtons(false);
163
109
  }
164
110
  };
165
111
 
166
- const focusMainButton = () => {
167
- isMainButtonFocused.current = true;
168
-
169
- if (isFocusedAfterClosing.current) {
170
- isFocusedAfterClosing.current = false;
171
- return;
172
- }
173
-
174
- showButtons();
175
- };
176
-
177
- const blurMainButton = () => {
178
- isMainButtonFocused.current = false;
179
- };
180
-
181
112
  const mainButtonProps = {
182
113
  disabled,
183
114
  displayed: showAdditionalButtons,
184
115
  onTouchStart: showButtons,
185
- onFocus: focusMainButton,
186
- onBlur: blurMainButton,
187
116
  onKeyDown: handleMainButtonKeyDown,
188
117
  buttonType,
189
118
  size,
@@ -203,7 +132,8 @@ const MultiActionButton = ({
203
132
  "data-element": "additional-buttons",
204
133
  align: align,
205
134
  minWidth: minWidth,
206
- ref: buttonContainer
135
+ ref: buttonContainer,
136
+ onKeyDown: handleKeyDown
207
137
  }, childrenWithProps()));
208
138
 
209
139
  (0, _useClickAwayListener.default)([ref], hideButtons);
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = highlightPartOfText;
6
+ exports.default = highlightPartOfTextRecursive;
7
7
 
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
 
@@ -37,4 +37,16 @@ function highlightPartOfText(text, partToHighlight) {
37
37
  key: "following"
38
38
  }, followingText)];
39
39
  return newValue;
40
+ }
41
+
42
+ function highlightPartOfTextRecursive(child, partToHighlight) {
43
+ if (typeof child === "string") {
44
+ return highlightPartOfText(child, partToHighlight);
45
+ }
46
+
47
+ const highlightedChildren = _react.default.Children.map(child.props.children, grandChild => highlightPartOfTextRecursive(grandChild, partToHighlight));
48
+
49
+ return /*#__PURE__*/_react.default.cloneElement(child, {
50
+ children: highlightedChildren
51
+ });
40
52
  }
@@ -50,9 +50,10 @@ const filterOptionRows = (optionRow, filterText) => {
50
50
  const processedText = cell.props.children.toLowerCase();
51
51
  const processedValue = filterText.toLowerCase();
52
52
  return processedText.includes(processedValue);
53
- }
53
+ } // filter recursively based on children
54
+
54
55
 
55
- return false;
56
+ return filterOptionRows(cell, filterText);
56
57
  });
57
58
 
58
59
  if (hasText) {
@@ -54,6 +54,7 @@ const Sidebar = /*#__PURE__*/_react.default.forwardRef(({
54
54
  children,
55
55
  onCancel,
56
56
  role = "dialog",
57
+ focusableContainers,
57
58
  ...rest
58
59
  }, ref) => {
59
60
  const locale = (0, _useLocale.default)();
@@ -114,7 +115,8 @@ const Sidebar = /*#__PURE__*/_react.default.forwardRef(({
114
115
  className: "carbon-sidebar"
115
116
  }, componentTags), enableBackgroundUI ? sidebar : /*#__PURE__*/_react.default.createElement(_focusTrap.default, {
116
117
  wrapperRef: sidebarRef,
117
- isOpen: open
118
+ isOpen: open,
119
+ additionalWrapperRefs: focusableContainers
118
120
  }, sidebar));
119
121
  });
120
122
 
@@ -153,7 +155,12 @@ Sidebar.propTypes = {
153
155
  header: _propTypes.default.node,
154
156
 
155
157
  /** The ARIA role to be applied to the container */
156
- role: _propTypes.default.string
158
+ role: _propTypes.default.string,
159
+
160
+ /** an optional array of refs to containers whose content should also be reachable by tabbing from the sidebar */
161
+ focusableContainers: _propTypes.default.arrayOf(_propTypes.default.shape({
162
+ current: _propTypes.default.any
163
+ }))
157
164
  };
158
165
  Sidebar.defaultProps = {
159
166
  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>;
@@ -35,7 +35,7 @@ var _utils = require("../../style/utils");
35
35
 
36
36
  var _themes = require("../../style/themes");
37
37
 
38
- var _focusTrapUtils = require("../../__internal__/focus-trap/focus-trap-utils");
38
+ var _useMenuKeyboardNavigation = _interopRequireDefault(require("../../hooks/__internal__/useMenuKeyboardNavigation"));
39
39
 
40
40
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
41
41
 
@@ -65,75 +65,19 @@ const SplitButton = ({
65
65
  }) => {
66
66
  const theme = (0, _react.useContext)(_styledComponents.ThemeContext) || _themes.baseTheme;
67
67
 
68
- const isToggleButtonFocused = (0, _react.useRef)(false);
69
- const isFocusedAfterClosing = (0, _react.useRef)(false);
70
68
  const buttonLabelId = (0, _react.useRef)((0, _guid.default)());
71
-
72
- const buttonChildren = _react.default.Children.toArray(children);
73
-
74
- const additionalButtons = (0, _react.useRef)(buttonChildren.map(() => /*#__PURE__*/_react.default.createRef()));
69
+ const buttonChildren = (0, _react.useMemo)(() => _react.default.Children.toArray(children), [children]);
70
+ const buttonChildrenRefs = (0, _react.useMemo)(() => buttonChildren.map(() => /*#__PURE__*/_react.default.createRef()), [buttonChildren]);
75
71
  const splitButtonNode = (0, _react.useRef)();
76
72
  const toggleButton = (0, _react.useRef)();
77
73
  const buttonContainer = (0, _react.useRef)();
78
74
  const [showAdditionalButtons, setShowAdditionalButtons] = (0, _react.useState)(false);
79
75
  const [minWidth, setMinWidth] = (0, _react.useState)(0);
80
- const listening = (0, _react.useRef)(false);
81
76
  const hideButtons = (0, _react.useCallback)(() => {
82
- if (isToggleButtonFocused.current) return;
77
+ if (toggleButton.current === document.activeElement) return;
83
78
  setShowAdditionalButtons(false);
84
79
  }, []);
85
- const handleKeyDown = (0, _react.useCallback)(ev => {
86
- const numOfChildren = children.length - 1;
87
- const currentIndex = additionalButtons.current.findIndex(node => node.current === document.activeElement);
88
- let nextIndex = -1;
89
-
90
- if (_events.default.isUpKey(ev)) {
91
- nextIndex = currentIndex > 0 ? currentIndex - 1 : numOfChildren;
92
- ev.preventDefault();
93
- }
94
-
95
- if (_events.default.isDownKey(ev)) {
96
- nextIndex = currentIndex < numOfChildren ? currentIndex + 1 : 0;
97
- ev.preventDefault();
98
- }
99
-
100
- if (_events.default.isTabKey(ev)) {
101
- var _elements$indexOf;
102
-
103
- const elements = Array.from(document.querySelectorAll(_focusTrapUtils.defaultFocusableSelectors)).filter(el => Number(el.tabIndex) !== -1);
104
- const indexOf = elements.indexOf(toggleButton.current);
105
- (_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
106
-
107
- setTimeout(hideButtons, 0);
108
- }
109
-
110
- if (nextIndex > -1) {
111
- additionalButtons.current[nextIndex].current.focus();
112
- }
113
- }, [hideButtons, children]);
114
- const addListeners = (0, _react.useCallback)(() => {
115
- /* istanbul ignore else */
116
- if (!listening.current) {
117
- document.addEventListener("keydown", handleKeyDown);
118
- listening.current = true;
119
- }
120
- }, [handleKeyDown]);
121
- const removeListeners = (0, _react.useCallback)(() => {
122
- /* istanbul ignore else */
123
- if (listening.current) {
124
- document.removeEventListener("keydown", handleKeyDown);
125
- listening.current = false;
126
- }
127
- }, [handleKeyDown]);
128
- (0, _react.useEffect)(() => {
129
- if (showAdditionalButtons) {
130
- addListeners();
131
- }
132
-
133
- return () => {
134
- removeListeners();
135
- };
136
- }, [showAdditionalButtons, addListeners, removeListeners]);
80
+ const handleKeyDown = (0, _useMenuKeyboardNavigation.default)(toggleButton, buttonChildrenRefs, hideButtons);
137
81
 
138
82
  function mainButtonProps() {
139
83
  return {
@@ -156,10 +100,6 @@ const SplitButton = ({
156
100
  disabled,
157
101
  displayed: showAdditionalButtons,
158
102
  onTouchStart: showButtons,
159
- onFocus: focusToggleButton,
160
- onBlur: () => {
161
- isToggleButtonFocused.current = false;
162
- },
163
103
  onKeyDown: handleToggleButtonKeyDown,
164
104
  buttonType,
165
105
  size
@@ -216,7 +156,7 @@ const SplitButton = ({
216
156
  }
217
157
 
218
158
  function handleToggleButtonKeyDown(ev) {
219
- if (_events.default.isEnterKey(ev) || _events.default.isSpaceKey(ev) || _events.default.isDownKey(ev)) {
159
+ if (_events.default.isEnterKey(ev) || _events.default.isSpaceKey(ev) || _events.default.isDownKey(ev) || _events.default.isUpKey(ev)) {
220
160
  ev.preventDefault();
221
161
 
222
162
  if (!showAdditionalButtons) {
@@ -224,10 +164,13 @@ const SplitButton = ({
224
164
  }
225
165
 
226
166
  setTimeout(() => {
227
- var _additionalButtons$cu, _additionalButtons$cu2;
167
+ var _buttonChildrenRefs$, _buttonChildrenRefs$$;
228
168
 
229
- (_additionalButtons$cu = additionalButtons.current[0]) === null || _additionalButtons$cu === void 0 ? void 0 : (_additionalButtons$cu2 = _additionalButtons$cu.current) === null || _additionalButtons$cu2 === void 0 ? void 0 : _additionalButtons$cu2.focus();
169
+ (_buttonChildrenRefs$ = buttonChildrenRefs[0]) === null || _buttonChildrenRefs$ === void 0 ? void 0 : (_buttonChildrenRefs$$ = _buttonChildrenRefs$.current) === null || _buttonChildrenRefs$$ === void 0 ? void 0 : _buttonChildrenRefs$$.focus();
230
170
  }, 0);
171
+ } else if (_events.default.isEscKey(ev)) {
172
+ setShowAdditionalButtons(false);
173
+ ev.preventDefault();
231
174
  }
232
175
  }
233
176
 
@@ -237,15 +180,13 @@ const SplitButton = ({
237
180
  const childProps = {
238
181
  key: index.toString(),
239
182
  role: "menuitem",
240
- ref: additionalButtons.current[index],
183
+ ref: buttonChildrenRefs[index],
241
184
  tabIndex: -1,
242
185
  onClick: ev => {
243
186
  var _toggleButton$current;
244
187
 
245
188
  if (child.props.onClick) child.props.onClick(ev);
246
- isToggleButtonFocused.current = false;
247
189
  hideButtons();
248
- isFocusedAfterClosing.current = true;
249
190
  (_toggleButton$current = toggleButton.current) === null || _toggleButton$current === void 0 ? void 0 : _toggleButton$current.focus();
250
191
  }
251
192
  };
@@ -253,17 +194,6 @@ const SplitButton = ({
253
194
  });
254
195
  }
255
196
 
256
- function focusToggleButton() {
257
- isToggleButtonFocused.current = true;
258
-
259
- if (isFocusedAfterClosing.current) {
260
- isFocusedAfterClosing.current = false;
261
- return;
262
- }
263
-
264
- showButtons();
265
- }
266
-
267
197
  function renderAdditionalButtons() {
268
198
  if (!showAdditionalButtons) return null;
269
199
  return /*#__PURE__*/_react.default.createElement(_popover.default, {
@@ -275,7 +205,8 @@ const SplitButton = ({
275
205
  "data-element": "additional-buttons",
276
206
  align: align,
277
207
  minWidth: minWidth,
278
- ref: buttonContainer
208
+ ref: buttonContainer,
209
+ onKeyDown: handleKeyDown
279
210
  }, childrenWithProps()));
280
211
  }
281
212
 
@@ -35,7 +35,7 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj;
35
35
 
36
36
  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); }
37
37
 
38
- const Toast = ({
38
+ const Toast = /*#__PURE__*/_react.default.forwardRef(({
39
39
  children,
40
40
  className,
41
41
  id,
@@ -46,12 +46,16 @@ const Toast = ({
46
46
  targetPortalId,
47
47
  timeout,
48
48
  variant,
49
+ disableAutoFocus,
49
50
  ...restProps
50
- }) => {
51
+ }, ref) => {
51
52
  const locale = (0, _useLocale.default)();
52
53
  const toastRef = (0, _react.useRef)();
53
54
  const timer = (0, _react.useRef)();
54
55
  const toastContentNodeRef = (0, _react.useRef)();
56
+ const closeIconRef = (0, _react.useRef)();
57
+ const focusedElementBeforeOpening = (0, _react.useRef)();
58
+ const refToPass = ref || toastRef;
55
59
  const componentClasses = (0, _react.useMemo)(() => {
56
60
  return (0, _classnames.default)(className);
57
61
  }, [className]);
@@ -61,7 +65,7 @@ const Toast = ({
61
65
  onDismiss(ev);
62
66
  }
63
67
  }, [onDismiss]);
64
- (0, _useModalManager.default)(open, dismissToast, toastRef);
68
+ (0, _useModalManager.default)(open, dismissToast, refToPass);
65
69
  (0, _react.useEffect)(() => {
66
70
  clearTimeout(timer.current);
67
71
 
@@ -71,13 +75,34 @@ const Toast = ({
71
75
 
72
76
  timer.current = setTimeout(() => onDismiss(), timeout);
73
77
  }, [onDismiss, open, timeout]);
78
+ (0, _react.useEffect)(() => {
79
+ if (onDismiss && !disableAutoFocus) {
80
+ if (open) {
81
+ var _closeIconRef$current;
82
+
83
+ focusedElementBeforeOpening.current = document.activeElement;
84
+ (_closeIconRef$current = closeIconRef.current) === null || _closeIconRef$current === void 0 ? void 0 : _closeIconRef$current.focus();
85
+ } else if (focusedElementBeforeOpening.current) {
86
+ focusedElementBeforeOpening.current.focus();
87
+ focusedElementBeforeOpening.current = undefined;
88
+ }
89
+ }
90
+ }, [open, onDismiss, disableAutoFocus]);
91
+ (0, _react.useEffect)(() => {
92
+ return () => {
93
+ if (focusedElementBeforeOpening.current) {
94
+ focusedElementBeforeOpening.current.focus();
95
+ }
96
+ };
97
+ }, []);
74
98
 
75
99
  function renderCloseIcon() {
76
100
  if (!onDismiss) return null;
77
101
  return /*#__PURE__*/_react.default.createElement(_iconButton.default, {
78
102
  "aria-label": locale.toast.ariaLabels.close(),
79
103
  "data-element": "close",
80
- onAction: onDismiss
104
+ onAction: onDismiss,
105
+ ref: closeIconRef
81
106
  }, /*#__PURE__*/_react.default.createElement(_icon.default, {
82
107
  type: "close"
83
108
  }));
@@ -119,9 +144,9 @@ const Toast = ({
119
144
  isCenter: isCenter
120
145
  }, /*#__PURE__*/_react.default.createElement(_toast.ToastWrapper, {
121
146
  isCenter: isCenter,
122
- ref: toastRef
147
+ ref: refToPass
123
148
  }, /*#__PURE__*/_react.default.createElement(_reactTransitionGroup.TransitionGroup, null, renderToastContent())));
124
- };
149
+ });
125
150
 
126
151
  Toast.propTypes = {
127
152
  /** Customizes the appearance in the DLS theme */
@@ -155,7 +180,10 @@ Toast.propTypes = {
155
180
  targetPortalId: _propTypes.default.string,
156
181
 
157
182
  /** Maximum toast width */
158
- maxWidth: _propTypes.default.string
183
+ maxWidth: _propTypes.default.string,
184
+
185
+ /** Disables auto focus functionality when the Toast has a close icon */
186
+ disableAutoFocus: _propTypes.default.bool
159
187
  };
160
188
  var _default = Toast;
161
189
  exports.default = _default;
@@ -25,8 +25,12 @@ export interface ToastPropTypes {
25
25
  targetPortalId?: string;
26
26
  /** Maximum toast width */
27
27
  maxWidth?: string;
28
+ /** Disables auto focus functionality when the Toast has a close icon */
29
+ disableAutoFocus?: boolean;
28
30
  }
29
31
 
30
- declare class Toast extends React.Component<ToastPropTypes> {}
32
+ declare function Toast(
33
+ props: ToastPropTypes & React.RefAttributes<HTMLDivElement>
34
+ ): JSX.Element;
31
35
 
32
36
  export default Toast;
@@ -0,0 +1 @@
1
+ export { default } from "./useMenuKeyboardNavigation";