@patternfly/react-core 6.3.1-prerelease.14 → 6.3.1-prerelease.15

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 (223) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/components/package.json +1 -1
  3. package/deprecated/package.json +1 -1
  4. package/dist/dynamic/components/AboutModal/package.json +1 -1
  5. package/dist/dynamic/components/Accordion/package.json +1 -1
  6. package/dist/dynamic/components/ActionList/package.json +1 -1
  7. package/dist/dynamic/components/Alert/package.json +1 -1
  8. package/dist/dynamic/components/Avatar/package.json +1 -1
  9. package/dist/dynamic/components/BackToTop/package.json +1 -1
  10. package/dist/dynamic/components/Backdrop/package.json +1 -1
  11. package/dist/dynamic/components/BackgroundImage/package.json +1 -1
  12. package/dist/dynamic/components/Badge/package.json +1 -1
  13. package/dist/dynamic/components/Banner/package.json +1 -1
  14. package/dist/dynamic/components/Brand/package.json +1 -1
  15. package/dist/dynamic/components/Breadcrumb/package.json +1 -1
  16. package/dist/dynamic/components/Button/package.json +1 -1
  17. package/dist/dynamic/components/CalendarMonth/package.json +1 -1
  18. package/dist/dynamic/components/Card/package.json +1 -1
  19. package/dist/dynamic/components/Checkbox/package.json +1 -1
  20. package/dist/dynamic/components/ClipboardCopy/package.json +1 -1
  21. package/dist/dynamic/components/CodeBlock/package.json +1 -1
  22. package/dist/dynamic/components/Content/package.json +1 -1
  23. package/dist/dynamic/components/DataList/package.json +1 -1
  24. package/dist/dynamic/components/DatePicker/package.json +1 -1
  25. package/dist/dynamic/components/DescriptionList/package.json +1 -1
  26. package/dist/dynamic/components/Divider/package.json +1 -1
  27. package/dist/dynamic/components/Drawer/package.json +1 -1
  28. package/dist/dynamic/components/Dropdown/package.json +1 -1
  29. package/dist/dynamic/components/DualListSelector/package.json +1 -1
  30. package/dist/dynamic/components/EmptyState/package.json +1 -1
  31. package/dist/dynamic/components/ExpandableSection/package.json +1 -1
  32. package/dist/dynamic/components/FileUpload/package.json +1 -1
  33. package/dist/dynamic/components/Form/package.json +1 -1
  34. package/dist/dynamic/components/FormSelect/package.json +1 -1
  35. package/dist/dynamic/components/HelperText/package.json +1 -1
  36. package/dist/dynamic/components/Hint/package.json +1 -1
  37. package/dist/dynamic/components/Icon/package.json +1 -1
  38. package/dist/dynamic/components/InputGroup/package.json +1 -1
  39. package/dist/dynamic/components/JumpLinks/package.json +1 -1
  40. package/dist/dynamic/components/Label/package.json +1 -1
  41. package/dist/dynamic/components/List/package.json +1 -1
  42. package/dist/dynamic/components/LoginPage/package.json +1 -1
  43. package/dist/dynamic/components/Masthead/package.json +1 -1
  44. package/dist/dynamic/components/Menu/package.json +1 -1
  45. package/dist/dynamic/components/MenuToggle/package.json +1 -1
  46. package/dist/dynamic/components/Modal/package.json +1 -1
  47. package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
  48. package/dist/dynamic/components/Nav/package.json +1 -1
  49. package/dist/dynamic/components/NotificationBadge/package.json +1 -1
  50. package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
  51. package/dist/dynamic/components/NumberInput/package.json +1 -1
  52. package/dist/dynamic/components/OverflowMenu/package.json +1 -1
  53. package/dist/dynamic/components/Page/package.json +1 -1
  54. package/dist/dynamic/components/Pagination/package.json +1 -1
  55. package/dist/dynamic/components/Panel/package.json +1 -1
  56. package/dist/dynamic/components/Popover/package.json +1 -1
  57. package/dist/dynamic/components/Progress/package.json +1 -1
  58. package/dist/dynamic/components/ProgressStepper/package.json +1 -1
  59. package/dist/dynamic/components/Radio/package.json +1 -1
  60. package/dist/dynamic/components/SearchInput/package.json +1 -1
  61. package/dist/dynamic/components/Select/package.json +1 -1
  62. package/dist/dynamic/components/Sidebar/package.json +1 -1
  63. package/dist/dynamic/components/SimpleList/package.json +1 -1
  64. package/dist/dynamic/components/Skeleton/package.json +1 -1
  65. package/dist/dynamic/components/SkipToContent/package.json +1 -1
  66. package/dist/dynamic/components/Slider/package.json +1 -1
  67. package/dist/dynamic/components/Spinner/package.json +1 -1
  68. package/dist/dynamic/components/Switch/package.json +1 -1
  69. package/dist/dynamic/components/Tabs/package.json +1 -1
  70. package/dist/dynamic/components/TextArea/package.json +1 -1
  71. package/dist/dynamic/components/TextInput/package.json +1 -1
  72. package/dist/dynamic/components/TextInputGroup/package.json +1 -1
  73. package/dist/dynamic/components/TimePicker/package.json +1 -1
  74. package/dist/dynamic/components/Timestamp/package.json +1 -1
  75. package/dist/dynamic/components/Title/package.json +1 -1
  76. package/dist/dynamic/components/ToggleGroup/package.json +1 -1
  77. package/dist/dynamic/components/Toolbar/package.json +1 -1
  78. package/dist/dynamic/components/Tooltip/package.json +1 -1
  79. package/dist/dynamic/components/TreeView/package.json +1 -1
  80. package/dist/dynamic/components/Truncate/package.json +1 -1
  81. package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
  82. package/dist/dynamic/components/Wizard/package.json +1 -1
  83. package/dist/dynamic/deprecated/components/Chip/package.json +1 -1
  84. package/dist/dynamic/deprecated/components/DragDrop/package.json +1 -1
  85. package/dist/dynamic/deprecated/components/DualListSelector/package.json +1 -1
  86. package/dist/dynamic/deprecated/components/Modal/package.json +1 -1
  87. package/dist/dynamic/deprecated/components/Tile/package.json +1 -1
  88. package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
  89. package/dist/dynamic/deprecated/components/package.json +1 -1
  90. package/dist/dynamic/helpers/AnimationsProvider/AnimationsProvider/package.json +1 -0
  91. package/dist/dynamic/helpers/AnimationsProvider/package.json +1 -0
  92. package/dist/dynamic/helpers/FocusTrap/FocusTrap/package.json +1 -1
  93. package/dist/dynamic/helpers/GenerateId/GenerateId/package.json +1 -1
  94. package/dist/dynamic/helpers/KeyboardHandler/package.json +1 -1
  95. package/dist/dynamic/helpers/OUIA/ouia/package.json +1 -1
  96. package/dist/dynamic/helpers/Popper/Popper/package.json +1 -1
  97. package/dist/dynamic/helpers/constants/package.json +1 -1
  98. package/dist/dynamic/helpers/datetimeUtils/package.json +1 -1
  99. package/dist/dynamic/helpers/fileUtils/package.json +1 -1
  100. package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
  101. package/dist/dynamic/helpers/package.json +1 -1
  102. package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
  103. package/dist/dynamic/helpers/typeUtils/package.json +1 -1
  104. package/dist/dynamic/helpers/useInterval/package.json +1 -1
  105. package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
  106. package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
  107. package/dist/dynamic/helpers/util/package.json +1 -1
  108. package/dist/dynamic/layouts/Bullseye/package.json +1 -1
  109. package/dist/dynamic/layouts/Flex/package.json +1 -1
  110. package/dist/dynamic/layouts/Gallery/package.json +1 -1
  111. package/dist/dynamic/layouts/Grid/package.json +1 -1
  112. package/dist/dynamic/layouts/Level/package.json +1 -1
  113. package/dist/dynamic/layouts/Split/package.json +1 -1
  114. package/dist/dynamic/layouts/Stack/package.json +1 -1
  115. package/dist/dynamic/styles/package.json +1 -1
  116. package/dist/dynamic-modules.json +5 -0
  117. package/dist/esm/components/Alert/AlertGroup.d.ts +2 -13
  118. package/dist/esm/components/Alert/AlertGroup.d.ts.map +1 -1
  119. package/dist/esm/components/Alert/AlertGroup.js +33 -38
  120. package/dist/esm/components/Alert/AlertGroup.js.map +1 -1
  121. package/dist/esm/components/Alert/AlertGroupInline.d.ts.map +1 -1
  122. package/dist/esm/components/Alert/AlertGroupInline.js +3 -1
  123. package/dist/esm/components/Alert/AlertGroupInline.js.map +1 -1
  124. package/dist/esm/components/DualListSelector/DualListSelector.d.ts +2 -9
  125. package/dist/esm/components/DualListSelector/DualListSelector.d.ts.map +1 -1
  126. package/dist/esm/components/DualListSelector/DualListSelector.js +6 -16
  127. package/dist/esm/components/DualListSelector/DualListSelector.js.map +1 -1
  128. package/dist/esm/components/DualListSelector/DualListSelectorTreeItem.d.ts.map +1 -1
  129. package/dist/esm/components/DualListSelector/DualListSelectorTreeItem.js +3 -1
  130. package/dist/esm/components/DualListSelector/DualListSelectorTreeItem.js.map +1 -1
  131. package/dist/esm/components/Form/FormFieldGroupExpandable.d.ts.map +1 -1
  132. package/dist/esm/components/Form/FormFieldGroupExpandable.js +3 -1
  133. package/dist/esm/components/Form/FormFieldGroupExpandable.js.map +1 -1
  134. package/dist/esm/components/Form/InternalFormFieldGroup.d.ts.map +1 -1
  135. package/dist/esm/components/Form/InternalFormFieldGroup.js +3 -1
  136. package/dist/esm/components/Form/InternalFormFieldGroup.js.map +1 -1
  137. package/dist/esm/components/SearchInput/SearchInput.d.ts.map +1 -1
  138. package/dist/esm/components/SearchInput/SearchInput.js +3 -1
  139. package/dist/esm/components/SearchInput/SearchInput.js.map +1 -1
  140. package/dist/esm/components/TreeView/TreeView.d.ts.map +1 -1
  141. package/dist/esm/components/TreeView/TreeView.js +3 -1
  142. package/dist/esm/components/TreeView/TreeView.js.map +1 -1
  143. package/dist/esm/components/TreeView/TreeViewListItem.d.ts.map +1 -1
  144. package/dist/esm/components/TreeView/TreeViewListItem.js +3 -1
  145. package/dist/esm/components/TreeView/TreeViewListItem.js.map +1 -1
  146. package/dist/esm/helpers/AnimationsProvider/AnimationsProvider.d.ts +76 -0
  147. package/dist/esm/helpers/AnimationsProvider/AnimationsProvider.d.ts.map +1 -0
  148. package/dist/esm/helpers/AnimationsProvider/AnimationsProvider.js +83 -0
  149. package/dist/esm/helpers/AnimationsProvider/AnimationsProvider.js.map +1 -0
  150. package/dist/esm/helpers/AnimationsProvider/index.d.ts +2 -0
  151. package/dist/esm/helpers/AnimationsProvider/index.d.ts.map +1 -0
  152. package/dist/esm/helpers/AnimationsProvider/index.js +2 -0
  153. package/dist/esm/helpers/AnimationsProvider/index.js.map +1 -0
  154. package/dist/esm/helpers/index.d.ts +1 -0
  155. package/dist/esm/helpers/index.d.ts.map +1 -1
  156. package/dist/esm/helpers/index.js +1 -0
  157. package/dist/esm/helpers/index.js.map +1 -1
  158. package/dist/js/components/Alert/AlertGroup.d.ts +2 -13
  159. package/dist/js/components/Alert/AlertGroup.d.ts.map +1 -1
  160. package/dist/js/components/Alert/AlertGroup.js +33 -37
  161. package/dist/js/components/Alert/AlertGroup.js.map +1 -1
  162. package/dist/js/components/Alert/AlertGroupInline.d.ts.map +1 -1
  163. package/dist/js/components/Alert/AlertGroupInline.js +3 -1
  164. package/dist/js/components/Alert/AlertGroupInline.js.map +1 -1
  165. package/dist/js/components/DualListSelector/DualListSelector.d.ts +2 -9
  166. package/dist/js/components/DualListSelector/DualListSelector.d.ts.map +1 -1
  167. package/dist/js/components/DualListSelector/DualListSelector.js +7 -16
  168. package/dist/js/components/DualListSelector/DualListSelector.js.map +1 -1
  169. package/dist/js/components/DualListSelector/DualListSelectorTreeItem.d.ts.map +1 -1
  170. package/dist/js/components/DualListSelector/DualListSelectorTreeItem.js +3 -1
  171. package/dist/js/components/DualListSelector/DualListSelectorTreeItem.js.map +1 -1
  172. package/dist/js/components/Form/FormFieldGroupExpandable.d.ts.map +1 -1
  173. package/dist/js/components/Form/FormFieldGroupExpandable.js +3 -1
  174. package/dist/js/components/Form/FormFieldGroupExpandable.js.map +1 -1
  175. package/dist/js/components/Form/InternalFormFieldGroup.d.ts.map +1 -1
  176. package/dist/js/components/Form/InternalFormFieldGroup.js +3 -1
  177. package/dist/js/components/Form/InternalFormFieldGroup.js.map +1 -1
  178. package/dist/js/components/SearchInput/SearchInput.d.ts.map +1 -1
  179. package/dist/js/components/SearchInput/SearchInput.js +3 -1
  180. package/dist/js/components/SearchInput/SearchInput.js.map +1 -1
  181. package/dist/js/components/TreeView/TreeView.d.ts.map +1 -1
  182. package/dist/js/components/TreeView/TreeView.js +3 -1
  183. package/dist/js/components/TreeView/TreeView.js.map +1 -1
  184. package/dist/js/components/TreeView/TreeViewListItem.d.ts.map +1 -1
  185. package/dist/js/components/TreeView/TreeViewListItem.js +3 -1
  186. package/dist/js/components/TreeView/TreeViewListItem.js.map +1 -1
  187. package/dist/js/helpers/AnimationsProvider/AnimationsProvider.d.ts +76 -0
  188. package/dist/js/helpers/AnimationsProvider/AnimationsProvider.d.ts.map +1 -0
  189. package/dist/js/helpers/AnimationsProvider/AnimationsProvider.js +89 -0
  190. package/dist/js/helpers/AnimationsProvider/AnimationsProvider.js.map +1 -0
  191. package/dist/js/helpers/AnimationsProvider/index.d.ts +2 -0
  192. package/dist/js/helpers/AnimationsProvider/index.d.ts.map +1 -0
  193. package/dist/js/helpers/AnimationsProvider/index.js +5 -0
  194. package/dist/js/helpers/AnimationsProvider/index.js.map +1 -0
  195. package/dist/js/helpers/index.d.ts +1 -0
  196. package/dist/js/helpers/index.d.ts.map +1 -1
  197. package/dist/js/helpers/index.js +1 -0
  198. package/dist/js/helpers/index.js.map +1 -1
  199. package/dist/umd/assets/{output-BRqYjXqq.css → output-BwG6uaWN.css} +12790 -12790
  200. package/dist/umd/react-core.min.js +3 -3
  201. package/helpers/package.json +1 -1
  202. package/layouts/package.json +1 -1
  203. package/next/package.json +1 -1
  204. package/package.json +2 -2
  205. package/src/components/Alert/AlertGroup.tsx +59 -63
  206. package/src/components/Alert/AlertGroupInline.tsx +3 -1
  207. package/src/components/Alert/__tests__/AlertGroup.test.tsx +55 -4
  208. package/src/components/DualListSelector/DualListSelector.tsx +32 -39
  209. package/src/components/DualListSelector/DualListSelectorTreeItem.tsx +3 -1
  210. package/src/components/DualListSelector/__tests__/DualListSelector.test.tsx +28 -0
  211. package/src/components/Form/FormFieldGroupExpandable.tsx +3 -1
  212. package/src/components/Form/InternalFormFieldGroup.tsx +3 -1
  213. package/src/components/Form/__tests__/FormFieldGroupExpandable.test.tsx +30 -0
  214. package/src/components/SearchInput/SearchInput.tsx +3 -1
  215. package/src/components/SearchInput/__tests__/SearchInput.test.tsx +52 -0
  216. package/src/components/TreeView/TreeView.tsx +3 -1
  217. package/src/components/TreeView/TreeViewListItem.tsx +3 -1
  218. package/src/components/TreeView/__tests__/TreeView.test.tsx +28 -0
  219. package/src/components/TreeView/__tests__/__snapshots__/TreeView.test.tsx.snap +1 -1
  220. package/src/helpers/AnimationsProvider/AnimationsProvider.tsx +104 -0
  221. package/src/helpers/AnimationsProvider/__tests__/AnimationsProvider.test.tsx +157 -0
  222. package/src/helpers/AnimationsProvider/index.ts +1 -0
  223. package/src/helpers/index.ts +1 -0
@@ -1 +1 @@
1
- {"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.3.1-prerelease.13","private":true}
1
+ {"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.3.1-prerelease.14","private":true}
@@ -1 +1 @@
1
- {"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.3.1-prerelease.13","private":true}
1
+ {"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.3.1-prerelease.14","private":true}
package/next/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.3.1-prerelease.13","private":true}
1
+ {"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.3.1-prerelease.14","private":true}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "6.3.1-prerelease.14",
3
+ "version": "6.3.1-prerelease.15",
4
4
  "description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
5
5
  "main": "dist/js/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -63,5 +63,5 @@
63
63
  "react": "^17 || ^18 || ^19",
64
64
  "react-dom": "^17 || ^18 || ^19"
65
65
  },
66
- "gitHead": "e8f9fc0c84607e9f4cd3a9ea30b374508eaa889c"
66
+ "gitHead": "b75c944f1dbfb1e5c8621a70513b90dc45ad2e65"
67
67
  }
@@ -1,7 +1,8 @@
1
- import { Component } from 'react';
1
+ import { useEffect, useRef, useState } from 'react';
2
2
  import * as ReactDOM from 'react-dom';
3
3
  import { canUseDOM } from '../../helpers';
4
4
  import { AlertGroupInline } from './AlertGroupInline';
5
+ import { useHasAnimations } from '../../helpers';
5
6
 
6
7
  export interface AlertGroupProps extends Omit<React.HTMLProps<HTMLUListElement>, 'className'> {
7
8
  /** Additional classes added to the AlertGroup */
@@ -26,78 +27,73 @@ export interface AlertGroupProps extends Omit<React.HTMLProps<HTMLUListElement>,
26
27
  'aria-label'?: string;
27
28
  }
28
29
 
29
- interface AlertGroupState {
30
- container: HTMLElement;
31
- }
32
-
33
- class AlertGroup extends Component<AlertGroupProps, AlertGroupState> {
34
- static displayName = 'AlertGroup';
35
- state = {
36
- container: undefined
37
- } as AlertGroupState;
38
-
39
- componentDidMount() {
40
- const container = document.createElement('div');
41
- const target: HTMLElement = this.getTargetElement();
42
- this.setState({ container });
43
- target.appendChild(container);
44
- }
30
+ export const AlertGroup: React.FunctionComponent<AlertGroupProps> = ({
31
+ className,
32
+ children,
33
+ hasAnimations: hasAnimationsProp,
34
+ isToast,
35
+ isLiveRegion,
36
+ onOverflowClick,
37
+ overflowMessage,
38
+ 'aria-label': ariaLabel,
45
39
 
46
- componentWillUnmount() {
47
- const target: HTMLElement = this.getTargetElement();
48
- if (this.state.container) {
49
- target.removeChild(this.state.container);
50
- }
51
- }
40
+ appendTo,
41
+ ...props
42
+ }: AlertGroupProps) => {
43
+ const containerRef = useRef<HTMLElement | null>(null);
44
+ const [isContainerReady, setIsContainerReady] = useState(false);
45
+ const hasAnimations = useHasAnimations(hasAnimationsProp);
52
46
 
53
- getTargetElement() {
54
- const appendTo = this.props.appendTo;
47
+ const getTargetElement = () => {
55
48
  if (typeof appendTo === 'function') {
56
49
  return appendTo();
57
50
  }
58
51
  return appendTo || document.body;
59
- }
52
+ };
53
+
54
+ useEffect(() => {
55
+ if (isToast && canUseDOM) {
56
+ const container = document.createElement('div');
57
+ const target = getTargetElement();
58
+ containerRef.current = container;
59
+ target.appendChild(container);
60
+ setIsContainerReady(true);
60
61
 
61
- render() {
62
- const {
63
- className,
64
- children,
65
- hasAnimations = false,
66
- isToast,
67
- isLiveRegion,
68
- onOverflowClick,
69
- overflowMessage,
70
- 'aria-label': ariaLabel,
71
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
72
- appendTo, // do not pass down to ul
73
- ...props
74
- } = this.props;
75
- const alertGroup = (
76
- <AlertGroupInline
77
- onOverflowClick={onOverflowClick}
78
- className={className}
79
- isToast={isToast}
80
- isLiveRegion={isLiveRegion}
81
- overflowMessage={overflowMessage}
82
- aria-label={ariaLabel}
83
- hasAnimations={hasAnimations}
84
- {...props}
85
- >
86
- {children}
87
- </AlertGroupInline>
88
- );
89
- if (!this.props.isToast) {
90
- return alertGroup;
62
+ return () => {
63
+ if (containerRef.current) {
64
+ target.removeChild(containerRef.current);
65
+ containerRef.current = null;
66
+ }
67
+ setIsContainerReady(false);
68
+ };
91
69
  }
70
+ }, [isToast, appendTo]);
92
71
 
93
- const container = this.state.container;
72
+ const alertGroup = (
73
+ <AlertGroupInline
74
+ onOverflowClick={onOverflowClick}
75
+ className={className}
76
+ isToast={isToast}
77
+ isLiveRegion={isLiveRegion}
78
+ overflowMessage={overflowMessage}
79
+ aria-label={ariaLabel}
80
+ hasAnimations={hasAnimations}
81
+ {...props}
82
+ >
83
+ {children}
84
+ </AlertGroupInline>
85
+ );
94
86
 
95
- if (!canUseDOM || !container) {
96
- return null;
97
- }
87
+ if (!isToast) {
88
+ return alertGroup;
89
+ }
90
+
91
+ const container = containerRef.current;
98
92
 
99
- return ReactDOM.createPortal(alertGroup, container);
93
+ if (!canUseDOM || !container || !isContainerReady) {
94
+ return null;
100
95
  }
101
- }
102
96
 
103
- export { AlertGroup };
97
+ return ReactDOM.createPortal(alertGroup, container);
98
+ };
99
+ AlertGroup.displayName = 'AlertGroup';
@@ -4,17 +4,19 @@ import styles from '@patternfly/react-styles/css/components/Alert/alert-group';
4
4
  import { AlertGroupProps } from './AlertGroup';
5
5
  import { AlertProps } from '../Alert';
6
6
  import { AlertGroupContext } from './AlertGroupContext';
7
+ import { useHasAnimations } from '../../helpers';
7
8
 
8
9
  export const AlertGroupInline: React.FunctionComponent<AlertGroupProps> = ({
9
10
  className,
10
11
  children,
11
- hasAnimations,
12
+ hasAnimations: hasAnimationsProp,
12
13
  isToast,
13
14
  isLiveRegion,
14
15
  onOverflowClick,
15
16
  overflowMessage,
16
17
  ...props
17
18
  }: AlertGroupProps) => {
19
+ const hasAnimations = useHasAnimations(hasAnimationsProp);
18
20
  const [handleTransitionEnd, setHandleTransitionEnd] = useState<() => void>(() => () => {});
19
21
 
20
22
  const updateTransitionEnd = (onTransitionEnd: () => void) => {
@@ -4,6 +4,7 @@ import userEvent from '@testing-library/user-event';
4
4
  import { Alert } from '../../Alert';
5
5
  import { AlertGroup } from '../../Alert';
6
6
  import { AlertActionCloseButton } from '../../../components/Alert/AlertActionCloseButton';
7
+ import { AnimationsProvider } from '../../../helpers/AnimationsProvider';
7
8
 
8
9
  test('Alert Group renders without children', () => {
9
10
  render(
@@ -56,14 +57,16 @@ test('Standard Alert Group is not a toast alert group', () => {
56
57
  expect(screen.getByText('alert title').parentElement).not.toHaveClass('pf-m-toast');
57
58
  });
58
59
 
59
- test('Toast Alert Group contains expected modifier class', () => {
60
+ test('Toast Alert Group contains expected modifier class', async () => {
60
61
  render(
61
62
  <AlertGroup isToast aria-label="group label">
62
63
  <Alert variant="warning" title="alert title" />
63
64
  </AlertGroup>
64
65
  );
65
66
 
66
- expect(screen.getByLabelText('group label')).toHaveClass('pf-m-toast');
67
+ // Wait for the portal to be created and rendered
68
+ const alertGroup = await screen.findByLabelText('group label');
69
+ expect(alertGroup).toHaveClass('pf-m-toast');
67
70
  });
68
71
 
69
72
  test('Calls the callback set by updateTransitionEnd when transition ends and animations are enabled', async () => {
@@ -90,8 +93,11 @@ test('Calls the callback set by updateTransitionEnd when transition ends and ani
90
93
  </AlertGroup>
91
94
  );
92
95
 
93
- await user.click(screen.getByLabelText('Close'));
96
+ const closeButton = await screen.findByLabelText('Close');
97
+ await user.click(closeButton);
94
98
  expect(mockCallback).not.toHaveBeenCalled();
99
+ // fireEvent is needed here because transitionEnd is a browser event that occurs automatically
100
+ // when CSS transitions complete, not a user interaction that userEvent can simulate
95
101
  fireEvent.transitionEnd(screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item') as HTMLElement);
96
102
  expect(mockCallback).toHaveBeenCalled();
97
103
  });
@@ -120,9 +126,54 @@ test('Does not call the callback set by updateTransitionEnd when transition ends
120
126
  </AlertGroup>
121
127
  );
122
128
 
123
- await user.click(screen.getByLabelText('Close'));
129
+ const closeButton = await screen.findByLabelText('Close');
130
+ await user.click(closeButton);
124
131
  expect(mockCallback).toHaveBeenCalledTimes(1);
125
132
  // The transitionend event firing should not cause the callback to be called again
133
+ // fireEvent is needed here because transitionEnd is a browser event that occurs automatically
134
+ // when CSS transitions complete, not a user interaction that userEvent can simulate
126
135
  fireEvent.transitionEnd(screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item') as HTMLElement);
127
136
  expect(mockCallback).toHaveBeenCalledTimes(1);
128
137
  });
138
+
139
+ describe('Animation context behavior', () => {
140
+ test('respects AnimationsProvider context when no local hasAnimations prop', () => {
141
+ render(
142
+ <AnimationsProvider config={{ hasAnimations: true }}>
143
+ <AlertGroup>
144
+ <Alert title="Test Alert" />
145
+ </AlertGroup>
146
+ </AnimationsProvider>
147
+ );
148
+
149
+ // Should apply animation class when animations are enabled via context
150
+ const alertGroupItem = screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item');
151
+ expect(alertGroupItem).toHaveClass('pf-m-offstage-top');
152
+ });
153
+
154
+ test('local hasAnimations prop takes precedence over context', () => {
155
+ render(
156
+ <AnimationsProvider config={{ hasAnimations: true }}>
157
+ <AlertGroup hasAnimations={false}>
158
+ <Alert title="Test Alert" />
159
+ </AlertGroup>
160
+ </AnimationsProvider>
161
+ );
162
+
163
+ // Should not apply animation class when local hasAnimations=false overrides context
164
+ const alertGroupItem = screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item');
165
+ expect(alertGroupItem).not.toHaveClass('pf-m-offstage-top');
166
+ });
167
+
168
+ test('works without AnimationsProvider (backward compatibility)', () => {
169
+ render(
170
+ <AlertGroup>
171
+ <Alert title="Test Alert" />
172
+ </AlertGroup>
173
+ );
174
+
175
+ // Should not apply animation class when no context and no local hasAnimations
176
+ const alertGroupItem = screen.getByText('Test Alert').closest('.pf-v6-c-alert-group__item');
177
+ expect(alertGroupItem).not.toHaveClass('pf-m-offstage-top');
178
+ });
179
+ });
@@ -1,8 +1,8 @@
1
- import { Component } from 'react';
2
1
  import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector';
3
2
  import { css } from '@patternfly/react-styles';
4
- import { GenerateId, PickOptional } from '../../helpers';
3
+ import { GenerateId } from '../../helpers';
5
4
  import { DualListSelectorContext } from './DualListSelectorContext';
5
+ import { useHasAnimations } from '../../helpers';
6
6
 
7
7
  /** Acts as a container for all other DualListSelector sub-components when using a
8
8
  * composable dual list selector.
@@ -24,41 +24,34 @@ export interface DualListSelectorProps {
24
24
  hasAnimations?: boolean;
25
25
  }
26
26
 
27
- class DualListSelector extends Component<DualListSelectorProps> {
28
- static displayName = 'DualListSelector';
29
- static defaultProps: PickOptional<DualListSelectorProps> = {
30
- children: '',
31
- isTree: false,
32
- hasAnimations: false
33
- };
27
+ export const DualListSelector: React.FunctionComponent<DualListSelectorProps> = ({
28
+ className,
29
+ children,
30
+ id,
31
+ isTree = false,
32
+ hasAnimations: hasAnimationsProp,
33
+ ...props
34
+ }: DualListSelectorProps) => {
35
+ const hasAnimations = useHasAnimations(hasAnimationsProp);
34
36
 
35
- constructor(props: DualListSelectorProps) {
36
- super(props);
37
- }
38
-
39
- render() {
40
- const { className, children, id, isTree, hasAnimations, ...props } = this.props;
41
-
42
- return (
43
- <DualListSelectorContext.Provider value={{ isTree, hasAnimations }}>
44
- <GenerateId>
45
- {(randomId) => (
46
- <div
47
- className={css(
48
- styles.dualListSelector,
49
- hasAnimations && isTree && styles.modifiers.animateExpand,
50
- className
51
- )}
52
- id={id || randomId}
53
- {...props}
54
- >
55
- {children}
56
- </div>
57
- )}
58
- </GenerateId>
59
- </DualListSelectorContext.Provider>
60
- );
61
- }
62
- }
63
-
64
- export { DualListSelector };
37
+ return (
38
+ <DualListSelectorContext.Provider value={{ isTree, hasAnimations }}>
39
+ <GenerateId>
40
+ {(randomId) => (
41
+ <div
42
+ className={css(
43
+ styles.dualListSelector,
44
+ hasAnimations && isTree && styles.modifiers.animateExpand,
45
+ className
46
+ )}
47
+ id={id || randomId}
48
+ {...props}
49
+ >
50
+ {children}
51
+ </div>
52
+ )}
53
+ </GenerateId>
54
+ </DualListSelectorContext.Provider>
55
+ );
56
+ };
57
+ DualListSelector.displayName = 'DualListSelector';
@@ -6,6 +6,7 @@ import { Badge } from '../Badge';
6
6
  import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
7
7
  import { flattenTree } from './treeUtils';
8
8
  import { DualListSelectorListContext } from './DualListSelectorContext';
9
+ import { useHasAnimations } from '../../helpers';
9
10
 
10
11
  export interface DualListSelectorTreeItemProps extends React.HTMLProps<HTMLLIElement> {
11
12
  /** Content rendered inside the dual list selector. */
@@ -58,7 +59,7 @@ const DualListSelectorTreeItemBase: React.FunctionComponent<DualListSelectorTree
58
59
  badgeProps,
59
60
  itemData,
60
61
  isDisabled = false,
61
- hasAnimations,
62
+ hasAnimations: hasAnimationsProp,
62
63
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
64
  useMemo,
64
65
  ...props
@@ -66,6 +67,7 @@ const DualListSelectorTreeItemBase: React.FunctionComponent<DualListSelectorTree
66
67
  const ref = useRef(null);
67
68
  const [isExpanded, setIsExpanded] = useState(defaultExpanded || false);
68
69
  const { setFocusedOption } = useContext(DualListSelectorListContext);
70
+ const hasAnimations = useHasAnimations(hasAnimationsProp);
69
71
 
70
72
  useEffect(() => {
71
73
  setIsExpanded(defaultExpanded);
@@ -3,6 +3,7 @@ import styles from '@patternfly/react-styles/css/components/DualListSelector/dua
3
3
  import { DualListSelector } from '../DualListSelector';
4
4
  import { DualListSelectorPane } from '../DualListSelectorPane';
5
5
  import { SearchInput } from '../../SearchInput';
6
+ import { AnimationsProvider } from '../../../helpers/AnimationsProvider';
6
7
 
7
8
  // The following tests can be removed as part of https://github.com/patternfly/patternfly-react/issues/11838
8
9
  describe('Opt-in animations', () => {
@@ -29,6 +30,33 @@ describe('Opt-in animations', () => {
29
30
 
30
31
  expect(screen.getByTestId('test-id')).toHaveClass(styles.modifiers.animateExpand);
31
32
  });
33
+
34
+ // Animation context tests
35
+ test('respects AnimationsProvider context when no local hasAnimations prop', () => {
36
+ render(
37
+ <AnimationsProvider config={{ hasAnimations: true }}>
38
+ <DualListSelector isTree data-testid="test-id" />
39
+ </AnimationsProvider>
40
+ );
41
+
42
+ expect(screen.getByTestId('test-id')).toHaveClass(styles.modifiers.animateExpand);
43
+ });
44
+
45
+ test('local hasAnimations prop takes precedence over context', () => {
46
+ render(
47
+ <AnimationsProvider config={{ hasAnimations: true }}>
48
+ <DualListSelector isTree hasAnimations={false} data-testid="test-id" />
49
+ </AnimationsProvider>
50
+ );
51
+
52
+ expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand);
53
+ });
54
+
55
+ test('works without AnimationsProvider (backward compatibility)', () => {
56
+ render(<DualListSelector isTree data-testid="test-id" />);
57
+
58
+ expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand);
59
+ });
32
60
  });
33
61
 
34
62
  // Following tests should be moved to a separate DualListSelectorPane test file
@@ -1,5 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import { InternalFormFieldGroup } from './InternalFormFieldGroup';
3
+ import { useHasAnimations } from '../../helpers';
3
4
 
4
5
  export interface FormFieldGroupExpandableProps extends Omit<React.HTMLProps<HTMLDivElement>, 'onToggle'> {
5
6
  /** Anything that can be rendered as form field group content. */
@@ -25,10 +26,11 @@ export const FormFieldGroupExpandable: React.FunctionComponent<FormFieldGroupExp
25
26
  header,
26
27
  isExpanded = false,
27
28
  toggleAriaLabel,
28
- hasAnimations,
29
+ hasAnimations: hasAnimationsProp,
29
30
  ...props
30
31
  }: FormFieldGroupExpandableProps) => {
31
32
  const [localIsExpanded, setIsExpanded] = useState(isExpanded);
33
+ const hasAnimations = useHasAnimations(hasAnimationsProp);
32
34
 
33
35
  return (
34
36
  <InternalFormFieldGroup
@@ -2,6 +2,7 @@ import styles from '@patternfly/react-styles/css/components/Form/form';
2
2
  import { css } from '@patternfly/react-styles';
3
3
  import { FormFieldGroupToggle } from './FormFieldGroupToggle';
4
4
  import { GenerateId } from '../../helpers';
5
+ import { useHasAnimations } from '../../helpers';
5
6
 
6
7
  export interface InternalFormFieldGroupProps extends Omit<React.HTMLProps<HTMLDivElement>, 'label' | 'onToggle'> {
7
8
  /** Anything that can be rendered as form field group content. */
@@ -33,9 +34,10 @@ export const InternalFormFieldGroup: React.FunctionComponent<InternalFormFieldGr
33
34
  isExpanded,
34
35
  onToggle,
35
36
  toggleAriaLabel,
36
- hasAnimations,
37
+ hasAnimations: hasAnimationsProp,
37
38
  ...props
38
39
  }: InternalFormFieldGroupProps) => {
40
+ const hasAnimations = useHasAnimations(hasAnimationsProp);
39
41
  const headerTitleText = header ? header.props.titleText : null;
40
42
  if (isExpandable && !toggleAriaLabel && !headerTitleText) {
41
43
  // eslint-disable-next-line no-console
@@ -1,5 +1,6 @@
1
1
  import { render, screen } from '@testing-library/react';
2
2
  import { FormFieldGroupExpandable } from '../FormFieldGroupExpandable';
3
+ import { AnimationsProvider } from '../../../helpers/AnimationsProvider';
3
4
  import styles from '@patternfly/react-styles/css/components/Form/form';
4
5
 
5
6
  test('Does not render children by default', () => {
@@ -53,3 +54,32 @@ test(`Renders with class ${styles.modifiers.expandable} when hasAnimations is tr
53
54
 
54
55
  expect(screen.getByRole('group')).toHaveClass(styles.modifiers.expandable);
55
56
  });
57
+
58
+ // Regression tests for AnimationsProvider context
59
+ test('respects AnimationsProvider context when no local hasAnimations prop', () => {
60
+ render(
61
+ <AnimationsProvider config={{ hasAnimations: true }}>
62
+ <FormFieldGroupExpandable toggleAriaLabel="Toggle label">Child content</FormFieldGroupExpandable>
63
+ </AnimationsProvider>
64
+ );
65
+
66
+ expect(screen.getByRole('group')).toHaveClass(styles.modifiers.expandable);
67
+ });
68
+
69
+ test('local hasAnimations prop takes precedence over context', () => {
70
+ render(
71
+ <AnimationsProvider config={{ hasAnimations: true }}>
72
+ <FormFieldGroupExpandable hasAnimations={false} toggleAriaLabel="Toggle label">
73
+ Child content
74
+ </FormFieldGroupExpandable>
75
+ </AnimationsProvider>
76
+ );
77
+
78
+ expect(screen.getByRole('group')).not.toHaveClass(styles.modifiers.expandable);
79
+ });
80
+
81
+ test('works without AnimationsProvider (backward compatibility)', () => {
82
+ render(<FormFieldGroupExpandable toggleAriaLabel="Toggle label">Child content</FormFieldGroupExpandable>);
83
+
84
+ expect(screen.getByRole('group')).not.toHaveClass(styles.modifiers.expandable);
85
+ });
@@ -13,6 +13,7 @@ import { AdvancedSearchMenu } from './AdvancedSearchMenu';
13
13
  import { TextInputGroup, TextInputGroupMain, TextInputGroupUtilities } from '../TextInputGroup';
14
14
  import { InputGroup, InputGroupItem } from '../InputGroup';
15
15
  import { Popper } from '../../helpers';
16
+ import { useHasAnimations } from '../../helpers';
16
17
  import textInputGroupStyles from '@patternfly/react-styles/css/components/TextInputGroup/text-input-group';
17
18
  import inputGroupStyles from '@patternfly/react-styles/css/components/InputGroup/input-group';
18
19
 
@@ -180,7 +181,8 @@ const SearchInputBase: React.FunctionComponent<SearchInputProps> = ({
180
181
  const popperRef = useRef(null);
181
182
  const [focusAfterExpandChange, setFocusAfterExpandChange] = useState(false);
182
183
 
183
- const { isExpanded, onToggleExpand, toggleAriaLabel, hasAnimations } = expandableInput || {};
184
+ const { isExpanded, onToggleExpand, toggleAriaLabel, hasAnimations: hasAnimationsProp } = expandableInput || {};
185
+ const hasAnimations = useHasAnimations(hasAnimationsProp);
184
186
 
185
187
  useEffect(() => {
186
188
  // this effect and the focusAfterExpandChange variable are needed to focus the input/toggle as needed when the
@@ -5,6 +5,7 @@ import userEvent from '@testing-library/user-event';
5
5
  import { SearchInput } from '../SearchInput';
6
6
  import { FormGroup } from '../../Form';
7
7
  import { Button } from '../../Button';
8
+ import { AnimationsProvider } from '../../../helpers/AnimationsProvider';
8
9
  import ExternalLinkSquareAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-square-alt-icon';
9
10
  import badgeStyles from '@patternfly/react-styles/css/components/Badge/badge';
10
11
  import textInputGroupStyles from '@patternfly/react-styles/css/components/TextInputGroup/text-input-group';
@@ -363,3 +364,54 @@ test('Additional props are spread when inputProps prop is passed', () => {
363
364
  render(<SearchInput aria-label="Test input" inputProps={{ autofocus: 'true' }} />);
364
365
  expect(screen.getByLabelText('Test input')).toHaveAttribute('autofocus', 'true');
365
366
  });
367
+
368
+ // Animation context tests
369
+ test('respects AnimationsProvider context when no local hasAnimations prop for expandable input', () => {
370
+ render(
371
+ <AnimationsProvider config={{ hasAnimations: true }}>
372
+ <SearchInput
373
+ data-testid="test-id"
374
+ expandableInput={{
375
+ isExpanded: false,
376
+ onToggleExpand: () => {},
377
+ toggleAriaLabel: 'Test label'
378
+ }}
379
+ />
380
+ </AnimationsProvider>
381
+ );
382
+
383
+ expect(screen.getByTestId('test-id')).toHaveClass(`${inputGroupStyles.modifiers.searchExpandable}`);
384
+ });
385
+
386
+ test('local hasAnimations prop takes precedence over context for expandable input', () => {
387
+ render(
388
+ <AnimationsProvider config={{ hasAnimations: true }}>
389
+ <SearchInput
390
+ data-testid="test-id"
391
+ expandableInput={{
392
+ hasAnimations: false,
393
+ isExpanded: false,
394
+ onToggleExpand: () => {},
395
+ toggleAriaLabel: 'Test label'
396
+ }}
397
+ />
398
+ </AnimationsProvider>
399
+ );
400
+
401
+ expect(screen.getByTestId('test-id')).not.toHaveClass(`${inputGroupStyles.modifiers.searchExpandable}`);
402
+ });
403
+
404
+ test('works without AnimationsProvider for expandable input (backward compatibility)', () => {
405
+ render(
406
+ <SearchInput
407
+ data-testid="test-id"
408
+ expandableInput={{
409
+ isExpanded: false,
410
+ onToggleExpand: () => {},
411
+ toggleAriaLabel: 'Test label'
412
+ }}
413
+ />
414
+ );
415
+
416
+ expect(screen.getByTestId('test-id')).not.toHaveClass(`${inputGroupStyles.modifiers.searchExpandable}`);
417
+ });
@@ -1,6 +1,7 @@
1
1
  import { TreeViewList } from './TreeViewList';
2
2
  import { TreeViewCheckProps, TreeViewListItem } from './TreeViewListItem';
3
3
  import { TreeViewRoot } from './TreeViewRoot';
4
+ import { useHasAnimations } from '../../helpers';
4
5
 
5
6
  /** Properties that make up a tree view data item. These properties should be passed in as an
6
7
  * object to one of the various tree view component properties which accept TreeViewDataItem as
@@ -135,9 +136,10 @@ export const TreeView: React.FunctionComponent<TreeViewProps> = ({
135
136
  useMemo,
136
137
  'aria-label': ariaLabel,
137
138
  'aria-labelledby': ariaLabelledby,
138
- hasAnimations,
139
+ hasAnimations: hasAnimationsProp,
139
140
  ...props
140
141
  }: TreeViewProps) => {
142
+ const hasAnimations = useHasAnimations(hasAnimationsProp);
141
143
  const treeViewList = (
142
144
  <TreeViewList
143
145
  isNested={isNested}
@@ -5,6 +5,7 @@ import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-i
5
5
  import { TreeViewDataItem } from './TreeView';
6
6
  import { Badge } from '../Badge';
7
7
  import { GenerateId } from '../../helpers/GenerateId/GenerateId';
8
+ import { useHasAnimations } from '../../helpers';
8
9
 
9
10
  export interface TreeViewCheckProps extends Omit<Partial<React.InputHTMLAttributes<HTMLInputElement>>, 'checked'> {
10
11
  checked?: boolean | null;
@@ -102,10 +103,11 @@ const TreeViewListItemBase: React.FunctionComponent<TreeViewListItemProps> = ({
102
103
  expandedIcon,
103
104
  action,
104
105
  compareItems,
105
- hasAnimations,
106
+ hasAnimations: hasAnimationsProp,
106
107
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
107
108
  useMemo
108
109
  }: TreeViewListItemProps) => {
110
+ const hasAnimations = useHasAnimations(hasAnimationsProp);
109
111
  const [internalIsExpanded, setIsExpanded] = useState(defaultExpanded);
110
112
  useEffect(() => {
111
113
  if (isExpanded !== undefined && isExpanded !== null) {