carbon-react 119.4.0 → 119.4.1

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 (23) hide show
  1. package/esm/__spec_helper__/mock-resize-observer.js +20 -5
  2. package/esm/components/global-header/global-header.component.js +6 -29
  3. package/esm/components/menu/__internal__/submenu/submenu.component.js +6 -1
  4. package/esm/components/menu/__internal__/submenu/submenu.style.d.ts +1 -0
  5. package/esm/components/menu/__internal__/submenu/submenu.style.js +4 -1
  6. package/esm/components/navigation-bar/fixed-navigation-bar.context.d.ts +11 -0
  7. package/esm/components/navigation-bar/fixed-navigation-bar.context.js +31 -0
  8. package/esm/components/navigation-bar/navigation-bar.component.d.ts +3 -1
  9. package/esm/components/navigation-bar/navigation-bar.component.js +20 -8
  10. package/esm/components/navigation-bar/navigation-bar.style.d.ts +4 -0
  11. package/esm/components/navigation-bar/navigation-bar.style.js +3 -2
  12. package/lib/__spec_helper__/mock-resize-observer.js +20 -5
  13. package/lib/components/global-header/global-header.component.js +6 -31
  14. package/lib/components/menu/__internal__/submenu/submenu.component.js +6 -1
  15. package/lib/components/menu/__internal__/submenu/submenu.style.d.ts +1 -0
  16. package/lib/components/menu/__internal__/submenu/submenu.style.js +4 -1
  17. package/lib/components/navigation-bar/fixed-navigation-bar.context.d.ts +11 -0
  18. package/lib/components/navigation-bar/fixed-navigation-bar.context.js +42 -0
  19. package/lib/components/navigation-bar/navigation-bar.component.d.ts +3 -1
  20. package/lib/components/navigation-bar/navigation-bar.component.js +22 -8
  21. package/lib/components/navigation-bar/navigation-bar.style.d.ts +4 -0
  22. package/lib/components/navigation-bar/navigation-bar.style.js +3 -2
  23. package/package.json +1 -1
@@ -2,10 +2,25 @@ const setupResizeObserverMock = () => {
2
2
  if (!window) {
3
3
  return;
4
4
  }
5
- window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({
6
- disconnect: jest.fn(),
7
- observe: jest.fn(),
8
- unobserve: jest.fn()
9
- }));
5
+ window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(callback => {
6
+ let hasCalledCallback = false;
7
+ const observer = {
8
+ disconnect: jest.fn(),
9
+ // observe mock needs to actually call the callback straight away, as this is what a real ResizeObserver does
10
+ // and this behaviour is needed for the FixedNavigationBarContextProvider to work properly.
11
+ // Note that we must only call the callback once per ResizeObserver instance, to avoid stack overflows in
12
+ // react-virtual.
13
+ observe: jest.fn(target => {
14
+ if (!hasCalledCallback) {
15
+ hasCalledCallback = true;
16
+ callback([{
17
+ target
18
+ }], observer);
19
+ }
20
+ }),
21
+ unobserve: jest.fn()
22
+ };
23
+ return observer;
24
+ });
10
25
  };
11
26
  export default setupResizeObserverMock;
@@ -1,27 +1,9 @@
1
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
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
- import styled, { css } from "styled-components";
5
- import { baseTheme } from "../../style/themes";
6
- import StyledNavigationBar from "../navigation-bar/navigation-bar.style";
4
+ import styled from "styled-components";
7
5
  import Box from "../box";
8
- const StyledGlobalHeader = styled(StyledNavigationBar).attrs(_ref => {
9
- let {
10
- theme
11
- } = _ref;
12
- return {
13
- theme: theme || /* istanbul ignore next */baseTheme
14
- };
15
- })`
16
- ${_ref2 => {
17
- let {
18
- theme
19
- } = _ref2;
20
- return css`
21
- z-index: ${theme.zIndex.globalNav};
22
- `;
23
- }}
24
- `;
6
+ import NavigationBar from "../navigation-bar";
25
7
  const StyledLogo = styled(Box)`
26
8
  display: flex;
27
9
  align-items: center;
@@ -42,19 +24,14 @@ const StyledLogo = styled(Box)`
42
24
  margin-left: var(--spacing500);
43
25
  }
44
26
  `;
45
- const GlobalHeader = _ref3 => {
27
+ const GlobalHeader = _ref => {
46
28
  let {
47
29
  children,
48
30
  logo,
49
31
  ...rest
50
- } = _ref3;
51
- return /*#__PURE__*/React.createElement(StyledGlobalHeader, _extends({
52
- "aria-label": "Global Header",
53
- "data-component": "global-header",
54
- navigationType: "black",
55
- orientation: "top",
56
- offset: "0px",
57
- position: "fixed"
32
+ } = _ref;
33
+ return /*#__PURE__*/React.createElement(NavigationBar, _extends({
34
+ isGlobal: true
58
35
  }, rest), logo && /*#__PURE__*/React.createElement(StyledLogo, {
59
36
  "data-element": "global-header-logo-wrapper"
60
37
  }, logo), children);
@@ -11,6 +11,7 @@ import useClickAwayListener from "../../../../hooks/__internal__/useClickAwayLis
11
11
  import guid from "../../../../__internal__/utils/helpers/guid";
12
12
  import { SCROLLABLE_BLOCK, SCROLLABLE_BLOCK_PARENT, BLOCK_INDEX_SELECTOR, ALL_CHILDREN_SELECTOR } from "../locators";
13
13
  import useStableCallback from "../../../../hooks/__internal__/useStableCallback/useStableCallback";
14
+ import FixedNavigationBarContext from "../../../navigation-bar/fixed-navigation-bar.context";
14
15
  const Submenu = /*#__PURE__*/React.forwardRef((_ref, ref) => {
15
16
  let {
16
17
  children,
@@ -46,6 +47,9 @@ const Submenu = /*#__PURE__*/React.forwardRef((_ref, ref) => {
46
47
  const shiftTabPressed = useRef(false);
47
48
  const focusFirstMenuItemOnOpen = useRef(false);
48
49
  const numberOfChildren = submenuItemIds.length;
50
+ const {
51
+ submenuMaxHeight
52
+ } = useContext(FixedNavigationBarContext);
49
53
  const onSubmenuOpen = useStableCallback(onSubmenuOpenProp);
50
54
  const blockIndex = useMemo(() => {
51
55
  const items = submenuRef.current?.querySelectorAll(BLOCK_INDEX_SELECTOR);
@@ -282,7 +286,8 @@ const Submenu = /*#__PURE__*/React.forwardRef((_ref, ref) => {
282
286
  submenuDirection: submenuDirection,
283
287
  variant: variant,
284
288
  menuType: menuType,
285
- role: blockIndex === 0 ? "presentation" : "list"
289
+ role: blockIndex === 0 ? "presentation" : "list",
290
+ maxHeight: submenuMaxHeight
286
291
  }, /*#__PURE__*/React.createElement(SubmenuContext.Provider, {
287
292
  value: {
288
293
  submenuFocusId,
@@ -10,6 +10,7 @@ interface StyledSubmenuWrapperProps extends SharedStyleProps {
10
10
  }
11
11
  interface StyledSubmenuProps extends SharedStyleProps, Pick<SubmenuProps, "variant"> {
12
12
  submenuDirection?: string;
13
+ maxHeight?: string;
13
14
  }
14
15
  declare const StyledSubmenuWrapper: import("styled-components").StyledComponent<"div", any, StyledSubmenuWrapperProps, never>;
15
16
  declare const StyledSubmenu: import("styled-components").StyledComponent<"ul", any, StyledSubmenuProps, never>;
@@ -45,7 +45,8 @@ const StyledSubmenu = styled.ul`
45
45
  menuType,
46
46
  submenuDirection,
47
47
  variant,
48
- inFullscreenView
48
+ inFullscreenView,
49
+ maxHeight
49
50
  } = _ref3;
50
51
  return css`
51
52
  ${!inFullscreenView && menuType && css`
@@ -69,6 +70,8 @@ const StyledSubmenu = styled.ul`
69
70
  ${!inFullscreenView && css`
70
71
  border-bottom-right-radius: var(--borderRadius100);
71
72
  border-bottom-left-radius: var(--borderRadius100);
73
+ overflow-y: auto;
74
+ ${maxHeight && `max-height: ${maxHeight};`}
72
75
 
73
76
  ${StyledMenuItem}:last-child a,
74
77
  ${StyledMenuItem}:last-child button,
@@ -0,0 +1,11 @@
1
+ import React from "react";
2
+ import { NavigationBarProps } from ".";
3
+ declare type FixedNavigationBarContextProps = {
4
+ submenuMaxHeight?: string;
5
+ };
6
+ declare const FixedNavigationBarContext: React.Context<FixedNavigationBarContextProps>;
7
+ export interface FixedNavigationBarContextProviderProps extends Pick<NavigationBarProps, "position" | "orientation" | "offset" | "children"> {
8
+ navbarElement: HTMLElement | null;
9
+ }
10
+ export declare const FixedNavigationBarContextProvider: ({ position, orientation, offset, children, navbarElement, }: FixedNavigationBarContextProviderProps) => React.JSX.Element;
11
+ export default FixedNavigationBarContext;
@@ -0,0 +1,31 @@
1
+ import React, { createContext, useState, useCallback } from "react";
2
+ import useResizeObserver from "../../hooks/__internal__/useResizeObserver/useResizeObserver";
3
+ const FixedNavigationBarContext = /*#__PURE__*/createContext({});
4
+ export const FixedNavigationBarContextProvider = _ref => {
5
+ let {
6
+ position,
7
+ orientation,
8
+ offset,
9
+ children,
10
+ navbarElement
11
+ } = _ref;
12
+ const [navbarHeight, setNavbarHeight] = useState(navbarElement?.offsetHeight);
13
+ const updateHeight = useCallback(() => setNavbarHeight(navbarElement?.offsetHeight), [navbarElement]);
14
+ useResizeObserver({
15
+ current: navbarElement
16
+ }, updateHeight);
17
+ let submenuMaxHeight;
18
+ if (position === "fixed") {
19
+ if (orientation === "top" && navbarHeight !== undefined) {
20
+ submenuMaxHeight = `calc(100vh - ${navbarHeight}px - ${offset})`;
21
+ } else if (orientation === "bottom") {
22
+ submenuMaxHeight = offset;
23
+ }
24
+ }
25
+ return /*#__PURE__*/React.createElement(FixedNavigationBarContext.Provider, {
26
+ value: {
27
+ submenuMaxHeight
28
+ }
29
+ }, children);
30
+ };
31
+ export default FixedNavigationBarContext;
@@ -18,6 +18,8 @@ export interface NavigationBarProps extends PaddingProps, FlexboxProps {
18
18
  offset?: string;
19
19
  /** Defines whether the navigation bar should be positioned top or bottom */
20
20
  orientation?: Orientation;
21
+ /** @private @ignore set to true only when rendering the GlobalHeader component */
22
+ isGlobal?: boolean;
21
23
  }
22
- export declare const NavigationBar: ({ navigationType, isLoading, children, ariaLabel, position, offset, orientation, ...props }: NavigationBarProps) => JSX.Element;
24
+ export declare const NavigationBar: ({ navigationType, isLoading, children, ariaLabel, position, offset, orientation, isGlobal, ...props }: NavigationBarProps) => JSX.Element;
23
25
  export default NavigationBar;
@@ -1,7 +1,8 @@
1
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 from "react";
2
+ import React, { useState } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import StyledNavigationBar from "./navigation-bar.style";
5
+ import { FixedNavigationBarContextProvider } from "./fixed-navigation-bar.context";
5
6
  const NavigationBar = _ref => {
6
7
  let {
7
8
  navigationType = "light",
@@ -11,17 +12,27 @@ const NavigationBar = _ref => {
11
12
  position,
12
13
  offset = "0",
13
14
  orientation,
15
+ isGlobal,
14
16
  ...props
15
17
  } = _ref;
18
+ const [navbarElement, setNavbarElement] = useState(null);
16
19
  return /*#__PURE__*/React.createElement(StyledNavigationBar, _extends({
17
20
  role: "navigation",
18
- "aria-label": ariaLabel,
19
- navigationType: navigationType,
20
- "data-component": "navigation-bar",
21
- position: position,
22
- offset: offset,
23
- orientation: orientation
24
- }, props), !isLoading && children);
21
+ "data-component": isGlobal ? "global-header" : "navigation-bar",
22
+ "aria-label": isGlobal ? "Global Header" : ariaLabel,
23
+ navigationType: isGlobal ? "black" : navigationType,
24
+ orientation: isGlobal ? "top" : orientation,
25
+ offset: isGlobal ? "0px" : offset,
26
+ position: isGlobal ? "fixed" : position
27
+ }, props, {
28
+ isGlobal: isGlobal,
29
+ ref: setNavbarElement
30
+ }), /*#__PURE__*/React.createElement(FixedNavigationBarContextProvider, {
31
+ orientation: isGlobal ? "top" : orientation,
32
+ offset: isGlobal ? "0px" : offset,
33
+ position: isGlobal ? "fixed" : position,
34
+ navbarElement: navbarElement
35
+ }, !isLoading && children));
25
36
  };
26
37
  NavigationBar.propTypes = {
27
38
  "alignContent": PropTypes.oneOfType([PropTypes.oneOf(["-moz-initial", "baseline", "center", "end", "flex-end", "flex-start", "inherit", "initial", "normal", "revert", "space-around", "space-between", "space-evenly", "start", "stretch", "unset"]), PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.oneOf(["-moz-initial", "baseline", "center", "end", "flex-end", "flex-start", "inherit", "initial", "normal", "revert", "space-around", "space-between", "space-evenly", "start", "stretch", "unset", null]), PropTypes.shape({
@@ -563,6 +574,7 @@ NavigationBar.propTypes = {
563
574
  "valueOf": PropTypes.func.isRequired
564
575
  })]),
565
576
  "flexWrap": PropTypes.oneOfType([PropTypes.oneOf(["-moz-initial", "inherit", "initial", "nowrap", "revert", "unset", "wrap-reverse", "wrap"]), PropTypes.arrayOf(PropTypes.oneOf(["-moz-initial", "inherit", "initial", "nowrap", "revert", "unset", "wrap-reverse", "wrap", null])), PropTypes.object]),
577
+ "isGlobal": PropTypes.bool,
566
578
  "isLoading": PropTypes.bool,
567
579
  "justifyContent": PropTypes.oneOfType([PropTypes.oneOf(["-moz-initial", "center", "end", "flex-end", "flex-start", "inherit", "initial", "left", "normal", "revert", "right", "space-around", "space-between", "space-evenly", "start", "stretch", "unset"]), PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.oneOf(["-moz-initial", "center", "end", "flex-end", "flex-start", "inherit", "initial", "left", "normal", "revert", "right", "space-around", "space-between", "space-evenly", "start", "stretch", "unset", null]), PropTypes.shape({
568
580
  "__@iterator": PropTypes.func.isRequired,
@@ -9,6 +9,8 @@ export declare type StyledNavigationBarProps = PaddingProps & FlexboxProps & {
9
9
  offset?: string;
10
10
  /** Defines whether the navigation bar should be positioned top or bottom */
11
11
  orientation?: Orientation;
12
+ /** set to true only when rendering the GlobalHeader component */
13
+ isGlobal?: boolean;
12
14
  };
13
15
  declare const StyledNavigationBar: import("styled-components").StyledComponent<"nav", any, PaddingProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & FlexboxProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & {
14
16
  /** Color scheme of navigation component */
@@ -19,5 +21,7 @@ declare const StyledNavigationBar: import("styled-components").StyledComponent<"
19
21
  offset?: string | undefined;
20
22
  /** Defines whether the navigation bar should be positioned top or bottom */
21
23
  orientation?: Orientation | undefined;
24
+ /** set to true only when rendering the GlobalHeader component */
25
+ isGlobal?: boolean | undefined;
22
26
  }, never>;
23
27
  export default StyledNavigationBar;
@@ -55,11 +55,12 @@ const StyledNavigationBar = styled.nav`
55
55
  ${_ref2 => {
56
56
  let {
57
57
  navigationType,
58
- theme
58
+ theme,
59
+ isGlobal
59
60
  } = _ref2;
60
61
  return css`
61
62
  min-height: 40px;
62
- z-index: ${theme.zIndex.nav};
63
+ z-index: ${isGlobal ? theme.zIndex.globalNav : theme.zIndex.nav};
63
64
 
64
65
  ${navigationType === "light" && css`
65
66
  background-color: var(--colorsComponentsMenuSpringStandard500);
@@ -8,11 +8,26 @@ const setupResizeObserverMock = () => {
8
8
  if (!window) {
9
9
  return;
10
10
  }
11
- window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({
12
- disconnect: jest.fn(),
13
- observe: jest.fn(),
14
- unobserve: jest.fn()
15
- }));
11
+ window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(callback => {
12
+ let hasCalledCallback = false;
13
+ const observer = {
14
+ disconnect: jest.fn(),
15
+ // observe mock needs to actually call the callback straight away, as this is what a real ResizeObserver does
16
+ // and this behaviour is needed for the FixedNavigationBarContextProvider to work properly.
17
+ // Note that we must only call the callback once per ResizeObserver instance, to avoid stack overflows in
18
+ // react-virtual.
19
+ observe: jest.fn(target => {
20
+ if (!hasCalledCallback) {
21
+ hasCalledCallback = true;
22
+ callback([{
23
+ target
24
+ }], observer);
25
+ }
26
+ }),
27
+ unobserve: jest.fn()
28
+ };
29
+ return observer;
30
+ });
16
31
  };
17
32
  var _default = setupResizeObserverMock;
18
33
  exports.default = _default;
@@ -6,31 +6,11 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _react = _interopRequireDefault(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
- var _styledComponents = _interopRequireWildcard(require("styled-components"));
10
- var _themes = require("../../style/themes");
11
- var _navigationBar = _interopRequireDefault(require("../navigation-bar/navigation-bar.style"));
9
+ var _styledComponents = _interopRequireDefault(require("styled-components"));
12
10
  var _box = _interopRequireDefault(require("../box"));
13
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
14
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
11
+ var _navigationBar = _interopRequireDefault(require("../navigation-bar"));
15
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
16
13
  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); }
17
- const StyledGlobalHeader = (0, _styledComponents.default)(_navigationBar.default).attrs(_ref => {
18
- let {
19
- theme
20
- } = _ref;
21
- return {
22
- theme: theme || /* istanbul ignore next */_themes.baseTheme
23
- };
24
- })`
25
- ${_ref2 => {
26
- let {
27
- theme
28
- } = _ref2;
29
- return (0, _styledComponents.css)`
30
- z-index: ${theme.zIndex.globalNav};
31
- `;
32
- }}
33
- `;
34
14
  const StyledLogo = (0, _styledComponents.default)(_box.default)`
35
15
  display: flex;
36
16
  align-items: center;
@@ -51,19 +31,14 @@ const StyledLogo = (0, _styledComponents.default)(_box.default)`
51
31
  margin-left: var(--spacing500);
52
32
  }
53
33
  `;
54
- const GlobalHeader = _ref3 => {
34
+ const GlobalHeader = _ref => {
55
35
  let {
56
36
  children,
57
37
  logo,
58
38
  ...rest
59
- } = _ref3;
60
- return /*#__PURE__*/_react.default.createElement(StyledGlobalHeader, _extends({
61
- "aria-label": "Global Header",
62
- "data-component": "global-header",
63
- navigationType: "black",
64
- orientation: "top",
65
- offset: "0px",
66
- position: "fixed"
39
+ } = _ref;
40
+ return /*#__PURE__*/_react.default.createElement(_navigationBar.default, _extends({
41
+ isGlobal: true
67
42
  }, rest), logo && /*#__PURE__*/_react.default.createElement(StyledLogo, {
68
43
  "data-element": "global-header-logo-wrapper"
69
44
  }, logo), children);
@@ -16,6 +16,7 @@ var _useClickAwayListener = _interopRequireDefault(require("../../../../hooks/__
16
16
  var _guid = _interopRequireDefault(require("../../../../__internal__/utils/helpers/guid"));
17
17
  var _locators = require("../locators");
18
18
  var _useStableCallback = _interopRequireDefault(require("../../../../hooks/__internal__/useStableCallback/useStableCallback"));
19
+ var _fixedNavigationBar = _interopRequireDefault(require("../../../navigation-bar/fixed-navigation-bar.context"));
19
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
21
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
21
22
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
@@ -55,6 +56,9 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
55
56
  const shiftTabPressed = (0, _react.useRef)(false);
56
57
  const focusFirstMenuItemOnOpen = (0, _react.useRef)(false);
57
58
  const numberOfChildren = submenuItemIds.length;
59
+ const {
60
+ submenuMaxHeight
61
+ } = (0, _react.useContext)(_fixedNavigationBar.default);
58
62
  const onSubmenuOpen = (0, _useStableCallback.default)(onSubmenuOpenProp);
59
63
  const blockIndex = (0, _react.useMemo)(() => {
60
64
  const items = submenuRef.current?.querySelectorAll(_locators.BLOCK_INDEX_SELECTOR);
@@ -291,7 +295,8 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
291
295
  submenuDirection: submenuDirection,
292
296
  variant: variant,
293
297
  menuType: menuType,
294
- role: blockIndex === 0 ? "presentation" : "list"
298
+ role: blockIndex === 0 ? "presentation" : "list",
299
+ maxHeight: submenuMaxHeight
295
300
  }, /*#__PURE__*/_react.default.createElement(_submenu2.default.Provider, {
296
301
  value: {
297
302
  submenuFocusId,
@@ -10,6 +10,7 @@ interface StyledSubmenuWrapperProps extends SharedStyleProps {
10
10
  }
11
11
  interface StyledSubmenuProps extends SharedStyleProps, Pick<SubmenuProps, "variant"> {
12
12
  submenuDirection?: string;
13
+ maxHeight?: string;
13
14
  }
14
15
  declare const StyledSubmenuWrapper: import("styled-components").StyledComponent<"div", any, StyledSubmenuWrapperProps, never>;
15
16
  declare const StyledSubmenu: import("styled-components").StyledComponent<"ul", any, StyledSubmenuProps, never>;
@@ -55,7 +55,8 @@ const StyledSubmenu = _styledComponents.default.ul`
55
55
  menuType,
56
56
  submenuDirection,
57
57
  variant,
58
- inFullscreenView
58
+ inFullscreenView,
59
+ maxHeight
59
60
  } = _ref3;
60
61
  return (0, _styledComponents.css)`
61
62
  ${!inFullscreenView && menuType && (0, _styledComponents.css)`
@@ -79,6 +80,8 @@ const StyledSubmenu = _styledComponents.default.ul`
79
80
  ${!inFullscreenView && (0, _styledComponents.css)`
80
81
  border-bottom-right-radius: var(--borderRadius100);
81
82
  border-bottom-left-radius: var(--borderRadius100);
83
+ overflow-y: auto;
84
+ ${maxHeight && `max-height: ${maxHeight};`}
82
85
 
83
86
  ${_menu.StyledMenuItem}:last-child a,
84
87
  ${_menu.StyledMenuItem}:last-child button,
@@ -0,0 +1,11 @@
1
+ import React from "react";
2
+ import { NavigationBarProps } from ".";
3
+ declare type FixedNavigationBarContextProps = {
4
+ submenuMaxHeight?: string;
5
+ };
6
+ declare const FixedNavigationBarContext: React.Context<FixedNavigationBarContextProps>;
7
+ export interface FixedNavigationBarContextProviderProps extends Pick<NavigationBarProps, "position" | "orientation" | "offset" | "children"> {
8
+ navbarElement: HTMLElement | null;
9
+ }
10
+ export declare const FixedNavigationBarContextProvider: ({ position, orientation, offset, children, navbarElement, }: FixedNavigationBarContextProviderProps) => React.JSX.Element;
11
+ export default FixedNavigationBarContext;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.FixedNavigationBarContextProvider = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _useResizeObserver = _interopRequireDefault(require("../../hooks/__internal__/useResizeObserver/useResizeObserver"));
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
11
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
12
+ const FixedNavigationBarContext = /*#__PURE__*/(0, _react.createContext)({});
13
+ const FixedNavigationBarContextProvider = _ref => {
14
+ let {
15
+ position,
16
+ orientation,
17
+ offset,
18
+ children,
19
+ navbarElement
20
+ } = _ref;
21
+ const [navbarHeight, setNavbarHeight] = (0, _react.useState)(navbarElement?.offsetHeight);
22
+ const updateHeight = (0, _react.useCallback)(() => setNavbarHeight(navbarElement?.offsetHeight), [navbarElement]);
23
+ (0, _useResizeObserver.default)({
24
+ current: navbarElement
25
+ }, updateHeight);
26
+ let submenuMaxHeight;
27
+ if (position === "fixed") {
28
+ if (orientation === "top" && navbarHeight !== undefined) {
29
+ submenuMaxHeight = `calc(100vh - ${navbarHeight}px - ${offset})`;
30
+ } else if (orientation === "bottom") {
31
+ submenuMaxHeight = offset;
32
+ }
33
+ }
34
+ return /*#__PURE__*/_react.default.createElement(FixedNavigationBarContext.Provider, {
35
+ value: {
36
+ submenuMaxHeight
37
+ }
38
+ }, children);
39
+ };
40
+ exports.FixedNavigationBarContextProvider = FixedNavigationBarContextProvider;
41
+ var _default = FixedNavigationBarContext;
42
+ exports.default = _default;
@@ -18,6 +18,8 @@ export interface NavigationBarProps extends PaddingProps, FlexboxProps {
18
18
  offset?: string;
19
19
  /** Defines whether the navigation bar should be positioned top or bottom */
20
20
  orientation?: Orientation;
21
+ /** @private @ignore set to true only when rendering the GlobalHeader component */
22
+ isGlobal?: boolean;
21
23
  }
22
- export declare const NavigationBar: ({ navigationType, isLoading, children, ariaLabel, position, offset, orientation, ...props }: NavigationBarProps) => JSX.Element;
24
+ export declare const NavigationBar: ({ navigationType, isLoading, children, ariaLabel, position, offset, orientation, isGlobal, ...props }: NavigationBarProps) => JSX.Element;
23
25
  export default NavigationBar;
@@ -4,10 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = exports.NavigationBar = void 0;
7
- var _react = _interopRequireDefault(require("react"));
7
+ var _react = _interopRequireWildcard(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _navigationBar = _interopRequireDefault(require("./navigation-bar.style"));
10
+ var _fixedNavigationBar = require("./fixed-navigation-bar.context");
10
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && 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; }
11
14
  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); }
12
15
  const NavigationBar = _ref => {
13
16
  let {
@@ -18,17 +21,27 @@ const NavigationBar = _ref => {
18
21
  position,
19
22
  offset = "0",
20
23
  orientation,
24
+ isGlobal,
21
25
  ...props
22
26
  } = _ref;
27
+ const [navbarElement, setNavbarElement] = (0, _react.useState)(null);
23
28
  return /*#__PURE__*/_react.default.createElement(_navigationBar.default, _extends({
24
29
  role: "navigation",
25
- "aria-label": ariaLabel,
26
- navigationType: navigationType,
27
- "data-component": "navigation-bar",
28
- position: position,
29
- offset: offset,
30
- orientation: orientation
31
- }, props), !isLoading && children);
30
+ "data-component": isGlobal ? "global-header" : "navigation-bar",
31
+ "aria-label": isGlobal ? "Global Header" : ariaLabel,
32
+ navigationType: isGlobal ? "black" : navigationType,
33
+ orientation: isGlobal ? "top" : orientation,
34
+ offset: isGlobal ? "0px" : offset,
35
+ position: isGlobal ? "fixed" : position
36
+ }, props, {
37
+ isGlobal: isGlobal,
38
+ ref: setNavbarElement
39
+ }), /*#__PURE__*/_react.default.createElement(_fixedNavigationBar.FixedNavigationBarContextProvider, {
40
+ orientation: isGlobal ? "top" : orientation,
41
+ offset: isGlobal ? "0px" : offset,
42
+ position: isGlobal ? "fixed" : position,
43
+ navbarElement: navbarElement
44
+ }, !isLoading && children));
32
45
  };
33
46
  exports.NavigationBar = NavigationBar;
34
47
  NavigationBar.propTypes = {
@@ -571,6 +584,7 @@ NavigationBar.propTypes = {
571
584
  "valueOf": _propTypes.default.func.isRequired
572
585
  })]),
573
586
  "flexWrap": _propTypes.default.oneOfType([_propTypes.default.oneOf(["-moz-initial", "inherit", "initial", "nowrap", "revert", "unset", "wrap-reverse", "wrap"]), _propTypes.default.arrayOf(_propTypes.default.oneOf(["-moz-initial", "inherit", "initial", "nowrap", "revert", "unset", "wrap-reverse", "wrap", null])), _propTypes.default.object]),
587
+ "isGlobal": _propTypes.default.bool,
574
588
  "isLoading": _propTypes.default.bool,
575
589
  "justifyContent": _propTypes.default.oneOfType([_propTypes.default.oneOf(["-moz-initial", "center", "end", "flex-end", "flex-start", "inherit", "initial", "left", "normal", "revert", "right", "space-around", "space-between", "space-evenly", "start", "stretch", "unset"]), _propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.oneOf(["-moz-initial", "center", "end", "flex-end", "flex-start", "inherit", "initial", "left", "normal", "revert", "right", "space-around", "space-between", "space-evenly", "start", "stretch", "unset", null]), _propTypes.default.shape({
576
590
  "__@iterator": _propTypes.default.func.isRequired,
@@ -9,6 +9,8 @@ export declare type StyledNavigationBarProps = PaddingProps & FlexboxProps & {
9
9
  offset?: string;
10
10
  /** Defines whether the navigation bar should be positioned top or bottom */
11
11
  orientation?: Orientation;
12
+ /** set to true only when rendering the GlobalHeader component */
13
+ isGlobal?: boolean;
12
14
  };
13
15
  declare const StyledNavigationBar: import("styled-components").StyledComponent<"nav", any, PaddingProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & FlexboxProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & {
14
16
  /** Color scheme of navigation component */
@@ -19,5 +21,7 @@ declare const StyledNavigationBar: import("styled-components").StyledComponent<"
19
21
  offset?: string | undefined;
20
22
  /** Defines whether the navigation bar should be positioned top or bottom */
21
23
  orientation?: Orientation | undefined;
24
+ /** set to true only when rendering the GlobalHeader component */
25
+ isGlobal?: boolean | undefined;
22
26
  }, never>;
23
27
  export default StyledNavigationBar;
@@ -63,11 +63,12 @@ const StyledNavigationBar = _styledComponents.default.nav`
63
63
  ${_ref2 => {
64
64
  let {
65
65
  navigationType,
66
- theme
66
+ theme,
67
+ isGlobal
67
68
  } = _ref2;
68
69
  return (0, _styledComponents.css)`
69
70
  min-height: 40px;
70
- z-index: ${theme.zIndex.nav};
71
+ z-index: ${isGlobal ? theme.zIndex.globalNav : theme.zIndex.nav};
71
72
 
72
73
  ${navigationType === "light" && (0, _styledComponents.css)`
73
74
  background-color: var(--colorsComponentsMenuSpringStandard500);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "119.4.0",
3
+ "version": "119.4.1",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "files": [
6
6
  "lib",