carbon-react 117.5.0 → 117.6.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 (146) hide show
  1. package/esm/__internal__/input/input.component.d.ts +3 -3
  2. package/esm/components/advanced-color-picker/advanced-color-picker.component.js +8 -0
  3. package/esm/components/button-toggle/button-toggle.component.js +7 -0
  4. package/esm/components/checkbox/checkbox.component.js +6 -0
  5. package/esm/components/decimal/decimal.component.js +7 -0
  6. package/esm/components/grouped-character/grouped-character.component.js +6 -0
  7. package/esm/components/menu/__internal__/locators.d.ts +6 -6
  8. package/esm/components/menu/__internal__/spec-helper/index.d.ts +3 -0
  9. package/esm/components/menu/__internal__/submenu/index.d.ts +2 -0
  10. package/esm/components/menu/__internal__/submenu/index.js +1 -0
  11. package/esm/components/menu/__internal__/submenu/submenu.component.d.ts +42 -0
  12. package/esm/components/menu/__internal__/submenu/submenu.component.js +162 -85
  13. package/esm/components/menu/__internal__/submenu/submenu.context.d.ts +10 -0
  14. package/esm/components/menu/__internal__/submenu/submenu.style.d.ts +16 -0
  15. package/esm/components/menu/__internal__/submenu/submenu.style.js +4 -4
  16. package/esm/components/menu/index.d.ts +12 -6
  17. package/esm/components/menu/index.js +5 -5
  18. package/esm/components/menu/menu-divider/index.d.ts +2 -2
  19. package/esm/components/menu/menu-divider/index.js +1 -0
  20. package/esm/components/menu/menu-divider/menu-divider.component.d.ts +7 -0
  21. package/esm/components/menu/menu-divider/menu-divider.component.js +14 -7
  22. package/esm/components/menu/menu-divider/menu-divider.style.d.ts +6 -0
  23. package/esm/components/menu/menu-full-screen/index.d.ts +2 -2
  24. package/esm/components/menu/menu-full-screen/menu-full-screen.component.d.ts +14 -0
  25. package/esm/components/menu/menu-full-screen/menu-full-screen.component.js +20 -30
  26. package/esm/components/menu/menu-full-screen/menu-full-screen.style.d.ts +8 -0
  27. package/esm/components/menu/menu-full-screen/menu-full-screen.style.js +29 -27
  28. package/esm/components/menu/menu-item/index.d.ts +2 -2
  29. package/esm/components/menu/menu-item/menu-item.component.d.ts +67 -0
  30. package/esm/components/menu/menu-item/menu-item.component.js +2084 -121
  31. package/esm/components/menu/menu-item/menu-item.style.d.ts +21 -0
  32. package/esm/components/menu/menu-item/menu-item.style.js +188 -146
  33. package/esm/components/menu/menu-segment-title/index.d.ts +2 -2
  34. package/esm/components/menu/menu-segment-title/index.js +1 -0
  35. package/esm/components/menu/menu-segment-title/menu-segment-title.component.d.ts +10 -0
  36. package/esm/components/menu/menu-segment-title/menu-segment-title.component.js +13 -9
  37. package/esm/components/menu/menu-segment-title/menu-segment-title.style.d.ts +8 -0
  38. package/esm/components/menu/menu.component.d.ts +11 -9
  39. package/esm/components/menu/menu.component.js +1887 -18
  40. package/esm/components/menu/menu.config.d.ts +58 -94
  41. package/esm/components/menu/menu.context.d.ts +12 -6
  42. package/esm/components/menu/menu.style.d.ts +12 -2
  43. package/esm/components/menu/menu.style.js +11 -11
  44. package/esm/components/menu/scrollable-block/index.d.ts +2 -1
  45. package/esm/components/menu/scrollable-block/scrollable-block.component.d.ts +19 -0
  46. package/esm/components/menu/scrollable-block/scrollable-block.component.js +13 -20
  47. package/esm/components/menu/scrollable-block/scrollable-block.style.d.ts +8 -0
  48. package/esm/components/message/message-content/message-content.component.d.ts +4 -2
  49. package/esm/components/message/message-content/message-content.component.js +7 -2
  50. package/esm/components/message/message-content/message-content.style.d.ts +2 -1
  51. package/esm/components/message/message-content/message-content.style.js +4 -1
  52. package/esm/components/message/message.component.js +1 -0
  53. package/esm/components/number/number.component.js +6 -0
  54. package/esm/components/numeral-date/numeral-date.component.js +8 -0
  55. package/esm/components/radio-button/radio-button-group.component.js +8 -0
  56. package/esm/components/radio-button/radio-button.style.js +1 -1
  57. package/esm/components/search/search.component.js +6 -0
  58. package/esm/components/select/filterable-select/filterable-select.component.js +9 -1
  59. package/esm/components/select/multi-select/multi-select.component.js +9 -1
  60. package/esm/components/select/simple-select/simple-select.component.js +9 -1
  61. package/esm/components/simple-color-picker/simple-color-picker.component.js +8 -0
  62. package/esm/components/switch/switch.component.js +6 -0
  63. package/esm/components/textarea/textarea.component.js +6 -0
  64. package/esm/components/textbox/textbox.component.js +6 -0
  65. package/esm/components/toast/toast.style.d.ts +1 -1
  66. package/lib/__internal__/input/input.component.d.ts +3 -3
  67. package/lib/components/advanced-color-picker/advanced-color-picker.component.js +11 -0
  68. package/lib/components/button-toggle/button-toggle.component.js +10 -0
  69. package/lib/components/checkbox/checkbox.component.js +7 -0
  70. package/lib/components/decimal/decimal.component.js +8 -0
  71. package/lib/components/grouped-character/grouped-character.component.js +7 -0
  72. package/lib/components/menu/__internal__/locators.d.ts +6 -6
  73. package/lib/components/menu/__internal__/spec-helper/index.d.ts +3 -0
  74. package/lib/components/menu/__internal__/submenu/index.d.ts +2 -0
  75. package/lib/components/menu/__internal__/submenu/index.js +15 -0
  76. package/lib/components/menu/__internal__/submenu/package.json +6 -0
  77. package/lib/components/menu/__internal__/submenu/submenu.component.d.ts +42 -0
  78. package/lib/components/menu/__internal__/submenu/submenu.component.js +162 -86
  79. package/lib/components/menu/__internal__/submenu/submenu.context.d.ts +10 -0
  80. package/lib/components/menu/__internal__/submenu/submenu.style.d.ts +16 -0
  81. package/lib/components/menu/__internal__/submenu/submenu.style.js +4 -4
  82. package/lib/components/menu/index.d.ts +12 -6
  83. package/lib/components/menu/index.js +5 -5
  84. package/lib/components/menu/menu-divider/index.d.ts +2 -2
  85. package/lib/components/menu/menu-divider/index.js +15 -0
  86. package/lib/components/menu/menu-divider/menu-divider.component.d.ts +7 -0
  87. package/lib/components/menu/menu-divider/menu-divider.component.js +15 -7
  88. package/lib/components/menu/menu-divider/menu-divider.style.d.ts +6 -0
  89. package/lib/components/menu/menu-divider/package.json +6 -0
  90. package/lib/components/menu/menu-full-screen/index.d.ts +2 -2
  91. package/lib/components/menu/menu-full-screen/menu-full-screen.component.d.ts +14 -0
  92. package/lib/components/menu/menu-full-screen/menu-full-screen.component.js +22 -31
  93. package/lib/components/menu/menu-full-screen/menu-full-screen.style.d.ts +8 -0
  94. package/lib/components/menu/menu-full-screen/menu-full-screen.style.js +30 -28
  95. package/lib/components/menu/menu-item/index.d.ts +2 -2
  96. package/lib/components/menu/menu-item/menu-item.component.d.ts +67 -0
  97. package/lib/components/menu/menu-item/menu-item.component.js +2085 -122
  98. package/lib/components/menu/menu-item/menu-item.style.d.ts +21 -0
  99. package/lib/components/menu/menu-item/menu-item.style.js +191 -146
  100. package/lib/components/menu/menu-segment-title/index.d.ts +2 -2
  101. package/lib/components/menu/menu-segment-title/index.js +15 -0
  102. package/lib/components/menu/menu-segment-title/menu-segment-title.component.d.ts +10 -0
  103. package/lib/components/menu/menu-segment-title/menu-segment-title.component.js +14 -9
  104. package/lib/components/menu/menu-segment-title/menu-segment-title.style.d.ts +8 -0
  105. package/lib/components/menu/menu-segment-title/package.json +6 -0
  106. package/lib/components/menu/menu.component.d.ts +11 -9
  107. package/lib/components/menu/menu.component.js +1889 -20
  108. package/lib/components/menu/menu.config.d.ts +58 -94
  109. package/lib/components/menu/menu.context.d.ts +12 -6
  110. package/lib/components/menu/menu.style.d.ts +12 -2
  111. package/lib/components/menu/menu.style.js +12 -12
  112. package/lib/components/menu/scrollable-block/index.d.ts +2 -1
  113. package/lib/components/menu/scrollable-block/scrollable-block.component.d.ts +19 -0
  114. package/lib/components/menu/scrollable-block/scrollable-block.component.js +15 -21
  115. package/lib/components/menu/scrollable-block/scrollable-block.style.d.ts +8 -0
  116. package/lib/components/message/message-content/message-content.component.d.ts +4 -2
  117. package/lib/components/message/message-content/message-content.component.js +7 -2
  118. package/lib/components/message/message-content/message-content.style.d.ts +2 -1
  119. package/lib/components/message/message-content/message-content.style.js +4 -1
  120. package/lib/components/message/message.component.js +1 -0
  121. package/lib/components/number/number.component.js +7 -0
  122. package/lib/components/numeral-date/numeral-date.component.js +10 -0
  123. package/lib/components/radio-button/radio-button-group.component.js +11 -0
  124. package/lib/components/radio-button/radio-button.style.js +1 -1
  125. package/lib/components/search/search.component.js +7 -0
  126. package/lib/components/select/filterable-select/filterable-select.component.js +10 -1
  127. package/lib/components/select/multi-select/multi-select.component.js +10 -1
  128. package/lib/components/select/simple-select/simple-select.component.js +10 -1
  129. package/lib/components/simple-color-picker/simple-color-picker.component.js +11 -0
  130. package/lib/components/switch/switch.component.js +7 -0
  131. package/lib/components/textarea/textarea.component.js +7 -0
  132. package/lib/components/textbox/textbox.component.js +7 -0
  133. package/lib/components/toast/toast.style.d.ts +1 -1
  134. package/package.json +2 -2
  135. package/esm/components/menu/menu-divider/menu-divider.d.ts +0 -11
  136. package/esm/components/menu/menu-full-screen/menu-full-screen.d.ts +0 -16
  137. package/esm/components/menu/menu-item/menu-item.d.ts +0 -60
  138. package/esm/components/menu/menu-segment-title/menu-segment-title.d.ts +0 -12
  139. package/esm/components/menu/menu.d.ts +0 -28
  140. package/esm/components/menu/scrollable-block/scrollable-block.d.ts +0 -20
  141. package/lib/components/menu/menu-divider/menu-divider.d.ts +0 -11
  142. package/lib/components/menu/menu-full-screen/menu-full-screen.d.ts +0 -16
  143. package/lib/components/menu/menu-item/menu-item.d.ts +0 -60
  144. package/lib/components/menu/menu-segment-title/menu-segment-title.d.ts +0 -12
  145. package/lib/components/menu/menu.d.ts +0 -28
  146. package/lib/components/menu/scrollable-block/scrollable-block.d.ts +0 -20
@@ -19,7 +19,7 @@ export interface CommonInputProps extends Omit<React.InputHTMLAttributes<HTMLInp
19
19
  onBlur?: (ev: React.FocusEvent<HTMLInputElement>) => void;
20
20
  /** Specify a callback triggered on change */
21
21
  onChange?: (ev: React.ChangeEvent<HTMLInputElement>) => void;
22
- /** pecify a callback triggered on click */
22
+ /** Specify a callback triggered on click */
23
23
  onClick?: (ev: React.MouseEvent<HTMLInputElement>) => void;
24
24
  /** Specify a callback triggered on focus */
25
25
  onFocus?: (ev: React.FocusEvent<HTMLInputElement>) => void;
@@ -37,9 +37,9 @@ export interface CommonInputProps extends Omit<React.InputHTMLAttributes<HTMLInp
37
37
  export interface InputProps extends CommonInputProps {
38
38
  /** The visible width of the text control, in average character widths */
39
39
  cols?: number;
40
- /** Integer to determine a timeout for the defered callback */
40
+ /** Integer to determine a timeout for the deferred callback */
41
41
  deferTimeout?: number;
42
- /** Defered callback to be called after the onChange event */
42
+ /** Deferred callback to be called after the onChange event */
43
43
  onChangeDeferred?: (ev: React.ChangeEvent<HTMLInputElement>) => void;
44
44
  /** The number of visible text lines for the control */
45
45
  rows?: number;
@@ -9,6 +9,8 @@ import { filterStyledSystemMarginProps } from "../../style/utils";
9
9
  import guid from "../../__internal__/utils/helpers/guid";
10
10
  import useLocale from "../../hooks/__internal__/useLocale";
11
11
  import { Dt, Dd } from "../definition-list";
12
+ import Logger from "../../__internal__/utils/logger";
13
+ let deprecateUncontrolledWarnTriggered = false;
12
14
 
13
15
  const AdvancedColorPicker = ({
14
16
  "aria-describedby": ariaDescribedBy,
@@ -123,6 +125,12 @@ const AdvancedColorPicker = ({
123
125
  onBlur(e);
124
126
  }
125
127
  }, [onBlur]);
128
+
129
+ if (!deprecateUncontrolledWarnTriggered && !onChange) {
130
+ deprecateUncontrolledWarnTriggered = true;
131
+ Logger.deprecate("Uncontrolled behaviour in `Advanced Color Picker` is deprecated and support will soon be removed. Please make sure all your inputs are controlled.");
132
+ }
133
+
126
134
  return /*#__PURE__*/React.createElement(StyledAdvancedColorPickerWrapper, _extends({
127
135
  m: "15px auto auto 15px"
128
136
  }, filterStyledSystemMarginProps(props)), /*#__PURE__*/React.createElement(StyledAdvancedColorPickerCell, {
@@ -6,6 +6,8 @@ import guid from "../../__internal__/utils/helpers/guid";
6
6
  import ButtonToggleIcon from "./button-toggle-icon.component";
7
7
  import ButtonToggleInput from "./button-toggle-input.component";
8
8
  import { InputGroupContext } from "../../__internal__/input-behaviour";
9
+ import Logger from "../../__internal__/utils/logger";
10
+ let deprecateUncontrolledWarnTriggered = false;
9
11
 
10
12
  const ButtonToggle = ({
11
13
  "aria-label": ariaLabel,
@@ -50,6 +52,11 @@ const ButtonToggle = ({
50
52
  (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 ? void 0 : _inputRef$current.focus();
51
53
  }
52
54
 
55
+ if (!deprecateUncontrolledWarnTriggered && !onChange) {
56
+ deprecateUncontrolledWarnTriggered = true;
57
+ Logger.deprecate("Uncontrolled behaviour in `Button Toggle` is deprecated and support will soon be removed. Please make sure all your inputs are controlled.");
58
+ }
59
+
53
60
  return /*#__PURE__*/React.createElement(StyledButtonToggle, {
54
61
  "data-component": dataComponent || "button-toggle",
55
62
  "data-element": dataElement,
@@ -11,6 +11,7 @@ import { CheckboxGroupContext } from "./checkbox-group.component";
11
11
  import Logger from "../../__internal__/utils/logger";
12
12
  import useFormSpacing from "../../hooks/__internal__/useFormSpacing";
13
13
  let deprecateInputRefWarnTriggered = false;
14
+ let deprecateUncontrolledWarnTriggered = false;
14
15
  const Checkbox = /*#__PURE__*/React.forwardRef(({
15
16
  "aria-labelledby": ariaLabelledBy,
16
17
  id,
@@ -61,6 +62,11 @@ const Checkbox = /*#__PURE__*/React.forwardRef(({
61
62
  Logger.deprecate("The `inputRef` prop in `Checkbox` component is deprecated and will soon be removed. Please use `ref` instead.");
62
63
  }
63
64
 
65
+ if (!deprecateUncontrolledWarnTriggered && !onChange) {
66
+ deprecateUncontrolledWarnTriggered = true;
67
+ Logger.deprecate("Uncontrolled behaviour in `Checkbox` is deprecated and support will soon be removed. Please make sure all your inputs are controlled.");
68
+ }
69
+
64
70
  const inputProps = {
65
71
  ariaLabelledBy,
66
72
  onClick,
@@ -8,6 +8,7 @@ import LocaleContext from "../../__internal__/i18n-context";
8
8
  import usePrevious from "../../hooks/__internal__/usePrevious";
9
9
  import Logger from "../../__internal__/utils/logger";
10
10
  let deprecateInputRefWarnTriggered = false;
11
+ let deprecateUncontrolledWarnTriggered = false;
11
12
  const Decimal = /*#__PURE__*/React.forwardRef(({
12
13
  align = "right",
13
14
  defaultValue,
@@ -192,6 +193,12 @@ const Decimal = /*#__PURE__*/React.forwardRef(({
192
193
  }
193
194
  }
194
195
  }, [emptyValue, formatValue, getSafeValueProp, isControlled, prevValue, stateValue, toStandardDecimal, value]);
196
+
197
+ if (!deprecateUncontrolledWarnTriggered && !isControlled) {
198
+ deprecateUncontrolledWarnTriggered = true;
199
+ Logger.deprecate("Uncontrolled behaviour in `Decimal` is deprecated and support will soon be removed. Please make sure all your inputs are controlled.");
200
+ }
201
+
195
202
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Textbox, _extends({
196
203
  onKeyPress: onKeyPress,
197
204
  align: align,
@@ -24,6 +24,7 @@ const buildCustomTarget = ({
24
24
  };
25
25
 
26
26
  let deprecateInputRefWarnTriggered = false;
27
+ let deprecateUncontrolledWarnTriggered = false;
27
28
  const GroupedCharacter = /*#__PURE__*/React.forwardRef(({
28
29
  defaultValue,
29
30
  groups,
@@ -45,6 +46,11 @@ const GroupedCharacter = /*#__PURE__*/React.forwardRef(({
45
46
  Logger.deprecate("The `inputRef` prop in `GroupedCharacter` component is deprecated and will soon be removed. Please use `ref` instead.");
46
47
  }
47
48
 
49
+ if (!deprecateUncontrolledWarnTriggered && !isControlled) {
50
+ deprecateUncontrolledWarnTriggered = true;
51
+ Logger.deprecate("Uncontrolled behaviour in `Grouped Character` is deprecated and support will soon be removed. Please make sure all your inputs are controlled.");
52
+ }
53
+
48
54
  const formatValue = val => generateGroups(groups, val).join(separator);
49
55
 
50
56
  const sanitizeValue = val => val.split(separator).join("").substring(0, maxRawLength);
@@ -1,6 +1,6 @@
1
- export const MENU_ITEM: "menu-item";
2
- export const SCROLLABLE_BLOCK: "submenu-scrollable-block";
3
- export const SCROLLABLE_BLOCK_PARENT: "scrollable-block-parent";
4
- export const ALL_CHILDREN_SELECTOR: string;
5
- export const BLOCK_INDEX_SELECTOR: string;
6
- export const MENU_ITEM_CHILDREN_LOCATOR: string;
1
+ export declare const MENU_ITEM = "menu-item";
2
+ export declare const SCROLLABLE_BLOCK = "submenu-scrollable-block";
3
+ export declare const SCROLLABLE_BLOCK_PARENT = "scrollable-block-parent";
4
+ export declare const ALL_CHILDREN_SELECTOR: string;
5
+ export declare const BLOCK_INDEX_SELECTOR: string;
6
+ export declare const MENU_ITEM_CHILDREN_LOCATOR: string;
@@ -0,0 +1,3 @@
1
+ import { ReactWrapper } from "enzyme";
2
+ declare const openSubmenu: (wrapper: ReactWrapper, index?: number) => void;
3
+ export default openSubmenu;
@@ -0,0 +1,2 @@
1
+ export { default } from "./submenu.component";
2
+ export type { SubmenuProps } from "./submenu.component";
@@ -0,0 +1 @@
1
+ export { default } from "./submenu.component";
@@ -0,0 +1,42 @@
1
+ import React from "react";
2
+ import { MaxWidthProps } from "styled-system";
3
+ import { VariantType } from "../../menu-item";
4
+ export interface SubmenuProps {
5
+ /** Children elements */
6
+ children: React.ReactNode;
7
+ /** Custom className */
8
+ className?: string;
9
+ /**
10
+ * * <a href="https://brand.sage.com/d/NdbrveWvNheA/foundations#/icons/icons" target="_blank">List of supported icons</a>
11
+ *
12
+ * Adds an icon to the menu item.
13
+ * */
14
+ icon?: string;
15
+ /** Defines which direction the submenu will hang eg. left/right */
16
+ submenuDirection?: string;
17
+ /** A title for the menu item that has a submenu. */
18
+ title?: string;
19
+ /** onKeyDown handler */
20
+ onKeyDown?: (event: React.KeyboardEvent<HTMLAnchorElement> | React.KeyboardEvent<HTMLButtonElement>) => void;
21
+ /** set the colour variant for a menuType */
22
+ variant?: VariantType;
23
+ /** Flag to display the dropdown arrow when an item has a submenu */
24
+ showDropdownArrow?: boolean;
25
+ /** When set the submenu opens by click instead of hover */
26
+ clickToOpen?: boolean;
27
+ /** The href to use for the menu item. */
28
+ href?: string;
29
+ /** Maximum width. Any valid CSS string */
30
+ maxWidth?: MaxWidthProps["maxWidth"];
31
+ /** Used to set a submenu parent to passive styling in MenuFullscreen */
32
+ asPassiveItem?: boolean;
33
+ /** Callback triggered when submenu opens. Only valid with submenu prop */
34
+ onSubmenuOpen?: () => void;
35
+ /** Callback triggered when submenu closes. Only valid with submenu prop */
36
+ onSubmenuClose?: () => void;
37
+ /** Callback triggered when the top-level menu item is clicked */
38
+ onClick?: (event: React.MouseEvent<HTMLAnchorElement> | React.MouseEvent<HTMLButtonElement>) => void;
39
+ ariaLabel?: string;
40
+ }
41
+ declare const Submenu: React.ForwardRefExoticComponent<SubmenuProps & React.RefAttributes<HTMLAnchorElement & HTMLButtonElement & HTMLDivElement>>;
42
+ export default Submenu;
@@ -4,7 +4,6 @@ import React, { useCallback, useEffect, useContext, useMemo, useRef, useState }
4
4
  import PropTypes from "prop-types";
5
5
  import StyledMenuItemWrapper from "../../menu-item/menu-item.style";
6
6
  import { StyledSubmenu, StyledSubmenuWrapper } from "./submenu.style";
7
- import Link from "../../../link";
8
7
  import Events from "../../../../__internal__/utils/helpers/events";
9
8
  import MenuContext from "../../menu.context";
10
9
  import { characterNavigation } from "../keyboard-navigation";
@@ -36,7 +35,8 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
36
35
  const {
37
36
  inFullscreenView,
38
37
  openSubmenuId,
39
- setOpenSubmenuId
38
+ setOpenSubmenuId,
39
+ menuType
40
40
  } = menuContext;
41
41
  const [submenuOpen, setSubmenuOpen] = useState(false);
42
42
  const [submenuFocusId, setSubmenuFocusId] = useState(null);
@@ -44,37 +44,35 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
44
44
  const [characterString, setCharacterString] = useState("");
45
45
  const shiftTabPressed = useRef(false);
46
46
  const focusFirstMenuItemOnOpen = useRef(false);
47
- const registerItem = useCallback(id => {
48
- setSubmenuItemIds(prevState => {
49
- return [...prevState, id];
50
- });
51
- }, []);
52
- const unregisterItem = useCallback(id => {
53
- setSubmenuItemIds(prevState => {
54
- return prevState.filter(itemId => itemId !== id);
55
- });
56
- }, []);
57
47
  const numberOfChildren = submenuItemIds.length;
58
48
  const blockIndex = useMemo(() => {
59
- if (submenuOpen && numberOfChildren) {
60
- var _submenuRef$current, _submenuRef$current2;
49
+ var _submenuRef$current;
50
+
51
+ const items = (_submenuRef$current = submenuRef.current) === null || _submenuRef$current === void 0 ? void 0 : _submenuRef$current.querySelectorAll(BLOCK_INDEX_SELECTOR);
61
52
 
62
- const childrenArray = Array.from((_submenuRef$current = submenuRef.current) === null || _submenuRef$current === void 0 ? void 0 : _submenuRef$current.querySelectorAll(BLOCK_INDEX_SELECTOR));
53
+ if (items && submenuOpen && numberOfChildren) {
54
+ var _submenuRef$current2;
55
+
56
+ const childrenArray = Array.from(items);
63
57
  const scrollableBlock = (_submenuRef$current2 = submenuRef.current) === null || _submenuRef$current2 === void 0 ? void 0 : _submenuRef$current2.querySelector(`[data-component='${SCROLLABLE_BLOCK}']`);
64
- const index = childrenArray.indexOf(scrollableBlock);
58
+ const index = scrollableBlock ? childrenArray.indexOf(scrollableBlock) : -1;
65
59
  return scrollableBlock !== null && scrollableBlock !== void 0 && scrollableBlock.querySelector(`[data-component='${SCROLLABLE_BLOCK_PARENT}']`) ? index + 1 : index;
66
60
  }
67
61
 
68
62
  return -1;
69
63
  }, [submenuOpen, numberOfChildren]);
70
- const characterTimer = useRef();
64
+ const characterTimer = useRef(null);
71
65
  const startCharacterTimeout = useCallback(() => {
72
66
  characterTimer.current = setTimeout(() => {
73
67
  setCharacterString("");
74
68
  }, 1500);
75
69
  }, []);
76
70
  const restartCharacterTimeout = useCallback(() => {
77
- clearTimeout(characterTimer.current);
71
+ /* istanbul ignore else */
72
+ if (characterTimer.current) {
73
+ clearTimeout(characterTimer.current);
74
+ }
75
+
78
76
  startCharacterTimeout();
79
77
  }, [startCharacterTimeout]);
80
78
  const openSubmenu = useCallback(() => {
@@ -165,7 +163,7 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
165
163
  }
166
164
 
167
165
  if (Events.isEscKey(event)) {
168
- onKeyDown(event);
166
+ onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
169
167
  closeSubmenu();
170
168
  return;
171
169
  }
@@ -213,6 +211,19 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
213
211
  }
214
212
  }
215
213
  }, [submenuItemIds, submenuOpen, href, numberOfChildren, submenuFocusId, findCurrentIndex, openSubmenu, closeSubmenu, onKeyDown, characterString, restartCharacterTimeout, startCharacterTimeout]);
214
+ useEffect(() => {
215
+ /* istanbul ignore else */
216
+ if (submenuRef.current && children) {
217
+ var _submenuRef$current3;
218
+
219
+ const items = (_submenuRef$current3 = submenuRef.current) === null || _submenuRef$current3 === void 0 ? void 0 : _submenuRef$current3.querySelectorAll(ALL_CHILDREN_SELECTOR);
220
+ /* istanbul ignore else */
221
+
222
+ if (items) {
223
+ setSubmenuItemIds(Array.from(items).map(item => item.getAttribute("id")));
224
+ }
225
+ }
226
+ }, [children, submenuOpen]);
216
227
  useEffect(() => {
217
228
  if (focusFirstMenuItemOnOpen.current && submenuOpen && !submenuFocusId && submenuItemIds.length) {
218
229
  focusFirstMenuItemOnOpen.current = false;
@@ -225,6 +236,8 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
225
236
  closeSubmenu();
226
237
  };
227
238
 
239
+ const handleClickInside = useClickAwayListener(handleClickAway);
240
+
228
241
  const handleClick = event => {
229
242
  openSubmenu();
230
243
 
@@ -234,10 +247,12 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
234
247
  };
235
248
 
236
249
  useEffect(() => {
237
- if (characterString !== "") {
238
- var _submenuRef$current3;
250
+ var _submenuRef$current4;
251
+
252
+ const items = (_submenuRef$current4 = submenuRef.current) === null || _submenuRef$current4 === void 0 ? void 0 : _submenuRef$current4.querySelectorAll(ALL_CHILDREN_SELECTOR);
239
253
 
240
- const submenuChildren = Array.from((_submenuRef$current3 = submenuRef.current) === null || _submenuRef$current3 === void 0 ? void 0 : _submenuRef$current3.querySelectorAll(ALL_CHILDREN_SELECTOR));
254
+ if (items && characterString !== "") {
255
+ const submenuChildren = Array.from(items);
241
256
  const nextItem = characterNavigation(characterString, submenuChildren);
242
257
 
243
258
  if (nextItem) {
@@ -245,37 +260,33 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
245
260
  }
246
261
  }
247
262
  }, [characterString, submenuItemIds]);
248
- const handleClickInside = useClickAwayListener(handleClickAway);
249
263
 
250
264
  if (inFullscreenView) {
251
265
  return /*#__PURE__*/React.createElement(StyledSubmenuWrapper, {
252
266
  "data-component": "submenu-wrapper",
253
267
  inFullscreenView: inFullscreenView,
254
- menuType: menuContext.menuType,
255
268
  asPassiveItem: asPassiveItem,
269
+ menuType: menuContext.menuType,
256
270
  onClick: handleClickInside
257
271
  }, /*#__PURE__*/React.createElement(StyledMenuItemWrapper, _extends({}, rest, {
258
- onClick: onClick,
272
+ onClick: asPassiveItem ? undefined : onClick,
259
273
  className: className,
260
- menuType: menuContext.menuType,
274
+ menuType: menuType,
261
275
  ref: ref,
262
- as: asPassiveItem ? "div" : Link,
263
276
  href: href,
264
- icon: icon,
265
277
  variant: variant,
266
- inFullscreenView: inFullscreenView
278
+ inFullscreenView: inFullscreenView,
279
+ asDiv: asPassiveItem
267
280
  }), title), /*#__PURE__*/React.createElement(StyledSubmenu, {
268
281
  "data-component": "submenu",
269
282
  variant: variant,
270
- menuType: menuContext.menuType,
283
+ menuType: menuType,
271
284
  inFullscreenView: inFullscreenView,
272
285
  ref: submenuRef
273
286
  }, /*#__PURE__*/React.createElement(SubmenuContext.Provider, {
274
287
  value: {
275
288
  handleKeyDown,
276
289
  blockIndex,
277
- registerItem,
278
- unregisterItem,
279
290
  updateFocusId: setSubmenuFocusId
280
291
  }
281
292
  }, children)));
@@ -290,13 +301,12 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
290
301
  ref: submenuRef
291
302
  }, /*#__PURE__*/React.createElement(StyledMenuItemWrapper, _extends({}, rest, {
292
303
  className: className,
293
- menuType: menuContext.menuType,
304
+ menuType: menuType,
294
305
  ref: ref,
295
306
  icon: icon,
296
307
  tabIndex: -1,
297
308
  variant: variant,
298
309
  isOpen: submenuOpen,
299
- as: Link,
300
310
  hasSubmenu: true,
301
311
  showDropdownArrow: showDropdownArrow,
302
312
  onKeyDown: handleKeyDown,
@@ -309,68 +319,135 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
309
319
  "data-component": "submenu",
310
320
  submenuDirection: submenuDirection,
311
321
  variant: variant,
312
- menuType: menuContext.menuType,
322
+ menuType: menuType,
313
323
  role: blockIndex === 0 ? "presentation" : "list"
314
324
  }, /*#__PURE__*/React.createElement(SubmenuContext.Provider, {
315
325
  value: {
316
326
  submenuFocusId,
317
327
  handleKeyDown,
318
328
  blockIndex,
319
- registerItem,
320
- unregisterItem,
321
329
  updateFocusId: setSubmenuFocusId,
322
330
  shiftTabPressed: shiftTabPressed.current
323
331
  }
324
332
  }, children)));
325
333
  });
326
334
  Submenu.propTypes = {
327
- /** Children elements */
328
- children: PropTypes.node.isRequired,
329
-
330
- /** Custom className */
331
- className: PropTypes.string,
332
-
333
- /**
334
- * * <a href="https://brand.sage.com/d/NdbrveWvNheA/foundations#/icons/icons" target="_blank">List of supported icons</a>
335
- *
336
- * Adds an icon to the menu item.
337
- * */
338
- icon: PropTypes.string,
339
-
340
- /** Defines which direction the submenu will hang eg. left/right */
341
- submenuDirection: PropTypes.string,
342
-
343
- /** A title for the menu item that has a submenu. */
344
- title: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
345
-
346
- /** onKeyDown handler */
347
- onKeyDown: PropTypes.func,
348
-
349
- /** set the colour variant for a menuType */
350
- variant: PropTypes.oneOf(["default", "alternate"]),
351
-
352
- /** Flag to display the dropdown arrow when an item has a submenu */
353
- showDropdownArrow: PropTypes.bool,
354
-
355
- /** When set the submenu opens by click instead of hover */
356
- clickToOpen: PropTypes.bool,
357
-
358
- /** The href to use for the menu item. */
359
- href: PropTypes.string,
360
-
361
- /** Maximum width. Any valid CSS string */
362
- maxWidth: PropTypes.string,
363
-
364
- /** Used to set a submenu parent to passive styling in MenuFullscreen */
365
- asPassiveItem: PropTypes.bool,
366
-
367
- /** Callback triggered when submenu opens. Only valid with submenu prop */
368
- onSubmenuOpen: PropTypes.func,
369
-
370
- /** Callback triggered when submenu closes. Only valid with submenu prop */
371
- onSubmenuClose: PropTypes.func,
372
-
373
- /** Callback triggered when the top-level menu item is clicked */
374
- onClick: PropTypes.func
335
+ "ariaLabel": PropTypes.string,
336
+ "asPassiveItem": PropTypes.bool,
337
+ "children": PropTypes.node,
338
+ "className": PropTypes.string,
339
+ "clickToOpen": PropTypes.bool,
340
+ "href": PropTypes.string,
341
+ "icon": PropTypes.string,
342
+ "maxWidth": PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.oneOf([null]), PropTypes.number, PropTypes.shape({
343
+ "__@iterator": PropTypes.func.isRequired,
344
+ "anchor": PropTypes.func.isRequired,
345
+ "at": PropTypes.func.isRequired,
346
+ "big": PropTypes.func.isRequired,
347
+ "blink": PropTypes.func.isRequired,
348
+ "bold": PropTypes.func.isRequired,
349
+ "charAt": PropTypes.func.isRequired,
350
+ "charCodeAt": PropTypes.func.isRequired,
351
+ "codePointAt": PropTypes.func.isRequired,
352
+ "concat": PropTypes.func.isRequired,
353
+ "endsWith": PropTypes.func.isRequired,
354
+ "fixed": PropTypes.func.isRequired,
355
+ "fontcolor": PropTypes.func.isRequired,
356
+ "fontsize": PropTypes.func.isRequired,
357
+ "includes": PropTypes.func.isRequired,
358
+ "indexOf": PropTypes.func.isRequired,
359
+ "italics": PropTypes.func.isRequired,
360
+ "lastIndexOf": PropTypes.func.isRequired,
361
+ "length": PropTypes.number.isRequired,
362
+ "link": PropTypes.func.isRequired,
363
+ "localeCompare": PropTypes.func.isRequired,
364
+ "match": PropTypes.func.isRequired,
365
+ "matchAll": PropTypes.func.isRequired,
366
+ "normalize": PropTypes.func.isRequired,
367
+ "padEnd": PropTypes.func.isRequired,
368
+ "padStart": PropTypes.func.isRequired,
369
+ "repeat": PropTypes.func.isRequired,
370
+ "replace": PropTypes.func.isRequired,
371
+ "search": PropTypes.func.isRequired,
372
+ "slice": PropTypes.func.isRequired,
373
+ "small": PropTypes.func.isRequired,
374
+ "split": PropTypes.func.isRequired,
375
+ "startsWith": PropTypes.func.isRequired,
376
+ "strike": PropTypes.func.isRequired,
377
+ "sub": PropTypes.func.isRequired,
378
+ "substr": PropTypes.func.isRequired,
379
+ "substring": PropTypes.func.isRequired,
380
+ "sup": PropTypes.func.isRequired,
381
+ "toLocaleLowerCase": PropTypes.func.isRequired,
382
+ "toLocaleUpperCase": PropTypes.func.isRequired,
383
+ "toLowerCase": PropTypes.func.isRequired,
384
+ "toString": PropTypes.func.isRequired,
385
+ "toUpperCase": PropTypes.func.isRequired,
386
+ "trim": PropTypes.func.isRequired,
387
+ "trimEnd": PropTypes.func.isRequired,
388
+ "trimLeft": PropTypes.func.isRequired,
389
+ "trimRight": PropTypes.func.isRequired,
390
+ "trimStart": PropTypes.func.isRequired,
391
+ "valueOf": PropTypes.func.isRequired
392
+ }), PropTypes.string])), PropTypes.number, PropTypes.object, PropTypes.shape({
393
+ "__@iterator": PropTypes.func.isRequired,
394
+ "anchor": PropTypes.func.isRequired,
395
+ "at": PropTypes.func.isRequired,
396
+ "big": PropTypes.func.isRequired,
397
+ "blink": PropTypes.func.isRequired,
398
+ "bold": PropTypes.func.isRequired,
399
+ "charAt": PropTypes.func.isRequired,
400
+ "charCodeAt": PropTypes.func.isRequired,
401
+ "codePointAt": PropTypes.func.isRequired,
402
+ "concat": PropTypes.func.isRequired,
403
+ "endsWith": PropTypes.func.isRequired,
404
+ "fixed": PropTypes.func.isRequired,
405
+ "fontcolor": PropTypes.func.isRequired,
406
+ "fontsize": PropTypes.func.isRequired,
407
+ "includes": PropTypes.func.isRequired,
408
+ "indexOf": PropTypes.func.isRequired,
409
+ "italics": PropTypes.func.isRequired,
410
+ "lastIndexOf": PropTypes.func.isRequired,
411
+ "length": PropTypes.number.isRequired,
412
+ "link": PropTypes.func.isRequired,
413
+ "localeCompare": PropTypes.func.isRequired,
414
+ "match": PropTypes.func.isRequired,
415
+ "matchAll": PropTypes.func.isRequired,
416
+ "normalize": PropTypes.func.isRequired,
417
+ "padEnd": PropTypes.func.isRequired,
418
+ "padStart": PropTypes.func.isRequired,
419
+ "repeat": PropTypes.func.isRequired,
420
+ "replace": PropTypes.func.isRequired,
421
+ "search": PropTypes.func.isRequired,
422
+ "slice": PropTypes.func.isRequired,
423
+ "small": PropTypes.func.isRequired,
424
+ "split": PropTypes.func.isRequired,
425
+ "startsWith": PropTypes.func.isRequired,
426
+ "strike": PropTypes.func.isRequired,
427
+ "sub": PropTypes.func.isRequired,
428
+ "substr": PropTypes.func.isRequired,
429
+ "substring": PropTypes.func.isRequired,
430
+ "sup": PropTypes.func.isRequired,
431
+ "toLocaleLowerCase": PropTypes.func.isRequired,
432
+ "toLocaleUpperCase": PropTypes.func.isRequired,
433
+ "toLowerCase": PropTypes.func.isRequired,
434
+ "toString": PropTypes.func.isRequired,
435
+ "toUpperCase": PropTypes.func.isRequired,
436
+ "trim": PropTypes.func.isRequired,
437
+ "trimEnd": PropTypes.func.isRequired,
438
+ "trimLeft": PropTypes.func.isRequired,
439
+ "trimRight": PropTypes.func.isRequired,
440
+ "trimStart": PropTypes.func.isRequired,
441
+ "valueOf": PropTypes.func.isRequired
442
+ }), PropTypes.string]),
443
+ "onClick": PropTypes.func,
444
+ "onKeyDown": PropTypes.func,
445
+ "onSubmenuClose": PropTypes.func,
446
+ "onSubmenuOpen": PropTypes.func,
447
+ "showDropdownArrow": PropTypes.bool,
448
+ "submenuDirection": PropTypes.string,
449
+ "title": PropTypes.string,
450
+ "variant": PropTypes.oneOf(["alternate", "default"])
375
451
  };
452
+ Submenu.displayName = "submenu";
376
453
  export default Submenu;
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ export interface SubmenuContextProps {
3
+ submenuFocusId?: string | null;
4
+ updateFocusId?: (id: string) => void;
5
+ handleKeyDown?: (event: React.KeyboardEvent<HTMLAnchorElement>) => void;
6
+ shiftTabPressed?: boolean;
7
+ blockIndex?: number;
8
+ }
9
+ declare const SubmenuContext: React.Context<SubmenuContextProps>;
10
+ export default SubmenuContext;
@@ -0,0 +1,16 @@
1
+ import { SubmenuProps } from "./submenu.component";
2
+ import { MenuType } from "../../menu.context";
3
+ interface SharedStyleProps {
4
+ inFullscreenView?: boolean;
5
+ menuType?: MenuType;
6
+ }
7
+ interface StyledSubmenuWrapperProps extends SharedStyleProps {
8
+ isSubmenuOpen?: boolean;
9
+ asPassiveItem?: boolean;
10
+ }
11
+ interface StyledSubmenuProps extends SharedStyleProps, Pick<SubmenuProps, "variant"> {
12
+ submenuDirection?: string;
13
+ }
14
+ declare const StyledSubmenuWrapper: import("styled-components").StyledComponent<"div", any, StyledSubmenuWrapperProps, never>;
15
+ declare const StyledSubmenu: import("styled-components").StyledComponent<"ul", any, StyledSubmenuProps, never>;
16
+ export { StyledSubmenu, StyledSubmenuWrapper };
@@ -25,7 +25,7 @@ const StyledSubmenuWrapper = styled.div`
25
25
  }) => inFullscreenView && css`
26
26
  width: 100%;
27
27
 
28
- ${asPassiveItem && css`
28
+ ${asPassiveItem && menuType && css`
29
29
  ${StyledMenuItemWrapper} {
30
30
  outline: none;
31
31
  color: ${menuConfigVariants[menuType].title};
@@ -40,7 +40,7 @@ const StyledSubmenu = styled.ul`
40
40
  variant,
41
41
  inFullscreenView
42
42
  }) => css`
43
- ${!inFullscreenView && css`
43
+ ${!inFullscreenView && menuType && css`
44
44
  box-shadow: var(--boxShadow100);
45
45
  position: absolute;
46
46
  background-color: ${variant === "default" ? menuConfigVariants[menuType].submenuItemBackground : menuConfigVariants[menuType].background};
@@ -76,7 +76,7 @@ const StyledSubmenu = styled.ul`
76
76
  white-space: nowrap;
77
77
  cursor: pointer;
78
78
 
79
- ${!inFullscreenView && css`
79
+ ${!inFullscreenView && menuType && css`
80
80
  background-color: ${menuConfigVariants[menuType].submenuItemBackground};
81
81
 
82
82
  a:focus,
@@ -86,7 +86,7 @@ const StyledSubmenu = styled.ul`
86
86
 
87
87
  a:hover,
88
88
  button:hover {
89
- background-color: ${menuConfigVariants[menuType].submenuItemBackgroundHover};
89
+ background-color: transparent;
90
90
  color: var(--colorsComponentsMenuYang100);
91
91
 
92
92
  [data-component="icon"] {
@@ -1,6 +1,12 @@
1
- export { default as Menu } from "./menu";
2
- export { default as MenuItem } from "./menu-item/menu-item";
3
- export { default as ScrollableBlock } from "./scrollable-block/scrollable-block";
4
- export { default as MenuDivider } from "./menu-divider/menu-divider";
5
- export { default as MenuSegmentTitle } from "./menu-segment-title/menu-segment-title";
6
- export { default as MenuFullscreen } from "./menu-full-screen/menu-full-screen";
1
+ export { default as Menu } from "./menu.component";
2
+ export type { MenuProps } from "./menu.component";
3
+ export { default as MenuItem } from "./menu-item";
4
+ export type { MenuWithIcon, MenuWithChildren } from "./menu-item";
5
+ export { default as MenuDivider } from "./menu-divider";
6
+ export type { MenuDividerProps } from "./menu-divider";
7
+ export { default as MenuSegmentTitle } from "./menu-segment-title";
8
+ export type { MenuTitleProps } from "./menu-segment-title";
9
+ export { default as MenuFullscreen } from "./menu-full-screen";
10
+ export type { MenuFullscreenProps } from "./menu-full-screen";
11
+ export { default as ScrollableBlock } from "./scrollable-block";
12
+ export type { ScrollableBlockProps } from "./scrollable-block";