carbon-react 140.1.0 → 140.2.0

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 (43) hide show
  1. package/esm/__internal__/character-count/character-count.component.d.ts +2 -1
  2. package/esm/__internal__/character-count/character-count.component.js +3 -1
  3. package/esm/components/anchor-navigation/anchor-navigation.component.d.ts +3 -2
  4. package/esm/components/anchor-navigation/anchor-navigation.component.js +10 -3
  5. package/esm/components/draggable/__internal__/drop-target.component.d.ts +1 -1
  6. package/esm/components/draggable/__internal__/drop-target.component.js +6 -1
  7. package/esm/components/draggable/draggable-container.component.d.ts +3 -2
  8. package/esm/components/draggable/draggable-container.component.js +8 -0
  9. package/esm/components/draggable/draggable-item/draggable-item.component.js +1 -0
  10. package/esm/components/heading/heading.component.js +4 -1
  11. package/esm/components/portrait/portrait.component.d.ts +1 -1
  12. package/esm/components/portrait/portrait.component.js +7 -0
  13. package/esm/components/profile/profile.component.d.ts +1 -1
  14. package/esm/components/profile/profile.component.js +1 -0
  15. package/esm/components/settings-row/settings-row.component.js +2 -1
  16. package/esm/components/text-editor/text-editor.component.js +1 -1
  17. package/esm/components/textarea/textarea.component.js +21 -2
  18. package/esm/components/textbox/textbox.component.js +19 -4
  19. package/esm/components/vertical-divider/vertical-divider.component.js +1 -1
  20. package/esm/hooks/__internal__/useCharacterCount/useCharacterCount.d.ts +1 -1
  21. package/esm/hooks/__internal__/useCharacterCount/useCharacterCount.js +2 -1
  22. package/lib/__internal__/character-count/character-count.component.d.ts +2 -1
  23. package/lib/__internal__/character-count/character-count.component.js +3 -1
  24. package/lib/components/anchor-navigation/anchor-navigation.component.d.ts +3 -2
  25. package/lib/components/anchor-navigation/anchor-navigation.component.js +10 -3
  26. package/lib/components/draggable/__internal__/drop-target.component.d.ts +1 -1
  27. package/lib/components/draggable/__internal__/drop-target.component.js +6 -1
  28. package/lib/components/draggable/draggable-container.component.d.ts +3 -2
  29. package/lib/components/draggable/draggable-container.component.js +8 -0
  30. package/lib/components/draggable/draggable-item/draggable-item.component.js +1 -0
  31. package/lib/components/heading/heading.component.js +4 -1
  32. package/lib/components/portrait/portrait.component.d.ts +1 -1
  33. package/lib/components/portrait/portrait.component.js +7 -0
  34. package/lib/components/profile/profile.component.d.ts +1 -1
  35. package/lib/components/profile/profile.component.js +1 -0
  36. package/lib/components/settings-row/settings-row.component.js +2 -1
  37. package/lib/components/text-editor/text-editor.component.js +1 -1
  38. package/lib/components/textarea/textarea.component.js +20 -1
  39. package/lib/components/textbox/textbox.component.js +18 -3
  40. package/lib/components/vertical-divider/vertical-divider.component.js +2 -2
  41. package/lib/hooks/__internal__/useCharacterCount/useCharacterCount.d.ts +1 -1
  42. package/lib/hooks/__internal__/useCharacterCount/useCharacterCount.js +2 -1
  43. package/package.json +4 -2
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  interface CharacterCountProps {
3
+ ariaLive?: "off" | "polite";
3
4
  value: number;
4
5
  debouncedValue?: number;
5
6
  limit: number;
@@ -7,5 +8,5 @@ interface CharacterCountProps {
7
8
  isOverLimit: boolean;
8
9
  visuallyHiddenHintId?: string;
9
10
  }
10
- declare const CharacterCount: ({ value, debouncedValue, limit, isDebouncedOverLimit, isOverLimit, visuallyHiddenHintId, }: CharacterCountProps) => React.JSX.Element;
11
+ declare const CharacterCount: ({ ariaLive, value, debouncedValue, limit, isDebouncedOverLimit, isOverLimit, visuallyHiddenHintId, }: CharacterCountProps) => React.JSX.Element;
11
12
  export default CharacterCount;
@@ -3,6 +3,7 @@ import PropTypes from "prop-types";
3
3
  import { StyledCharacterCountWrapper, StyledCharacterCount, VisuallyHiddenCharacterCount, VisuallyHiddenHint } from "./character-count.style";
4
4
  import useLocale from "../../hooks/__internal__/useLocale";
5
5
  const CharacterCount = ({
6
+ ariaLive = "off",
6
7
  value,
7
8
  debouncedValue = value,
8
9
  limit,
@@ -25,7 +26,8 @@ const CharacterCount = ({
25
26
  "data-element": "character-count"
26
27
  }, !isOverLimit ? l.characterCount.charactersLeft(limitMinusValue, getFormatNumber(limitMinusValue, l.locale())) : l.characterCount.tooManyCharacters(valueMinusLimit, getFormatNumber(valueMinusLimit, l.locale()))), /*#__PURE__*/React.createElement(VisuallyHiddenCharacterCount, {
27
28
  "data-element": "visually-hidden-character-count",
28
- "aria-live": "polite"
29
+ "data-role": "visually-hidden-character-count",
30
+ "aria-live": ariaLive
29
31
  }, !isDebouncedOverLimit ? l.characterCount.charactersLeft(debouncedLimitMinusValue, getFormatNumber(debouncedLimitMinusValue, l.locale())) : l.characterCount.tooManyCharacters(debouncedValueMinusLimit, getFormatNumber(debouncedValueMinusLimit, l.locale()))));
30
32
  };
31
33
  export default CharacterCount;
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
- export interface AnchorNavigationProps {
2
+ import { TagProps } from "../../__internal__/utils/helpers/tags";
3
+ export interface AnchorNavigationProps extends Omit<TagProps, "data-component"> {
3
4
  /** Child elements */
4
5
  children?: React.ReactNode;
5
6
  /** The AnchorNavigationItems components to be rendered in the sticky navigation.
@@ -8,7 +9,7 @@ export interface AnchorNavigationProps {
8
9
  stickyNavigation?: React.ReactNode;
9
10
  }
10
11
  declare const AnchorNavigation: {
11
- ({ children, stickyNavigation, }: AnchorNavigationProps): JSX.Element;
12
+ ({ children, stickyNavigation, "data-element": dataElement, "data-role": dataRole, }: AnchorNavigationProps): JSX.Element;
12
13
  displayName: string;
13
14
  };
14
15
  export default AnchorNavigation;
@@ -11,7 +11,9 @@ const SECTION_VISIBILITY_OFFSET = 200;
11
11
  const SCROLL_THROTTLE = 100;
12
12
  const AnchorNavigation = ({
13
13
  children,
14
- stickyNavigation
14
+ stickyNavigation,
15
+ "data-element": dataElement,
16
+ "data-role": dataRole
15
17
  }) => {
16
18
  !isFragment(stickyNavigation) ? process.env.NODE_ENV !== "production" ? invariant(false, "`stickyNavigation` prop in `AnchorNavigation` should be a React Fragment.") : invariant(false) : void 0;
17
19
  const hasCorrectItemStructure = useMemo(() => {
@@ -45,13 +47,14 @@ const AnchorNavigation = ({
45
47
  setSelectedIndex(indexOfSmallestNegativeTopOffset);
46
48
  }, []);
47
49
  const scrollHandler = useMemo(() => throttle(() => {
50
+ /* istanbul ignore else */
48
51
  if (isUserScroll.current) {
49
52
  setSelectedAnchorBasedOnScroll();
50
53
  } else {
51
54
  if (isUserScrollTimer.current !== undefined) {
52
55
  window.clearTimeout(isUserScrollTimer.current);
53
56
  }
54
- isUserScrollTimer.current = setTimeout( /* istanbul ignore next */() => {
57
+ isUserScrollTimer.current = setTimeout(() => {
55
58
  isUserScroll.current = true;
56
59
  }, SCROLL_THROTTLE + 50);
57
60
  }
@@ -106,7 +109,9 @@ const AnchorNavigation = ({
106
109
  };
107
110
  return /*#__PURE__*/React.createElement(StyledAnchorNavigation, {
108
111
  ref: contentRef,
109
- "data-component": "anchor-navigation"
112
+ "data-component": "anchor-navigation",
113
+ "data-element": dataElement,
114
+ "data-role": dataRole
110
115
  }, /*#__PURE__*/React.createElement(StyledNavigation, {
111
116
  ref: navigationRef,
112
117
  "data-element": "anchor-sticky-navigation"
@@ -121,6 +126,8 @@ const AnchorNavigation = ({
121
126
  if (process.env.NODE_ENV !== "production") {
122
127
  AnchorNavigation.propTypes = {
123
128
  "children": PropTypes.node,
129
+ "data-element": PropTypes.string,
130
+ "data-role": PropTypes.string,
124
131
  "stickyNavigation": PropTypes.node
125
132
  };
126
133
  }
@@ -4,5 +4,5 @@ interface DropTargetProps extends Omit<DraggableContainerProps, "getOrder"> {
4
4
  children?: React.ReactNode;
5
5
  getOrder: (movedItemId?: string | number | undefined) => void;
6
6
  }
7
- declare const DropTarget: ({ children, getOrder, ...rest }: DropTargetProps) => React.JSX.Element;
7
+ declare const DropTarget: ({ "data-element": dataElement, "data-role": dataRole, children, getOrder, ...rest }: DropTargetProps) => React.JSX.Element;
8
8
  export default DropTarget;
@@ -4,6 +4,8 @@ import PropTypes from "prop-types";
4
4
  import { useDrop } from "react-dnd";
5
5
  import { StyledDraggableContainer } from "../draggable-item/draggable-item.style";
6
6
  const DropTarget = ({
7
+ "data-element": dataElement,
8
+ "data-role": dataRole,
7
9
  children,
8
10
  getOrder,
9
11
  ...rest
@@ -18,7 +20,10 @@ const DropTarget = ({
18
20
  }
19
21
  });
20
22
  return /*#__PURE__*/React.createElement(StyledDraggableContainer, _extends({
21
- ref: drop
23
+ ref: drop,
24
+ "data-component": "draggable-container",
25
+ "data-element": dataElement,
26
+ "data-role": dataRole
22
27
  }, rest), children);
23
28
  };
24
29
  export default DropTarget;
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import { MarginProps } from "styled-system";
3
- export interface DraggableContainerProps extends MarginProps {
3
+ import { TagProps } from "../../__internal__/utils/helpers/tags";
4
+ export interface DraggableContainerProps extends MarginProps, Omit<TagProps, "data-component"> {
4
5
  /** Callback fired when order is changed */
5
6
  getOrder?: (draggableItemIds?: (string | number | undefined)[], movedItemId?: string | number | undefined) => void;
6
7
  /**
@@ -11,7 +12,7 @@ export interface DraggableContainerProps extends MarginProps {
11
12
  children?: React.ReactNode;
12
13
  }
13
14
  declare const DraggableContainer: {
14
- ({ children, getOrder, ...rest }: DraggableContainerProps): JSX.Element;
15
+ ({ "data-element": dataElement, "data-role": dataRole, children, getOrder, ...rest }: DraggableContainerProps): JSX.Element;
15
16
  displayName: string;
16
17
  };
17
18
  export default DraggableContainer;
@@ -8,6 +8,8 @@ import { filterStyledSystemMarginProps } from "../../style/utils";
8
8
  import DraggableItem from "./draggable-item/draggable-item.component";
9
9
  import DropTarget from "./__internal__/drop-target.component";
10
10
  const DraggableContainer = ({
11
+ "data-element": dataElement,
12
+ "data-role": dataRole = "draggable-container",
11
13
  children,
12
14
  getOrder,
13
15
  ...rest
@@ -39,6 +41,8 @@ const DraggableContainer = ({
39
41
  draggableItem,
40
42
  index
41
43
  } = findItem(id);
44
+
45
+ // istanbul ignore if
42
46
  if (!draggableItem) return;
43
47
  const copyOfDraggableItems = [...draggableItems];
44
48
  copyOfDraggableItems.splice(index, 1);
@@ -56,6 +60,8 @@ const DraggableContainer = ({
56
60
  return /*#__PURE__*/React.createElement(DndProvider, {
57
61
  backend: HTML5Backend
58
62
  }, /*#__PURE__*/React.createElement(DropTarget, _extends({
63
+ "data-element": dataElement,
64
+ "data-role": dataRole,
59
65
  getOrder: getItemsId
60
66
  }, marginProps), draggableItems.map(item => {
61
67
  return /*#__PURE__*/React.isValidElement(item) && /*#__PURE__*/React.cloneElement(item, {
@@ -68,6 +74,8 @@ const DraggableContainer = ({
68
74
  if (process.env.NODE_ENV !== "production") {
69
75
  DraggableContainer.propTypes = {
70
76
  "children": PropTypes.node,
77
+ "data-element": PropTypes.string,
78
+ "data-role": PropTypes.string,
71
79
  "getOrder": PropTypes.func,
72
80
  "m": PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.oneOf([null]), PropTypes.number, PropTypes.shape({
73
81
  "__@toStringTag": PropTypes.string.isRequired,
@@ -57,6 +57,7 @@ const DraggableItem = ({
57
57
  const paddingProps = filterStyledSystemPaddingProps(rest);
58
58
  return /*#__PURE__*/React.createElement(StyledDraggableItem, _extends({
59
59
  "data-element": "draggable",
60
+ "data-role": "draggable-item",
60
61
  isDragging: isDragging,
61
62
  ref: node => drag(drop(node)),
62
63
  py: py
@@ -49,6 +49,7 @@ export const Heading = ({
49
49
  const getSubheader = () => {
50
50
  return /*#__PURE__*/React.createElement(StyledSubHeader, {
51
51
  "data-element": "subtitle",
52
+ "data-role": "subtitle",
52
53
  id: subtitleId,
53
54
  hasBackLink: !!backLink,
54
55
  hasSeparator: separator
@@ -74,7 +75,9 @@ export const Heading = ({
74
75
  variant: headingType,
75
76
  "data-element": "title",
76
77
  id: titleId
77
- }, title), (help || helpLink) && getHelp(), pills && getPills()), separator && /*#__PURE__*/React.createElement(StyledSeparator, null), subheader && getSubheader()), divider && /*#__PURE__*/React.createElement(StyledDivider, {
78
+ }, title), (help || helpLink) && getHelp(), pills && getPills()), separator && /*#__PURE__*/React.createElement(StyledSeparator, {
79
+ "data-role": "heading-separator"
80
+ }), subheader && getSubheader()), divider && /*#__PURE__*/React.createElement(StyledDivider, {
78
81
  "data-element": "divider"
79
82
  }), children) : null;
80
83
  };
@@ -4,7 +4,7 @@ import { IconType } from "../icon";
4
4
  export declare type PortraitShapes = "circle" | "square";
5
5
  export declare type PortraitSizes = "XS" | "S" | "M" | "ML" | "L" | "XL" | "XXL";
6
6
  export interface PortraitProps extends MarginProps {
7
- /** An email address registered with Gravatar. */
7
+ /** (Deprecated) An email address registered with Gravatar. */
8
8
  gravatar?: string;
9
9
  /** A custom image URL. */
10
10
  src?: string;
@@ -3,12 +3,14 @@ import React, { useEffect, useState, useContext } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import MD5 from "crypto-js/md5";
5
5
  import invariant from "invariant";
6
+ import Logger from "../../__internal__/utils/logger";
6
7
  import Tooltip from "../tooltip";
7
8
  import tagComponent from "../../__internal__/utils/helpers/tags/tags";
8
9
  import { PORTRAIT_SIZE_PARAMS } from "./portrait.config";
9
10
  import { StyledCustomImg, StyledIcon, StyledPortraitContainer, StyledPortraitInitials, StyledPortraitGravatar } from "./portrait.style";
10
11
  import { filterStyledSystemMarginProps } from "../../style/utils";
11
12
  import RoundedCornersOptOutContext from "../carbon-provider/__internal__/new-validation.context";
13
+ let deprecatedGravatarWarnTriggered = false;
12
14
  const Portrait = ({
13
15
  alt,
14
16
  name,
@@ -36,6 +38,10 @@ const Portrait = ({
36
38
  } = useContext(RoundedCornersOptOutContext);
37
39
  const defaultShape = roundedCornersOptOut ? "square" : "circle";
38
40
  !!(src && gravatar) ? process.env.NODE_ENV !== "production" ? invariant(false, "The `src` prop cannot be used in conjunction with the `gravatar` prop." + " Please use one or the other.") : invariant(false) : void 0;
41
+ const logGravatarDeprecationWarning = () => {
42
+ deprecatedGravatarWarnTriggered = true;
43
+ Logger.deprecate("The `gravatar` prop has been deprecated and will soon be removed.");
44
+ };
39
45
  useEffect(() => {
40
46
  setExternalError(false);
41
47
  }, [gravatar, src]);
@@ -74,6 +80,7 @@ const Portrait = ({
74
80
  portrait = /*#__PURE__*/React.createElement(StyledPortraitGravatar, {
75
81
  src: gravatarSrc(),
76
82
  alt: alt || name || "",
83
+ onLoad: () => !deprecatedGravatarWarnTriggered && logGravatarDeprecationWarning(),
77
84
  onError: () => setExternalError(true)
78
85
  });
79
86
  }
@@ -10,7 +10,7 @@ export interface ProfileProps extends MarginProps {
10
10
  alt?: string;
11
11
  /** Define the name to display. */
12
12
  name?: string;
13
- /** Define the email to use (will check Gravatar for image). */
13
+ /** Define the email to use. */
14
14
  email?: string;
15
15
  /** Define read-only text to display. */
16
16
  text?: string;
@@ -60,6 +60,7 @@ export const Profile = ({
60
60
  }, name), email && /*#__PURE__*/React.createElement(ProfileEmailStyle, {
61
61
  href: `mailto: ${email}`,
62
62
  size: size,
63
+ "data-role": "email-link",
63
64
  darkBackground: darkBackground,
64
65
  "data-element": "email"
65
66
  }, email), text && /*#__PURE__*/React.createElement(ProfileTextStyle, {
@@ -26,7 +26,8 @@ export const SettingsRow = ({
26
26
  };
27
27
  return /*#__PURE__*/React.createElement(StyledSettingsRow, _extends({
28
28
  className: className,
29
- hasDivider: divider
29
+ hasDivider: divider,
30
+ "data-role": "settings-row"
30
31
  }, tagComponent("settings-row", rest), {
31
32
  m: 0
32
33
  }, filterStyledSystemMarginProps(rest)), /*#__PURE__*/React.createElement(StyledSettingsRowHeader, null, heading()), /*#__PURE__*/React.createElement(StyledSettingsRowInput, null, children));
@@ -66,7 +66,7 @@ const TextEditor = /*#__PURE__*/React.forwardRef(({
66
66
  info,
67
67
  label: labelText
68
68
  });
69
- const [characterCount, visuallyHiddenHintId] = useCharacterCount(getContent(value).getPlainText(""), characterLimit);
69
+ const [characterCount, visuallyHiddenHintId] = useCharacterCount(getContent(value).getPlainText(""), characterLimit, isFocused ? "polite" : "off");
70
70
  const combinedAriaDescribedBy = [ariaDescribedBy, inputHint ? inputHintId.current : undefined, visuallyHiddenHintId].filter(Boolean).join(" ");
71
71
  if (rows && (typeof rows !== "number" || rows < 2)) {
72
72
  // eslint-disable-next-line no-console
@@ -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, { useRef, useEffect, useContext, useCallback } from "react";
2
+ import React, { useRef, useEffect, useContext, useCallback, useState } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { InputPresentation } from "../../__internal__/input";
5
5
  import FormField from "../../__internal__/form-field";
@@ -28,6 +28,8 @@ const Textarea = /*#__PURE__*/React.forwardRef(({
28
28
  children,
29
29
  characterLimit,
30
30
  onChange,
31
+ onFocus,
32
+ onBlur,
31
33
  disabled = false,
32
34
  labelInline,
33
35
  labelAlign,
@@ -79,6 +81,21 @@ const Textarea = /*#__PURE__*/React.forwardRef(({
79
81
  ref(inputElement);
80
82
  }
81
83
  }, [ref]);
84
+ const [characterCountAriaLive, setCharacterCountAriaLive] = useState("off");
85
+
86
+ // This block of code has been covered in a Playwright test.
87
+ // istanbul ignore next
88
+ const handleFocus = ev => {
89
+ if (characterLimit) setCharacterCountAriaLive("polite");
90
+ onFocus?.(ev);
91
+ };
92
+
93
+ // This block of code has been covered in a Playwright test.
94
+ // istanbul ignore next
95
+ const handleBlur = ev => {
96
+ if (characterLimit) setCharacterCountAriaLive("off");
97
+ onBlur?.(ev);
98
+ };
82
99
  if (!deprecateUncontrolledWarnTriggered && !onChange) {
83
100
  deprecateUncontrolledWarnTriggered = true;
84
101
  Logger.deprecate("Uncontrolled behaviour in `Textarea` is deprecated and support will soon be removed. Please make sure all your inputs are controlled.");
@@ -120,7 +137,7 @@ const Textarea = /*#__PURE__*/React.forwardRef(({
120
137
  label,
121
138
  fieldHelp
122
139
  });
123
- const [characterCount, visuallyHiddenHintId] = useCharacterCount(value, characterLimit);
140
+ const [characterCount, visuallyHiddenHintId] = useCharacterCount(value, characterLimit, characterCountAriaLive);
124
141
  useEffect(() => {
125
142
  if (rows) {
126
143
  minHeight.current = internalRef?.current?.scrollHeight || 0;
@@ -169,6 +186,8 @@ const Textarea = /*#__PURE__*/React.forwardRef(({
169
186
  value: value,
170
187
  ref: callbackRef,
171
188
  onChange: onChange,
189
+ onFocus: handleFocus,
190
+ onBlur: handleBlur,
172
191
  disabled: disabled,
173
192
  readOnly: readOnly,
174
193
  placeholder: disabled ? "" : placeholder,
@@ -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, { useContext, useRef } from "react";
2
+ import React, { useContext, useRef, useState } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { filterStyledSystemMarginProps } from "../../style/utils";
5
5
  import { Input, InputPresentation } from "../../__internal__/input";
@@ -78,7 +78,22 @@ const Textbox = /*#__PURE__*/React.forwardRef(({
78
78
  }, ref) => {
79
79
  const characterCountValue = typeof value === "string" ? value : "";
80
80
  const [uniqueId, uniqueName] = useUniqueId(id, name);
81
- const [characterCount, visuallyHiddenHintId] = useCharacterCount(characterCountValue, characterLimit);
81
+ const [characterCountAriaLive, setCharacterCountAriaLive] = useState("off");
82
+
83
+ // This block of code has been covered in a Playwright test.
84
+ // istanbul ignore next
85
+ const handleFocus = ev => {
86
+ if (characterLimit) setCharacterCountAriaLive("polite");
87
+ onFocus?.(ev);
88
+ };
89
+
90
+ // This block of code has been covered in a Playwright test.
91
+ // istanbul ignore next
92
+ const handleBlur = ev => {
93
+ if (characterLimit) setCharacterCountAriaLive("off");
94
+ onBlur?.(ev);
95
+ };
96
+ const [characterCount, visuallyHiddenHintId] = useCharacterCount(characterCountValue, characterLimit, characterCountAriaLive);
82
97
  const {
83
98
  validationRedesignOptIn
84
99
  } = useContext(NewValidationContext);
@@ -137,11 +152,11 @@ const Textbox = /*#__PURE__*/React.forwardRef(({
137
152
  id: uniqueId,
138
153
  ref: ref,
139
154
  name: uniqueName,
140
- onBlur: onBlur,
155
+ onBlur: handleBlur,
141
156
  onChange: onChange,
142
157
  onChangeDeferred: onChangeDeferred,
143
158
  onClick: disabled || readOnly ? undefined : onClick,
144
- onFocus: onFocus,
159
+ onFocus: handleFocus,
145
160
  onMouseDown: disabled || readOnly ? undefined : onMouseDown,
146
161
  placeholder: disabled || readOnly ? "" : placeholder,
147
162
  readOnly: readOnly,
@@ -1,7 +1,7 @@
1
1
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
2
  import React, { useContext } from "react";
3
3
  import PropTypes from "prop-types";
4
- import { MenuContext } from "../menu/menu.component";
4
+ import MenuContext from "../menu/__internal__/menu.context";
5
5
  import { StyledVerticalWrapper, StyledDivider } from "./vertical-divider.style";
6
6
  const VerticalDivider = ({
7
7
  h,
@@ -1,2 +1,2 @@
1
- declare const useCharacterCount: (value?: string, characterLimit?: number) => [JSX.Element | null, string | undefined];
1
+ declare const useCharacterCount: (value?: string, characterLimit?: number, characterCountAriaLive?: "off" | "polite") => [JSX.Element | null, string | undefined];
2
2
  export default useCharacterCount;
@@ -2,7 +2,7 @@ import React, { useMemo, useRef, useEffect, useState } from "react";
2
2
  import CharacterCount from "../../../__internal__/character-count";
3
3
  import guid from "../../../__internal__/utils/helpers/guid";
4
4
  import useDebounce from "../useDebounce";
5
- const useCharacterCount = (value = "", characterLimit) => {
5
+ const useCharacterCount = (value = "", characterLimit, characterCountAriaLive) => {
6
6
  const isCharacterLimitValid = typeof characterLimit === "number" && !Number.isNaN(characterLimit);
7
7
  const [debouncedValue, setDebouncedValue] = useState(value);
8
8
  const debounceWaitTime = 2000;
@@ -28,6 +28,7 @@ const useCharacterCount = (value = "", characterLimit) => {
28
28
  return false;
29
29
  }, [debouncedValue, characterLimit, isCharacterLimitValid]);
30
30
  return [isCharacterLimitValid ? /*#__PURE__*/React.createElement(CharacterCount, {
31
+ ariaLive: characterCountAriaLive,
31
32
  isOverLimit: isOverLimit,
32
33
  isDebouncedOverLimit: isDebouncedOverLimit,
33
34
  value: value.length,
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  interface CharacterCountProps {
3
+ ariaLive?: "off" | "polite";
3
4
  value: number;
4
5
  debouncedValue?: number;
5
6
  limit: number;
@@ -7,5 +8,5 @@ interface CharacterCountProps {
7
8
  isOverLimit: boolean;
8
9
  visuallyHiddenHintId?: string;
9
10
  }
10
- declare const CharacterCount: ({ value, debouncedValue, limit, isDebouncedOverLimit, isOverLimit, visuallyHiddenHintId, }: CharacterCountProps) => React.JSX.Element;
11
+ declare const CharacterCount: ({ ariaLive, value, debouncedValue, limit, isDebouncedOverLimit, isOverLimit, visuallyHiddenHintId, }: CharacterCountProps) => React.JSX.Element;
11
12
  export default CharacterCount;
@@ -10,6 +10,7 @@ var _characterCount = require("./character-count.style");
10
10
  var _useLocale = _interopRequireDefault(require("../../hooks/__internal__/useLocale"));
11
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
12
  const CharacterCount = ({
13
+ ariaLive = "off",
13
14
  value,
14
15
  debouncedValue = value,
15
16
  limit,
@@ -32,7 +33,8 @@ const CharacterCount = ({
32
33
  "data-element": "character-count"
33
34
  }, !isOverLimit ? l.characterCount.charactersLeft(limitMinusValue, getFormatNumber(limitMinusValue, l.locale())) : l.characterCount.tooManyCharacters(valueMinusLimit, getFormatNumber(valueMinusLimit, l.locale()))), /*#__PURE__*/_react.default.createElement(_characterCount.VisuallyHiddenCharacterCount, {
34
35
  "data-element": "visually-hidden-character-count",
35
- "aria-live": "polite"
36
+ "data-role": "visually-hidden-character-count",
37
+ "aria-live": ariaLive
36
38
  }, !isDebouncedOverLimit ? l.characterCount.charactersLeft(debouncedLimitMinusValue, getFormatNumber(debouncedLimitMinusValue, l.locale())) : l.characterCount.tooManyCharacters(debouncedValueMinusLimit, getFormatNumber(debouncedValueMinusLimit, l.locale()))));
37
39
  };
38
40
  var _default = exports.default = CharacterCount;
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
- export interface AnchorNavigationProps {
2
+ import { TagProps } from "../../__internal__/utils/helpers/tags";
3
+ export interface AnchorNavigationProps extends Omit<TagProps, "data-component"> {
3
4
  /** Child elements */
4
5
  children?: React.ReactNode;
5
6
  /** The AnchorNavigationItems components to be rendered in the sticky navigation.
@@ -8,7 +9,7 @@ export interface AnchorNavigationProps {
8
9
  stickyNavigation?: React.ReactNode;
9
10
  }
10
11
  declare const AnchorNavigation: {
11
- ({ children, stickyNavigation, }: AnchorNavigationProps): JSX.Element;
12
+ ({ children, stickyNavigation, "data-element": dataElement, "data-role": dataRole, }: AnchorNavigationProps): JSX.Element;
12
13
  displayName: string;
13
14
  };
14
15
  export default AnchorNavigation;
@@ -20,7 +20,9 @@ const SECTION_VISIBILITY_OFFSET = 200;
20
20
  const SCROLL_THROTTLE = 100;
21
21
  const AnchorNavigation = ({
22
22
  children,
23
- stickyNavigation
23
+ stickyNavigation,
24
+ "data-element": dataElement,
25
+ "data-role": dataRole
24
26
  }) => {
25
27
  !(0, _reactIs.isFragment)(stickyNavigation) ? process.env.NODE_ENV !== "production" ? (0, _invariant.default)(false, "`stickyNavigation` prop in `AnchorNavigation` should be a React Fragment.") : (0, _invariant.default)(false) : void 0;
26
28
  const hasCorrectItemStructure = (0, _react.useMemo)(() => {
@@ -54,13 +56,14 @@ const AnchorNavigation = ({
54
56
  setSelectedIndex(indexOfSmallestNegativeTopOffset);
55
57
  }, []);
56
58
  const scrollHandler = (0, _react.useMemo)(() => (0, _throttle.default)(() => {
59
+ /* istanbul ignore else */
57
60
  if (isUserScroll.current) {
58
61
  setSelectedAnchorBasedOnScroll();
59
62
  } else {
60
63
  if (isUserScrollTimer.current !== undefined) {
61
64
  window.clearTimeout(isUserScrollTimer.current);
62
65
  }
63
- isUserScrollTimer.current = setTimeout( /* istanbul ignore next */() => {
66
+ isUserScrollTimer.current = setTimeout(() => {
64
67
  isUserScroll.current = true;
65
68
  }, SCROLL_THROTTLE + 50);
66
69
  }
@@ -115,7 +118,9 @@ const AnchorNavigation = ({
115
118
  };
116
119
  return /*#__PURE__*/_react.default.createElement(_anchorNavigation.StyledAnchorNavigation, {
117
120
  ref: contentRef,
118
- "data-component": "anchor-navigation"
121
+ "data-component": "anchor-navigation",
122
+ "data-element": dataElement,
123
+ "data-role": dataRole
119
124
  }, /*#__PURE__*/_react.default.createElement(_anchorNavigation.StyledNavigation, {
120
125
  ref: navigationRef,
121
126
  "data-element": "anchor-sticky-navigation"
@@ -130,6 +135,8 @@ const AnchorNavigation = ({
130
135
  if (process.env.NODE_ENV !== "production") {
131
136
  AnchorNavigation.propTypes = {
132
137
  "children": _propTypes.default.node,
138
+ "data-element": _propTypes.default.string,
139
+ "data-role": _propTypes.default.string,
133
140
  "stickyNavigation": _propTypes.default.node
134
141
  };
135
142
  }
@@ -4,5 +4,5 @@ interface DropTargetProps extends Omit<DraggableContainerProps, "getOrder"> {
4
4
  children?: React.ReactNode;
5
5
  getOrder: (movedItemId?: string | number | undefined) => void;
6
6
  }
7
- declare const DropTarget: ({ children, getOrder, ...rest }: DropTargetProps) => React.JSX.Element;
7
+ declare const DropTarget: ({ "data-element": dataElement, "data-role": dataRole, children, getOrder, ...rest }: DropTargetProps) => React.JSX.Element;
8
8
  export default DropTarget;
@@ -11,6 +11,8 @@ var _draggableItem = require("../draggable-item/draggable-item.style");
11
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
12
  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); }
13
13
  const DropTarget = ({
14
+ "data-element": dataElement,
15
+ "data-role": dataRole,
14
16
  children,
15
17
  getOrder,
16
18
  ...rest
@@ -25,7 +27,10 @@ const DropTarget = ({
25
27
  }
26
28
  });
27
29
  return /*#__PURE__*/_react.default.createElement(_draggableItem.StyledDraggableContainer, _extends({
28
- ref: drop
30
+ ref: drop,
31
+ "data-component": "draggable-container",
32
+ "data-element": dataElement,
33
+ "data-role": dataRole
29
34
  }, rest), children);
30
35
  };
31
36
  var _default = exports.default = DropTarget;
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import { MarginProps } from "styled-system";
3
- export interface DraggableContainerProps extends MarginProps {
3
+ import { TagProps } from "../../__internal__/utils/helpers/tags";
4
+ export interface DraggableContainerProps extends MarginProps, Omit<TagProps, "data-component"> {
4
5
  /** Callback fired when order is changed */
5
6
  getOrder?: (draggableItemIds?: (string | number | undefined)[], movedItemId?: string | number | undefined) => void;
6
7
  /**
@@ -11,7 +12,7 @@ export interface DraggableContainerProps extends MarginProps {
11
12
  children?: React.ReactNode;
12
13
  }
13
14
  declare const DraggableContainer: {
14
- ({ children, getOrder, ...rest }: DraggableContainerProps): JSX.Element;
15
+ ({ "data-element": dataElement, "data-role": dataRole, children, getOrder, ...rest }: DraggableContainerProps): JSX.Element;
15
16
  displayName: string;
16
17
  };
17
18
  export default DraggableContainer;
@@ -17,6 +17,8 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return
17
17
  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; }
18
18
  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); }
19
19
  const DraggableContainer = ({
20
+ "data-element": dataElement,
21
+ "data-role": dataRole = "draggable-container",
20
22
  children,
21
23
  getOrder,
22
24
  ...rest
@@ -48,6 +50,8 @@ const DraggableContainer = ({
48
50
  draggableItem,
49
51
  index
50
52
  } = findItem(id);
53
+
54
+ // istanbul ignore if
51
55
  if (!draggableItem) return;
52
56
  const copyOfDraggableItems = [...draggableItems];
53
57
  copyOfDraggableItems.splice(index, 1);
@@ -65,6 +69,8 @@ const DraggableContainer = ({
65
69
  return /*#__PURE__*/_react.default.createElement(_reactDnd.DndProvider, {
66
70
  backend: _reactDndHtml5Backend.HTML5Backend
67
71
  }, /*#__PURE__*/_react.default.createElement(_dropTarget.default, _extends({
72
+ "data-element": dataElement,
73
+ "data-role": dataRole,
68
74
  getOrder: getItemsId
69
75
  }, marginProps), draggableItems.map(item => {
70
76
  return /*#__PURE__*/_react.default.isValidElement(item) && /*#__PURE__*/_react.default.cloneElement(item, {
@@ -77,6 +83,8 @@ const DraggableContainer = ({
77
83
  if (process.env.NODE_ENV !== "production") {
78
84
  DraggableContainer.propTypes = {
79
85
  "children": _propTypes.default.node,
86
+ "data-element": _propTypes.default.string,
87
+ "data-role": _propTypes.default.string,
80
88
  "getOrder": _propTypes.default.func,
81
89
  "m": _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.oneOf([null]), _propTypes.default.number, _propTypes.default.shape({
82
90
  "__@toStringTag": _propTypes.default.string.isRequired,
@@ -64,6 +64,7 @@ const DraggableItem = ({
64
64
  const paddingProps = (0, _utils.filterStyledSystemPaddingProps)(rest);
65
65
  return /*#__PURE__*/_react.default.createElement(_draggableItem.StyledDraggableItem, _extends({
66
66
  "data-element": "draggable",
67
+ "data-role": "draggable-item",
67
68
  isDragging: isDragging,
68
69
  ref: node => drag(drop(node)),
69
70
  py: py
@@ -56,6 +56,7 @@ const Heading = ({
56
56
  const getSubheader = () => {
57
57
  return /*#__PURE__*/_react.default.createElement(_heading.StyledSubHeader, {
58
58
  "data-element": "subtitle",
59
+ "data-role": "subtitle",
59
60
  id: subtitleId,
60
61
  hasBackLink: !!backLink,
61
62
  hasSeparator: separator
@@ -81,7 +82,9 @@ const Heading = ({
81
82
  variant: headingType,
82
83
  "data-element": "title",
83
84
  id: titleId
84
- }, title), (help || helpLink) && getHelp(), pills && getPills()), separator && /*#__PURE__*/_react.default.createElement(_heading.StyledSeparator, null), subheader && getSubheader()), divider && /*#__PURE__*/_react.default.createElement(_heading.StyledDivider, {
85
+ }, title), (help || helpLink) && getHelp(), pills && getPills()), separator && /*#__PURE__*/_react.default.createElement(_heading.StyledSeparator, {
86
+ "data-role": "heading-separator"
87
+ }), subheader && getSubheader()), divider && /*#__PURE__*/_react.default.createElement(_heading.StyledDivider, {
85
88
  "data-element": "divider"
86
89
  }), children) : null;
87
90
  };
@@ -4,7 +4,7 @@ import { IconType } from "../icon";
4
4
  export declare type PortraitShapes = "circle" | "square";
5
5
  export declare type PortraitSizes = "XS" | "S" | "M" | "ML" | "L" | "XL" | "XXL";
6
6
  export interface PortraitProps extends MarginProps {
7
- /** An email address registered with Gravatar. */
7
+ /** (Deprecated) An email address registered with Gravatar. */
8
8
  gravatar?: string;
9
9
  /** A custom image URL. */
10
10
  src?: string;
@@ -8,6 +8,7 @@ var _react = _interopRequireWildcard(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _md = _interopRequireDefault(require("crypto-js/md5"));
10
10
  var _invariant = _interopRequireDefault(require("invariant"));
11
+ var _logger = _interopRequireDefault(require("../../__internal__/utils/logger"));
11
12
  var _tooltip = _interopRequireDefault(require("../tooltip"));
12
13
  var _tags = _interopRequireDefault(require("../../__internal__/utils/helpers/tags/tags"));
13
14
  var _portrait = require("./portrait.config");
@@ -18,6 +19,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
18
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); }
19
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; }
20
21
  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); }
22
+ let deprecatedGravatarWarnTriggered = false;
21
23
  const Portrait = ({
22
24
  alt,
23
25
  name,
@@ -45,6 +47,10 @@ const Portrait = ({
45
47
  } = (0, _react.useContext)(_newValidation.default);
46
48
  const defaultShape = roundedCornersOptOut ? "square" : "circle";
47
49
  !!(src && gravatar) ? process.env.NODE_ENV !== "production" ? (0, _invariant.default)(false, "The `src` prop cannot be used in conjunction with the `gravatar` prop." + " Please use one or the other.") : (0, _invariant.default)(false) : void 0;
50
+ const logGravatarDeprecationWarning = () => {
51
+ deprecatedGravatarWarnTriggered = true;
52
+ _logger.default.deprecate("The `gravatar` prop has been deprecated and will soon be removed.");
53
+ };
48
54
  (0, _react.useEffect)(() => {
49
55
  setExternalError(false);
50
56
  }, [gravatar, src]);
@@ -83,6 +89,7 @@ const Portrait = ({
83
89
  portrait = /*#__PURE__*/_react.default.createElement(_portrait2.StyledPortraitGravatar, {
84
90
  src: gravatarSrc(),
85
91
  alt: alt || name || "",
92
+ onLoad: () => !deprecatedGravatarWarnTriggered && logGravatarDeprecationWarning(),
86
93
  onError: () => setExternalError(true)
87
94
  });
88
95
  }
@@ -10,7 +10,7 @@ export interface ProfileProps extends MarginProps {
10
10
  alt?: string;
11
11
  /** Define the name to display. */
12
12
  name?: string;
13
- /** Define the email to use (will check Gravatar for image). */
13
+ /** Define the email to use. */
14
14
  email?: string;
15
15
  /** Define read-only text to display. */
16
16
  text?: string;
@@ -67,6 +67,7 @@ const Profile = ({
67
67
  }, name), email && /*#__PURE__*/_react.default.createElement(_profile.ProfileEmailStyle, {
68
68
  href: `mailto: ${email}`,
69
69
  size: size,
70
+ "data-role": "email-link",
70
71
  darkBackground: darkBackground,
71
72
  "data-element": "email"
72
73
  }, email), text && /*#__PURE__*/_react.default.createElement(_profile.ProfileTextStyle, {
@@ -33,7 +33,8 @@ const SettingsRow = ({
33
33
  };
34
34
  return /*#__PURE__*/_react.default.createElement(_settingsRow.StyledSettingsRow, _extends({
35
35
  className: className,
36
- hasDivider: divider
36
+ hasDivider: divider,
37
+ "data-role": "settings-row"
37
38
  }, (0, _tags.default)("settings-row", rest), {
38
39
  m: 0
39
40
  }, (0, _utils.filterStyledSystemMarginProps)(rest)), /*#__PURE__*/_react.default.createElement(_settingsRow.StyledSettingsRowHeader, null, heading()), /*#__PURE__*/_react.default.createElement(_settingsRow.StyledSettingsRowInput, null, children));
@@ -75,7 +75,7 @@ const TextEditor = exports.TextEditor = /*#__PURE__*/_react.default.forwardRef((
75
75
  info,
76
76
  label: labelText
77
77
  });
78
- const [characterCount, visuallyHiddenHintId] = (0, _useCharacterCount.default)((0, _utils.getContent)(value).getPlainText(""), characterLimit);
78
+ const [characterCount, visuallyHiddenHintId] = (0, _useCharacterCount.default)((0, _utils.getContent)(value).getPlainText(""), characterLimit, isFocused ? "polite" : "off");
79
79
  const combinedAriaDescribedBy = [ariaDescribedBy, inputHint ? inputHintId.current : undefined, visuallyHiddenHintId].filter(Boolean).join(" ");
80
80
  if (rows && (typeof rows !== "number" || rows < 2)) {
81
81
  // eslint-disable-next-line no-console
@@ -37,6 +37,8 @@ const Textarea = exports.OriginalTextarea = exports.Textarea = /*#__PURE__*/_rea
37
37
  children,
38
38
  characterLimit,
39
39
  onChange,
40
+ onFocus,
41
+ onBlur,
40
42
  disabled = false,
41
43
  labelInline,
42
44
  labelAlign,
@@ -88,6 +90,21 @@ const Textarea = exports.OriginalTextarea = exports.Textarea = /*#__PURE__*/_rea
88
90
  ref(inputElement);
89
91
  }
90
92
  }, [ref]);
93
+ const [characterCountAriaLive, setCharacterCountAriaLive] = (0, _react.useState)("off");
94
+
95
+ // This block of code has been covered in a Playwright test.
96
+ // istanbul ignore next
97
+ const handleFocus = ev => {
98
+ if (characterLimit) setCharacterCountAriaLive("polite");
99
+ onFocus?.(ev);
100
+ };
101
+
102
+ // This block of code has been covered in a Playwright test.
103
+ // istanbul ignore next
104
+ const handleBlur = ev => {
105
+ if (characterLimit) setCharacterCountAriaLive("off");
106
+ onBlur?.(ev);
107
+ };
91
108
  if (!deprecateUncontrolledWarnTriggered && !onChange) {
92
109
  deprecateUncontrolledWarnTriggered = true;
93
110
  _logger.default.deprecate("Uncontrolled behaviour in `Textarea` is deprecated and support will soon be removed. Please make sure all your inputs are controlled.");
@@ -129,7 +146,7 @@ const Textarea = exports.OriginalTextarea = exports.Textarea = /*#__PURE__*/_rea
129
146
  label,
130
147
  fieldHelp
131
148
  });
132
- const [characterCount, visuallyHiddenHintId] = (0, _useCharacterCount.default)(value, characterLimit);
149
+ const [characterCount, visuallyHiddenHintId] = (0, _useCharacterCount.default)(value, characterLimit, characterCountAriaLive);
133
150
  (0, _react.useEffect)(() => {
134
151
  if (rows) {
135
152
  minHeight.current = internalRef?.current?.scrollHeight || 0;
@@ -178,6 +195,8 @@ const Textarea = exports.OriginalTextarea = exports.Textarea = /*#__PURE__*/_rea
178
195
  value: value,
179
196
  ref: callbackRef,
180
197
  onChange: onChange,
198
+ onFocus: handleFocus,
199
+ onBlur: handleBlur,
181
200
  disabled: disabled,
182
201
  readOnly: readOnly,
183
202
  placeholder: disabled ? "" : placeholder,
@@ -87,7 +87,22 @@ const Textbox = exports.Textbox = /*#__PURE__*/_react.default.forwardRef(({
87
87
  }, ref) => {
88
88
  const characterCountValue = typeof value === "string" ? value : "";
89
89
  const [uniqueId, uniqueName] = (0, _useUniqueId.default)(id, name);
90
- const [characterCount, visuallyHiddenHintId] = (0, _useCharacterCount.default)(characterCountValue, characterLimit);
90
+ const [characterCountAriaLive, setCharacterCountAriaLive] = (0, _react.useState)("off");
91
+
92
+ // This block of code has been covered in a Playwright test.
93
+ // istanbul ignore next
94
+ const handleFocus = ev => {
95
+ if (characterLimit) setCharacterCountAriaLive("polite");
96
+ onFocus?.(ev);
97
+ };
98
+
99
+ // This block of code has been covered in a Playwright test.
100
+ // istanbul ignore next
101
+ const handleBlur = ev => {
102
+ if (characterLimit) setCharacterCountAriaLive("off");
103
+ onBlur?.(ev);
104
+ };
105
+ const [characterCount, visuallyHiddenHintId] = (0, _useCharacterCount.default)(characterCountValue, characterLimit, characterCountAriaLive);
91
106
  const {
92
107
  validationRedesignOptIn
93
108
  } = (0, _react.useContext)(_newValidation.default);
@@ -146,11 +161,11 @@ const Textbox = exports.Textbox = /*#__PURE__*/_react.default.forwardRef(({
146
161
  id: uniqueId,
147
162
  ref: ref,
148
163
  name: uniqueName,
149
- onBlur: onBlur,
164
+ onBlur: handleBlur,
150
165
  onChange: onChange,
151
166
  onChangeDeferred: onChangeDeferred,
152
167
  onClick: disabled || readOnly ? undefined : onClick,
153
- onFocus: onFocus,
168
+ onFocus: handleFocus,
154
169
  onMouseDown: disabled || readOnly ? undefined : onMouseDown,
155
170
  placeholder: disabled || readOnly ? "" : placeholder,
156
171
  readOnly: readOnly,
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = exports.VerticalDivider = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _propTypes = _interopRequireDefault(require("prop-types"));
9
- var _menu = require("../menu/menu.component");
9
+ var _menu = _interopRequireDefault(require("../menu/__internal__/menu.context"));
10
10
  var _verticalDivider = require("./vertical-divider.style");
11
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
12
  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,7 +21,7 @@ const VerticalDivider = ({
21
21
  }) => {
22
22
  const {
23
23
  inMenu
24
- } = (0, _react.useContext)(_menu.MenuContext);
24
+ } = (0, _react.useContext)(_menu.default);
25
25
  return /*#__PURE__*/_react.default.createElement(_verticalDivider.StyledVerticalWrapper, _extends({
26
26
  "data-component": "vertical-divider",
27
27
  "data-role": "vertical-divider",
@@ -1,2 +1,2 @@
1
- declare const useCharacterCount: (value?: string, characterLimit?: number) => [JSX.Element | null, string | undefined];
1
+ declare const useCharacterCount: (value?: string, characterLimit?: number, characterCountAriaLive?: "off" | "polite") => [JSX.Element | null, string | undefined];
2
2
  export default useCharacterCount;
@@ -11,7 +11,7 @@ var _useDebounce = _interopRequireDefault(require("../useDebounce"));
11
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
12
  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); }
13
13
  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; }
14
- const useCharacterCount = (value = "", characterLimit) => {
14
+ const useCharacterCount = (value = "", characterLimit, characterCountAriaLive) => {
15
15
  const isCharacterLimitValid = typeof characterLimit === "number" && !Number.isNaN(characterLimit);
16
16
  const [debouncedValue, setDebouncedValue] = (0, _react.useState)(value);
17
17
  const debounceWaitTime = 2000;
@@ -37,6 +37,7 @@ const useCharacterCount = (value = "", characterLimit) => {
37
37
  return false;
38
38
  }, [debouncedValue, characterLimit, isCharacterLimitValid]);
39
39
  return [isCharacterLimitValid ? /*#__PURE__*/_react.default.createElement(_characterCount.default, {
40
+ ariaLive: characterCountAriaLive,
40
41
  isOverLimit: isOverLimit,
41
42
  isDebouncedOverLimit: isDebouncedOverLimit,
42
43
  value: value.length,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carbon-react",
3
- "version": "140.1.0",
3
+ "version": "140.2.0",
4
4
  "description": "A library of reusable React components for easily building user interfaces.",
5
5
  "files": [
6
6
  "lib",
@@ -88,6 +88,7 @@
88
88
  "@storybook/react": "^7.6.4",
89
89
  "@storybook/react-webpack5": "^7.6.4",
90
90
  "@storybook/theming": "^7.6.4",
91
+ "@testing-library/dom": "^9.0.0",
91
92
  "@testing-library/jest-dom": "^5.16.5",
92
93
  "@testing-library/react": "^12.1.5",
93
94
  "@testing-library/react-hooks": "^8.0.1",
@@ -202,7 +203,8 @@
202
203
  "styled-system": "^5.1.5"
203
204
  },
204
205
  "overrides": {
205
- "playwright-core": "$@playwright/experimental-ct-react17"
206
+ "playwright-core": "$@playwright/experimental-ct-react17",
207
+ "@testing-library/dom": "$@testing-library/dom"
206
208
  },
207
209
  "config": {
208
210
  "commitizen": {