carbon-react 119.8.0 → 119.9.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.
- package/README.md +1 -1
- package/esm/components/action-popover/action-popover-context.d.ts +2 -0
- package/esm/components/action-popover/action-popover-item/action-popover-item.component.d.ts +17 -2
- package/esm/components/action-popover/action-popover-item/action-popover-item.component.js +89 -41
- package/esm/components/action-popover/action-popover-menu/action-popover-menu.component.d.ts +6 -3
- package/esm/components/action-popover/action-popover-menu/action-popover-menu.component.js +19 -6
- package/esm/components/action-popover/action-popover.component.d.ts +5 -2
- package/esm/components/action-popover/action-popover.component.js +2 -0
- package/esm/components/action-popover/action-popover.style.d.ts +12 -4
- package/esm/components/action-popover/action-popover.style.js +107 -19
- package/esm/components/textarea/textarea.component.js +13 -0
- package/lib/components/action-popover/action-popover-context.d.ts +2 -0
- package/lib/components/action-popover/action-popover-item/action-popover-item.component.d.ts +17 -2
- package/lib/components/action-popover/action-popover-item/action-popover-item.component.js +88 -40
- package/lib/components/action-popover/action-popover-menu/action-popover-menu.component.d.ts +6 -3
- package/lib/components/action-popover/action-popover-menu/action-popover-menu.component.js +18 -5
- package/lib/components/action-popover/action-popover.component.d.ts +5 -2
- package/lib/components/action-popover/action-popover.component.js +2 -0
- package/lib/components/action-popover/action-popover.style.d.ts +12 -4
- package/lib/components/action-popover/action-popover.style.js +109 -19
- package/lib/components/textarea/textarea.component.js +13 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Carbon is a [React](https://facebook.github.io/react/) component library develop
|
|
|
4
4
|
|
|
5
5
|
## Getting started
|
|
6
6
|
|
|
7
|
-
Our [getting started guide](
|
|
7
|
+
Our [getting started guide](https://carbon.sage.com/?path=/story/getting-started-installation--page) provides instructions on how to install and use the Carbon library.
|
|
8
8
|
|
|
9
9
|
## Examples
|
|
10
10
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
export declare type Alignment = "left" | "right";
|
|
2
3
|
declare type ActionPopoverContextType = {
|
|
3
4
|
setOpenPopover: (isOpen: boolean) => void;
|
|
4
5
|
focusButton: () => void;
|
|
6
|
+
submenuPosition: Alignment;
|
|
5
7
|
isOpenPopover: boolean;
|
|
6
8
|
};
|
|
7
9
|
declare const ActionPopoverContext: React.Context<ActionPopoverContextType | null>;
|
package/esm/components/action-popover/action-popover-item/action-popover-item.component.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { Alignment } from "../action-popover-context";
|
|
2
3
|
import { IconType } from "../../icon";
|
|
3
4
|
export interface ActionPopoverItemProps {
|
|
4
5
|
/** The text label to display for this Item */
|
|
@@ -20,10 +21,24 @@ export interface ActionPopoverItemProps {
|
|
|
20
21
|
/** @ignore @private */
|
|
21
22
|
focusItem?: boolean;
|
|
22
23
|
/** @ignore @private */
|
|
23
|
-
horizontalAlignment?:
|
|
24
|
+
horizontalAlignment?: Alignment;
|
|
25
|
+
/** @ignore @private */
|
|
26
|
+
childHasSubmenu?: boolean;
|
|
27
|
+
/** @ignore @private */
|
|
28
|
+
childHasIcon?: boolean;
|
|
29
|
+
/** @ignore @private */
|
|
30
|
+
currentSubmenuPosition?: Alignment;
|
|
31
|
+
/** @ignore @private */
|
|
32
|
+
setChildHasSubmenu?: (value: boolean) => void;
|
|
33
|
+
/** @ignore @private */
|
|
34
|
+
setChildHasIcon?: (value: boolean) => void;
|
|
35
|
+
/** @ignore @private */
|
|
36
|
+
setCurrentSubmenuPosition?: (value: Alignment) => void;
|
|
37
|
+
/** @ignore @private */
|
|
38
|
+
isASubmenu?: boolean;
|
|
24
39
|
}
|
|
25
40
|
export declare const ActionPopoverItem: {
|
|
26
|
-
({ children, icon, disabled, onClick: onClickProp, submenu, placement, focusItem, download, href, horizontalAlignment, ...rest }: ActionPopoverItemProps): React.JSX.Element;
|
|
41
|
+
({ children, icon, disabled, onClick: onClickProp, submenu, placement, focusItem, download, href, horizontalAlignment, childHasSubmenu, childHasIcon, currentSubmenuPosition, setChildHasSubmenu, setChildHasIcon, setCurrentSubmenuPosition, isASubmenu, ...rest }: ActionPopoverItemProps): React.JSX.Element;
|
|
27
42
|
displayName: string;
|
|
28
43
|
};
|
|
29
44
|
export default ActionPopoverItem;
|
|
@@ -2,7 +2,7 @@ function _extends() { _extends = Object.assign ? Object.assign.bind() : function
|
|
|
2
2
|
import React, { useCallback, useEffect, useRef, useState, useContext } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import invariant from "invariant";
|
|
5
|
-
import { MenuItemIcon, SubMenuItemIcon, StyledMenuItem, StyledMenuItemWrapper } from "../action-popover.style";
|
|
5
|
+
import { MenuItemIcon, SubMenuItemIcon, StyledMenuItem, StyledMenuItemInnerText, StyledMenuItemOuterContainer, StyledMenuItemWrapper } from "../action-popover.style";
|
|
6
6
|
import Events from "../../../__internal__/utils/helpers/events";
|
|
7
7
|
import createGuid from "../../../__internal__/utils/helpers/guid";
|
|
8
8
|
import ActionPopoverContext from "../action-popover-context";
|
|
@@ -12,33 +12,22 @@ const INTERVAL = 150;
|
|
|
12
12
|
function checkRef(ref) {
|
|
13
13
|
return Boolean(ref && ref.current);
|
|
14
14
|
}
|
|
15
|
-
function
|
|
15
|
+
function calculateSubmenuPosition(ref, submenuRef, submenuPosition, currentSubmenuPosition) {
|
|
16
16
|
/* istanbul ignore if */
|
|
17
|
-
|
|
17
|
+
|
|
18
|
+
if (!ref.current || !submenuRef.current) return currentSubmenuPosition || submenuPosition;
|
|
18
19
|
const {
|
|
19
|
-
left
|
|
20
|
+
left,
|
|
21
|
+
right
|
|
20
22
|
} = ref.current.getBoundingClientRect();
|
|
21
23
|
const {
|
|
22
24
|
offsetWidth
|
|
23
25
|
} = submenuRef.current;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const {
|
|
30
|
-
offsetWidth: parentWidth
|
|
31
|
-
} = itemRef.current;
|
|
32
|
-
const {
|
|
33
|
-
offsetWidth: submenuWidth
|
|
34
|
-
} = submenuRef.current;
|
|
35
|
-
const xPositionValue = leftAlignSubmenu(itemRef, submenuRef) ? -submenuWidth : parentWidth;
|
|
36
|
-
const yPositionName = placement === "top" ? "bottom" : "top";
|
|
37
|
-
return {
|
|
38
|
-
left: xPositionValue,
|
|
39
|
-
[yPositionName]: "calc(-1 * var(--spacing100))",
|
|
40
|
-
right: "auto"
|
|
41
|
-
};
|
|
26
|
+
const windowWidth = document.body.clientWidth;
|
|
27
|
+
if (submenuPosition === "left") {
|
|
28
|
+
return left >= offsetWidth ? "left" : "right";
|
|
29
|
+
}
|
|
30
|
+
return windowWidth >= right + offsetWidth ? "right" : "left";
|
|
42
31
|
}
|
|
43
32
|
export const ActionPopoverItem = _ref => {
|
|
44
33
|
let {
|
|
@@ -52,6 +41,13 @@ export const ActionPopoverItem = _ref => {
|
|
|
52
41
|
download,
|
|
53
42
|
href,
|
|
54
43
|
horizontalAlignment,
|
|
44
|
+
childHasSubmenu,
|
|
45
|
+
childHasIcon,
|
|
46
|
+
currentSubmenuPosition,
|
|
47
|
+
setChildHasSubmenu,
|
|
48
|
+
setChildHasIcon,
|
|
49
|
+
setCurrentSubmenuPosition,
|
|
50
|
+
isASubmenu = false,
|
|
55
51
|
...rest
|
|
56
52
|
} = _ref;
|
|
57
53
|
const l = useLocale();
|
|
@@ -61,14 +57,14 @@ export const ActionPopoverItem = _ref => {
|
|
|
61
57
|
const {
|
|
62
58
|
setOpenPopover,
|
|
63
59
|
isOpenPopover,
|
|
64
|
-
focusButton
|
|
60
|
+
focusButton,
|
|
61
|
+
submenuPosition
|
|
65
62
|
} = context;
|
|
66
63
|
const isHref = !!href;
|
|
67
64
|
const [containerPosition, setContainerPosition] = useState(undefined);
|
|
68
65
|
const [guid] = useState(createGuid());
|
|
69
66
|
const [isOpen, setOpen] = useState(false);
|
|
70
67
|
const [focusIndex, setFocusIndex] = useState(0);
|
|
71
|
-
const [isLeftAligned, setIsLeftAligned] = useState(true);
|
|
72
68
|
const submenuRef = useRef(null);
|
|
73
69
|
const ref = useRef(null);
|
|
74
70
|
const mouseEnterTimer = useRef(null);
|
|
@@ -78,19 +74,48 @@ export const ActionPopoverItem = _ref => {
|
|
|
78
74
|
setOpen(false);
|
|
79
75
|
}
|
|
80
76
|
}, [isOpenPopover]);
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
if (icon) {
|
|
79
|
+
setChildHasIcon?.(true);
|
|
80
|
+
}
|
|
81
|
+
if (submenu) {
|
|
82
|
+
setChildHasSubmenu?.(true);
|
|
83
|
+
}
|
|
84
|
+
}, [icon, setChildHasSubmenu, setChildHasIcon, submenu]);
|
|
81
85
|
const alignSubmenu = useCallback(() => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
+
const checkCalculatedSubmenuPosition = calculateSubmenuPosition(ref, submenuRef, submenuPosition, currentSubmenuPosition);
|
|
87
|
+
setCurrentSubmenuPosition?.(checkCalculatedSubmenuPosition);
|
|
88
|
+
return checkRef(ref) && checkRef(submenuRef) && submenu;
|
|
89
|
+
}, [submenu, setCurrentSubmenuPosition, submenuPosition, currentSubmenuPosition]);
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
const getContainerPosition = () => {
|
|
92
|
+
/* istanbul ignore if */
|
|
93
|
+
if (!ref.current || !submenuRef.current) return undefined;
|
|
94
|
+
const {
|
|
95
|
+
offsetWidth: submenuWidth
|
|
96
|
+
} = submenuRef.current;
|
|
97
|
+
const leftAlignedSubmenu = currentSubmenuPosition === "left";
|
|
98
|
+
const leftValue = leftAlignedSubmenu ? -submenuWidth : "auto";
|
|
99
|
+
const rightValue = leftAlignedSubmenu ? "auto" : -submenuWidth;
|
|
100
|
+
const yPositionName = placement === "top" ? "bottom" : "top";
|
|
101
|
+
return {
|
|
102
|
+
left: leftValue,
|
|
103
|
+
[yPositionName]: "calc(-1 * var(--spacing100))",
|
|
104
|
+
right: rightValue
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
setContainerPosition(getContainerPosition);
|
|
108
|
+
}, [submenu, currentSubmenuPosition, placement]);
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (submenu) {
|
|
111
|
+
alignSubmenu();
|
|
86
112
|
}
|
|
87
|
-
}, [
|
|
113
|
+
}, [alignSubmenu, submenu]);
|
|
88
114
|
useEffect(() => {
|
|
89
|
-
alignSubmenu();
|
|
90
115
|
if (focusItem) {
|
|
91
116
|
ref.current?.focus();
|
|
92
117
|
}
|
|
93
|
-
}, [
|
|
118
|
+
}, [focusItem]);
|
|
94
119
|
useEffect(() => {
|
|
95
120
|
return function cleanup() {
|
|
96
121
|
if (mouseEnterTimer.current) clearTimeout(mouseEnterTimer.current);
|
|
@@ -123,7 +148,7 @@ export const ActionPopoverItem = _ref => {
|
|
|
123
148
|
e.stopPropagation();
|
|
124
149
|
} else if (!disabled) {
|
|
125
150
|
if (submenu) {
|
|
126
|
-
if (
|
|
151
|
+
if (currentSubmenuPosition === "left") {
|
|
127
152
|
// LEFT: open if has submenu and left aligned otherwise close submenu
|
|
128
153
|
if (Events.isLeftKey(e) || Events.isEnterKey(e)) {
|
|
129
154
|
setOpen(true);
|
|
@@ -159,7 +184,7 @@ export const ActionPopoverItem = _ref => {
|
|
|
159
184
|
} else if (Events.isEnterKey(e)) {
|
|
160
185
|
e.stopPropagation();
|
|
161
186
|
}
|
|
162
|
-
}, [disabled, download, isHref,
|
|
187
|
+
}, [disabled, download, isHref, onClick, submenu, currentSubmenuPosition]);
|
|
163
188
|
const itemSubmenuProps = {
|
|
164
189
|
...(!disabled && {
|
|
165
190
|
onClick: e => {
|
|
@@ -195,8 +220,15 @@ export const ActionPopoverItem = _ref => {
|
|
|
195
220
|
};
|
|
196
221
|
const renderMenuItemIcon = () => {
|
|
197
222
|
return icon && /*#__PURE__*/React.createElement(MenuItemIcon, {
|
|
198
|
-
|
|
199
|
-
|
|
223
|
+
type: icon,
|
|
224
|
+
"data-element": "action-popover-menu-item-icon",
|
|
225
|
+
horizontalAlignment: horizontalAlignment,
|
|
226
|
+
submenuPosition: currentSubmenuPosition,
|
|
227
|
+
childHasIcon: childHasIcon,
|
|
228
|
+
childHasSubmenu: childHasSubmenu,
|
|
229
|
+
hasIcon: !!icon,
|
|
230
|
+
hasSubmenu: !!submenu,
|
|
231
|
+
isASubmenu: isASubmenu
|
|
200
232
|
});
|
|
201
233
|
};
|
|
202
234
|
return /*#__PURE__*/React.createElement(StyledMenuItemWrapper, submenu && wrapperDivProps, /*#__PURE__*/React.createElement("div", {
|
|
@@ -209,17 +241,31 @@ export const ActionPopoverItem = _ref => {
|
|
|
209
241
|
role: "menuitem",
|
|
210
242
|
tabIndex: 0,
|
|
211
243
|
isDisabled: disabled,
|
|
212
|
-
horizontalAlignment: horizontalAlignment
|
|
244
|
+
horizontalAlignment: horizontalAlignment,
|
|
245
|
+
submenuPosition: currentSubmenuPosition,
|
|
246
|
+
hasSubmenu: !!submenu,
|
|
247
|
+
childHasSubmenu: childHasSubmenu
|
|
213
248
|
}, disabled && {
|
|
214
249
|
"aria-disabled": true
|
|
215
250
|
}, isHref && {
|
|
216
251
|
as: "a",
|
|
217
252
|
download,
|
|
218
253
|
href
|
|
219
|
-
}, submenu && itemSubmenuProps), submenu && checkRef(ref) &&
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
254
|
+
}, submenu && itemSubmenuProps), submenu && checkRef(ref) && currentSubmenuPosition === "left" ? /*#__PURE__*/React.createElement(SubMenuItemIcon, {
|
|
255
|
+
"data-element": "action-popover-menu-item-chevron",
|
|
256
|
+
type: "chevron_left_thick"
|
|
257
|
+
}) : null, /*#__PURE__*/React.createElement(StyledMenuItemOuterContainer, null, horizontalAlignment === "left" ? renderMenuItemIcon() : null, /*#__PURE__*/React.createElement(StyledMenuItemInnerText, {
|
|
258
|
+
"data-element": "action-popover-menu-item-inner-text",
|
|
259
|
+
horizontalAlignment: horizontalAlignment,
|
|
260
|
+
submenuPosition: currentSubmenuPosition,
|
|
261
|
+
isASubmenu: isASubmenu,
|
|
262
|
+
childHasSubmenu: childHasSubmenu,
|
|
263
|
+
childHasIcon: childHasIcon,
|
|
264
|
+
hasIcon: !!icon,
|
|
265
|
+
hasSubmenu: !!submenu
|
|
266
|
+
}, children), horizontalAlignment === "right" ? renderMenuItemIcon() : null), submenu && checkRef(ref) && currentSubmenuPosition === "right" ? /*#__PURE__*/React.createElement(SubMenuItemIcon, {
|
|
267
|
+
"data-element": "action-popover-menu-item-chevron",
|
|
268
|
+
type: "chevron_right_thick"
|
|
223
269
|
}) : null), /*#__PURE__*/React.isValidElement(submenu) ? /*#__PURE__*/React.cloneElement(submenu, {
|
|
224
270
|
parentID: `ActionPopoverItem_${guid}`,
|
|
225
271
|
menuID: `ActionPopoverMenu_${guid}`,
|
|
@@ -229,7 +275,9 @@ export const ActionPopoverItem = _ref => {
|
|
|
229
275
|
style: containerPosition,
|
|
230
276
|
setOpen,
|
|
231
277
|
setFocusIndex,
|
|
232
|
-
focusIndex
|
|
278
|
+
focusIndex,
|
|
279
|
+
isASubmenu: true,
|
|
280
|
+
horizontalAlignment
|
|
233
281
|
}) : null));
|
|
234
282
|
};
|
|
235
283
|
ActionPopoverItem.displayName = "ActionPopoverItem";
|
package/esm/components/action-popover/action-popover-menu/action-popover-menu.component.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { Alignment } from "../action-popover-context";
|
|
2
3
|
export interface ActionPopoverMenuBaseProps {
|
|
3
4
|
/** Children for the menu */
|
|
4
5
|
children?: React.ReactNode;
|
|
@@ -15,19 +16,21 @@ export interface ActionPopoverMenuBaseProps {
|
|
|
15
16
|
/** Unique ID for the menu's parent */
|
|
16
17
|
parentID?: string;
|
|
17
18
|
/** Horizontal alignment of menu items content */
|
|
18
|
-
horizontalAlignment?:
|
|
19
|
+
horizontalAlignment?: Alignment;
|
|
19
20
|
/** Set whether the menu should open above or below the button */
|
|
20
21
|
placement?: "bottom" | "top";
|
|
21
22
|
/** @ignore @private */
|
|
22
23
|
role?: string;
|
|
23
24
|
/** @ignore @private */
|
|
25
|
+
isASubmenu?: boolean;
|
|
26
|
+
/** @ignore @private */
|
|
24
27
|
"data-element"?: string;
|
|
25
28
|
/** @ignore @private */
|
|
26
29
|
style?: {
|
|
27
|
-
left: number;
|
|
30
|
+
left: string | number;
|
|
28
31
|
top?: string;
|
|
29
32
|
bottom?: string;
|
|
30
|
-
right:
|
|
33
|
+
right: string | number;
|
|
31
34
|
};
|
|
32
35
|
}
|
|
33
36
|
export interface ActionPopoverMenuProps extends ActionPopoverMenuBaseProps, React.RefAttributes<HTMLDivElement> {
|
|
@@ -1,5 +1,5 @@
|
|
|
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, { useCallback, useMemo, useContext } from "react";
|
|
2
|
+
import React, { useCallback, useMemo, useContext, useState } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import invariant from "invariant";
|
|
5
5
|
import { Menu } from "../action-popover.style";
|
|
@@ -18,12 +18,14 @@ const ActionPopoverMenu = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
18
18
|
setFocusIndex,
|
|
19
19
|
placement = "bottom",
|
|
20
20
|
horizontalAlignment,
|
|
21
|
+
isASubmenu,
|
|
21
22
|
...rest
|
|
22
23
|
} = _ref;
|
|
23
24
|
const context = useContext(ActionPopoverContext);
|
|
24
25
|
!context ? process.env.NODE_ENV !== "production" ? invariant(false, "ActionPopoverMenu must be used within an ActionPopover component") : invariant(false) : void 0;
|
|
25
26
|
const {
|
|
26
|
-
focusButton
|
|
27
|
+
focusButton,
|
|
28
|
+
submenuPosition
|
|
27
29
|
} = context;
|
|
28
30
|
!(setOpen && setFocusIndex && typeof focusIndex !== "undefined") ? process.env.NODE_ENV !== "production" ? invariant(false, "ActionPopoverMenu must be used within an ActionPopover or ActionPopoverItem component") : invariant(false) : void 0;
|
|
29
31
|
const hasProperChildren = useMemo(() => {
|
|
@@ -92,6 +94,9 @@ const ActionPopoverMenu = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
}, [focusButton, setOpen, focusIndex, items, setFocusIndex]);
|
|
97
|
+
const [childHasSubmenu, setChildHasSubmenu] = useState(false);
|
|
98
|
+
const [childHasIcon, setChildHasIcon] = useState(false);
|
|
99
|
+
const [currentSubmenuPosition, setCurrentSubmenuPosition] = useState(submenuPosition);
|
|
95
100
|
const clonedChildren = useMemo(() => {
|
|
96
101
|
let index = 0;
|
|
97
102
|
return React.Children.map(children, child => {
|
|
@@ -100,12 +105,19 @@ const ActionPopoverMenu = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
100
105
|
return /*#__PURE__*/React.cloneElement(child, {
|
|
101
106
|
focusItem: isOpen && focusIndex === index - 1,
|
|
102
107
|
placement: child.props.submenu ? placement : undefined,
|
|
103
|
-
horizontalAlignment
|
|
108
|
+
horizontalAlignment,
|
|
109
|
+
childHasSubmenu,
|
|
110
|
+
setChildHasSubmenu,
|
|
111
|
+
childHasIcon,
|
|
112
|
+
setChildHasIcon,
|
|
113
|
+
currentSubmenuPosition,
|
|
114
|
+
setCurrentSubmenuPosition,
|
|
115
|
+
isASubmenu
|
|
104
116
|
});
|
|
105
117
|
}
|
|
106
118
|
return child;
|
|
107
119
|
});
|
|
108
|
-
}, [children, focusIndex, isOpen, placement, horizontalAlignment]);
|
|
120
|
+
}, [children, focusIndex, isOpen, placement, horizontalAlignment, childHasSubmenu, childHasIcon, currentSubmenuPosition, isASubmenu]);
|
|
109
121
|
return /*#__PURE__*/React.createElement(Menu, _extends({
|
|
110
122
|
"data-component": "action-popover",
|
|
111
123
|
isOpen: isOpen,
|
|
@@ -121,6 +133,7 @@ ActionPopoverMenu.propTypes = {
|
|
|
121
133
|
"data-element": PropTypes.string,
|
|
122
134
|
"focusIndex": PropTypes.number,
|
|
123
135
|
"horizontalAlignment": PropTypes.oneOf(["left", "right"]),
|
|
136
|
+
"isASubmenu": PropTypes.bool,
|
|
124
137
|
"isOpen": PropTypes.bool,
|
|
125
138
|
"menuID": PropTypes.string,
|
|
126
139
|
"parentID": PropTypes.string,
|
|
@@ -130,8 +143,8 @@ ActionPopoverMenu.propTypes = {
|
|
|
130
143
|
"setOpen": PropTypes.func,
|
|
131
144
|
"style": PropTypes.shape({
|
|
132
145
|
"bottom": PropTypes.string,
|
|
133
|
-
"left": PropTypes.number.isRequired,
|
|
134
|
-
"right": PropTypes.
|
|
146
|
+
"left": PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
|
147
|
+
"right": PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
|
135
148
|
"top": PropTypes.string
|
|
136
149
|
})
|
|
137
150
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { MarginProps } from "styled-system";
|
|
3
|
+
import { Alignment } from "./action-popover-context";
|
|
3
4
|
export interface RenderButtonProps {
|
|
4
5
|
tabIndex: number;
|
|
5
6
|
"data-element": string;
|
|
@@ -14,7 +15,9 @@ export interface ActionPopoverProps extends MarginProps {
|
|
|
14
15
|
/** Children for popover component */
|
|
15
16
|
children?: React.ReactNode;
|
|
16
17
|
/** Horizontal alignment of menu items content */
|
|
17
|
-
horizontalAlignment?:
|
|
18
|
+
horizontalAlignment?: Alignment;
|
|
19
|
+
/** Sets submenu position */
|
|
20
|
+
submenuPosition?: Alignment;
|
|
18
21
|
/** Unique ID */
|
|
19
22
|
id?: string;
|
|
20
23
|
/** Callback to be called on menu open */
|
|
@@ -28,5 +31,5 @@ export interface ActionPopoverProps extends MarginProps {
|
|
|
28
31
|
/** Boolean to control whether menu should align to right */
|
|
29
32
|
rightAlignMenu?: boolean;
|
|
30
33
|
}
|
|
31
|
-
export declare const ActionPopover: ({ children, id, onOpen, onClose, rightAlignMenu, renderButton, placement, horizontalAlignment, ...rest }: ActionPopoverProps) => React.JSX.Element;
|
|
34
|
+
export declare const ActionPopover: ({ children, id, onOpen, onClose, rightAlignMenu, renderButton, placement, horizontalAlignment, submenuPosition, ...rest }: ActionPopoverProps) => React.JSX.Element;
|
|
32
35
|
export default ActionPopover;
|
|
@@ -24,6 +24,7 @@ export const ActionPopover = _ref => {
|
|
|
24
24
|
renderButton,
|
|
25
25
|
placement = "bottom",
|
|
26
26
|
horizontalAlignment = "left",
|
|
27
|
+
submenuPosition = "left",
|
|
27
28
|
...rest
|
|
28
29
|
} = _ref;
|
|
29
30
|
const l = useLocale();
|
|
@@ -185,6 +186,7 @@ export const ActionPopover = _ref => {
|
|
|
185
186
|
value: {
|
|
186
187
|
setOpenPopover: setOpen,
|
|
187
188
|
focusButton,
|
|
189
|
+
submenuPosition,
|
|
188
190
|
isOpenPopover: isOpen
|
|
189
191
|
}
|
|
190
192
|
}, isOpen && /*#__PURE__*/React.createElement(Popover, {
|
|
@@ -4,9 +4,17 @@ declare const Menu: import("styled-components").StyledComponent<"div", any, {
|
|
|
4
4
|
}, never>;
|
|
5
5
|
declare type StyledMenuItemProps = {
|
|
6
6
|
isDisabled: boolean;
|
|
7
|
-
horizontalAlignment
|
|
7
|
+
horizontalAlignment?: "left" | "right";
|
|
8
|
+
submenuPosition?: "left" | "right";
|
|
9
|
+
childHasSubmenu?: boolean;
|
|
10
|
+
childHasIcon?: boolean;
|
|
11
|
+
hasSubmenu?: boolean;
|
|
12
|
+
hasIcon?: boolean;
|
|
13
|
+
isASubmenu?: boolean;
|
|
8
14
|
};
|
|
9
|
-
declare const
|
|
15
|
+
declare const StyledMenuItemInnerText: import("styled-components").StyledComponent<"div", any, Omit<StyledMenuItemProps, "isDisabled">, never>;
|
|
16
|
+
declare const StyledMenuItemOuterContainer: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
17
|
+
declare const StyledMenuItem: import("styled-components").StyledComponent<"button", any, Omit<StyledMenuItemProps, "variant">, never>;
|
|
10
18
|
declare const StyledMenuItemWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
11
19
|
declare const MenuItemDivider: import("styled-components").StyledComponent<"div", any, {
|
|
12
20
|
"data-element": string;
|
|
@@ -14,7 +22,7 @@ declare const MenuItemDivider: import("styled-components").StyledComponent<"div"
|
|
|
14
22
|
declare const MenuButton: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
15
23
|
declare const ButtonIcon: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../icon").IconProps & import("react").RefAttributes<HTMLSpanElement>>, any, {}, never>;
|
|
16
24
|
declare const StyledButtonIcon: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
17
|
-
declare const MenuItemIcon: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../icon").IconProps & import("react").RefAttributes<HTMLSpanElement>>, any,
|
|
25
|
+
declare const MenuItemIcon: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../icon").IconProps & import("react").RefAttributes<HTMLSpanElement>>, any, Omit<StyledMenuItemProps, "isDisabled">, never>;
|
|
18
26
|
declare const SubMenuItemIcon: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../icon").IconProps & import("react").RefAttributes<HTMLSpanElement>>, any, {}, never>;
|
|
19
27
|
declare const MenuButtonOverrideWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
20
|
-
export { Menu, MenuButton, ButtonIcon, StyledButtonIcon, MenuItemIcon, MenuItemDivider, SubMenuItemIcon, MenuButtonOverrideWrapper, StyledMenuItem, StyledMenuItemWrapper, };
|
|
28
|
+
export { Menu, MenuButton, ButtonIcon, StyledButtonIcon, MenuItemIcon, MenuItemDivider, SubMenuItemIcon, MenuButtonOverrideWrapper, StyledMenuItemInnerText, StyledMenuItemOuterContainer, StyledMenuItem, StyledMenuItemWrapper, };
|
|
@@ -24,7 +24,85 @@ const Menu = styled.div`
|
|
|
24
24
|
return `${theme.zIndex?.popover}`;
|
|
25
25
|
}}; // TODO (tokens): implement elevation tokens - FE-4437
|
|
26
26
|
`;
|
|
27
|
+
function getPaddingValues(childHasSubmenu, childHasIcon, hasIcon, hasSubmenu) {
|
|
28
|
+
if (!childHasIcon && childHasSubmenu && !hasIcon && !hasSubmenu) {
|
|
29
|
+
return "var(--spacing400)";
|
|
30
|
+
}
|
|
31
|
+
if (childHasIcon && childHasSubmenu && !hasIcon && hasSubmenu) {
|
|
32
|
+
return "var(--spacing600)";
|
|
33
|
+
}
|
|
34
|
+
if (childHasIcon && childHasSubmenu && !hasIcon && !hasSubmenu) {
|
|
35
|
+
return "var(--spacing900)";
|
|
36
|
+
}
|
|
37
|
+
return "var(--spacing100)";
|
|
38
|
+
}
|
|
39
|
+
function getIconPaddingValues(index, horizontalAlignment, submenuPosition, siblingsHaveIconAndSubmenu, isASubmenu) {
|
|
40
|
+
const sameAlignment = horizontalAlignment === "left" && submenuPosition === "left" || horizontalAlignment === "right" && submenuPosition === "right";
|
|
41
|
+
if (siblingsHaveIconAndSubmenu && sameAlignment) {
|
|
42
|
+
if (horizontalAlignment === "left") {
|
|
43
|
+
return index === 1 ? "var(--spacing100)" : "var(--spacing400)";
|
|
44
|
+
}
|
|
45
|
+
return index === 1 ? "var(--spacing400)" : "var(--spacing100)";
|
|
46
|
+
}
|
|
47
|
+
if (isASubmenu) {
|
|
48
|
+
if (horizontalAlignment === "left") {
|
|
49
|
+
return index === 1 ? "var(--spacing100)" : "var(--spacing000)";
|
|
50
|
+
}
|
|
51
|
+
return index === 1 ? "var(--spacing000)" : "var(--spacing100)";
|
|
52
|
+
}
|
|
53
|
+
return "var(--spacing100)";
|
|
54
|
+
}
|
|
55
|
+
const StyledMenuItemInnerText = styled.div`
|
|
56
|
+
${_ref3 => {
|
|
57
|
+
let {
|
|
58
|
+
childHasSubmenu,
|
|
59
|
+
childHasIcon,
|
|
60
|
+
hasIcon,
|
|
61
|
+
hasSubmenu,
|
|
62
|
+
submenuPosition,
|
|
63
|
+
horizontalAlignment,
|
|
64
|
+
isASubmenu
|
|
65
|
+
} = _ref3;
|
|
66
|
+
return css`
|
|
67
|
+
padding-left: ${isASubmenu ? `var(--spacing000)` : `var(--spacing100)`};
|
|
68
|
+
padding-right: ${isASubmenu ? `var(--spacing000)` : `var(--spacing100)`};
|
|
69
|
+
|
|
70
|
+
${horizontalAlignment === "left" && submenuPosition === "left" && !isASubmenu && css`
|
|
71
|
+
padding-left: ${getPaddingValues(childHasSubmenu, childHasIcon, hasIcon, hasSubmenu)};
|
|
72
|
+
`}
|
|
73
|
+
|
|
74
|
+
${horizontalAlignment === "right" && submenuPosition === "right" && !isASubmenu && css`
|
|
75
|
+
padding-right: ${getPaddingValues(childHasSubmenu, childHasIcon, hasIcon, hasSubmenu)};
|
|
76
|
+
`}
|
|
77
|
+
`;
|
|
78
|
+
}}
|
|
79
|
+
`;
|
|
80
|
+
const StyledMenuItemOuterContainer = styled.div`
|
|
81
|
+
display: inherit;
|
|
82
|
+
`;
|
|
27
83
|
const StyledMenuItem = styled.button`
|
|
84
|
+
${_ref4 => {
|
|
85
|
+
let {
|
|
86
|
+
horizontalAlignment,
|
|
87
|
+
submenuPosition,
|
|
88
|
+
childHasSubmenu,
|
|
89
|
+
hasSubmenu
|
|
90
|
+
} = _ref4;
|
|
91
|
+
return css`
|
|
92
|
+
justify-content: ${horizontalAlignment === "left" ? "flex-start" : "flex-end"};
|
|
93
|
+
|
|
94
|
+
${horizontalAlignment === "left" && submenuPosition === "right" && css`
|
|
95
|
+
justify-content: space-between;
|
|
96
|
+
`}
|
|
97
|
+
|
|
98
|
+
${horizontalAlignment === "right" && submenuPosition === "left" && css`
|
|
99
|
+
${childHasSubmenu && hasSubmenu && css`
|
|
100
|
+
justify-content: space-between;
|
|
101
|
+
`}
|
|
102
|
+
`}
|
|
103
|
+
`;
|
|
104
|
+
}}
|
|
105
|
+
|
|
28
106
|
text-decoration: none;
|
|
29
107
|
background-color: var(--colorsActionMajorYang100);
|
|
30
108
|
cursor: pointer;
|
|
@@ -41,12 +119,6 @@ const StyledMenuItem = styled.button`
|
|
|
41
119
|
color: var(--colorsUtilityYin090);
|
|
42
120
|
font-size: 14px;
|
|
43
121
|
font-weight: 700;
|
|
44
|
-
justify-content: ${_ref3 => {
|
|
45
|
-
let {
|
|
46
|
-
horizontalAlignment
|
|
47
|
-
} = _ref3;
|
|
48
|
-
return horizontalAlignment === "left" ? "flex-start" : "flex-end";
|
|
49
|
-
}};
|
|
50
122
|
|
|
51
123
|
&:focus {
|
|
52
124
|
outline: var(--borderWidth300) solid var(--colorsSemanticFocus500);
|
|
@@ -54,10 +126,10 @@ const StyledMenuItem = styled.button`
|
|
|
54
126
|
border-radius: var(--borderRadius000);
|
|
55
127
|
}
|
|
56
128
|
|
|
57
|
-
${
|
|
129
|
+
${_ref5 => {
|
|
58
130
|
let {
|
|
59
131
|
isDisabled
|
|
60
|
-
} =
|
|
132
|
+
} = _ref5;
|
|
61
133
|
return isDisabled && css`
|
|
62
134
|
color: var(--colorsUtilityYin030);
|
|
63
135
|
cursor: not-allowed;
|
|
@@ -69,10 +141,10 @@ const StyledMenuItem = styled.button`
|
|
|
69
141
|
`;
|
|
70
142
|
}}
|
|
71
143
|
|
|
72
|
-
${
|
|
144
|
+
${_ref6 => {
|
|
73
145
|
let {
|
|
74
146
|
isDisabled
|
|
75
|
-
} =
|
|
147
|
+
} = _ref6;
|
|
76
148
|
return !isDisabled && css`
|
|
77
149
|
&:focus,
|
|
78
150
|
&:hover {
|
|
@@ -117,21 +189,37 @@ const StyledButtonIcon = styled.div`
|
|
|
117
189
|
}
|
|
118
190
|
`;
|
|
119
191
|
const MenuItemIcon = styled(Icon)`
|
|
120
|
-
|
|
121
|
-
|
|
192
|
+
${_ref7 => {
|
|
193
|
+
let {
|
|
194
|
+
horizontalAlignment,
|
|
195
|
+
submenuPosition,
|
|
196
|
+
childHasIcon,
|
|
197
|
+
childHasSubmenu,
|
|
198
|
+
hasIcon,
|
|
199
|
+
hasSubmenu,
|
|
200
|
+
isASubmenu
|
|
201
|
+
} = _ref7;
|
|
202
|
+
return css`
|
|
203
|
+
justify-content: ${horizontalAlignment};
|
|
204
|
+
padding: var(--spacing100)
|
|
205
|
+
${getIconPaddingValues(1, horizontalAlignment, submenuPosition, childHasIcon && childHasSubmenu && hasIcon && !hasSubmenu, isASubmenu)}
|
|
206
|
+
var(--spacing100)
|
|
207
|
+
${getIconPaddingValues(2, horizontalAlignment, submenuPosition, childHasIcon && childHasSubmenu && hasIcon && !hasSubmenu, isASubmenu)};
|
|
208
|
+
color: var(--colorsUtilityYin065);
|
|
209
|
+
`;
|
|
210
|
+
}}
|
|
122
211
|
`;
|
|
123
212
|
const SubMenuItemIcon = styled(ButtonIcon)`
|
|
124
|
-
${
|
|
213
|
+
${_ref8 => {
|
|
125
214
|
let {
|
|
126
215
|
type
|
|
127
|
-
} =
|
|
216
|
+
} = _ref8;
|
|
128
217
|
return css`
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
left: -2px;
|
|
218
|
+
${type === "chevron_left_thick" && css`
|
|
219
|
+
left: -5px;
|
|
132
220
|
`}
|
|
133
221
|
|
|
134
|
-
${type === "
|
|
222
|
+
${type === "chevron_right_thick" && css`
|
|
135
223
|
right: -5px;
|
|
136
224
|
${isSafari(navigator) && css`
|
|
137
225
|
top: var(--sizing100);
|
|
@@ -156,4 +244,4 @@ const MenuButtonOverrideWrapper = styled.div`
|
|
|
156
244
|
}
|
|
157
245
|
}
|
|
158
246
|
`;
|
|
159
|
-
export { Menu, MenuButton, ButtonIcon, StyledButtonIcon, MenuItemIcon, MenuItemDivider, SubMenuItemIcon, MenuButtonOverrideWrapper, StyledMenuItem, StyledMenuItemWrapper };
|
|
247
|
+
export { Menu, MenuButton, ButtonIcon, StyledButtonIcon, MenuItemIcon, MenuItemDivider, SubMenuItemIcon, MenuButtonOverrideWrapper, StyledMenuItemInnerText, StyledMenuItemOuterContainer, StyledMenuItem, StyledMenuItemWrapper };
|
|
@@ -92,9 +92,18 @@ const Textarea = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
92
92
|
const expandTextarea = () => {
|
|
93
93
|
const textarea = internalRef.current;
|
|
94
94
|
if (textarea?.scrollHeight && textarea?.scrollHeight > minHeight.current) {
|
|
95
|
+
// need to reset scroll position of the nearest parent which scrolls
|
|
96
|
+
let scrollElement = textarea;
|
|
97
|
+
while (scrollElement && !scrollElement?.scrollTop) {
|
|
98
|
+
scrollElement = scrollElement?.parentElement || null;
|
|
99
|
+
}
|
|
100
|
+
const scrollPosition = scrollElement?.scrollTop;
|
|
95
101
|
textarea.style.height = "0px";
|
|
96
102
|
// Set the height so all content is shown
|
|
97
103
|
textarea.style.height = `${Math.max(textarea.scrollHeight, minHeight.current)}px`;
|
|
104
|
+
if (scrollElement && scrollPosition) {
|
|
105
|
+
scrollElement.scrollTop = scrollPosition;
|
|
106
|
+
}
|
|
98
107
|
}
|
|
99
108
|
};
|
|
100
109
|
const {
|
|
@@ -126,10 +135,14 @@ const Textarea = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
126
135
|
if (expandable) {
|
|
127
136
|
window.addEventListener("resize", expandTextarea);
|
|
128
137
|
minHeight.current = internalRef?.current?.clientHeight || 0;
|
|
138
|
+
// need to also run expandTextarea when the Sage UI font completes loading, to prevent strange scroll
|
|
139
|
+
// behaviour when it only loads after the component is rendered
|
|
140
|
+
document.fonts?.addEventListener("loadingdone", expandTextarea);
|
|
129
141
|
}
|
|
130
142
|
return () => {
|
|
131
143
|
if (expandable) {
|
|
132
144
|
window.removeEventListener("resize", expandTextarea);
|
|
145
|
+
document.fonts?.removeEventListener("loadingdone", expandTextarea);
|
|
133
146
|
}
|
|
134
147
|
};
|
|
135
148
|
}, [expandable]);
|