carbon-react 128.2.0 → 128.3.0

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.
@@ -1,6 +1,8 @@
1
1
  import React from "react";
2
- import { TagProps } from "../../../__internal__/utils/helpers/tags";
3
- export interface MenuFullscreenProps extends TagProps {
2
+ import type { TagProps } from "../../../__internal__/utils/helpers/tags";
3
+ export interface MenuFullscreenProps extends Omit<TagProps, "data-component"> {
4
+ /** Accessible name that conveys the purpose of the menu */
5
+ "aria-label"?: string;
4
6
  /** The child elements to render */
5
7
  children?: React.ReactNode;
6
8
  /** Sets whether the component is open or closed */
@@ -8,7 +10,9 @@ export interface MenuFullscreenProps extends TagProps {
8
10
  /** The start position for the component to open from */
9
11
  startPosition?: "left" | "right";
10
12
  /** A callback to be called when the close icon is clicked or enter is pressed when focused */
11
- onClose: (ev: React.KeyboardEvent<HTMLElement> | React.MouseEvent<HTMLButtonElement>) => void;
13
+ onClose: (ev: React.KeyboardEvent<HTMLButtonElement> | React.MouseEvent<HTMLButtonElement> | KeyboardEvent) => void;
14
+ /** Manually override the internal modal stacking order to set this as top */
15
+ topModalOverride?: boolean;
12
16
  }
13
- export declare const MenuFullscreen: ({ children, isOpen, startPosition, onClose, ...rest }: MenuFullscreenProps) => React.JSX.Element;
17
+ export declare const MenuFullscreen: ({ "aria-label": ariaLabel, "data-element": dataElement, "data-role": dataRole, children, isOpen, onClose, startPosition, topModalOverride, }: MenuFullscreenProps) => React.JSX.Element;
14
18
  export default MenuFullscreen;
@@ -1,48 +1,53 @@
1
- function _extends() { _extends = Object.assign ? Object.assign.bind() : 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
- import React, { useContext, useRef } from "react";
1
+ import React, { useCallback, useContext, useRef } from "react";
3
2
  import PropTypes from "prop-types";
4
- import { StyledMenuFullscreen, StyledMenuFullscreenHeader } from "./menu-full-screen.style";
3
+ import { CSSTransition } from "react-transition-group";
4
+ import { StyledMenuFullscreen, StyledMenuModal, StyledMenuFullscreenHeader } from "./menu-full-screen.style";
5
5
  import { StyledMenuWrapper } from "../menu.style";
6
6
  import MenuContext from "../menu.context";
7
- import FocusTrap from "../../../__internal__/focus-trap";
8
7
  import Events from "../../../__internal__/utils/helpers/events";
9
8
  import Box from "../../box";
10
9
  import IconButton from "../../icon-button";
11
10
  import Icon from "../../icon";
12
11
  import Portal from "../../portal";
12
+ import FocusTrap from "../../../__internal__/focus-trap";
13
13
  import MenuDivider from "../menu-divider/menu-divider.component";
14
- import tagComponent from "../../../__internal__/utils/helpers/tags";
14
+ import useLocale from "../../../hooks/__internal__/useLocale";
15
+ import useModalAria from "../../../hooks/__internal__/useModalAria";
16
+ import useModalManager from "../../../hooks/__internal__/useModalManager";
15
17
  export const MenuFullscreen = ({
18
+ "aria-label": ariaLabel = "Fullscreen menu",
19
+ "data-element": dataElement,
20
+ "data-role": dataRole,
16
21
  children,
17
- isOpen,
18
- startPosition = "left",
22
+ isOpen = false,
19
23
  onClose,
20
- ...rest
24
+ startPosition = "left",
25
+ topModalOverride
21
26
  }) => {
22
- const menuWrapperRef = useRef(null);
23
- const menuContentRef = useRef(null);
27
+ const menuRef = useRef(null);
28
+ const modalRef = useRef(null);
29
+ const contentRef = useRef(null);
30
+ const isTopModal = useModalAria(modalRef);
24
31
  const {
25
32
  menuType
26
33
  } = useContext(MenuContext);
27
34
  const isDarkVariant = ["dark", "black"].includes(menuType);
28
- const handleKeyDown = ev => {
29
- /* istanbul ignore else */
30
- if (Events.isEscKey(ev)) {
31
- onClose(ev);
32
- }
33
- if (Events.isTabKey(ev) && !Events.isShiftKey(ev)) {
34
- const search = menuWrapperRef.current?.querySelector('[data-component="search"');
35
- const searchInput = search?.querySelector("input");
36
- const searchButton = search?.querySelector("button");
35
+ const transitionDuration = 200;
36
+ const locale = useLocale();
37
37
 
38
- // if there is no value in the search input the button disappears when the input blurs
39
- // this means we need to programatically set focus to the next menu item
40
- if (searchButton && searchInput && !searchInput.value && searchInput === document.activeElement) {
41
- ev.preventDefault();
42
- const elements = Array.from(menuWrapperRef.current?.querySelectorAll("a, input, button"));
43
- const index = elements.indexOf(searchInput);
44
- elements[index + 2]?.focus();
45
- }
38
+ // TODO: Remove this temporary event handler as part of FE-6078
39
+ const handleFocusedSearchButton = ev => {
40
+ const search = modalRef.current?.querySelector('[data-component="search"]');
41
+ const searchInput = search?.querySelector("input");
42
+ const searchButton = search?.querySelector("button");
43
+
44
+ // if there is no value in the search input the button disappears when the input blurs
45
+ // this means we need to programmatically set focus to the next menu item
46
+ if (searchButton && searchInput && !searchInput.value && searchInput === document.activeElement) {
47
+ ev.preventDefault();
48
+ const elements = Array.from(modalRef.current?.querySelectorAll("a, input, button"));
49
+ const index = elements.indexOf(searchInput);
50
+ elements[index + 2]?.focus();
46
51
  }
47
52
  };
48
53
  const flattenedChildren = React.Children.toArray(children);
@@ -52,23 +57,45 @@ export const MenuFullscreen = ({
52
57
  }
53
58
  return child;
54
59
  }));
55
- return /*#__PURE__*/React.createElement("li", {
56
- "aria-label": "menu-fullscreen"
57
- }, /*#__PURE__*/React.createElement(Portal, null, /*#__PURE__*/React.createElement(FocusTrap, {
58
- wrapperRef: menuWrapperRef,
59
- isOpen: isOpen
60
- }, /*#__PURE__*/React.createElement(StyledMenuFullscreen, _extends({
61
- ref: menuWrapperRef,
62
- isOpen: isOpen,
63
- menuType: menuType,
60
+ const closeModal = useCallback(ev => {
61
+ if (onClose && Events.isEscKey(ev)) {
62
+ ev.stopImmediatePropagation();
63
+ onClose(ev);
64
+ }
65
+ }, [onClose]);
66
+ useModalManager({
67
+ open: isOpen,
68
+ closeModal,
69
+ modalRef: menuRef,
70
+ topModalOverride
71
+ });
72
+ return /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement(Portal, null, /*#__PURE__*/React.createElement(CSSTransition, {
73
+ nodeRef: menuRef,
74
+ in: isOpen,
75
+ timeout: transitionDuration,
76
+ unmountOnExit: true
77
+ }, /*#__PURE__*/React.createElement(StyledMenuFullscreen, {
78
+ ref: menuRef,
64
79
  startPosition: startPosition,
65
- onKeyDown: handleKeyDown
66
- }, rest, tagComponent("menu-fullscreen", rest)), /*#__PURE__*/React.createElement(StyledMenuFullscreenHeader, {
67
- isOpen: isOpen,
80
+ transitionDuration: transitionDuration
81
+ }, /*#__PURE__*/React.createElement(FocusTrap, {
82
+ wrapperRef: modalRef,
83
+ isOpen: isOpen
84
+ }, /*#__PURE__*/React.createElement(StyledMenuModal, {
85
+ "aria-label": ariaLabel,
86
+ "aria-modal": isTopModal ? true : undefined,
87
+ "data-component": "menu-fullscreen",
88
+ "data-element": dataElement,
89
+ "data-role": dataRole,
68
90
  menuType: menuType,
69
- startPosition: startPosition
91
+ onKeyDown: ev => Events.isTabKey(ev) && !Events.isShiftKey(ev) && handleFocusedSearchButton(ev),
92
+ ref: modalRef,
93
+ role: "dialog",
94
+ tabIndex: -1
95
+ }, /*#__PURE__*/React.createElement(StyledMenuFullscreenHeader, {
96
+ menuType: menuType
70
97
  }, /*#__PURE__*/React.createElement(IconButton, {
71
- "aria-label": "menu fullscreen close button",
98
+ "aria-label": locale.menuFullscreen.ariaLabels.closeButton(),
72
99
  onClick: onClose,
73
100
  "data-element": "close"
74
101
  }, /*#__PURE__*/React.createElement(Icon, {
@@ -82,7 +109,7 @@ export const MenuFullscreen = ({
82
109
  }, /*#__PURE__*/React.createElement(StyledMenuWrapper, {
83
110
  "data-component": "menu",
84
111
  menuType: menuType,
85
- ref: menuContentRef,
112
+ ref: contentRef,
86
113
  display: "flex",
87
114
  flexDirection: "column",
88
115
  role: "list",
@@ -95,6 +122,6 @@ export const MenuFullscreen = ({
95
122
  openSubmenuId: null,
96
123
  setOpenSubmenuId: /* istanbul ignore next */() => {}
97
124
  }
98
- }, childArray)))))));
125
+ }, childArray)))))))));
99
126
  };
100
127
  export default MenuFullscreen;
@@ -1,8 +1,12 @@
1
- import { MenuFullscreenProps } from "./menu-full-screen.component";
2
1
  import { MenuType } from "../menu.context";
3
- interface StyledMenuFullScreenProps extends Pick<MenuFullscreenProps, "isOpen" | "startPosition"> {
2
+ declare const StyledMenuFullscreen: import("styled-components").StyledComponent<"div", any, {
3
+ transitionDuration: number;
4
+ startPosition: "left" | "right";
5
+ }, never>;
6
+ declare const StyledMenuModal: import("styled-components").StyledComponent<"div", any, {
4
7
  menuType: MenuType;
5
- }
6
- declare const StyledMenuFullscreen: import("styled-components").StyledComponent<"div", any, StyledMenuFullScreenProps, never>;
7
- declare const StyledMenuFullscreenHeader: import("styled-components").StyledComponent<"div", any, StyledMenuFullScreenProps, never>;
8
- export { StyledMenuFullscreen, StyledMenuFullscreenHeader };
8
+ }, never>;
9
+ declare const StyledMenuFullscreenHeader: import("styled-components").StyledComponent<"div", any, {
10
+ menuType: MenuType;
11
+ }, never>;
12
+ export { StyledMenuModal, StyledMenuFullscreen, StyledMenuFullscreenHeader };
@@ -8,15 +8,50 @@ import StyledButton from "../../button/button.style";
8
8
  import menuConfigVariants from "../menu.config";
9
9
  import addFocusStyling from "../../../style/utils/add-focus-styling";
10
10
  const oldFocusStyling = `
11
- outline: solid 3px var(--colorsSemanticFocus500);
12
- box-shadow: none;
11
+ outline: solid 3px var(--colorsSemanticFocus500);
12
+ box-shadow: none;
13
13
  `;
14
14
  const StyledMenuFullscreen = styled.div`
15
15
  position: fixed;
16
16
  top: 0;
17
17
  bottom: 0;
18
+
19
+ ${({
20
+ theme
21
+ }) => css`
22
+ z-index: ${theme.zIndex.fullScreenModal};
23
+ `}
24
+
25
+ ${({
26
+ startPosition,
27
+ transitionDuration
28
+ }) => css`
29
+ &.enter {
30
+ visibility: hidden;
31
+ ${startPosition}: -100%;
32
+ }
33
+
34
+ &.enter-active {
35
+ visibility: visible;
36
+ ${startPosition}: 0;
37
+ transition: all ${transitionDuration}ms ease;
38
+ }
39
+
40
+ &.exit {
41
+ visibility: visible;
42
+ ${startPosition}: 0;
43
+ }
44
+
45
+ &.exit-active {
46
+ visibility: hidden;
47
+ ${startPosition}: -100%;
48
+ transition: all ${transitionDuration}ms ease;
49
+ }
50
+ `}
51
+ `;
52
+ const StyledMenuModal = styled.div`
18
53
  height: 100vh;
19
- width: 100%;
54
+ width: 100vw;
20
55
  outline: none;
21
56
 
22
57
  a,
@@ -26,13 +61,10 @@ const StyledMenuFullscreen = styled.div`
26
61
  }
27
62
 
28
63
  ${({
29
- isOpen,
30
64
  menuType,
31
- startPosition,
32
65
  theme
33
66
  }) => css`
34
67
  background-color: ${menuConfigVariants[menuType].background};
35
- z-index: ${theme.zIndex.fullScreenModal};
36
68
 
37
69
  && {
38
70
  ${menuType === "dark" && css`
@@ -55,7 +87,7 @@ const StyledMenuFullscreen = styled.div`
55
87
  }
56
88
  `}
57
89
 
58
- ${StyledSearch} {
90
+ ${StyledSearch} {
59
91
  ${StyledIcon} {
60
92
  display: inline-flex;
61
93
  margin-right: 0;
@@ -76,18 +108,6 @@ const StyledMenuFullscreen = styled.div`
76
108
  }
77
109
  }
78
110
  }
79
-
80
- ${isOpen && css`
81
- visibility: visible;
82
- ${startPosition}: 0;
83
- transition: all 0.3s ease;
84
- `}
85
-
86
- ${!isOpen && css`
87
- visibility: hidden;
88
- ${startPosition}: -100%;
89
- transition: all 0.3s ease;
90
- `}
91
111
  `}
92
112
 
93
113
  ${StyledBox} {
@@ -115,4 +135,7 @@ const StyledMenuFullscreenHeader = styled.div`
115
135
  StyledMenuFullscreen.defaultProps = {
116
136
  theme: baseTheme
117
137
  };
118
- export { StyledMenuFullscreen, StyledMenuFullscreenHeader };
138
+ StyledMenuModal.defaultProps = {
139
+ theme: baseTheme
140
+ };
141
+ export { StyledMenuModal, StyledMenuFullscreen, StyledMenuFullscreenHeader };
@@ -89,6 +89,11 @@ const esES = {
89
89
  loader: {
90
90
  loading: () => "Cargando"
91
91
  },
92
+ menuFullscreen: {
93
+ ariaLabels: {
94
+ closeButton: () => "Cerrar"
95
+ }
96
+ },
92
97
  message: {
93
98
  closeButtonAriaLabel: () => "Cerrar"
94
99
  },
@@ -91,6 +91,11 @@ const enGB = {
91
91
  loader: {
92
92
  loading: () => "Loading"
93
93
  },
94
+ menuFullscreen: {
95
+ ariaLabels: {
96
+ closeButton: () => "Close"
97
+ }
98
+ },
94
99
  message: {
95
100
  closeButtonAriaLabel: () => "Close"
96
101
  },
@@ -74,6 +74,11 @@ interface Locale {
74
74
  loader: {
75
75
  loading: () => string;
76
76
  };
77
+ menuFullscreen: {
78
+ ariaLabels: {
79
+ closeButton: () => string;
80
+ };
81
+ };
77
82
  message: {
78
83
  closeButtonAriaLabel: () => string;
79
84
  };
@@ -1,6 +1,8 @@
1
1
  import React from "react";
2
- import { TagProps } from "../../../__internal__/utils/helpers/tags";
3
- export interface MenuFullscreenProps extends TagProps {
2
+ import type { TagProps } from "../../../__internal__/utils/helpers/tags";
3
+ export interface MenuFullscreenProps extends Omit<TagProps, "data-component"> {
4
+ /** Accessible name that conveys the purpose of the menu */
5
+ "aria-label"?: string;
4
6
  /** The child elements to render */
5
7
  children?: React.ReactNode;
6
8
  /** Sets whether the component is open or closed */
@@ -8,7 +10,9 @@ export interface MenuFullscreenProps extends TagProps {
8
10
  /** The start position for the component to open from */
9
11
  startPosition?: "left" | "right";
10
12
  /** A callback to be called when the close icon is clicked or enter is pressed when focused */
11
- onClose: (ev: React.KeyboardEvent<HTMLElement> | React.MouseEvent<HTMLButtonElement>) => void;
13
+ onClose: (ev: React.KeyboardEvent<HTMLButtonElement> | React.MouseEvent<HTMLButtonElement> | KeyboardEvent) => void;
14
+ /** Manually override the internal modal stacking order to set this as top */
15
+ topModalOverride?: boolean;
12
16
  }
13
- export declare const MenuFullscreen: ({ children, isOpen, startPosition, onClose, ...rest }: MenuFullscreenProps) => React.JSX.Element;
17
+ export declare const MenuFullscreen: ({ "aria-label": ariaLabel, "data-element": dataElement, "data-role": dataRole, children, isOpen, onClose, startPosition, topModalOverride, }: MenuFullscreenProps) => React.JSX.Element;
14
18
  export default MenuFullscreen;
@@ -6,52 +6,57 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = exports.MenuFullscreen = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
+ var _reactTransitionGroup = require("react-transition-group");
9
10
  var _menuFullScreen = require("./menu-full-screen.style");
10
11
  var _menu = require("../menu.style");
11
12
  var _menu2 = _interopRequireDefault(require("../menu.context"));
12
- var _focusTrap = _interopRequireDefault(require("../../../__internal__/focus-trap"));
13
13
  var _events = _interopRequireDefault(require("../../../__internal__/utils/helpers/events"));
14
14
  var _box = _interopRequireDefault(require("../../box"));
15
15
  var _iconButton = _interopRequireDefault(require("../../icon-button"));
16
16
  var _icon = _interopRequireDefault(require("../../icon"));
17
17
  var _portal = _interopRequireDefault(require("../../portal"));
18
+ var _focusTrap = _interopRequireDefault(require("../../../__internal__/focus-trap"));
18
19
  var _menuDivider = _interopRequireDefault(require("../menu-divider/menu-divider.component"));
19
- var _tags = _interopRequireDefault(require("../../../__internal__/utils/helpers/tags"));
20
+ var _useLocale = _interopRequireDefault(require("../../../hooks/__internal__/useLocale"));
21
+ var _useModalAria = _interopRequireDefault(require("../../../hooks/__internal__/useModalAria"));
22
+ var _useModalManager = _interopRequireDefault(require("../../../hooks/__internal__/useModalManager"));
20
23
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
24
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
22
25
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
23
- function _extends() { _extends = Object.assign ? Object.assign.bind() : 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); }
24
26
  const MenuFullscreen = ({
27
+ "aria-label": ariaLabel = "Fullscreen menu",
28
+ "data-element": dataElement,
29
+ "data-role": dataRole,
25
30
  children,
26
- isOpen,
27
- startPosition = "left",
31
+ isOpen = false,
28
32
  onClose,
29
- ...rest
33
+ startPosition = "left",
34
+ topModalOverride
30
35
  }) => {
31
- const menuWrapperRef = (0, _react.useRef)(null);
32
- const menuContentRef = (0, _react.useRef)(null);
36
+ const menuRef = (0, _react.useRef)(null);
37
+ const modalRef = (0, _react.useRef)(null);
38
+ const contentRef = (0, _react.useRef)(null);
39
+ const isTopModal = (0, _useModalAria.default)(modalRef);
33
40
  const {
34
41
  menuType
35
42
  } = (0, _react.useContext)(_menu2.default);
36
43
  const isDarkVariant = ["dark", "black"].includes(menuType);
37
- const handleKeyDown = ev => {
38
- /* istanbul ignore else */
39
- if (_events.default.isEscKey(ev)) {
40
- onClose(ev);
41
- }
42
- if (_events.default.isTabKey(ev) && !_events.default.isShiftKey(ev)) {
43
- const search = menuWrapperRef.current?.querySelector('[data-component="search"');
44
- const searchInput = search?.querySelector("input");
45
- const searchButton = search?.querySelector("button");
44
+ const transitionDuration = 200;
45
+ const locale = (0, _useLocale.default)();
46
46
 
47
- // if there is no value in the search input the button disappears when the input blurs
48
- // this means we need to programatically set focus to the next menu item
49
- if (searchButton && searchInput && !searchInput.value && searchInput === document.activeElement) {
50
- ev.preventDefault();
51
- const elements = Array.from(menuWrapperRef.current?.querySelectorAll("a, input, button"));
52
- const index = elements.indexOf(searchInput);
53
- elements[index + 2]?.focus();
54
- }
47
+ // TODO: Remove this temporary event handler as part of FE-6078
48
+ const handleFocusedSearchButton = ev => {
49
+ const search = modalRef.current?.querySelector('[data-component="search"]');
50
+ const searchInput = search?.querySelector("input");
51
+ const searchButton = search?.querySelector("button");
52
+
53
+ // if there is no value in the search input the button disappears when the input blurs
54
+ // this means we need to programmatically set focus to the next menu item
55
+ if (searchButton && searchInput && !searchInput.value && searchInput === document.activeElement) {
56
+ ev.preventDefault();
57
+ const elements = Array.from(modalRef.current?.querySelectorAll("a, input, button"));
58
+ const index = elements.indexOf(searchInput);
59
+ elements[index + 2]?.focus();
55
60
  }
56
61
  };
57
62
  const flattenedChildren = _react.default.Children.toArray(children);
@@ -61,23 +66,45 @@ const MenuFullscreen = ({
61
66
  }
62
67
  return child;
63
68
  }));
64
- return /*#__PURE__*/_react.default.createElement("li", {
65
- "aria-label": "menu-fullscreen"
66
- }, /*#__PURE__*/_react.default.createElement(_portal.default, null, /*#__PURE__*/_react.default.createElement(_focusTrap.default, {
67
- wrapperRef: menuWrapperRef,
68
- isOpen: isOpen
69
- }, /*#__PURE__*/_react.default.createElement(_menuFullScreen.StyledMenuFullscreen, _extends({
70
- ref: menuWrapperRef,
71
- isOpen: isOpen,
72
- menuType: menuType,
69
+ const closeModal = (0, _react.useCallback)(ev => {
70
+ if (onClose && _events.default.isEscKey(ev)) {
71
+ ev.stopImmediatePropagation();
72
+ onClose(ev);
73
+ }
74
+ }, [onClose]);
75
+ (0, _useModalManager.default)({
76
+ open: isOpen,
77
+ closeModal,
78
+ modalRef: menuRef,
79
+ topModalOverride
80
+ });
81
+ return /*#__PURE__*/_react.default.createElement("li", null, /*#__PURE__*/_react.default.createElement(_portal.default, null, /*#__PURE__*/_react.default.createElement(_reactTransitionGroup.CSSTransition, {
82
+ nodeRef: menuRef,
83
+ in: isOpen,
84
+ timeout: transitionDuration,
85
+ unmountOnExit: true
86
+ }, /*#__PURE__*/_react.default.createElement(_menuFullScreen.StyledMenuFullscreen, {
87
+ ref: menuRef,
73
88
  startPosition: startPosition,
74
- onKeyDown: handleKeyDown
75
- }, rest, (0, _tags.default)("menu-fullscreen", rest)), /*#__PURE__*/_react.default.createElement(_menuFullScreen.StyledMenuFullscreenHeader, {
76
- isOpen: isOpen,
89
+ transitionDuration: transitionDuration
90
+ }, /*#__PURE__*/_react.default.createElement(_focusTrap.default, {
91
+ wrapperRef: modalRef,
92
+ isOpen: isOpen
93
+ }, /*#__PURE__*/_react.default.createElement(_menuFullScreen.StyledMenuModal, {
94
+ "aria-label": ariaLabel,
95
+ "aria-modal": isTopModal ? true : undefined,
96
+ "data-component": "menu-fullscreen",
97
+ "data-element": dataElement,
98
+ "data-role": dataRole,
77
99
  menuType: menuType,
78
- startPosition: startPosition
100
+ onKeyDown: ev => _events.default.isTabKey(ev) && !_events.default.isShiftKey(ev) && handleFocusedSearchButton(ev),
101
+ ref: modalRef,
102
+ role: "dialog",
103
+ tabIndex: -1
104
+ }, /*#__PURE__*/_react.default.createElement(_menuFullScreen.StyledMenuFullscreenHeader, {
105
+ menuType: menuType
79
106
  }, /*#__PURE__*/_react.default.createElement(_iconButton.default, {
80
- "aria-label": "menu fullscreen close button",
107
+ "aria-label": locale.menuFullscreen.ariaLabels.closeButton(),
81
108
  onClick: onClose,
82
109
  "data-element": "close"
83
110
  }, /*#__PURE__*/_react.default.createElement(_icon.default, {
@@ -91,7 +118,7 @@ const MenuFullscreen = ({
91
118
  }, /*#__PURE__*/_react.default.createElement(_menu.StyledMenuWrapper, {
92
119
  "data-component": "menu",
93
120
  menuType: menuType,
94
- ref: menuContentRef,
121
+ ref: contentRef,
95
122
  display: "flex",
96
123
  flexDirection: "column",
97
124
  role: "list",
@@ -104,7 +131,7 @@ const MenuFullscreen = ({
104
131
  openSubmenuId: null,
105
132
  setOpenSubmenuId: /* istanbul ignore next */() => {}
106
133
  }
107
- }, childArray)))))));
134
+ }, childArray)))))))));
108
135
  };
109
136
  exports.MenuFullscreen = MenuFullscreen;
110
137
  var _default = exports.default = MenuFullscreen;
@@ -1,8 +1,12 @@
1
- import { MenuFullscreenProps } from "./menu-full-screen.component";
2
1
  import { MenuType } from "../menu.context";
3
- interface StyledMenuFullScreenProps extends Pick<MenuFullscreenProps, "isOpen" | "startPosition"> {
2
+ declare const StyledMenuFullscreen: import("styled-components").StyledComponent<"div", any, {
3
+ transitionDuration: number;
4
+ startPosition: "left" | "right";
5
+ }, never>;
6
+ declare const StyledMenuModal: import("styled-components").StyledComponent<"div", any, {
4
7
  menuType: MenuType;
5
- }
6
- declare const StyledMenuFullscreen: import("styled-components").StyledComponent<"div", any, StyledMenuFullScreenProps, never>;
7
- declare const StyledMenuFullscreenHeader: import("styled-components").StyledComponent<"div", any, StyledMenuFullScreenProps, never>;
8
- export { StyledMenuFullscreen, StyledMenuFullscreenHeader };
8
+ }, never>;
9
+ declare const StyledMenuFullscreenHeader: import("styled-components").StyledComponent<"div", any, {
10
+ menuType: MenuType;
11
+ }, never>;
12
+ export { StyledMenuModal, StyledMenuFullscreen, StyledMenuFullscreenHeader };
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.StyledMenuFullscreenHeader = exports.StyledMenuFullscreen = void 0;
6
+ exports.StyledMenuModal = exports.StyledMenuFullscreenHeader = exports.StyledMenuFullscreen = void 0;
7
7
  var _styledComponents = _interopRequireWildcard(require("styled-components"));
8
8
  var _themes = require("../../../style/themes");
9
9
  var _iconButton = _interopRequireDefault(require("../../icon-button/icon-button.style"));
@@ -17,15 +17,50 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
17
17
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
18
18
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
19
19
  const oldFocusStyling = `
20
- outline: solid 3px var(--colorsSemanticFocus500);
21
- box-shadow: none;
20
+ outline: solid 3px var(--colorsSemanticFocus500);
21
+ box-shadow: none;
22
22
  `;
23
23
  const StyledMenuFullscreen = exports.StyledMenuFullscreen = _styledComponents.default.div`
24
24
  position: fixed;
25
25
  top: 0;
26
26
  bottom: 0;
27
+
28
+ ${({
29
+ theme
30
+ }) => (0, _styledComponents.css)`
31
+ z-index: ${theme.zIndex.fullScreenModal};
32
+ `}
33
+
34
+ ${({
35
+ startPosition,
36
+ transitionDuration
37
+ }) => (0, _styledComponents.css)`
38
+ &.enter {
39
+ visibility: hidden;
40
+ ${startPosition}: -100%;
41
+ }
42
+
43
+ &.enter-active {
44
+ visibility: visible;
45
+ ${startPosition}: 0;
46
+ transition: all ${transitionDuration}ms ease;
47
+ }
48
+
49
+ &.exit {
50
+ visibility: visible;
51
+ ${startPosition}: 0;
52
+ }
53
+
54
+ &.exit-active {
55
+ visibility: hidden;
56
+ ${startPosition}: -100%;
57
+ transition: all ${transitionDuration}ms ease;
58
+ }
59
+ `}
60
+ `;
61
+ const StyledMenuModal = exports.StyledMenuModal = _styledComponents.default.div`
27
62
  height: 100vh;
28
- width: 100%;
63
+ width: 100vw;
29
64
  outline: none;
30
65
 
31
66
  a,
@@ -35,13 +70,10 @@ const StyledMenuFullscreen = exports.StyledMenuFullscreen = _styledComponents.de
35
70
  }
36
71
 
37
72
  ${({
38
- isOpen,
39
73
  menuType,
40
- startPosition,
41
74
  theme
42
75
  }) => (0, _styledComponents.css)`
43
76
  background-color: ${_menu.default[menuType].background};
44
- z-index: ${theme.zIndex.fullScreenModal};
45
77
 
46
78
  && {
47
79
  ${menuType === "dark" && (0, _styledComponents.css)`
@@ -64,7 +96,7 @@ const StyledMenuFullscreen = exports.StyledMenuFullscreen = _styledComponents.de
64
96
  }
65
97
  `}
66
98
 
67
- ${_search.default} {
99
+ ${_search.default} {
68
100
  ${_icon.default} {
69
101
  display: inline-flex;
70
102
  margin-right: 0;
@@ -85,18 +117,6 @@ const StyledMenuFullscreen = exports.StyledMenuFullscreen = _styledComponents.de
85
117
  }
86
118
  }
87
119
  }
88
-
89
- ${isOpen && (0, _styledComponents.css)`
90
- visibility: visible;
91
- ${startPosition}: 0;
92
- transition: all 0.3s ease;
93
- `}
94
-
95
- ${!isOpen && (0, _styledComponents.css)`
96
- visibility: hidden;
97
- ${startPosition}: -100%;
98
- transition: all 0.3s ease;
99
- `}
100
120
  `}
101
121
 
102
122
  ${_box.default} {
@@ -123,4 +143,7 @@ const StyledMenuFullscreenHeader = exports.StyledMenuFullscreenHeader = _styledC
123
143
  `;
124
144
  StyledMenuFullscreen.defaultProps = {
125
145
  theme: _themes.baseTheme
146
+ };
147
+ StyledMenuModal.defaultProps = {
148
+ theme: _themes.baseTheme
126
149
  };
@@ -95,6 +95,11 @@ const esES = {
95
95
  loader: {
96
96
  loading: () => "Cargando"
97
97
  },
98
+ menuFullscreen: {
99
+ ariaLabels: {
100
+ closeButton: () => "Cerrar"
101
+ }
102
+ },
98
103
  message: {
99
104
  closeButtonAriaLabel: () => "Cerrar"
100
105
  },
@@ -97,6 +97,11 @@ const enGB = {
97
97
  loader: {
98
98
  loading: () => "Loading"
99
99
  },
100
+ menuFullscreen: {
101
+ ariaLabels: {
102
+ closeButton: () => "Close"
103
+ }
104
+ },
100
105
  message: {
101
106
  closeButtonAriaLabel: () => "Close"
102
107
  },
@@ -74,6 +74,11 @@ interface Locale {
74
74
  loader: {
75
75
  loading: () => string;
76
76
  };
77
+ menuFullscreen: {
78
+ ariaLabels: {
79
+ closeButton: () => string;
80
+ };
81
+ };
77
82
  message: {
78
83
  closeButtonAriaLabel: () => string;
79
84
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "128.2.0",
3
+ "version": "128.3.0",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "files": [
6
6
  "lib",