carbon-react 106.6.1 → 106.6.4

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 (108) hide show
  1. package/esm/__spec_helper__/expect.d.ts +8 -1
  2. package/esm/__spec_helper__/expect.js +1 -5
  3. package/esm/__spec_helper__/test-utils.d.ts +71 -33
  4. package/esm/__spec_helper__/test-utils.js +63 -65
  5. package/esm/components/action-popover/action-popover-context.d.ts +7 -2
  6. package/esm/components/action-popover/action-popover-context.js +1 -1
  7. package/esm/components/action-popover/action-popover-divider/action-popover-divider.component.d.ts +1 -1
  8. package/esm/components/action-popover/action-popover-item/action-popover-item.component.d.ts +28 -41
  9. package/esm/components/action-popover/action-popover-item/action-popover-item.component.js +99 -118
  10. package/esm/components/action-popover/action-popover-menu/action-popover-menu.component.d.ts +35 -2
  11. package/esm/components/action-popover/action-popover-menu/action-popover-menu.component.js +42 -53
  12. package/esm/components/action-popover/action-popover-menu-button/action-popover-menu-button.component.d.ts +20 -18
  13. package/esm/components/action-popover/action-popover-menu-button/action-popover-menu-button.component.js +13 -5
  14. package/esm/components/action-popover/action-popover-test.stories.js +76 -0
  15. package/esm/components/action-popover/action-popover.component.d.ts +30 -53
  16. package/esm/components/action-popover/action-popover.component.js +205 -67
  17. package/esm/components/action-popover/action-popover.style.d.ts +17 -11
  18. package/esm/components/action-popover/action-popover.style.js +20 -26
  19. package/esm/components/action-popover/index.d.ts +9 -5
  20. package/esm/components/box/box.component.d.ts +12 -1
  21. package/esm/components/box/box.component.js +12 -23
  22. package/esm/components/box/box.config.d.ts +10 -12
  23. package/esm/components/box/index.d.ts +2 -1
  24. package/esm/components/button-bar/button-bar-test.stories.js +122 -0
  25. package/esm/components/button-bar/button-bar.component.d.ts +12 -15
  26. package/esm/components/button-bar/button-bar.component.js +331 -33
  27. package/esm/components/button-bar/button-bar.config.d.ts +2 -2
  28. package/esm/components/button-bar/button-bar.style.d.ts +4 -4
  29. package/esm/components/button-bar/button-bar.style.js +18 -33
  30. package/esm/components/button-bar/index.d.ts +2 -1
  31. package/esm/components/dismissible-box/dismissible-box.style.d.ts +1 -2
  32. package/esm/components/drawer/drawer.style.d.ts +1 -2
  33. package/esm/components/duelling-picklist/picklist/picklist.style.d.ts +2 -3
  34. package/esm/components/flat-table/flat-table.style.d.ts +1 -2
  35. package/esm/components/form/form.component.js +2 -1
  36. package/esm/components/link/link.component.js +1 -5
  37. package/esm/components/menu/__internal__/spec-helper/index.js +2 -1
  38. package/esm/components/menu/__internal__/submenu/submenu.component.js +21 -4
  39. package/esm/components/menu/menu.component.js +2 -1
  40. package/esm/components/menu/scrollable-block/scrollable-block.component.js +4 -2
  41. package/esm/components/modal/modal.component.js +3 -60
  42. package/esm/components/toast/toast.component.js +3 -13
  43. package/esm/hooks/__internal__/useModalManager/index.d.ts +1 -0
  44. package/esm/hooks/__internal__/useModalManager/index.js +1 -0
  45. package/esm/hooks/__internal__/useModalManager/useModalManager.d.ts +3 -0
  46. package/esm/hooks/__internal__/useModalManager/useModalManager.js +66 -0
  47. package/lib/__spec_helper__/expect.d.ts +8 -1
  48. package/lib/__spec_helper__/expect.js +2 -4
  49. package/lib/__spec_helper__/test-utils.d.ts +71 -33
  50. package/lib/__spec_helper__/test-utils.js +63 -65
  51. package/lib/components/action-popover/action-popover-context.d.ts +7 -2
  52. package/lib/components/action-popover/action-popover-context.js +1 -1
  53. package/lib/components/action-popover/action-popover-divider/action-popover-divider.component.d.ts +1 -1
  54. package/lib/components/action-popover/action-popover-item/action-popover-item.component.d.ts +28 -41
  55. package/lib/components/action-popover/action-popover-item/action-popover-item.component.js +100 -119
  56. package/lib/components/action-popover/action-popover-menu/action-popover-menu.component.d.ts +35 -2
  57. package/lib/components/action-popover/action-popover-menu/action-popover-menu.component.js +44 -55
  58. package/lib/components/action-popover/action-popover-menu-button/action-popover-menu-button.component.d.ts +20 -18
  59. package/lib/components/action-popover/action-popover-menu-button/action-popover-menu-button.component.js +13 -5
  60. package/lib/components/action-popover/action-popover-test.stories.js +95 -0
  61. package/lib/components/action-popover/action-popover.component.d.ts +30 -53
  62. package/lib/components/action-popover/action-popover.component.js +206 -71
  63. package/lib/components/action-popover/action-popover.style.d.ts +17 -11
  64. package/lib/components/action-popover/action-popover.style.js +21 -28
  65. package/lib/components/action-popover/index.d.ts +9 -5
  66. package/lib/components/box/box.component.d.ts +12 -1
  67. package/lib/components/box/box.component.js +13 -26
  68. package/lib/components/box/box.config.d.ts +10 -12
  69. package/lib/components/box/index.d.ts +2 -1
  70. package/lib/components/button-bar/button-bar-test.stories.js +145 -0
  71. package/lib/components/button-bar/button-bar.component.d.ts +12 -15
  72. package/lib/components/button-bar/button-bar.component.js +336 -35
  73. package/lib/components/button-bar/button-bar.config.d.ts +2 -2
  74. package/lib/components/button-bar/button-bar.style.d.ts +4 -4
  75. package/lib/components/button-bar/button-bar.style.js +18 -35
  76. package/lib/components/button-bar/index.d.ts +2 -1
  77. package/lib/components/dismissible-box/dismissible-box.style.d.ts +1 -2
  78. package/lib/components/drawer/drawer.style.d.ts +1 -2
  79. package/lib/components/duelling-picklist/picklist/picklist.style.d.ts +2 -3
  80. package/lib/components/flat-table/flat-table.style.d.ts +1 -2
  81. package/lib/components/form/form.component.js +2 -1
  82. package/lib/components/link/link.component.js +1 -5
  83. package/lib/components/menu/__internal__/spec-helper/index.js +2 -1
  84. package/lib/components/menu/__internal__/submenu/submenu.component.js +21 -4
  85. package/lib/components/menu/menu.component.js +2 -1
  86. package/lib/components/menu/scrollable-block/scrollable-block.component.js +4 -2
  87. package/lib/components/modal/modal.component.js +3 -62
  88. package/lib/components/toast/toast.component.js +4 -17
  89. package/lib/hooks/__internal__/useModalManager/index.d.ts +1 -0
  90. package/lib/hooks/__internal__/useModalManager/index.js +15 -0
  91. package/lib/hooks/__internal__/useModalManager/package.json +6 -0
  92. package/lib/hooks/__internal__/useModalManager/useModalManager.d.ts +3 -0
  93. package/lib/hooks/__internal__/useModalManager/useModalManager.js +79 -0
  94. package/package.json +5 -1
  95. package/esm/components/action-popover/action-popover-divider/action-popover-divider.d.ts +0 -12
  96. package/esm/components/action-popover/action-popover-item/action-popover-item.d.ts +0 -26
  97. package/esm/components/action-popover/action-popover-menu/action-popover-menu.d.ts +0 -33
  98. package/esm/components/action-popover/action-popover-menu-button/action-popover-menu-button.d.ts +0 -13
  99. package/esm/components/action-popover/action-popover.d.ts +0 -39
  100. package/esm/components/box/box.d.ts +0 -31
  101. package/esm/components/button-bar/button-bar.d.ts +0 -24
  102. package/lib/components/action-popover/action-popover-divider/action-popover-divider.d.ts +0 -12
  103. package/lib/components/action-popover/action-popover-item/action-popover-item.d.ts +0 -26
  104. package/lib/components/action-popover/action-popover-menu/action-popover-menu.d.ts +0 -33
  105. package/lib/components/action-popover/action-popover-menu-button/action-popover-menu-button.d.ts +0 -13
  106. package/lib/components/action-popover/action-popover.d.ts +0 -39
  107. package/lib/components/box/box.d.ts +0 -31
  108. package/lib/components/button-bar/button-bar.d.ts +0 -24
@@ -2,21 +2,55 @@ function _extends() { _extends = Object.assign || function (target) { for (var i
2
2
 
3
3
  import React, { useCallback, useEffect, useRef, useState, useContext } from "react";
4
4
  import PropTypes from "prop-types";
5
- import { withTheme } from "styled-components";
6
- import { MenuItemFactory, MenuItemIcon, SubMenuItemIcon, StyledMenuItem } from "../action-popover.style";
5
+ import invariant from "invariant";
6
+ import { MenuItemIcon, SubMenuItemIcon, StyledMenuItem } from "../action-popover.style";
7
7
  import Events from "../../../__internal__/utils/helpers/events";
8
8
  import createGuid from "../../../__internal__/utils/helpers/guid";
9
9
  import ActionPopoverContext from "../action-popover-context";
10
10
  import useLocale from "../../../hooks/__internal__/useLocale";
11
+ import ActionPopoverMenu from "../action-popover-menu/action-popover-menu.component";
11
12
  const INTERVAL = 150;
12
13
 
13
- const MenuItem = ({
14
+ function checkRef(ref) {
15
+ return Boolean(ref && ref.current);
16
+ }
17
+
18
+ function leftAlignSubmenu(ref, submenuRef) {
19
+ /* istanbul ignore if */
20
+ if (!ref.current || !submenuRef.current) return true;
21
+ const {
22
+ left
23
+ } = ref.current.getBoundingClientRect();
24
+ const {
25
+ offsetWidth
26
+ } = submenuRef.current;
27
+ return left >= offsetWidth;
28
+ }
29
+
30
+ function getContainerPosition(itemRef, submenuRef, placement) {
31
+ /* istanbul ignore if */
32
+ if (!itemRef.current || !submenuRef.current) return undefined;
33
+ const {
34
+ offsetWidth: parentWidth
35
+ } = itemRef.current;
36
+ const {
37
+ offsetWidth: submenuWidth
38
+ } = submenuRef.current;
39
+ const xPositionValue = leftAlignSubmenu(itemRef, submenuRef) ? -submenuWidth : parentWidth;
40
+ const yPositionName = placement === "top" ? "bottom" : "top";
41
+ return {
42
+ left: xPositionValue,
43
+ [yPositionName]: "calc(-1 * var(--spacing100))",
44
+ right: "auto"
45
+ };
46
+ }
47
+
48
+ const ActionPopoverItem = ({
14
49
  children,
15
50
  icon,
16
51
  disabled = false,
17
52
  onClick: onClickProp,
18
53
  submenu,
19
- theme,
20
54
  placement = "bottom",
21
55
  focusItem,
22
56
  download,
@@ -25,47 +59,49 @@ const MenuItem = ({
25
59
  ...rest
26
60
  }) => {
27
61
  const l = useLocale();
62
+ const context = useContext(ActionPopoverContext);
63
+ invariant(context, "ActionPopoverItem must be used within an ActionPopover component");
64
+ invariant( /*#__PURE__*/React.isValidElement(submenu) ? submenu.type === ActionPopoverMenu : true, "ActionPopoverItem only accepts submenu of type `ActionPopoverMenu`");
28
65
  const {
29
66
  setOpenPopover,
30
67
  isOpenPopover,
31
68
  focusButton
32
- } = useContext(ActionPopoverContext);
69
+ } = context;
33
70
  const isHref = !!href;
34
- const [containerPosition, setContainerPosition] = useState(null);
71
+ const [containerPosition, setContainerPosition] = useState(undefined);
35
72
  const [guid] = useState(createGuid());
36
73
  const [isOpen, setOpen] = useState(false);
37
74
  const [focusIndex, setFocusIndex] = useState(0);
38
75
  const [isLeftAligned, setIsLeftAligned] = useState(true);
39
- const submenuRef = useRef();
40
- const ref = useRef();
41
- const mouseEnterTimer = useRef();
42
- const mouseLeaveTimer = useRef();
43
- const {
44
- spacing
45
- } = theme;
76
+ const submenuRef = useRef(null);
77
+ const ref = useRef(null);
78
+ const mouseEnterTimer = useRef(null);
79
+ const mouseLeaveTimer = useRef(null);
46
80
  useEffect(() => {
47
81
  if (!isOpenPopover) {
48
82
  setOpen(false);
49
83
  }
50
84
  }, [isOpenPopover]);
51
85
  const alignSubmenu = useCallback(() => {
52
- if (checkRef(ref) && checkRef(submenuRef)) {
53
- const align = submenu && leftAlignSubmenu(ref, submenuRef);
86
+ if (checkRef(ref) && checkRef(submenuRef) && submenu) {
87
+ const align = leftAlignSubmenu(ref, submenuRef);
54
88
  setIsLeftAligned(align);
55
- setContainerPosition(getContainerPosition(ref, submenuRef, spacing, placement));
89
+ setContainerPosition(getContainerPosition(ref, submenuRef, placement));
56
90
  }
57
- }, [submenu, spacing, placement]);
91
+ }, [submenu, placement]);
58
92
  useEffect(() => {
59
93
  alignSubmenu();
60
94
 
61
- if (focusItem && ref.current) {
62
- ref.current.focus();
95
+ if (focusItem) {
96
+ var _ref$current;
97
+
98
+ (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.focus();
63
99
  }
64
100
  }, [alignSubmenu, focusItem]);
65
101
  useEffect(() => {
66
102
  return function cleanup() {
67
- clearTimeout(mouseEnterTimer.current);
68
- clearTimeout(mouseLeaveTimer.current);
103
+ if (mouseEnterTimer.current) clearTimeout(mouseEnterTimer.current);
104
+ if (mouseLeaveTimer.current) clearTimeout(mouseLeaveTimer.current);
69
105
  };
70
106
  }, []);
71
107
  useEffect(() => {
@@ -83,10 +119,12 @@ const MenuItem = ({
83
119
  focusButton();
84
120
 
85
121
  if (onClickProp) {
86
- onClickProp();
122
+ onClickProp(e);
87
123
  }
88
124
  } else {
89
- ref.current.focus();
125
+ var _ref$current2;
126
+
127
+ (_ref$current2 = ref.current) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.focus();
90
128
  e.preventDefault();
91
129
  }
92
130
  }, [disabled, focusButton, onClickProp, setOpenPopover]);
@@ -107,8 +145,10 @@ const MenuItem = ({
107
145
  setFocusIndex(0);
108
146
  e.stopPropagation();
109
147
  } else if (Events.isRightKey(e)) {
148
+ var _ref$current3;
149
+
110
150
  setOpen(false);
111
- ref.current.focus();
151
+ (_ref$current3 = ref.current) === null || _ref$current3 === void 0 ? void 0 : _ref$current3.focus();
112
152
  e.stopPropagation();
113
153
  }
114
154
  } else {
@@ -120,8 +160,10 @@ const MenuItem = ({
120
160
  }
121
161
 
122
162
  if (Events.isLeftKey(e)) {
163
+ var _ref$current4;
164
+
123
165
  setOpen(false);
124
- ref.current.focus();
166
+ (_ref$current4 = ref.current) === null || _ref$current4 === void 0 ? void 0 : _ref$current4.focus();
125
167
  e.stopPropagation();
126
168
  }
127
169
  }
@@ -129,7 +171,9 @@ const MenuItem = ({
129
171
  e.preventDefault();
130
172
  } else if (Events.isEnterKey(e)) {
131
173
  if (isHref && download) {
132
- ref.current.click();
174
+ var _ref$current5;
175
+
176
+ (_ref$current5 = ref.current) === null || _ref$current5 === void 0 ? void 0 : _ref$current5.click();
133
177
  }
134
178
 
135
179
  e.preventDefault();
@@ -141,23 +185,25 @@ const MenuItem = ({
141
185
  }, [disabled, download, focusButton, isHref, isLeftAligned, onClick, setOpenPopover, submenu]);
142
186
  const itemSubmenuProps = { ...(!disabled && {
143
187
  onMouseEnter: e => {
144
- clearTimeout(mouseEnterTimer.current);
145
- setFocusIndex(null);
188
+ if (mouseEnterTimer.current) clearTimeout(mouseEnterTimer.current);
189
+ setFocusIndex(-1);
146
190
  mouseEnterTimer.current = setTimeout(() => {
147
191
  setOpen(true);
148
192
  }, INTERVAL);
149
193
  e.stopPropagation();
150
194
  },
151
195
  onMouseLeave: e => {
152
- clearTimeout(mouseLeaveTimer.current);
196
+ if (mouseLeaveTimer.current) clearTimeout(mouseLeaveTimer.current);
153
197
  mouseLeaveTimer.current = setTimeout(() => {
154
198
  setOpen(false);
155
199
  }, INTERVAL);
156
200
  e.stopPropagation();
157
201
  },
158
202
  onClick: e => {
203
+ var _ref$current6;
204
+
159
205
  setOpen(true);
160
- ref.current.focus();
206
+ (_ref$current6 = ref.current) === null || _ref$current6 === void 0 ? void 0 : _ref$current6.focus();
161
207
  e.preventDefault();
162
208
  e.stopPropagation();
163
209
  }
@@ -170,8 +216,8 @@ const MenuItem = ({
170
216
 
171
217
  const renderMenuItemIcon = () => {
172
218
  return icon && /*#__PURE__*/React.createElement(MenuItemIcon, {
173
- type: icon,
174
- horizontalAlignment: horizontalAlignment
219
+ as: undefined,
220
+ type: icon
175
221
  });
176
222
  };
177
223
 
@@ -180,15 +226,17 @@ const MenuItem = ({
180
226
  onClick: onClick,
181
227
  onKeyDown: onKeyDown,
182
228
  type: "button",
183
- tabIndex: "0",
184
- role: "menuitem"
229
+ tabIndex: 0,
230
+ role: "menuitem",
231
+ isDisabled: disabled,
232
+ horizontalAlignment: horizontalAlignment
185
233
  }, disabled && {
186
234
  "aria-disabled": true
187
235
  }, isHref && {
188
236
  as: "a",
189
237
  download,
190
238
  href
191
- }, submenu && itemSubmenuProps), submenu && /*#__PURE__*/React.cloneElement(submenu, {
239
+ }, submenu && itemSubmenuProps), /*#__PURE__*/React.isValidElement(submenu) ? /*#__PURE__*/React.cloneElement(submenu, {
192
240
  parentID: `ActionPopoverItem_${guid}`,
193
241
  menuID: `ActionPopoverMenu_${guid}`,
194
242
  "data-element": "action-popover-submenu",
@@ -198,92 +246,25 @@ const MenuItem = ({
198
246
  setOpen,
199
247
  setFocusIndex,
200
248
  focusIndex
201
- }), submenu && checkRef(ref) && isLeftAligned && /*#__PURE__*/React.createElement(SubMenuItemIcon, {
249
+ }) : null, submenu && checkRef(ref) && isLeftAligned ? /*#__PURE__*/React.createElement(SubMenuItemIcon, {
202
250
  type: "chevron_left"
203
- }), horizontalAlignment === "left" && renderMenuItemIcon(), children, horizontalAlignment === "right" && renderMenuItemIcon(), submenu && checkRef(ref) && !isLeftAligned && /*#__PURE__*/React.createElement(SubMenuItemIcon, {
251
+ }) : null, horizontalAlignment === "left" ? renderMenuItemIcon() : null, children, horizontalAlignment === "right" ? renderMenuItemIcon() : null, submenu && checkRef(ref) && !isLeftAligned ? /*#__PURE__*/React.createElement(SubMenuItemIcon, {
204
252
  type: "chevron_right"
205
- }));
206
- };
207
-
208
- function checkRef(ref) {
209
- return Boolean(ref && ref.current);
210
- }
211
-
212
- function leftAlignSubmenu(ref, submenuRef) {
213
- const itemRect = ref.current.getBoundingClientRect();
214
- const {
215
- offsetWidth
216
- } = submenuRef.current;
217
- return itemRect.left >= offsetWidth;
218
- }
219
-
220
- function getContainerPosition(itemRef, submenuRef, spacing, placement) {
221
- const {
222
- offsetWidth: parentWidth
223
- } = itemRef.current;
224
- const {
225
- offsetWidth: submenuWidth
226
- } = submenuRef.current;
227
- const xPositionValue = leftAlignSubmenu(itemRef, submenuRef) ? -submenuWidth : parentWidth;
228
- const yPositionName = placement === "top" ? "bottom" : "top";
229
- return {
230
- left: xPositionValue,
231
- [yPositionName]: -spacing,
232
- right: "auto"
233
- };
234
- }
235
-
236
- const StyledActionPopoverItem = MenuItemFactory(MenuItem);
237
- StyledActionPopoverItem.displayName = "ActionPopoverItem";
238
- const ActionPopoverItem = withTheme(StyledActionPopoverItem);
239
- const propTypes = {
240
- /** The text label to display for this Item */
241
- children: PropTypes.string.isRequired,
242
-
243
- /** Flag to indicate if item is disabled */
244
- disabled: PropTypes.bool,
245
-
246
- /**
247
- * <a href="https://brand.sage.com/d/NdbrveWvNheA/foundations#/icons/icons" target="_blank">List of supported icons</a>
248
- *
249
- * The name of the icon to display next to the label
250
- * */
251
- icon: PropTypes.string,
252
-
253
- /** Callback to run when item is clicked */
254
- onClick: PropTypes.func,
255
-
256
- /** allows to provide download prop that works dependent with href */
257
- download: PropTypes.bool,
258
-
259
- /** allows to provide href prop */
260
- href: PropTypes.string,
261
-
262
- /** Submenu component for item */
263
- submenu(props, propName, componentName) {
264
- let error;
265
-
266
- if (props[propName] && props[propName].type.displayName !== "ActionPopoverMenu") {
267
- error = new Error(`\`${componentName}\` only accepts submenu of type \`ActionPopoverMenu\``);
268
- }
269
-
270
- return error;
271
- },
272
-
273
- /** @ignore @private */
274
- placement: PropTypes.oneOf(["bottom", "top"]),
275
-
276
- /** @ignore @private */
277
- focusItem: PropTypes.bool,
278
-
279
- /** @ignore @private */
280
- horizontalAlignment: PropTypes.oneOf(["left", "right"])
253
+ }) : null);
281
254
  };
282
- ActionPopoverItem.propTypes = { ...propTypes
283
- }; // needed to export MenuItem to create prop tables in storybook
284
255
 
285
- MenuItem.propTypes = { ...propTypes
256
+ ActionPopoverItem.propTypes = {
257
+ "children": PropTypes.string.isRequired,
258
+ "disabled": PropTypes.bool,
259
+ "download": PropTypes.bool,
260
+ "focusItem": PropTypes.bool,
261
+ "horizontalAlignment": PropTypes.oneOf(["left", "right"]),
262
+ "href": PropTypes.string,
263
+ "icon": PropTypes.oneOf(["add", "alert", "analysis", "arrow_down", "arrow_left_boxed", "arrow_left_right_small", "arrow_left_small", "arrow_left", "arrow_right_small", "arrow_right", "arrow_up", "attach", "bank", "basket_with_squares", "basket", "bin", "block_arrow_right", "blocked_square", "blocked", "bold", "boxed_shapes", "bulk_destroy", "bullet_list_dotted", "bullet_list_numbers", "bullet_list", "business", "calendar_today", "calendar", "call", "camera", "card_view", "caret_down", "caret_large_down", "caret_large_left", "caret_large_right", "caret_large_up", "caret_left", "caret_right", "caret_up", "cart", "chart_bar", "chart_line", "chart_pie", "chat_notes", "chat", "chevron_down_thick", "chevron_down", "chevron_left_thick", "chevron_left", "chevron_right_thick", "chevron_right", "chevron_up_thick", "chevron_up", "circle_with_dots", "circles_connection", "clock", "close", "coins", "collaborate", "computer_clock", "connect", "copy", "credit_card_slash", "credit_card", "cross_circle", "cross", "csv", "delete", "delivery", "disconnect", "disputed", "document_right_align", "document_tick", "document_vertical_lines", "download", "draft", "drag_vertical", "drag", "dropdown", "duplicate", "edit", "edited", "ellipsis_horizontal", "ellipsis_vertical", "email_switch", "email", "error_square", "error", "euro", "expand", "factory", "favourite_lined", "favourite", "fax", "feedback", "file_excel", "file_generic", "file_image", "file_pdf", "file_word", "files_leaning", "filter_new", "filter", "fit_height", "fit_width", "flag", "folder", "gift", "graph", "grid", "help", "hide", "home", "image", "in_progress", "in_transit", "individual", "info", "italic", "key", "ledger_arrow_left", "ledger_arrow_right", "ledger", "link", "list_view", "location", "locked", "logout", "lookup", "marker", "message", "messages", "minus_large", "minus", "mobile", "money_bag", "pause_circle", "pause", "pdf", "people_switch", "people", "person_info", "person_tick", "person", "phone", "play_circle", "play", "plus_large", "plus", "pound", "print", "progress", "progressed", "question", "refresh_clock", "refresh", "remove", "sage_coin", "save", "scan", "search", "services", "settings", "share", "shop", "sort_down", "sort_up", "spanner", "split_container", "split", "square_dot", "squares_nine", "stacked_boxes", "stacked_squares", "submitted", "sync", "tag", "three_boxes", "tick_circle", "tick", "unlocked", "upload", "uploaded", "video", "view", "warning"]),
264
+ "onClick": PropTypes.func,
265
+ "placement": PropTypes.oneOf(["bottom", "top"]),
266
+ "submenu": PropTypes.node
286
267
  };
287
- MenuItem.displayName = "ActionPopoverItem";
288
- export { MenuItem };
268
+ export { ActionPopoverItem };
269
+ ActionPopoverItem.displayName = "ActionPopoverItem";
289
270
  export default ActionPopoverItem;
@@ -1,3 +1,36 @@
1
- export default ActionPopoverMenu;
2
- declare const ActionPopoverMenu: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
3
1
  import React from "react";
2
+ export interface ActionPopoverMenuBaseProps {
3
+ /** Children for the menu */
4
+ children?: React.ReactNode;
5
+ /** Index to control which item is focused */
6
+ focusIndex?: number;
7
+ /** Flag to indicate whether a menu should open */
8
+ isOpen?: boolean;
9
+ /** A unique ID for the menu */
10
+ menuID?: string;
11
+ /** Callback to set the index of the focused item */
12
+ setFocusIndex?: (args: number) => void;
13
+ /** Callback to set the isOpen flag */
14
+ setOpen?: (args: boolean) => void;
15
+ /** Unique ID for the menu's parent */
16
+ parentID?: string;
17
+ /** Horizontal alignment of menu items content */
18
+ horizontalAlignment?: "left" | "right";
19
+ /** Set whether the menu should open above or below the button */
20
+ placement?: "bottom" | "top";
21
+ /** @ignore @private */
22
+ role?: string;
23
+ /** @ignore @private */
24
+ "data-element"?: string;
25
+ /** @ignore @private */
26
+ style?: {
27
+ left: number;
28
+ top?: string;
29
+ bottom?: string;
30
+ right: "auto";
31
+ };
32
+ }
33
+ export interface ActionPopoverMenuProps extends ActionPopoverMenuBaseProps, React.RefAttributes<HTMLDivElement> {
34
+ }
35
+ declare const ActionPopoverMenu: React.ForwardRefExoticComponent<ActionPopoverMenuBaseProps & React.RefAttributes<HTMLDivElement>>;
36
+ export default ActionPopoverMenu;
@@ -2,28 +2,46 @@ function _extends() { _extends = Object.assign || function (target) { for (var i
2
2
 
3
3
  import React, { useCallback, useMemo, useContext } from "react";
4
4
  import PropTypes from "prop-types";
5
+ import invariant from "invariant";
5
6
  import { Menu } from "../action-popover.style";
6
7
  import Events from "../../../__internal__/utils/helpers/events";
7
8
  import ActionPopoverItem from "../action-popover-item/action-popover-item.component";
8
9
  import ActionPopoverDivider from "../action-popover-divider/action-popover-divider.component";
9
10
  import ActionPopoverContext from "../action-popover-context";
10
11
  const ActionPopoverMenu = /*#__PURE__*/React.forwardRef(({
11
- parentID,
12
12
  children,
13
+ parentID,
13
14
  focusIndex,
14
15
  isOpen,
15
16
  menuID,
16
- onClick,
17
17
  setOpen,
18
18
  setFocusIndex,
19
19
  placement = "bottom",
20
20
  horizontalAlignment,
21
21
  ...rest
22
22
  }, ref) => {
23
+ const context = useContext(ActionPopoverContext);
24
+ invariant(context, "ActionPopoverMenu must be used within an ActionPopover component");
23
25
  const {
24
26
  focusButton
25
- } = useContext(ActionPopoverContext);
26
- const items = useMemo(() => React.Children.toArray(children).filter(child => child && child.type === ActionPopoverItem), [children]);
27
+ } = context;
28
+ invariant(setOpen && setFocusIndex && typeof focusIndex !== "undefined", "ActionPopoverMenu must be used within an ActionPopover or ActionPopoverItem component");
29
+ const hasProperChildren = useMemo(() => {
30
+ const incorrectChild = React.Children.toArray(children).find(child => {
31
+ if (! /*#__PURE__*/React.isValidElement(child)) {
32
+ return true;
33
+ }
34
+
35
+ return child.type !== ActionPopoverItem && child.type !== ActionPopoverDivider;
36
+ });
37
+ return !incorrectChild;
38
+ }, [children]);
39
+ invariant(hasProperChildren, `ActionPopoverMenu only accepts children of type \`${ActionPopoverItem.displayName}\`` + ` and \`${ActionPopoverDivider.displayName}\`.`);
40
+ const items = useMemo(() => {
41
+ return React.Children.toArray(children).filter(child => {
42
+ return /*#__PURE__*/React.isValidElement(child) && child.type === ActionPopoverItem;
43
+ });
44
+ }, [children]);
27
45
  const onKeyDown = useCallback(e => {
28
46
  if (Events.isTabKey(e)) {
29
47
  e.preventDefault(); // TAB: close menu and allow focus to change to next focusable element
@@ -58,12 +76,8 @@ const ActionPopoverMenu = /*#__PURE__*/React.forwardRef(({
58
76
  e.stopPropagation();
59
77
  let firstMatch;
60
78
  let nextMatch;
61
- React.Children.forEach(items, ({
62
- props: {
63
- children: text
64
- }
65
- }, index) => {
66
- if (text && text.toLowerCase().startsWith(e.key.toLowerCase())) {
79
+ React.Children.forEach(items, (child, index) => {
80
+ if ( /*#__PURE__*/React.isValidElement(child) && child.props.children.toLowerCase().startsWith(e.key.toLowerCase())) {
67
81
  if (firstMatch === undefined) {
68
82
  firstMatch = index;
69
83
  }
@@ -84,7 +98,7 @@ const ActionPopoverMenu = /*#__PURE__*/React.forwardRef(({
84
98
  const clonedChildren = useMemo(() => {
85
99
  let index = 0;
86
100
  return React.Children.map(children, child => {
87
- if (child && child.type === ActionPopoverItem) {
101
+ if ( /*#__PURE__*/React.isValidElement(child) && child.type === ActionPopoverItem) {
88
102
  index += 1;
89
103
  return /*#__PURE__*/React.cloneElement(child, {
90
104
  focusItem: isOpen && focusIndex === index - 1,
@@ -107,48 +121,23 @@ const ActionPopoverMenu = /*#__PURE__*/React.forwardRef(({
107
121
  }, rest), clonedChildren);
108
122
  });
109
123
  ActionPopoverMenu.propTypes = {
110
- /** Unique ID for the menu's parent */
111
- parentID: PropTypes.string,
112
-
113
- /** Children for the menu */
114
- children(props, propName, componentName) {
115
- let error;
116
- const prop = props[propName];
117
- React.Children.forEach(prop, child => {
118
- if (child === null) {
119
- return;
120
- }
121
-
122
- if (![ActionPopoverItem.displayName, ActionPopoverDivider.displayName].includes(child.type.displayName)) {
123
- error = new Error(`\`${componentName}\` only accepts children of type \`${ActionPopoverItem.displayName}\`` + ` and \`${ActionPopoverDivider.displayName}\`.`);
124
- }
125
- });
126
- return error;
127
- },
128
-
129
- /** Index to control which item is focused */
130
- focusIndex: PropTypes.number,
131
-
132
- /** A unique ID for the menu */
133
- menuID: PropTypes.string,
134
-
135
- /** Flag to indicate whether a menu should open */
136
- isOpen: PropTypes.bool,
137
-
138
- /** Callback to set the index of the focused item */
139
- setFocusIndex: PropTypes.func,
140
-
141
- /** Callback to set the isOpen flag */
142
- setOpen: PropTypes.func,
143
-
144
- /** Callback called on click event */
145
- onClick: PropTypes.func,
146
-
147
- /** @ignore @private */
148
- placement: PropTypes.oneOf(["bottom", "top"]),
149
-
150
- /** @ignore @private */
151
- horizontalAlignment: PropTypes.oneOf(["left", "right"])
124
+ "children": PropTypes.node,
125
+ "data-element": PropTypes.string,
126
+ "focusIndex": PropTypes.number,
127
+ "horizontalAlignment": PropTypes.oneOf(["left", "right"]),
128
+ "isOpen": PropTypes.bool,
129
+ "menuID": PropTypes.string,
130
+ "parentID": PropTypes.string,
131
+ "placement": PropTypes.oneOf(["bottom", "top"]),
132
+ "role": PropTypes.string,
133
+ "setFocusIndex": PropTypes.func,
134
+ "setOpen": PropTypes.func,
135
+ "style": PropTypes.shape({
136
+ "bottom": PropTypes.string,
137
+ "left": PropTypes.number.isRequired,
138
+ "right": PropTypes.oneOf(["auto"]).isRequired,
139
+ "top": PropTypes.string
140
+ })
152
141
  };
153
142
  ActionPopoverMenu.displayName = "ActionPopoverMenu";
154
143
  export default ActionPopoverMenu;
@@ -1,19 +1,21 @@
1
- export default ActionPopoverMenuButton;
2
- declare function ActionPopoverMenuButton({ buttonType, iconType, iconPosition, size, children, ...props }: {
3
- [x: string]: any;
4
- buttonType: any;
5
- iconType: any;
6
- iconPosition: any;
7
- size: any;
8
- children: any;
9
- }): JSX.Element;
10
- declare namespace ActionPopoverMenuButton {
11
- namespace propTypes {
12
- const buttonType: PropTypes.Requireable<string>;
13
- const iconType: PropTypes.Requireable<string>;
14
- const iconPosition: PropTypes.Requireable<string>;
15
- const size: PropTypes.Requireable<string>;
16
- const children: PropTypes.Requireable<string>;
17
- }
1
+ /// <reference types="react" />
2
+ import { ButtonTypes } from "../../button/button.component";
3
+ import { IconType } from "../../icon";
4
+ export declare type ActionPopoverMenuButtonAria = {
5
+ "aria-haspopup": string;
6
+ "aria-label": string;
7
+ "aria-controls": string;
8
+ "aria-expanded": string;
9
+ };
10
+ export interface ActionPopoverMenuButtonProps {
11
+ children?: string;
12
+ buttonType?: ButtonTypes;
13
+ iconType?: IconType;
14
+ iconPosition?: "after" | "before";
15
+ size?: "small" | "medium" | "large";
16
+ tabIndex: number;
17
+ ariaAttributes: ActionPopoverMenuButtonAria;
18
+ "data-element": string;
18
19
  }
19
- import PropTypes from "prop-types";
20
+ declare const ActionPopoverMenuButton: ({ buttonType, iconType, iconPosition, size, children, ...props }: ActionPopoverMenuButtonProps) => JSX.Element;
21
+ export default ActionPopoverMenuButton;
@@ -20,10 +20,18 @@ const ActionPopoverMenuButton = ({
20
20
  }, props), children));
21
21
 
22
22
  ActionPopoverMenuButton.propTypes = {
23
- buttonType: PropTypes.string,
24
- iconType: PropTypes.string,
25
- iconPosition: PropTypes.string,
26
- size: PropTypes.string,
27
- children: PropTypes.string
23
+ "ariaAttributes": PropTypes.shape({
24
+ "aria-controls": PropTypes.string.isRequired,
25
+ "aria-expanded": PropTypes.string.isRequired,
26
+ "aria-haspopup": PropTypes.string.isRequired,
27
+ "aria-label": PropTypes.string.isRequired
28
+ }).isRequired,
29
+ "buttonType": PropTypes.oneOf(["darkBackground", "dashed", "primary", "secondary", "tertiary"]),
30
+ "children": PropTypes.string,
31
+ "data-element": PropTypes.string.isRequired,
32
+ "iconPosition": PropTypes.oneOf(["after", "before"]),
33
+ "iconType": PropTypes.oneOf(["add", "alert", "analysis", "arrow_down", "arrow_left_boxed", "arrow_left_right_small", "arrow_left_small", "arrow_left", "arrow_right_small", "arrow_right", "arrow_up", "attach", "bank", "basket_with_squares", "basket", "bin", "block_arrow_right", "blocked_square", "blocked", "bold", "boxed_shapes", "bulk_destroy", "bullet_list_dotted", "bullet_list_numbers", "bullet_list", "business", "calendar_today", "calendar", "call", "camera", "card_view", "caret_down", "caret_large_down", "caret_large_left", "caret_large_right", "caret_large_up", "caret_left", "caret_right", "caret_up", "cart", "chart_bar", "chart_line", "chart_pie", "chat_notes", "chat", "chevron_down_thick", "chevron_down", "chevron_left_thick", "chevron_left", "chevron_right_thick", "chevron_right", "chevron_up_thick", "chevron_up", "circle_with_dots", "circles_connection", "clock", "close", "coins", "collaborate", "computer_clock", "connect", "copy", "credit_card_slash", "credit_card", "cross_circle", "cross", "csv", "delete", "delivery", "disconnect", "disputed", "document_right_align", "document_tick", "document_vertical_lines", "download", "draft", "drag_vertical", "drag", "dropdown", "duplicate", "edit", "edited", "ellipsis_horizontal", "ellipsis_vertical", "email_switch", "email", "error_square", "error", "euro", "expand", "factory", "favourite_lined", "favourite", "fax", "feedback", "file_excel", "file_generic", "file_image", "file_pdf", "file_word", "files_leaning", "filter_new", "filter", "fit_height", "fit_width", "flag", "folder", "gift", "graph", "grid", "help", "hide", "home", "image", "in_progress", "in_transit", "individual", "info", "italic", "key", "ledger_arrow_left", "ledger_arrow_right", "ledger", "link", "list_view", "location", "locked", "logout", "lookup", "marker", "message", "messages", "minus_large", "minus", "mobile", "money_bag", "pause_circle", "pause", "pdf", "people_switch", "people", "person_info", "person_tick", "person", "phone", "play_circle", "play", "plus_large", "plus", "pound", "print", "progress", "progressed", "question", "refresh_clock", "refresh", "remove", "sage_coin", "save", "scan", "search", "services", "settings", "share", "shop", "sort_down", "sort_up", "spanner", "split_container", "split", "square_dot", "squares_nine", "stacked_boxes", "stacked_squares", "submitted", "sync", "tag", "three_boxes", "tick_circle", "tick", "unlocked", "upload", "uploaded", "video", "view", "warning"]),
34
+ "size": PropTypes.oneOf(["large", "medium", "small"]),
35
+ "tabIndex": PropTypes.number.isRequired
28
36
  };
29
37
  export default ActionPopoverMenuButton;