carbon-react 135.1.0 → 135.1.2

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 (35) hide show
  1. package/esm/__internal__/label/label.component.js +1 -0
  2. package/esm/__internal__/utils/helpers/tags/tags-specs/index.d.ts +1 -1
  3. package/esm/__internal__/utils/helpers/tags/tags-specs/index.js +1 -1
  4. package/esm/__internal__/utils/helpers/tags/tags-specs/tags-specs.d.ts +2 -4
  5. package/esm/__internal__/utils/helpers/tags/tags-specs/tags-specs.js +3 -11
  6. package/esm/components/file-input/__internal__/file-upload-status/file-upload-status.component.js +1 -0
  7. package/esm/components/file-input/file-input.component.d.ts +1 -1
  8. package/esm/components/file-input/file-input.component.js +1 -1
  9. package/esm/components/link/link.component.js +2 -1
  10. package/esm/components/menu/__internal__/submenu/submenu.component.js +21 -3
  11. package/esm/components/menu/__internal__/submenu/submenu.style.d.ts +1 -0
  12. package/esm/components/menu/__internal__/submenu/submenu.style.js +5 -4
  13. package/esm/components/menu/menu-item/menu-item.component.d.ts +2 -4
  14. package/esm/components/menu/menu-item/menu-item.component.js +10 -3
  15. package/esm/components/step-flow/step-flow.component.js +4 -1
  16. package/esm/components/toast/toast.style.js +1 -1
  17. package/esm/components/tooltip/tooltip.component.js +1 -0
  18. package/lib/__internal__/label/label.component.js +1 -0
  19. package/lib/__internal__/utils/helpers/tags/tags-specs/index.d.ts +1 -1
  20. package/lib/__internal__/utils/helpers/tags/tags-specs/index.js +0 -6
  21. package/lib/__internal__/utils/helpers/tags/tags-specs/tags-specs.d.ts +2 -4
  22. package/lib/__internal__/utils/helpers/tags/tags-specs/tags-specs.js +2 -10
  23. package/lib/components/file-input/__internal__/file-upload-status/file-upload-status.component.js +1 -0
  24. package/lib/components/file-input/file-input.component.d.ts +1 -1
  25. package/lib/components/file-input/file-input.component.js +1 -1
  26. package/lib/components/link/link.component.js +2 -1
  27. package/lib/components/menu/__internal__/submenu/submenu.component.js +21 -3
  28. package/lib/components/menu/__internal__/submenu/submenu.style.d.ts +1 -0
  29. package/lib/components/menu/__internal__/submenu/submenu.style.js +5 -4
  30. package/lib/components/menu/menu-item/menu-item.component.d.ts +2 -4
  31. package/lib/components/menu/menu-item/menu-item.component.js +10 -3
  32. package/lib/components/step-flow/step-flow.component.js +4 -1
  33. package/lib/components/toast/toast.style.js +1 -1
  34. package/lib/components/tooltip/tooltip.component.js +1 -0
  35. package/package.json +1 -1
@@ -97,6 +97,7 @@ export const Label = ({
97
97
  }, help));
98
98
  };
99
99
  return /*#__PURE__*/React.createElement(StyledLabelContainer, {
100
+ "data-role": "label-container",
100
101
  align: align,
101
102
  inline: inline,
102
103
  width: width,
@@ -1 +1 @@
1
- export { elementsTagTest, rootTagTest, rootTagTestRtl } from "./tags-specs";
1
+ export { elementsTagTest, rootTagTest } from "./tags-specs";
@@ -1 +1 @@
1
- export { elementsTagTest, rootTagTest, rootTagTestRtl } from "./tags-specs";
1
+ export { elementsTagTest, rootTagTest } from "./tags-specs";
@@ -1,5 +1,3 @@
1
1
  import { ReactWrapper, ShallowWrapper } from "enzyme";
2
- declare const elementsTagTest: (wrapper: ReactWrapper | ShallowWrapper, elements: string[]) => void;
3
- declare const rootTagTest: (rootNode: ReactWrapper | ShallowWrapper, comp: string, elem?: string, role?: string) => void;
4
- declare const rootTagTestRtl: (rootNode: HTMLElement, comp: string, elem?: string, role?: string) => void;
5
- export { elementsTagTest, rootTagTest, rootTagTestRtl };
2
+ export declare const elementsTagTest: (wrapper: ReactWrapper | ShallowWrapper, elements: string[]) => void;
3
+ export declare const rootTagTest: (rootNode: ReactWrapper | ShallowWrapper, comp: string, elem?: string, role?: string) => void;
@@ -1,4 +1,4 @@
1
- const elementsTagTest = (wrapper, elements) => {
1
+ export const elementsTagTest = (wrapper, elements) => {
2
2
  elements.forEach(element => {
3
3
  it(`include 'data-element="${element}"'`, () => {
4
4
  expect(wrapper.find({
@@ -7,16 +7,8 @@ const elementsTagTest = (wrapper, elements) => {
7
7
  });
8
8
  });
9
9
  };
10
- const rootTagTest = (rootNode, comp, elem, role) => {
10
+ export const rootTagTest = (rootNode, comp, elem, role) => {
11
11
  expect(rootNode.prop("data-component")).toEqual(comp);
12
12
  expect(rootNode.prop("data-element")).toEqual(elem);
13
13
  expect(rootNode.prop("data-role")).toEqual(role);
14
- };
15
- const rootTagTestRtl = (rootNode, comp, elem, role) => {
16
- expect(rootNode).toHaveAttribute("data-component", comp);
17
- expect(rootNode).toHaveAttribute("data-element", elem);
18
- expect(rootNode).toHaveAttribute("data-role", role);
19
- };
20
-
21
- // eslint-disable-next-line jest/no-export
22
- export { elementsTagTest, rootTagTest, rootTagTestRtl };
14
+ };
@@ -64,6 +64,7 @@ export const FileUploadStatus = ({
64
64
  lowerPadding: true
65
65
  }, /*#__PURE__*/React.createElement(StyledFileLinkContainer, null, fileLink)) : null;
66
66
  return /*#__PURE__*/React.createElement(StyledFileUploadStatus, {
67
+ "data-role": "file-upload-status",
67
68
  hasError: status === "error"
68
69
  }, mainRow, secondRow, progressBar);
69
70
  };
@@ -4,7 +4,7 @@ import { ValidationProps } from "../../__internal__/validations";
4
4
  import { InputProps } from "../../__internal__/input";
5
5
  import { TagProps } from "../../__internal__/utils/helpers/tags";
6
6
  import { FileUploadStatusProps } from "./__internal__/file-upload-status";
7
- export interface FileInputProps extends Pick<ValidationProps, "error">, Pick<InputProps, "id" | "name" | "required">, TagProps, MarginProps {
7
+ export interface FileInputProps extends Pick<ValidationProps, "error">, Pick<InputProps, "id" | "name" | "required">, Omit<TagProps, "data-component">, MarginProps {
8
8
  /** Which file format(s) to accept. Will be passed to the underlying HTML input.
9
9
  * See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept */
10
10
  accept?: string;
@@ -132,6 +132,7 @@ const FileInput = /*#__PURE__*/React.forwardRef(({
132
132
  onChange: onInputChange,
133
133
  type: "file"
134
134
  }, rest)), /*#__PURE__*/React.createElement(StyledFileInputPresentation, _extends({
135
+ "data-role": "file-input-presentation",
135
136
  isDraggedOver: isDraggedOver,
136
137
  isDraggingFile: isDraggingFile,
137
138
  error: error,
@@ -166,7 +167,6 @@ if (process.env.NODE_ENV !== "production") {
166
167
  FileInput.propTypes = {
167
168
  "accept": PropTypes.string,
168
169
  "buttonText": PropTypes.string,
169
- "data-component": PropTypes.string,
170
170
  "data-element": PropTypes.string,
171
171
  "data-role": PropTypes.string,
172
172
  "dragAndDropText": PropTypes.string,
@@ -79,7 +79,8 @@ const Link = /*#__PURE__*/React.forwardRef(({
79
79
  ...componentProps,
80
80
  ...(placeholderTabIndex && href === undefined && !onClick && {
81
81
  tabIndex: -1
82
- })
82
+ }),
83
+ "data-role": "link-anchor"
83
84
  }, /*#__PURE__*/React.createElement(React.Fragment, null, renderLinkIcon(), /*#__PURE__*/React.createElement(StyledContent, null, isSkipLink ? l.link.skipLinkLabel() : children), renderLinkIcon("right")));
84
85
  };
85
86
  return /*#__PURE__*/React.createElement(StyledLink, _extends({
@@ -44,6 +44,7 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
44
44
  const [submenuItemIds, setSubmenuItemIds] = useState([]);
45
45
  const [characterString, setCharacterString] = useState("");
46
46
  const [applyFocusRadius, setApplyFocusRadius] = useState(false);
47
+ const [applyFocusRadiusToLastItem, setApplyFocusRadiusToLastItem] = useState(false);
47
48
  const shiftTabPressed = useRef(false);
48
49
  const focusFirstMenuItemOnOpen = useRef(false);
49
50
  const numberOfChildren = submenuItemIds.length;
@@ -94,19 +95,34 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
94
95
  // Get the last segment block
95
96
  const lastSegmentBlock = ulElements.pop();
96
97
 
98
+ // Check if the last segment block is a scrollable block
99
+ const isLastSegmentBlockScrollableBlock = Boolean(lastSegmentBlock?.parentElement?.dataset.component === SCROLLABLE_BLOCK);
100
+
97
101
  // Get all the menu items from the last segment block
98
102
  const segmentBlockMenuItems = Array.from(lastSegmentBlock?.querySelectorAll("[data-component='menu-item']") || /* istanbul ignore next */[]);
99
103
 
100
104
  // Get the last menu item in the last segment block
101
105
  const lastMenuItemInSegmentBlock = segmentBlockMenuItems.pop();
106
+
107
+ // Check to see if the last menu item in the last segment block is visible
108
+ let isLastMenuItemInSegmentBlockVisible = false;
109
+ if (lastMenuItemInSegmentBlock && lastSegmentBlock) {
110
+ isLastMenuItemInSegmentBlockVisible = lastMenuItemInSegmentBlock.getBoundingClientRect().bottom < lastSegmentBlock.getBoundingClientRect().bottom;
111
+ }
112
+
102
113
  // Check if the last item in the segment block is the same as the last MenuItem in the submenu
103
114
  const menuItemsMatch = !!lastMenuItemInSegmentBlock && lastMenuItemInSegmentBlock === lastMenuItem;
115
+
116
+ // Applies the focus radius to the StyledBox of the StyledScrollableBlock
104
117
  setApplyFocusRadius(menuItemsMatch);
118
+
119
+ // Applies border radius to the last item in the segment block
120
+ setApplyFocusRadiusToLastItem(menuItemsMatch && !isLastSegmentBlockScrollableBlock || menuItemsMatch && isLastSegmentBlockScrollableBlock && !isLastMenuItemInSegmentBlockVisible);
105
121
  };
106
122
  if (submenuOpen && submenuRef) {
107
123
  handleBorderRadiusStyling();
108
124
  }
109
- }, [submenuOpen, submenuRef]);
125
+ }, [submenuOpen, submenuRef, numberOfChildren]);
110
126
  useEffect(() => {
111
127
  if (submenuOpen && onSubmenuOpen) {
112
128
  onSubmenuOpen();
@@ -283,7 +299,8 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
283
299
  menuType: menuType,
284
300
  inFullscreenView: inFullscreenView,
285
301
  ref: setSubmenuRef,
286
- applyFocusRadiusStyling: false
302
+ applyFocusRadiusStyling: false,
303
+ applyFocusRadiusStylingToLastItem: applyFocusRadiusToLastItem
287
304
  }, /*#__PURE__*/React.createElement(SubmenuContext.Provider, {
288
305
  value: {
289
306
  handleKeyDown,
@@ -322,7 +339,8 @@ const Submenu = /*#__PURE__*/React.forwardRef(({
322
339
  menuType: menuType,
323
340
  role: blockIndex === 0 ? "presentation" : "list",
324
341
  maxHeight: submenuMaxHeight,
325
- applyFocusRadiusStyling: applyFocusRadius
342
+ applyFocusRadiusStyling: applyFocusRadius,
343
+ applyFocusRadiusStylingToLastItem: applyFocusRadiusToLastItem
326
344
  }, /*#__PURE__*/React.createElement(SubmenuContext.Provider, {
327
345
  value: {
328
346
  submenuFocusId,
@@ -12,6 +12,7 @@ interface StyledSubmenuProps extends SharedStyleProps, Pick<SubmenuProps, "varia
12
12
  submenuDirection?: string;
13
13
  maxHeight?: string;
14
14
  applyFocusRadiusStyling: boolean;
15
+ applyFocusRadiusStylingToLastItem: boolean;
15
16
  }
16
17
  declare const StyledSubmenuWrapper: import("styled-components").StyledComponent<"div", any, StyledSubmenuWrapperProps, never>;
17
18
  declare const StyledSubmenu: import("styled-components").StyledComponent<"ul", any, StyledSubmenuProps, never>;
@@ -42,7 +42,8 @@ const StyledSubmenu = styled.ul`
42
42
  variant,
43
43
  inFullscreenView,
44
44
  maxHeight,
45
- applyFocusRadiusStyling
45
+ applyFocusRadiusStyling,
46
+ applyFocusRadiusStylingToLastItem
46
47
  }) => css`
47
48
  ${!inFullscreenView && menuType && css`
48
49
  box-shadow: var(--boxShadow100);
@@ -84,8 +85,8 @@ const StyledSubmenu = styled.ul`
84
85
  border-bottom-left-radius: var(--borderRadius000);
85
86
 
86
87
  :focus {
87
- border-bottom-right-radius: ${applyFocusRadiusStyling ? "var(--borderRadius100)" : "var(--borderRadius000)"};
88
- border-bottom-left-radius: ${applyFocusRadiusStyling ? "var(--borderRadius100)" : "var(--borderRadius000)"};
88
+ border-bottom-right-radius: ${applyFocusRadiusStylingToLastItem ? "var(--borderRadius100)" : "var(--borderRadius000)"};
89
+ border-bottom-left-radius: ${applyFocusRadiusStylingToLastItem ? "var(--borderRadius100)" : "var(--borderRadius000)"};
89
90
  }
90
91
  }
91
92
 
@@ -97,7 +98,7 @@ const StyledSubmenu = styled.ul`
97
98
  ${StyledMenuItem}:last-child ${StyledLink}, ${StyledMenuItem}:last-child a,
98
99
  ${StyledMenuItem}:last-child button {
99
100
  border-bottom-right-radius: var(--borderRadius000);
100
- border-bottom-left-radius: ${applyFocusRadiusStyling ? "var(--borderRadius100)" : "var(--borderRadius000)"};
101
+ border-bottom-left-radius: ${applyFocusRadiusStylingToLastItem ? "var(--borderRadius100)" : "var(--borderRadius000)"};
101
102
  }
102
103
  }
103
104
  }
@@ -3,7 +3,7 @@ import { FlexboxProps, LayoutProps, MaxWidthProps, PaddingProps } from "styled-s
3
3
  import { IconType } from "../../icon";
4
4
  import { TagProps } from "../../../__internal__/utils/helpers/tags";
5
5
  export declare type VariantType = "default" | "alternate";
6
- interface MenuItemBaseProps extends TagProps, LayoutProps, FlexboxProps, PaddingProps {
6
+ interface MenuItemBaseProps extends Omit<TagProps, "data-component">, LayoutProps, FlexboxProps, PaddingProps {
7
7
  /** Custom className */
8
8
  className?: string;
9
9
  /** onClick handler */
@@ -38,8 +38,6 @@ interface MenuItemBaseProps extends TagProps, LayoutProps, FlexboxProps, Padding
38
38
  for other MenuItems inside the block
39
39
  */
40
40
  overrideColor?: boolean;
41
- /** @private @ignore */
42
- "data-component"?: string;
43
41
  /** When set the submenu opens by click instead of hover */
44
42
  clickToOpen?: boolean;
45
43
  /** Sets the maxWidth of the MenuItem */
@@ -61,7 +59,7 @@ export interface MenuWithIcon extends MenuItemBaseProps {
61
59
  children?: React.ReactNode;
62
60
  }
63
61
  export declare const MenuItem: {
64
- ({ submenu, children, href, onClick, target, submenuDirection, icon, selected, onKeyDown, variant, showDropdownArrow, ariaLabel, clickToOpen, maxWidth, onSubmenuOpen, onSubmenuClose, overrideColor, rel, as, ...rest }: MenuWithChildren | MenuWithIcon): React.JSX.Element;
62
+ ({ submenu, children, href, onClick, target, submenuDirection, icon, selected, onKeyDown, variant, showDropdownArrow, ariaLabel, clickToOpen, maxWidth, onSubmenuOpen, onSubmenuClose, overrideColor, rel, as, "data-element": dataElement, "data-role": dataRole, ...rest }: MenuWithChildren | MenuWithIcon): React.JSX.Element;
65
63
  displayName: string;
66
64
  };
67
65
  export default MenuItem;
@@ -10,7 +10,6 @@ import Submenu from "../__internal__/submenu/submenu.component";
10
10
  import SubmenuContext from "../__internal__/submenu/submenu.context";
11
11
  import { StyledMenuItem } from "../menu.style";
12
12
  import guid from "../../../__internal__/utils/helpers/guid";
13
- import tagComponent from "../../../__internal__/utils/helpers/tags";
14
13
  export const MenuItem = ({
15
14
  submenu,
16
15
  children,
@@ -31,6 +30,8 @@ export const MenuItem = ({
31
30
  overrideColor,
32
31
  rel,
33
32
  as,
33
+ "data-element": dataElement,
34
+ "data-role": dataRole,
34
35
  ...rest
35
36
  }) => {
36
37
  !(icon || children) ? process.env.NODE_ENV !== "production" ? invariant(false, "Either prop `icon` must be defined or this node must have `children`.") : invariant(false) : void 0;
@@ -124,7 +125,10 @@ export const MenuItem = ({
124
125
  const asPassiveItem = !(onClick || href);
125
126
  const hasInput = !!inputRef.current;
126
127
  if (submenu) {
127
- return /*#__PURE__*/React.createElement(StyledMenuItem, _extends({}, tagComponent("menu-item", rest), {
128
+ return /*#__PURE__*/React.createElement(StyledMenuItem, _extends({
129
+ "data-component": "menu-item",
130
+ "data-element": dataElement,
131
+ "data-role": dataRole,
128
132
  menuType: menuType,
129
133
  title: getTitle(submenu),
130
134
  maxWidth: itemMaxWidth,
@@ -147,7 +151,10 @@ export const MenuItem = ({
147
151
  }, elementProps, rest), children));
148
152
  }
149
153
  const paddingProps = filterStyledSystemPaddingProps(rest);
150
- return /*#__PURE__*/React.createElement(StyledMenuItem, _extends({}, tagComponent("menu-item", rest), {
154
+ return /*#__PURE__*/React.createElement(StyledMenuItem, _extends({
155
+ "data-component": "menu-item",
156
+ "data-element": dataElement,
157
+ "data-role": dataRole,
151
158
  menuType: menuType,
152
159
  inSubmenu: !!handleSubmenuKeyDown,
153
160
  title: getTitle(children),
@@ -47,6 +47,7 @@ const StepFlow = /*#__PURE__*/forwardRef(({
47
47
  return /*#__PURE__*/React.createElement(StyledProgressIndicator, {
48
48
  key: step,
49
49
  "aria-hidden": "true",
50
+ "data-role": "progress-indicator",
50
51
  "data-element": "progress-indicator",
51
52
  isCompleted: step < validatedCurrentStep,
52
53
  isInProgress: step === validatedCurrentStep,
@@ -68,6 +69,7 @@ const StepFlow = /*#__PURE__*/forwardRef(({
68
69
  }
69
70
  }), []);
70
71
  const stepFlowTitle = /*#__PURE__*/React.createElement(StyledTitleFocusWrapper, {
72
+ "data-role": "title-text-wrapper",
71
73
  "data-element": "title-text-wrapper",
72
74
  tabIndex: -1,
73
75
  ref: titleRef
@@ -102,7 +104,8 @@ const StepFlow = /*#__PURE__*/forwardRef(({
102
104
  "data-element": "category-text",
103
105
  "aria-hidden": "true"
104
106
  }, category), stepFlowTitle) : stepFlowTitle, showCloseIcon ? closeIcon : null), showProgressIndicator ? /*#__PURE__*/React.createElement(StyledStepLabelAndProgress, null, stepFlowLabel, /*#__PURE__*/React.createElement(StyledProgressIndicatorBar, {
105
- "data-element": "progress-indicator-bar"
107
+ "data-element": "progress-indicator-bar",
108
+ "data-role": "progress-indicator-bar"
106
109
  }, progressIndicators)) : stepFlowLabel);
107
110
  });
108
111
  if (process.env.NODE_ENV !== "production") {
@@ -102,7 +102,7 @@ const StyledToast = styled.div`
102
102
 
103
103
  box-shadow: ${boxShadow};
104
104
  line-height: 22px;
105
- margin-top: ${alignY === "top" && isNotice || alignY === "center" ? "0" : "30px"};
105
+ margin-top: ${isNotice || alignY === "center" || alignY === "bottom" ? "0" : "30px"};
106
106
  margin-bottom: ${alignY === "bottom" && !isNotice ? "30px" : "0"};
107
107
  max-width: ${!maxWidth ? "300px" : maxWidth};
108
108
  position: relative;
@@ -176,6 +176,7 @@ const Tooltip = /*#__PURE__*/React.forwardRef(({
176
176
  type: type,
177
177
  ref: arrowReference,
178
178
  "data-element": "tooltip-pointer",
179
+ "data-role": "tooltip-pointer",
179
180
  bgColor: bgColor,
180
181
  style: arrowStyle
181
182
  }), message)) : null);
@@ -106,6 +106,7 @@ const Label = ({
106
106
  }, help));
107
107
  };
108
108
  return /*#__PURE__*/_react.default.createElement(_label.StyledLabelContainer, {
109
+ "data-role": "label-container",
109
110
  align: align,
110
111
  inline: inline,
111
112
  width: width,
@@ -1 +1 @@
1
- export { elementsTagTest, rootTagTest, rootTagTestRtl } from "./tags-specs";
1
+ export { elementsTagTest, rootTagTest } from "./tags-specs";
@@ -15,10 +15,4 @@ Object.defineProperty(exports, "rootTagTest", {
15
15
  return _tagsSpecs.rootTagTest;
16
16
  }
17
17
  });
18
- Object.defineProperty(exports, "rootTagTestRtl", {
19
- enumerable: true,
20
- get: function () {
21
- return _tagsSpecs.rootTagTestRtl;
22
- }
23
- });
24
18
  var _tagsSpecs = require("./tags-specs");
@@ -1,5 +1,3 @@
1
1
  import { ReactWrapper, ShallowWrapper } from "enzyme";
2
- declare const elementsTagTest: (wrapper: ReactWrapper | ShallowWrapper, elements: string[]) => void;
3
- declare const rootTagTest: (rootNode: ReactWrapper | ShallowWrapper, comp: string, elem?: string, role?: string) => void;
4
- declare const rootTagTestRtl: (rootNode: HTMLElement, comp: string, elem?: string, role?: string) => void;
5
- export { elementsTagTest, rootTagTest, rootTagTestRtl };
2
+ export declare const elementsTagTest: (wrapper: ReactWrapper | ShallowWrapper, elements: string[]) => void;
3
+ export declare const rootTagTest: (rootNode: ReactWrapper | ShallowWrapper, comp: string, elem?: string, role?: string) => void;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.rootTagTestRtl = exports.rootTagTest = exports.elementsTagTest = void 0;
6
+ exports.rootTagTest = exports.elementsTagTest = void 0;
7
7
  const elementsTagTest = (wrapper, elements) => {
8
8
  elements.forEach(element => {
9
9
  it(`include 'data-element="${element}"'`, () => {
@@ -19,12 +19,4 @@ const rootTagTest = (rootNode, comp, elem, role) => {
19
19
  expect(rootNode.prop("data-element")).toEqual(elem);
20
20
  expect(rootNode.prop("data-role")).toEqual(role);
21
21
  };
22
- exports.rootTagTest = rootTagTest;
23
- const rootTagTestRtl = (rootNode, comp, elem, role) => {
24
- expect(rootNode).toHaveAttribute("data-component", comp);
25
- expect(rootNode).toHaveAttribute("data-element", elem);
26
- expect(rootNode).toHaveAttribute("data-role", role);
27
- };
28
-
29
- // eslint-disable-next-line jest/no-export
30
- exports.rootTagTestRtl = rootTagTestRtl;
22
+ exports.rootTagTest = rootTagTest;
@@ -71,6 +71,7 @@ const FileUploadStatus = ({
71
71
  lowerPadding: true
72
72
  }, /*#__PURE__*/_react.default.createElement(_fileUploadStatus.StyledFileLinkContainer, null, fileLink)) : null;
73
73
  return /*#__PURE__*/_react.default.createElement(_fileUploadStatus.StyledFileUploadStatus, {
74
+ "data-role": "file-upload-status",
74
75
  hasError: status === "error"
75
76
  }, mainRow, secondRow, progressBar);
76
77
  };
@@ -4,7 +4,7 @@ import { ValidationProps } from "../../__internal__/validations";
4
4
  import { InputProps } from "../../__internal__/input";
5
5
  import { TagProps } from "../../__internal__/utils/helpers/tags";
6
6
  import { FileUploadStatusProps } from "./__internal__/file-upload-status";
7
- export interface FileInputProps extends Pick<ValidationProps, "error">, Pick<InputProps, "id" | "name" | "required">, TagProps, MarginProps {
7
+ export interface FileInputProps extends Pick<ValidationProps, "error">, Pick<InputProps, "id" | "name" | "required">, Omit<TagProps, "data-component">, MarginProps {
8
8
  /** Which file format(s) to accept. Will be passed to the underlying HTML input.
9
9
  * See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept */
10
10
  accept?: string;
@@ -141,6 +141,7 @@ const FileInput = exports.FileInput = /*#__PURE__*/_react.default.forwardRef(({
141
141
  onChange: onInputChange,
142
142
  type: "file"
143
143
  }, rest)), /*#__PURE__*/_react.default.createElement(_fileInput.StyledFileInputPresentation, _extends({
144
+ "data-role": "file-input-presentation",
144
145
  isDraggedOver: isDraggedOver,
145
146
  isDraggingFile: isDraggingFile,
146
147
  error: error,
@@ -175,7 +176,6 @@ if (process.env.NODE_ENV !== "production") {
175
176
  FileInput.propTypes = {
176
177
  "accept": _propTypes.default.string,
177
178
  "buttonText": _propTypes.default.string,
178
- "data-component": _propTypes.default.string,
179
179
  "data-element": _propTypes.default.string,
180
180
  "data-role": _propTypes.default.string,
181
181
  "dragAndDropText": _propTypes.default.string,
@@ -88,7 +88,8 @@ const Link = exports.Link = /*#__PURE__*/_react.default.forwardRef(({
88
88
  ...componentProps,
89
89
  ...(placeholderTabIndex && href === undefined && !onClick && {
90
90
  tabIndex: -1
91
- })
91
+ }),
92
+ "data-role": "link-anchor"
92
93
  }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, renderLinkIcon(), /*#__PURE__*/_react.default.createElement(_link.StyledContent, null, isSkipLink ? l.link.skipLinkLabel() : children), renderLinkIcon("right")));
93
94
  };
94
95
  return /*#__PURE__*/_react.default.createElement(_link.StyledLink, _extends({
@@ -53,6 +53,7 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
53
53
  const [submenuItemIds, setSubmenuItemIds] = (0, _react.useState)([]);
54
54
  const [characterString, setCharacterString] = (0, _react.useState)("");
55
55
  const [applyFocusRadius, setApplyFocusRadius] = (0, _react.useState)(false);
56
+ const [applyFocusRadiusToLastItem, setApplyFocusRadiusToLastItem] = (0, _react.useState)(false);
56
57
  const shiftTabPressed = (0, _react.useRef)(false);
57
58
  const focusFirstMenuItemOnOpen = (0, _react.useRef)(false);
58
59
  const numberOfChildren = submenuItemIds.length;
@@ -103,19 +104,34 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
103
104
  // Get the last segment block
104
105
  const lastSegmentBlock = ulElements.pop();
105
106
 
107
+ // Check if the last segment block is a scrollable block
108
+ const isLastSegmentBlockScrollableBlock = Boolean(lastSegmentBlock?.parentElement?.dataset.component === _locators.SCROLLABLE_BLOCK);
109
+
106
110
  // Get all the menu items from the last segment block
107
111
  const segmentBlockMenuItems = Array.from(lastSegmentBlock?.querySelectorAll("[data-component='menu-item']") || /* istanbul ignore next */[]);
108
112
 
109
113
  // Get the last menu item in the last segment block
110
114
  const lastMenuItemInSegmentBlock = segmentBlockMenuItems.pop();
115
+
116
+ // Check to see if the last menu item in the last segment block is visible
117
+ let isLastMenuItemInSegmentBlockVisible = false;
118
+ if (lastMenuItemInSegmentBlock && lastSegmentBlock) {
119
+ isLastMenuItemInSegmentBlockVisible = lastMenuItemInSegmentBlock.getBoundingClientRect().bottom < lastSegmentBlock.getBoundingClientRect().bottom;
120
+ }
121
+
111
122
  // Check if the last item in the segment block is the same as the last MenuItem in the submenu
112
123
  const menuItemsMatch = !!lastMenuItemInSegmentBlock && lastMenuItemInSegmentBlock === lastMenuItem;
124
+
125
+ // Applies the focus radius to the StyledBox of the StyledScrollableBlock
113
126
  setApplyFocusRadius(menuItemsMatch);
127
+
128
+ // Applies border radius to the last item in the segment block
129
+ setApplyFocusRadiusToLastItem(menuItemsMatch && !isLastSegmentBlockScrollableBlock || menuItemsMatch && isLastSegmentBlockScrollableBlock && !isLastMenuItemInSegmentBlockVisible);
114
130
  };
115
131
  if (submenuOpen && submenuRef) {
116
132
  handleBorderRadiusStyling();
117
133
  }
118
- }, [submenuOpen, submenuRef]);
134
+ }, [submenuOpen, submenuRef, numberOfChildren]);
119
135
  (0, _react.useEffect)(() => {
120
136
  if (submenuOpen && onSubmenuOpen) {
121
137
  onSubmenuOpen();
@@ -292,7 +308,8 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
292
308
  menuType: menuType,
293
309
  inFullscreenView: inFullscreenView,
294
310
  ref: setSubmenuRef,
295
- applyFocusRadiusStyling: false
311
+ applyFocusRadiusStyling: false,
312
+ applyFocusRadiusStylingToLastItem: applyFocusRadiusToLastItem
296
313
  }, /*#__PURE__*/_react.default.createElement(_submenu2.default.Provider, {
297
314
  value: {
298
315
  handleKeyDown,
@@ -331,7 +348,8 @@ const Submenu = /*#__PURE__*/_react.default.forwardRef(({
331
348
  menuType: menuType,
332
349
  role: blockIndex === 0 ? "presentation" : "list",
333
350
  maxHeight: submenuMaxHeight,
334
- applyFocusRadiusStyling: applyFocusRadius
351
+ applyFocusRadiusStyling: applyFocusRadius,
352
+ applyFocusRadiusStylingToLastItem: applyFocusRadiusToLastItem
335
353
  }, /*#__PURE__*/_react.default.createElement(_submenu2.default.Provider, {
336
354
  value: {
337
355
  submenuFocusId,
@@ -12,6 +12,7 @@ interface StyledSubmenuProps extends SharedStyleProps, Pick<SubmenuProps, "varia
12
12
  submenuDirection?: string;
13
13
  maxHeight?: string;
14
14
  applyFocusRadiusStyling: boolean;
15
+ applyFocusRadiusStylingToLastItem: boolean;
15
16
  }
16
17
  declare const StyledSubmenuWrapper: import("styled-components").StyledComponent<"div", any, StyledSubmenuWrapperProps, never>;
17
18
  declare const StyledSubmenu: import("styled-components").StyledComponent<"ul", any, StyledSubmenuProps, never>;
@@ -51,7 +51,8 @@ const StyledSubmenu = exports.StyledSubmenu = _styledComponents.default.ul`
51
51
  variant,
52
52
  inFullscreenView,
53
53
  maxHeight,
54
- applyFocusRadiusStyling
54
+ applyFocusRadiusStyling,
55
+ applyFocusRadiusStylingToLastItem
55
56
  }) => (0, _styledComponents.css)`
56
57
  ${!inFullscreenView && menuType && (0, _styledComponents.css)`
57
58
  box-shadow: var(--boxShadow100);
@@ -93,8 +94,8 @@ const StyledSubmenu = exports.StyledSubmenu = _styledComponents.default.ul`
93
94
  border-bottom-left-radius: var(--borderRadius000);
94
95
 
95
96
  :focus {
96
- border-bottom-right-radius: ${applyFocusRadiusStyling ? "var(--borderRadius100)" : "var(--borderRadius000)"};
97
- border-bottom-left-radius: ${applyFocusRadiusStyling ? "var(--borderRadius100)" : "var(--borderRadius000)"};
97
+ border-bottom-right-radius: ${applyFocusRadiusStylingToLastItem ? "var(--borderRadius100)" : "var(--borderRadius000)"};
98
+ border-bottom-left-radius: ${applyFocusRadiusStylingToLastItem ? "var(--borderRadius100)" : "var(--borderRadius000)"};
98
99
  }
99
100
  }
100
101
 
@@ -106,7 +107,7 @@ const StyledSubmenu = exports.StyledSubmenu = _styledComponents.default.ul`
106
107
  ${_menu.StyledMenuItem}:last-child ${_link.StyledLink}, ${_menu.StyledMenuItem}:last-child a,
107
108
  ${_menu.StyledMenuItem}:last-child button {
108
109
  border-bottom-right-radius: var(--borderRadius000);
109
- border-bottom-left-radius: ${applyFocusRadiusStyling ? "var(--borderRadius100)" : "var(--borderRadius000)"};
110
+ border-bottom-left-radius: ${applyFocusRadiusStylingToLastItem ? "var(--borderRadius100)" : "var(--borderRadius000)"};
110
111
  }
111
112
  }
112
113
  }
@@ -3,7 +3,7 @@ import { FlexboxProps, LayoutProps, MaxWidthProps, PaddingProps } from "styled-s
3
3
  import { IconType } from "../../icon";
4
4
  import { TagProps } from "../../../__internal__/utils/helpers/tags";
5
5
  export declare type VariantType = "default" | "alternate";
6
- interface MenuItemBaseProps extends TagProps, LayoutProps, FlexboxProps, PaddingProps {
6
+ interface MenuItemBaseProps extends Omit<TagProps, "data-component">, LayoutProps, FlexboxProps, PaddingProps {
7
7
  /** Custom className */
8
8
  className?: string;
9
9
  /** onClick handler */
@@ -38,8 +38,6 @@ interface MenuItemBaseProps extends TagProps, LayoutProps, FlexboxProps, Padding
38
38
  for other MenuItems inside the block
39
39
  */
40
40
  overrideColor?: boolean;
41
- /** @private @ignore */
42
- "data-component"?: string;
43
41
  /** When set the submenu opens by click instead of hover */
44
42
  clickToOpen?: boolean;
45
43
  /** Sets the maxWidth of the MenuItem */
@@ -61,7 +59,7 @@ export interface MenuWithIcon extends MenuItemBaseProps {
61
59
  children?: React.ReactNode;
62
60
  }
63
61
  export declare const MenuItem: {
64
- ({ submenu, children, href, onClick, target, submenuDirection, icon, selected, onKeyDown, variant, showDropdownArrow, ariaLabel, clickToOpen, maxWidth, onSubmenuOpen, onSubmenuClose, overrideColor, rel, as, ...rest }: MenuWithChildren | MenuWithIcon): React.JSX.Element;
62
+ ({ submenu, children, href, onClick, target, submenuDirection, icon, selected, onKeyDown, variant, showDropdownArrow, ariaLabel, clickToOpen, maxWidth, onSubmenuOpen, onSubmenuClose, overrideColor, rel, as, "data-element": dataElement, "data-role": dataRole, ...rest }: MenuWithChildren | MenuWithIcon): React.JSX.Element;
65
63
  displayName: string;
66
64
  };
67
65
  export default MenuItem;
@@ -15,7 +15,6 @@ var _submenu = _interopRequireDefault(require("../__internal__/submenu/submenu.c
15
15
  var _submenu2 = _interopRequireDefault(require("../__internal__/submenu/submenu.context"));
16
16
  var _menu2 = require("../menu.style");
17
17
  var _guid = _interopRequireDefault(require("../../../__internal__/utils/helpers/guid"));
18
- var _tags = _interopRequireDefault(require("../../../__internal__/utils/helpers/tags"));
19
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
19
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
21
20
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -40,6 +39,8 @@ const MenuItem = ({
40
39
  overrideColor,
41
40
  rel,
42
41
  as,
42
+ "data-element": dataElement,
43
+ "data-role": dataRole,
43
44
  ...rest
44
45
  }) => {
45
46
  !(icon || children) ? process.env.NODE_ENV !== "production" ? (0, _invariant.default)(false, "Either prop `icon` must be defined or this node must have `children`.") : (0, _invariant.default)(false) : void 0;
@@ -133,7 +134,10 @@ const MenuItem = ({
133
134
  const asPassiveItem = !(onClick || href);
134
135
  const hasInput = !!inputRef.current;
135
136
  if (submenu) {
136
- return /*#__PURE__*/_react.default.createElement(_menu2.StyledMenuItem, _extends({}, (0, _tags.default)("menu-item", rest), {
137
+ return /*#__PURE__*/_react.default.createElement(_menu2.StyledMenuItem, _extends({
138
+ "data-component": "menu-item",
139
+ "data-element": dataElement,
140
+ "data-role": dataRole,
137
141
  menuType: menuType,
138
142
  title: getTitle(submenu),
139
143
  maxWidth: itemMaxWidth,
@@ -156,7 +160,10 @@ const MenuItem = ({
156
160
  }, elementProps, rest), children));
157
161
  }
158
162
  const paddingProps = (0, _utils.filterStyledSystemPaddingProps)(rest);
159
- return /*#__PURE__*/_react.default.createElement(_menu2.StyledMenuItem, _extends({}, (0, _tags.default)("menu-item", rest), {
163
+ return /*#__PURE__*/_react.default.createElement(_menu2.StyledMenuItem, _extends({
164
+ "data-component": "menu-item",
165
+ "data-element": dataElement,
166
+ "data-role": dataRole,
160
167
  menuType: menuType,
161
168
  inSubmenu: !!handleSubmenuKeyDown,
162
169
  title: getTitle(children),
@@ -56,6 +56,7 @@ const StepFlow = exports.StepFlow = /*#__PURE__*/(0, _react.forwardRef)(({
56
56
  return /*#__PURE__*/_react.default.createElement(_stepFlow.StyledProgressIndicator, {
57
57
  key: step,
58
58
  "aria-hidden": "true",
59
+ "data-role": "progress-indicator",
59
60
  "data-element": "progress-indicator",
60
61
  isCompleted: step < validatedCurrentStep,
61
62
  isInProgress: step === validatedCurrentStep,
@@ -77,6 +78,7 @@ const StepFlow = exports.StepFlow = /*#__PURE__*/(0, _react.forwardRef)(({
77
78
  }
78
79
  }), []);
79
80
  const stepFlowTitle = /*#__PURE__*/_react.default.createElement(_stepFlow.StyledTitleFocusWrapper, {
81
+ "data-role": "title-text-wrapper",
80
82
  "data-element": "title-text-wrapper",
81
83
  tabIndex: -1,
82
84
  ref: titleRef
@@ -111,7 +113,8 @@ const StepFlow = exports.StepFlow = /*#__PURE__*/(0, _react.forwardRef)(({
111
113
  "data-element": "category-text",
112
114
  "aria-hidden": "true"
113
115
  }, category), stepFlowTitle) : stepFlowTitle, showCloseIcon ? closeIcon : null), showProgressIndicator ? /*#__PURE__*/_react.default.createElement(_stepFlow.StyledStepLabelAndProgress, null, stepFlowLabel, /*#__PURE__*/_react.default.createElement(_stepFlow.StyledProgressIndicatorBar, {
114
- "data-element": "progress-indicator-bar"
116
+ "data-element": "progress-indicator-bar",
117
+ "data-role": "progress-indicator-bar"
115
118
  }, progressIndicators)) : stepFlowLabel);
116
119
  });
117
120
  if (process.env.NODE_ENV !== "production") {
@@ -117,7 +117,7 @@ const StyledToast = exports.StyledToast = _styledComponents.default.div`
117
117
 
118
118
  box-shadow: ${boxShadow};
119
119
  line-height: 22px;
120
- margin-top: ${alignY === "top" && isNotice || alignY === "center" ? "0" : "30px"};
120
+ margin-top: ${isNotice || alignY === "center" || alignY === "bottom" ? "0" : "30px"};
121
121
  margin-bottom: ${alignY === "bottom" && !isNotice ? "30px" : "0"};
122
122
  max-width: ${!maxWidth ? "300px" : maxWidth};
123
123
  position: relative;
@@ -185,6 +185,7 @@ const Tooltip = exports.Tooltip = /*#__PURE__*/_react.default.forwardRef(({
185
185
  type: type,
186
186
  ref: arrowReference,
187
187
  "data-element": "tooltip-pointer",
188
+ "data-role": "tooltip-pointer",
188
189
  bgColor: bgColor,
189
190
  style: arrowStyle
190
191
  }), message)) : null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "135.1.0",
3
+ "version": "135.1.2",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "files": [
6
6
  "lib",