@patternfly/react-core 4.274.0 → 4.275.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 (227) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/components/Menu/MenuGroup.d.ts +1 -1
  3. package/components/Menu/MenuGroup.d.ts.map +1 -1
  4. package/components/Menu/MenuGroup.js.map +1 -1
  5. package/components/Select/Select.d.ts +2 -0
  6. package/components/Select/Select.d.ts.map +1 -1
  7. package/components/Select/Select.js +3 -3
  8. package/components/Select/Select.js.map +1 -1
  9. package/components/Select/SelectToggle.d.ts +4 -14
  10. package/components/Select/SelectToggle.d.ts.map +1 -1
  11. package/components/Select/SelectToggle.js +11 -5
  12. package/components/Select/SelectToggle.js.map +1 -1
  13. package/dist/esm/components/Menu/MenuGroup.d.ts +1 -1
  14. package/dist/esm/components/Menu/MenuGroup.d.ts.map +1 -1
  15. package/dist/esm/components/Menu/MenuGroup.js.map +1 -1
  16. package/dist/esm/components/Select/Select.d.ts +2 -0
  17. package/dist/esm/components/Select/Select.d.ts.map +1 -1
  18. package/dist/esm/components/Select/Select.js +3 -3
  19. package/dist/esm/components/Select/Select.js.map +1 -1
  20. package/dist/esm/components/Select/SelectToggle.d.ts +4 -14
  21. package/dist/esm/components/Select/SelectToggle.d.ts.map +1 -1
  22. package/dist/esm/components/Select/SelectToggle.js +11 -5
  23. package/dist/esm/components/Select/SelectToggle.js.map +1 -1
  24. package/dist/esm/next/components/Wizard/Wizard.d.ts +11 -14
  25. package/dist/esm/next/components/Wizard/Wizard.d.ts.map +1 -1
  26. package/dist/esm/next/components/Wizard/Wizard.js +30 -23
  27. package/dist/esm/next/components/Wizard/Wizard.js.map +1 -1
  28. package/dist/esm/next/components/Wizard/WizardContext.d.ts +16 -16
  29. package/dist/esm/next/components/Wizard/WizardContext.d.ts.map +1 -1
  30. package/dist/esm/next/components/Wizard/WizardContext.js +17 -19
  31. package/dist/esm/next/components/Wizard/WizardContext.js.map +1 -1
  32. package/dist/esm/next/components/Wizard/WizardFooter.d.ts +8 -5
  33. package/dist/esm/next/components/Wizard/WizardFooter.d.ts.map +1 -1
  34. package/dist/esm/next/components/Wizard/WizardFooter.js +1 -1
  35. package/dist/esm/next/components/Wizard/WizardFooter.js.map +1 -1
  36. package/dist/esm/next/components/Wizard/WizardHeader.d.ts +1 -1
  37. package/dist/esm/next/components/Wizard/WizardHeader.d.ts.map +1 -1
  38. package/dist/esm/next/components/Wizard/WizardNavInternal.d.ts +2 -2
  39. package/dist/esm/next/components/Wizard/WizardNavInternal.d.ts.map +1 -1
  40. package/dist/esm/next/components/Wizard/WizardNavInternal.js +15 -9
  41. package/dist/esm/next/components/Wizard/WizardNavInternal.js.map +1 -1
  42. package/dist/esm/next/components/Wizard/WizardNavItem.d.ts +10 -4
  43. package/dist/esm/next/components/Wizard/WizardNavItem.d.ts.map +1 -1
  44. package/dist/esm/next/components/Wizard/WizardNavItem.js +10 -9
  45. package/dist/esm/next/components/Wizard/WizardNavItem.js.map +1 -1
  46. package/dist/esm/next/components/Wizard/WizardStep.d.ts +3 -3
  47. package/dist/esm/next/components/Wizard/WizardStep.d.ts.map +1 -1
  48. package/dist/esm/next/components/Wizard/WizardStep.js +4 -2
  49. package/dist/esm/next/components/Wizard/WizardStep.js.map +1 -1
  50. package/dist/esm/next/components/Wizard/WizardToggle.d.ts +4 -4
  51. package/dist/esm/next/components/Wizard/WizardToggle.d.ts.map +1 -1
  52. package/dist/esm/next/components/Wizard/WizardToggle.js +1 -1
  53. package/dist/esm/next/components/Wizard/WizardToggle.js.map +1 -1
  54. package/dist/esm/next/components/Wizard/hooks/index.d.ts +1 -0
  55. package/dist/esm/next/components/Wizard/hooks/index.d.ts.map +1 -1
  56. package/dist/esm/next/components/Wizard/hooks/index.js +1 -0
  57. package/dist/esm/next/components/Wizard/hooks/index.js.map +1 -1
  58. package/dist/esm/next/components/Wizard/hooks/useGetMergedSteps.d.ts +9 -0
  59. package/dist/esm/next/components/Wizard/hooks/useGetMergedSteps.d.ts.map +1 -0
  60. package/dist/esm/next/components/Wizard/hooks/useGetMergedSteps.js +33 -0
  61. package/dist/esm/next/components/Wizard/hooks/useGetMergedSteps.js.map +1 -0
  62. package/dist/esm/next/components/Wizard/index.d.ts +2 -2
  63. package/dist/esm/next/components/Wizard/index.d.ts.map +1 -1
  64. package/dist/esm/next/components/Wizard/index.js +2 -2
  65. package/dist/esm/next/components/Wizard/index.js.map +1 -1
  66. package/dist/esm/next/components/Wizard/types.d.ts +13 -19
  67. package/dist/esm/next/components/Wizard/types.d.ts.map +1 -1
  68. package/dist/esm/next/components/Wizard/types.js +6 -0
  69. package/dist/esm/next/components/Wizard/types.js.map +1 -1
  70. package/dist/esm/next/components/Wizard/utils.d.ts +5 -6
  71. package/dist/esm/next/components/Wizard/utils.d.ts.map +1 -1
  72. package/dist/esm/next/components/Wizard/utils.js +15 -22
  73. package/dist/esm/next/components/Wizard/utils.js.map +1 -1
  74. package/dist/js/components/Menu/MenuGroup.d.ts +1 -1
  75. package/dist/js/components/Menu/MenuGroup.d.ts.map +1 -1
  76. package/dist/js/components/Menu/MenuGroup.js.map +1 -1
  77. package/dist/js/components/Select/Select.d.ts +2 -0
  78. package/dist/js/components/Select/Select.d.ts.map +1 -1
  79. package/dist/js/components/Select/Select.js +3 -3
  80. package/dist/js/components/Select/Select.js.map +1 -1
  81. package/dist/js/components/Select/SelectToggle.d.ts +4 -14
  82. package/dist/js/components/Select/SelectToggle.d.ts.map +1 -1
  83. package/dist/js/components/Select/SelectToggle.js +11 -6
  84. package/dist/js/components/Select/SelectToggle.js.map +1 -1
  85. package/dist/js/next/components/Wizard/Wizard.d.ts +11 -14
  86. package/dist/js/next/components/Wizard/Wizard.d.ts.map +1 -1
  87. package/dist/js/next/components/Wizard/Wizard.js +28 -21
  88. package/dist/js/next/components/Wizard/Wizard.js.map +1 -1
  89. package/dist/js/next/components/Wizard/WizardContext.d.ts +16 -16
  90. package/dist/js/next/components/Wizard/WizardContext.d.ts.map +1 -1
  91. package/dist/js/next/components/Wizard/WizardContext.js +16 -17
  92. package/dist/js/next/components/Wizard/WizardContext.js.map +1 -1
  93. package/dist/js/next/components/Wizard/WizardFooter.d.ts +8 -5
  94. package/dist/js/next/components/Wizard/WizardFooter.d.ts.map +1 -1
  95. package/dist/js/next/components/Wizard/WizardFooter.js +1 -1
  96. package/dist/js/next/components/Wizard/WizardFooter.js.map +1 -1
  97. package/dist/js/next/components/Wizard/WizardHeader.d.ts +1 -1
  98. package/dist/js/next/components/Wizard/WizardHeader.d.ts.map +1 -1
  99. package/dist/js/next/components/Wizard/WizardNavInternal.d.ts +2 -2
  100. package/dist/js/next/components/Wizard/WizardNavInternal.d.ts.map +1 -1
  101. package/dist/js/next/components/Wizard/WizardNavInternal.js +15 -9
  102. package/dist/js/next/components/Wizard/WizardNavInternal.js.map +1 -1
  103. package/dist/js/next/components/Wizard/WizardNavItem.d.ts +10 -4
  104. package/dist/js/next/components/Wizard/WizardNavItem.d.ts.map +1 -1
  105. package/dist/js/next/components/Wizard/WizardNavItem.js +10 -8
  106. package/dist/js/next/components/Wizard/WizardNavItem.js.map +1 -1
  107. package/dist/js/next/components/Wizard/WizardStep.d.ts +3 -3
  108. package/dist/js/next/components/Wizard/WizardStep.d.ts.map +1 -1
  109. package/dist/js/next/components/Wizard/WizardStep.js +4 -2
  110. package/dist/js/next/components/Wizard/WizardStep.js.map +1 -1
  111. package/dist/js/next/components/Wizard/WizardToggle.d.ts +4 -4
  112. package/dist/js/next/components/Wizard/WizardToggle.d.ts.map +1 -1
  113. package/dist/js/next/components/Wizard/WizardToggle.js +1 -1
  114. package/dist/js/next/components/Wizard/WizardToggle.js.map +1 -1
  115. package/dist/js/next/components/Wizard/hooks/index.d.ts +1 -0
  116. package/dist/js/next/components/Wizard/hooks/index.d.ts.map +1 -1
  117. package/dist/js/next/components/Wizard/hooks/index.js +3 -1
  118. package/dist/js/next/components/Wizard/hooks/index.js.map +1 -1
  119. package/dist/js/next/components/Wizard/hooks/useGetMergedSteps.d.ts +9 -0
  120. package/dist/js/next/components/Wizard/hooks/useGetMergedSteps.d.ts.map +1 -0
  121. package/dist/js/next/components/Wizard/hooks/useGetMergedSteps.js +38 -0
  122. package/dist/js/next/components/Wizard/hooks/useGetMergedSteps.js.map +1 -0
  123. package/dist/js/next/components/Wizard/index.d.ts +2 -2
  124. package/dist/js/next/components/Wizard/index.d.ts.map +1 -1
  125. package/dist/js/next/components/Wizard/index.js +4 -2
  126. package/dist/js/next/components/Wizard/index.js.map +1 -1
  127. package/dist/js/next/components/Wizard/types.d.ts +13 -19
  128. package/dist/js/next/components/Wizard/types.d.ts.map +1 -1
  129. package/dist/js/next/components/Wizard/types.js +7 -1
  130. package/dist/js/next/components/Wizard/types.js.map +1 -1
  131. package/dist/js/next/components/Wizard/utils.d.ts +5 -6
  132. package/dist/js/next/components/Wizard/utils.d.ts.map +1 -1
  133. package/dist/js/next/components/Wizard/utils.js +17 -25
  134. package/dist/js/next/components/Wizard/utils.js.map +1 -1
  135. package/dist/umd/react-core.min.js +2 -2
  136. package/next/components/Wizard/Wizard.d.ts +11 -14
  137. package/next/components/Wizard/Wizard.d.ts.map +1 -1
  138. package/next/components/Wizard/Wizard.js +30 -23
  139. package/next/components/Wizard/Wizard.js.map +1 -1
  140. package/next/components/Wizard/WizardContext.d.ts +16 -16
  141. package/next/components/Wizard/WizardContext.d.ts.map +1 -1
  142. package/next/components/Wizard/WizardContext.js +17 -19
  143. package/next/components/Wizard/WizardContext.js.map +1 -1
  144. package/next/components/Wizard/WizardFooter.d.ts +8 -5
  145. package/next/components/Wizard/WizardFooter.d.ts.map +1 -1
  146. package/next/components/Wizard/WizardFooter.js +1 -1
  147. package/next/components/Wizard/WizardFooter.js.map +1 -1
  148. package/next/components/Wizard/WizardHeader.d.ts +1 -1
  149. package/next/components/Wizard/WizardHeader.d.ts.map +1 -1
  150. package/next/components/Wizard/WizardNavInternal.d.ts +2 -2
  151. package/next/components/Wizard/WizardNavInternal.d.ts.map +1 -1
  152. package/next/components/Wizard/WizardNavInternal.js +15 -9
  153. package/next/components/Wizard/WizardNavInternal.js.map +1 -1
  154. package/next/components/Wizard/WizardNavItem.d.ts +10 -4
  155. package/next/components/Wizard/WizardNavItem.d.ts.map +1 -1
  156. package/next/components/Wizard/WizardNavItem.js +10 -9
  157. package/next/components/Wizard/WizardNavItem.js.map +1 -1
  158. package/next/components/Wizard/WizardStep.d.ts +3 -3
  159. package/next/components/Wizard/WizardStep.d.ts.map +1 -1
  160. package/next/components/Wizard/WizardStep.js +4 -2
  161. package/next/components/Wizard/WizardStep.js.map +1 -1
  162. package/next/components/Wizard/WizardToggle.d.ts +4 -4
  163. package/next/components/Wizard/WizardToggle.d.ts.map +1 -1
  164. package/next/components/Wizard/WizardToggle.js +1 -1
  165. package/next/components/Wizard/WizardToggle.js.map +1 -1
  166. package/next/components/Wizard/hooks/index.d.ts +1 -0
  167. package/next/components/Wizard/hooks/index.d.ts.map +1 -1
  168. package/next/components/Wizard/hooks/index.js +1 -0
  169. package/next/components/Wizard/hooks/index.js.map +1 -1
  170. package/next/components/Wizard/hooks/useGetMergedSteps.d.ts +9 -0
  171. package/next/components/Wizard/hooks/useGetMergedSteps.d.ts.map +1 -0
  172. package/next/components/Wizard/hooks/useGetMergedSteps.js +33 -0
  173. package/next/components/Wizard/hooks/useGetMergedSteps.js.map +1 -0
  174. package/next/components/Wizard/index.d.ts +2 -2
  175. package/next/components/Wizard/index.d.ts.map +1 -1
  176. package/next/components/Wizard/index.js +2 -2
  177. package/next/components/Wizard/index.js.map +1 -1
  178. package/next/components/Wizard/types.d.ts +13 -19
  179. package/next/components/Wizard/types.d.ts.map +1 -1
  180. package/next/components/Wizard/types.js +6 -0
  181. package/next/components/Wizard/types.js.map +1 -1
  182. package/next/components/Wizard/utils.d.ts +5 -6
  183. package/next/components/Wizard/utils.d.ts.map +1 -1
  184. package/next/components/Wizard/utils.js +15 -22
  185. package/next/components/Wizard/utils.js.map +1 -1
  186. package/package.json +2 -2
  187. package/src/components/Menu/MenuGroup.tsx +2 -2
  188. package/src/components/Select/Select.tsx +4 -0
  189. package/src/components/Select/SelectToggle.tsx +14 -3
  190. package/src/components/Select/examples/Select.md +28 -0
  191. package/src/next/components/Wizard/Wizard.tsx +71 -46
  192. package/src/next/components/Wizard/WizardContext.tsx +38 -43
  193. package/src/next/components/Wizard/WizardFooter.tsx +10 -6
  194. package/src/next/components/Wizard/WizardHeader.tsx +1 -1
  195. package/src/next/components/Wizard/WizardNavInternal.tsx +51 -43
  196. package/src/next/components/Wizard/WizardNavItem.tsx +21 -14
  197. package/src/next/components/Wizard/WizardStep.tsx +8 -6
  198. package/src/next/components/Wizard/WizardToggle.tsx +5 -5
  199. package/src/next/components/Wizard/__tests__/Wizard.test.tsx +129 -26
  200. package/src/next/components/Wizard/__tests__/WizardStep.test.tsx +5 -5
  201. package/src/next/components/Wizard/__tests__/WizardToggle.test.tsx +2 -2
  202. package/src/next/components/Wizard/__tests__/utils.test.tsx +3 -17
  203. package/src/next/components/Wizard/examples/Wizard.md +69 -41
  204. package/src/next/components/Wizard/examples/WizardBasic.tsx +6 -12
  205. package/src/next/components/Wizard/examples/WizardBasicDisabledSteps.tsx +22 -0
  206. package/src/next/components/Wizard/examples/WizardEnabledOnFormValidation.tsx +84 -0
  207. package/src/next/components/Wizard/examples/WizardExpandableSteps.tsx +42 -0
  208. package/src/next/components/Wizard/examples/WizardGetCurrentStep.tsx +53 -0
  209. package/src/next/components/Wizard/examples/WizardProgressiveSteps.tsx +31 -0
  210. package/src/next/components/Wizard/examples/WizardStepDrawerContent.tsx +80 -0
  211. package/src/next/components/Wizard/examples/WizardStepErrorStatus.tsx +55 -0
  212. package/src/next/components/Wizard/examples/WizardStepVisitRequired.tsx +22 -0
  213. package/src/next/components/Wizard/examples/WizardToggleStepVisibility.tsx +57 -0
  214. package/src/next/components/Wizard/examples/WizardValidateOnButtonPress.tsx +183 -0
  215. package/src/next/components/Wizard/examples/WizardWithCustomFooter.tsx +107 -0
  216. package/src/next/components/Wizard/examples/{WizardCustomNav.tsx → WizardWithCustomNav.tsx} +11 -11
  217. package/src/next/components/Wizard/examples/WizardWithCustomNavItem.tsx +22 -0
  218. package/src/next/components/Wizard/examples/WizardWithHeader.tsx +26 -0
  219. package/src/next/components/Wizard/examples/WizardWithNavAnchors.tsx +46 -0
  220. package/src/next/components/Wizard/examples/WizardWithSubmitProgress.tsx +86 -0
  221. package/src/next/components/Wizard/examples/WizardWithinModal.tsx +41 -0
  222. package/src/next/components/Wizard/hooks/index.ts +1 -0
  223. package/src/next/components/Wizard/hooks/useGetMergedSteps.tsx +45 -0
  224. package/src/next/components/Wizard/index.ts +2 -2
  225. package/src/next/components/Wizard/types.tsx +19 -29
  226. package/src/next/components/Wizard/utils.ts +27 -33
  227. package/src/next/components/Wizard/examples/WizardKitchenSink.tsx +0 -243
@@ -11,12 +11,12 @@ import { WizardNavItem } from './WizardNavItem';
11
11
  * This component is not exposed to consumers.
12
12
  */
13
13
 
14
- interface WizardNavInternalProps extends Pick<WizardProps, 'isStepVisitRequired'> {
14
+ interface WizardNavInternalProps extends Pick<WizardProps, 'isVisitRequired' | 'isProgressive'> {
15
15
  nav: Partial<WizardNavProps>;
16
16
  isNavExpanded: boolean;
17
17
  }
18
18
 
19
- export const WizardNavInternal = ({ nav, isStepVisitRequired, isNavExpanded }: WizardNavInternalProps) => {
19
+ export const WizardNavInternal = ({ nav, isVisitRequired, isProgressive, isNavExpanded }: WizardNavInternalProps) => {
20
20
  const { activeStep, steps, goToStepByIndex } = useWizardContext();
21
21
 
22
22
  const wizardNavProps: WizardNavProps = {
@@ -31,7 +31,7 @@ export const WizardNavInternal = ({ nav, isStepVisitRequired, isNavExpanded }: W
31
31
  <WizardNav {...wizardNavProps}>
32
32
  {steps.map((step, stepIndex) => {
33
33
  const hasVisitedNextStep = steps.some(step => step.index > stepIndex + 1 && step.isVisited);
34
- const isStepDisabled = step.isDisabled || (isStepVisitRequired && !step.isVisited && !hasVisitedNextStep);
34
+ const isStepDisabled = step.isDisabled || (isVisitRequired && !step.isVisited && !hasVisitedNextStep);
35
35
  const customStepNavItem = isCustomWizardNavItem(step.navItem) && (
36
36
  <React.Fragment key={step.id}>
37
37
  {typeof step.navItem === 'function' ? step.navItem(step, activeStep, steps, goToStepByIndex) : step.navItem}
@@ -46,7 +46,7 @@ export const WizardNavInternal = ({ nav, isStepVisitRequired, isNavExpanded }: W
46
46
  const subStep = steps.find(step => step.id === subStepId);
47
47
  const hasVisitedNextStep = steps.some(step => step.index > subStep.index && step.isVisited);
48
48
  const isSubStepDisabled =
49
- subStep.isDisabled || (isStepVisitRequired && !subStep.isVisited && !hasVisitedNextStep);
49
+ subStep.isDisabled || (isVisitRequired && !subStep.isVisited && !hasVisitedNextStep);
50
50
  const customSubStepNavItem = isCustomWizardNavItem(subStep.navItem) && (
51
51
  <React.Fragment key={subStep.id}>
52
52
  {typeof subStep.navItem === 'function'
@@ -70,51 +70,59 @@ export const WizardNavInternal = ({ nav, isStepVisitRequired, isNavExpanded }: W
70
70
  hasActiveChild = true;
71
71
  }
72
72
 
73
- return (
74
- customSubStepNavItem || (
75
- <WizardNavItem
76
- key={subStep.id}
77
- id={subStep.id}
78
- content={subStep.name}
79
- isCurrent={activeStep?.id === subStep.id}
80
- isDisabled={isSubStepDisabled}
81
- isVisited={subStep.isVisited}
82
- stepIndex={subStep.index}
83
- onNavItemClick={goToStepByIndex}
84
- status={subStep.status}
85
- {...subStep.navItem}
86
- />
87
- )
88
- );
73
+ if (!isProgressive || (isProgressive && subStep.index <= activeStep.index)) {
74
+ return (
75
+ customSubStepNavItem || (
76
+ <WizardNavItem
77
+ key={subStep.id}
78
+ id={subStep.id}
79
+ content={subStep.name}
80
+ isCurrent={activeStep?.id === subStep.id}
81
+ isDisabled={isSubStepDisabled}
82
+ isVisited={subStep.isVisited}
83
+ stepIndex={subStep.index}
84
+ onClick={() => goToStepByIndex(subStep.index)}
85
+ status={subStep.status}
86
+ {...subStep.navItem}
87
+ />
88
+ )
89
+ );
90
+ }
89
91
  });
90
92
  const hasEnabledChildren = React.Children.toArray(subNavItems).some(
91
93
  child => React.isValidElement(child) && !child.props.isDisabled
92
94
  );
93
95
 
94
- return (
95
- customStepNavItem || (
96
- <WizardNavItem
97
- key={step.id}
98
- id={step.id}
99
- content={step.name}
100
- isExpandable={step.isCollapsible ?? true}
101
- isCurrent={hasActiveChild}
102
- isDisabled={!hasEnabledChildren}
103
- isVisited={step.isVisited}
104
- stepIndex={firstSubStepIndex}
105
- onNavItemClick={goToStepByIndex}
106
- status={step.status}
107
- {...step.navItem}
108
- >
109
- <WizardNav {...wizardNavProps} isInnerList>
110
- {subNavItems}
111
- </WizardNav>
112
- </WizardNavItem>
113
- )
114
- );
96
+ if (!isProgressive || (isProgressive && step.index <= activeStep.index)) {
97
+ return (
98
+ customStepNavItem || (
99
+ <WizardNavItem
100
+ key={step.id}
101
+ id={step.id}
102
+ content={step.name}
103
+ isExpandable={step.isExpandable}
104
+ isCurrent={hasActiveChild}
105
+ isDisabled={!hasEnabledChildren}
106
+ isVisited={step.isVisited}
107
+ stepIndex={firstSubStepIndex}
108
+ onClick={() => goToStepByIndex(firstSubStepIndex)}
109
+ status={step.status}
110
+ {...step.navItem}
111
+ >
112
+ <WizardNav {...wizardNavProps} isInnerList>
113
+ {subNavItems}
114
+ </WizardNav>
115
+ </WizardNavItem>
116
+ )
117
+ );
118
+ }
115
119
  }
116
120
 
117
- if (isWizardBasicStep(step) && !step.isHidden) {
121
+ if (
122
+ isWizardBasicStep(step) &&
123
+ !step.isHidden &&
124
+ (!isProgressive || (isProgressive && step.index <= activeStep.index))
125
+ ) {
118
126
  return (
119
127
  customStepNavItem || (
120
128
  <WizardNavItem
@@ -125,7 +133,7 @@ export const WizardNavInternal = ({ nav, isStepVisitRequired, isNavExpanded }: W
125
133
  isDisabled={isStepDisabled}
126
134
  isVisited={step.isVisited}
127
135
  stepIndex={step.index}
128
- onNavItemClick={goToStepByIndex}
136
+ onClick={() => goToStepByIndex(step.index)}
129
137
  status={step.status}
130
138
  {...step.navItem}
131
139
  />
@@ -5,9 +5,10 @@ import styles from '@patternfly/react-styles/css/components/Wizard/wizard';
5
5
  import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
6
6
  import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
7
7
 
8
+ import { OUIAProps, useOUIAProps } from '../../../helpers';
8
9
  import { WizardNavItemStatus } from './types';
9
10
 
10
- export interface WizardNavItemProps {
11
+ export interface WizardNavItemProps extends OUIAProps {
11
12
  /** Can nest a WizardNav component for substeps */
12
13
  children?: React.ReactNode;
13
14
  /** The content to display in the navigation item */
@@ -21,11 +22,13 @@ export interface WizardNavItemProps {
21
22
  /** The step index passed into the onNavItemClick callback */
22
23
  stepIndex: number;
23
24
  /** Callback for when the navigation item is clicked */
24
- onNavItemClick?: (stepIndex: number) => any;
25
+ onClick?: (event: React.MouseEvent<HTMLButtonElement> | React.MouseEvent<HTMLAnchorElement>, index: number) => any;
25
26
  /** Component used to render WizardNavItem */
26
- navItemComponent?: 'button' | 'a';
27
+ component?: 'button' | 'a';
27
28
  /** An optional url to use for when using an anchor component */
28
29
  href?: string;
30
+ /** Where to display the linked URL when using an anchor component */
31
+ target?: React.HTMLAttributeAnchorTarget;
29
32
  /** Flag indicating that this NavItem has child steps and is expandable */
30
33
  isExpandable?: boolean;
31
34
  /** The id for the navigation item */
@@ -34,29 +37,31 @@ export interface WizardNavItemProps {
34
37
  status?: 'default' | 'error';
35
38
  }
36
39
 
37
- export const WizardNavItem: React.FunctionComponent<WizardNavItemProps> = ({
40
+ export const WizardNavItem = ({
38
41
  children = null,
39
42
  content = '',
40
43
  isCurrent = false,
41
44
  isDisabled = false,
42
45
  isVisited = false,
43
46
  stepIndex,
44
- onNavItemClick = () => undefined,
45
- navItemComponent = 'button',
46
- href = null,
47
+ onClick,
48
+ component: NavItemComponent = 'button',
49
+ href,
47
50
  isExpandable = false,
48
51
  id,
49
52
  status = 'default',
50
- ...rest
53
+ target,
54
+ ouiaId,
55
+ ouiaSafe = true
51
56
  }: WizardNavItemProps) => {
52
- const NavItemComponent = navItemComponent;
53
57
  const [isExpanded, setIsExpanded] = React.useState(false);
58
+ const ouiaProps = useOUIAProps(WizardNavItem.displayName, ouiaId, ouiaSafe);
54
59
 
55
60
  React.useEffect(() => {
56
61
  setIsExpanded(isCurrent);
57
62
  }, [isCurrent]);
58
63
 
59
- if (navItemComponent === 'a' && !href && process.env.NODE_ENV !== 'production') {
64
+ if (NavItemComponent === 'a' && !href && process.env.NODE_ENV !== 'production') {
60
65
  // eslint-disable-next-line no-console
61
66
  console.error('WizardNavItem: When using an anchor, please provide an href');
62
67
  }
@@ -87,12 +92,13 @@ export const WizardNavItem: React.FunctionComponent<WizardNavItemProps> = ({
87
92
  )}
88
93
  >
89
94
  <NavItemComponent
90
- {...rest}
91
- {...(navItemComponent === 'a' ? { tabIndex: isDisabled ? -1 : undefined, href } : { disabled: isDisabled })}
95
+ {...(NavItemComponent === 'a'
96
+ ? { tabIndex: isDisabled ? -1 : undefined, href, target }
97
+ : { disabled: isDisabled })}
92
98
  {...(id && { id: id.toString() })}
93
99
  onClick={e => {
94
- e.preventDefault();
95
- isExpandable ? setIsExpanded(!isExpanded || isCurrent) : onNavItemClick(stepIndex);
100
+ e.stopPropagation();
101
+ isExpandable ? setIsExpanded(!isExpanded || isCurrent) : onClick?.(e, stepIndex);
96
102
  }}
97
103
  className={css(
98
104
  styles.wizardNavLink,
@@ -103,6 +109,7 @@ export const WizardNavItem: React.FunctionComponent<WizardNavItemProps> = ({
103
109
  aria-current={isCurrent && !children ? 'step' : false}
104
110
  {...(isExpandable && { 'aria-expanded': isExpanded })}
105
111
  {...(ariaLabel && { 'aria-label': ariaLabel })}
112
+ {...ouiaProps}
106
113
  >
107
114
  {isExpandable ? (
108
115
  <>
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
 
3
- import { WizardNavItemType } from './types';
3
+ import { isWizardParentStep, WizardNavItemType } from './types';
4
4
  import { WizardBodyProps } from './WizardBody';
5
5
  import { useWizardContext } from './WizardContext';
6
6
  import { WizardFooterProps } from './WizardFooter';
@@ -15,7 +15,7 @@ export interface WizardStepProps {
15
15
  /** Unique identifier */
16
16
  id: string | number;
17
17
  /** Optional for when the step is used as a parent to sub-steps */
18
- children?: React.ReactNode;
18
+ children?: React.ReactNode | undefined;
19
19
  /** Props for WizardBody that wraps content by default. Can be set to null for exclusion of WizardBody. */
20
20
  body?: Omit<Omit<WizardBodyProps, 'children'>, 'children'> | null;
21
21
  /** Optional list of sub-steps */
@@ -30,8 +30,8 @@ export interface WizardStepProps {
30
30
  footer?: React.ReactElement | Partial<WizardFooterProps>;
31
31
  /** Used to determine icon next to the step's navigation item */
32
32
  status?: 'default' | 'error';
33
- /** Flag to determine whether sub-steps can collapse or not */
34
- isCollapsible?: boolean;
33
+ /** Flag to determine whether parent steps can expand or not. Defaults to false. */
34
+ isExpandable?: boolean;
35
35
  }
36
36
 
37
37
  export const WizardStep = ({ children, steps: _subSteps, ...props }: WizardStepProps) => {
@@ -40,6 +40,8 @@ export const WizardStep = ({ children, steps: _subSteps, ...props }: WizardStepP
40
40
 
41
41
  // Update step in context when props change or when the step is active has yet to be marked as visited.
42
42
  React.useEffect(() => {
43
+ const shouldUpdateIsVisited = !isWizardParentStep(activeStep) && id === activeStep?.id && !activeStep?.isVisited;
44
+
43
45
  setStep({
44
46
  id,
45
47
  name,
@@ -49,9 +51,9 @@ export const WizardStep = ({ children, steps: _subSteps, ...props }: WizardStepP
49
51
  ...(navItem && { navItem }),
50
52
  ...(footer && { footer }),
51
53
  ...(status && { status }),
52
- ...(id === activeStep?.id && !activeStep?.isVisited && { isVisited: true })
54
+ ...(shouldUpdateIsVisited && { isVisited: true })
53
55
  });
54
- }, [body, footer, id, isDisabled, isHidden, name, navItem, status, activeStep?.id, activeStep?.isVisited, setStep]);
56
+ }, [body, footer, id, isDisabled, isHidden, name, navItem, status, activeStep, setStep]);
55
57
 
56
58
  return <>{children}</>;
57
59
  };
@@ -7,7 +7,7 @@ import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-ico
7
7
 
8
8
  import { KeyTypes } from '../../../helpers/constants';
9
9
  import { WizardNavProps, WizardBody, WizardStep, WizardStepProps } from '../Wizard';
10
- import { WizardControlStep, isWizardSubStep } from './types';
10
+ import { WizardStepType, isWizardSubStep } from './types';
11
11
 
12
12
  /**
13
13
  * Used to toggle between step content, including the body and footer. This is also where the navigation and its expandability is controlled.
@@ -15,9 +15,9 @@ import { WizardControlStep, isWizardSubStep } from './types';
15
15
 
16
16
  export interface WizardToggleProps {
17
17
  /** List of steps and/or sub-steps */
18
- steps: WizardControlStep[];
18
+ steps: WizardStepType[];
19
19
  /** The current step */
20
- activeStep: WizardControlStep;
20
+ activeStep: WizardStepType;
21
21
  /** Wizard footer */
22
22
  footer: React.ReactElement;
23
23
  /** Wizard navigation */
@@ -27,7 +27,7 @@ export interface WizardToggleProps {
27
27
  /** Flag to determine whether the dropdown navigation is expanded */
28
28
  isNavExpanded?: boolean;
29
29
  /** Callback to expand or collapse the dropdown navigation */
30
- toggleNavExpanded?: () => void;
30
+ toggleNavExpanded?: (event: React.MouseEvent<HTMLButtonElement> | KeyboardEvent) => void;
31
31
  }
32
32
 
33
33
  export const WizardToggle = ({
@@ -49,7 +49,7 @@ export const WizardToggle = ({
49
49
  const handleKeyClicks = React.useCallback(
50
50
  (event: KeyboardEvent): void => {
51
51
  if (isNavExpanded && event.key === KeyTypes.Escape) {
52
- toggleNavExpanded?.();
52
+ toggleNavExpanded?.(event);
53
53
  }
54
54
  },
55
55
  [isNavExpanded, toggleNavExpanded]
@@ -18,21 +18,6 @@ test('renders step when child is of type WizardStep', () => {
18
18
  expect(screen.getByText('Step content')).toBeVisible();
19
19
  });
20
20
 
21
- test('renders step when child has required props; name, id, children', () => {
22
- const CustomStep = props => <div {...props} />;
23
-
24
- render(
25
- <Wizard>
26
- <CustomStep id="test-step" name="Test step">
27
- Custom step content
28
- </CustomStep>
29
- </Wizard>
30
- );
31
-
32
- expect(screen.getByRole('button', { name: 'Test step' })).toBeVisible();
33
- expect(screen.getByText('Custom step content')).toBeVisible();
34
- });
35
-
36
21
  test('renders a header when specified', () => {
37
22
  render(
38
23
  <Wizard header="Some header">
@@ -101,7 +86,7 @@ test('renders default nav with custom props', () => {
101
86
  };
102
87
 
103
88
  render(
104
- <Wizard id="wizard-id" nav={nav} isStepVisitRequired>
89
+ <Wizard id="wizard-id" nav={nav} isVisitRequired>
105
90
  <WizardStep id="step-1" name="Test step 1" steps={[<WizardStep id="nested-step" name="Nested step" />]} />
106
91
  <WizardStep id="step-2" name="Test step 2" />
107
92
  </Wizard>
@@ -111,7 +96,6 @@ test('renders default nav with custom props', () => {
111
96
 
112
97
  expect(navElement).toBeVisible();
113
98
  expect(navElement).toHaveAttribute('aria-labelledby', 'wizard-id');
114
- expect(screen.getByRole('button', { name: 'Test step 1, visited' }).parentElement).toHaveClass('pf-m-expandable');
115
99
  expect(screen.getByRole('button', { name: 'Test step 2' })).toHaveAttribute('disabled');
116
100
  });
117
101
 
@@ -183,7 +167,7 @@ test('calls onNavByIndex on nav item click', async () => {
183
167
  const onNavByIndex = jest.fn();
184
168
 
185
169
  render(
186
- <Wizard onNavByIndex={onNavByIndex}>
170
+ <Wizard onStepChange={onNavByIndex}>
187
171
  <WizardStep id="step-1" name="Test step 1" />
188
172
  <WizardStep id="step-2" name="Test step 2" />
189
173
  </Wizard>
@@ -199,7 +183,7 @@ test('calls onNext and not onSave on next button click when not on the last step
199
183
  const onSave = jest.fn();
200
184
 
201
185
  render(
202
- <Wizard onNext={onNext} onSave={onSave}>
186
+ <Wizard onStepChange={onNext} onSave={onSave}>
203
187
  <WizardStep id="step-1" name="Test step 1" />
204
188
  <WizardStep id="step-2" name="Test step 2" />
205
189
  </Wizard>
@@ -216,7 +200,7 @@ test('calls onBack on back button click', async () => {
216
200
  const onBack = jest.fn();
217
201
 
218
202
  render(
219
- <Wizard onBack={onBack}>
203
+ <Wizard onStepChange={onBack}>
220
204
  <WizardStep id="step-1" name="Test step 1" />
221
205
  <WizardStep id="step-2" name="Test step 2" />
222
206
  </Wizard>
@@ -298,13 +282,18 @@ test('does not render inactive step content', async () => {
298
282
  expect(screen.getByText('Step 2 content')).toBeVisible();
299
283
  });
300
284
 
301
- test('parent steps have collapsed sub-steps by default unless the step is active', async () => {
285
+ test('parent steps have collapsed sub-steps when isExpandable is true unless the step is active', async () => {
302
286
  const user = userEvent.setup();
303
287
 
304
288
  render(
305
- <Wizard startIndex={2}>
289
+ <Wizard>
306
290
  <WizardStep id="step-1" name="Test step 1" />
307
- <WizardStep id="step-2" name="Test step 2" steps={[<WizardStep id="sub-step-1" name="Test sub step 1" />]} />
291
+ <WizardStep
292
+ id="step-2"
293
+ name="Test step 2"
294
+ isExpandable
295
+ steps={[<WizardStep id="sub-step-1" name="Test sub step 1" />]}
296
+ />
308
297
  </Wizard>
309
298
  );
310
299
 
@@ -315,17 +304,131 @@ test('parent steps have collapsed sub-steps by default unless the step is active
315
304
  expect(screen.getByLabelText('Collapse step icon')).toBeVisible();
316
305
  });
317
306
 
318
- test('parent step can be non-collapsible by setting isCollapsible to false', () => {
307
+ test('parent step can be expandable by setting isExpandable to true', () => {
319
308
  render(
320
309
  <Wizard>
321
310
  <WizardStep
322
311
  id="step-1"
323
312
  name="Test step 1"
324
- isCollapsible={false}
313
+ isExpandable
325
314
  steps={[<WizardStep id="sub-step-1" name="Sub step 1" />]}
326
315
  />
327
316
  </Wizard>
328
317
  );
329
318
 
330
- expect(screen.queryByLabelText('step icon', { exact: false })).toBeNull();
319
+ expect(screen.queryByLabelText('step icon', { exact: false })).toBeVisible();
320
+ });
321
+
322
+ test('incrementally shows/hides steps based on the activeStep when isProgressive is enabled', async () => {
323
+ const user = userEvent.setup();
324
+
325
+ render(
326
+ <Wizard isProgressive>
327
+ <WizardStep id="step-1" name="Test step 1">
328
+ Step 1 content
329
+ </WizardStep>
330
+ <WizardStep id="step-2" name="Test step 2">
331
+ Step 2 content
332
+ </WizardStep>
333
+ <WizardStep id="step-3" name="Test step 3">
334
+ Step 3 content
335
+ </WizardStep>
336
+ </Wizard>
337
+ );
338
+
339
+ const nextButton = screen.getByRole('button', {
340
+ name: 'Next'
341
+ });
342
+ const backButton = screen.getByRole('button', {
343
+ name: 'Back'
344
+ });
345
+
346
+ // Initially only the first nav item will be visible
347
+ expect(
348
+ screen.getByRole('button', {
349
+ name: 'Test step 1'
350
+ })
351
+ ).toBeVisible();
352
+ expect(
353
+ screen.queryByRole('button', {
354
+ name: 'Test step 2'
355
+ })
356
+ ).toBeNull();
357
+ expect(
358
+ screen.queryByRole('button', {
359
+ name: 'Test step 3'
360
+ })
361
+ ).toBeNull();
362
+
363
+ // Progressing to the next step will show steps 1 & 2
364
+ await user.click(nextButton);
365
+ expect(
366
+ screen.getByRole('button', {
367
+ name: 'Test step 1, visited'
368
+ })
369
+ ).toBeVisible();
370
+ expect(
371
+ screen.getByRole('button', {
372
+ name: 'Test step 2'
373
+ })
374
+ ).toBeVisible();
375
+ expect(
376
+ screen.queryByRole('button', {
377
+ name: 'Test step 3'
378
+ })
379
+ ).toBeNull();
380
+
381
+ // Progressing to the next step will show all steps
382
+ await user.click(nextButton);
383
+ expect(
384
+ screen.getByRole('button', {
385
+ name: 'Test step 1, visited'
386
+ })
387
+ ).toBeVisible();
388
+ expect(
389
+ screen.getByRole('button', {
390
+ name: 'Test step 2, visited'
391
+ })
392
+ ).toBeVisible();
393
+ expect(
394
+ screen.getByRole('button', {
395
+ name: 'Test step 3'
396
+ })
397
+ ).toBeVisible();
398
+
399
+ // Going back a step will hide step 3
400
+ await user.click(backButton);
401
+ expect(
402
+ screen.getByRole('button', {
403
+ name: 'Test step 1, visited'
404
+ })
405
+ ).toBeVisible();
406
+ expect(
407
+ screen.getByRole('button', {
408
+ name: 'Test step 2'
409
+ })
410
+ ).toBeVisible();
411
+ expect(
412
+ screen.queryByRole('button', {
413
+ name: 'Test step 3'
414
+ })
415
+ ).toBeNull();
416
+
417
+ // Going back a step will hide step 2 & 3
418
+ await user.click(backButton);
419
+ expect(
420
+ screen.getByRole('button', {
421
+ name: 'Test step 1'
422
+ })
423
+ ).toBeVisible();
424
+ expect(
425
+ screen.queryByRole('button', {
426
+ name: 'Test step 2'
427
+ })
428
+ ).toBeNull();
429
+ expect(
430
+ screen.queryByRole('button', {
431
+ name: 'Test step 3'
432
+ })
433
+ ).toBeNull();
331
434
  });
@@ -4,7 +4,7 @@ import { render, screen } from '@testing-library/react';
4
4
 
5
5
  import { WizardStep, WizardStepProps } from '../WizardStep';
6
6
  import * as WizardContext from '../WizardContext';
7
- import { WizardControlStep } from '..';
7
+ import { WizardStepType } from '..';
8
8
 
9
9
  const testStepProps: WizardStepProps = {
10
10
  id: 'test-step',
@@ -12,7 +12,7 @@ const testStepProps: WizardStepProps = {
12
12
  footer: <>Step footer</>
13
13
  };
14
14
 
15
- const testStep: WizardControlStep = {
15
+ const testStep: WizardStepType = {
16
16
  ...testStepProps,
17
17
  index: 1
18
18
  };
@@ -24,9 +24,9 @@ const wizardContext: WizardContext.WizardContextProps = {
24
24
  steps: [testStep],
25
25
  activeStep: testStep,
26
26
  footer: <>Wizard footer</>,
27
- onNext: jest.fn(),
28
- onBack: jest.fn(),
29
- onClose: jest.fn(),
27
+ goToNextStep: jest.fn(),
28
+ goToPrevStep: jest.fn(),
29
+ close: jest.fn(),
30
30
  goToStepById: jest.fn(),
31
31
  goToStepByName: jest.fn(),
32
32
  goToStepByIndex: jest.fn(),
@@ -5,9 +5,9 @@ import userEvent from '@testing-library/user-event';
5
5
 
6
6
  import { KeyTypes } from '../../../../helpers';
7
7
  import { WizardToggle, WizardToggleProps } from '../WizardToggle';
8
- import { WizardControlStep } from '../types';
8
+ import { WizardStepType } from '../types';
9
9
 
10
- const steps: WizardControlStep[] = [
10
+ const steps: WizardStepType[] = [
11
11
  { id: 'id-1', name: 'First step', index: 1, component: <>First step content</> },
12
12
  { id: 'id-2', name: 'Second step', index: 2, component: <>Second step content</> }
13
13
  ];
@@ -5,11 +5,11 @@ import { buildSteps } from '../utils';
5
5
  import { WizardStep } from '../WizardStep';
6
6
 
7
7
  describe('buildSteps', () => {
8
- test('throws error if child does not have required props or type of WizardStep', () => {
8
+ test('throws error if child is not of type WizardStep', () => {
9
9
  try {
10
10
  buildSteps(<div />);
11
11
  } catch (error) {
12
- expect(error.message).toEqual('Wizard only accepts children with required WizardStepProps.');
12
+ expect(error.message).toEqual('Wizard only accepts children of type WizardStep.');
13
13
  }
14
14
  });
15
15
 
@@ -17,7 +17,7 @@ describe('buildSteps', () => {
17
17
  try {
18
18
  buildSteps('test' as any);
19
19
  } catch (error) {
20
- expect(error.message).toEqual('Wizard only accepts children with required WizardStepProps.');
20
+ expect(error.message).toEqual('Wizard only accepts children of type WizardStep.');
21
21
  }
22
22
  });
23
23
 
@@ -30,20 +30,6 @@ describe('buildSteps', () => {
30
30
  expect(step.component?.props).toEqual(component.props);
31
31
  });
32
32
 
33
- test('returns array of steps if children have required props', () => {
34
- const CustomStep = props => <div {...props} />;
35
- const component = (
36
- <CustomStep name="Step 1" id="step-1">
37
- Content
38
- </CustomStep>
39
- );
40
- const [step] = buildSteps(component);
41
-
42
- expect(step.id).toEqual('step-1');
43
- expect(step.name).toEqual('Step 1');
44
- expect(step.component?.props).toEqual(component.props);
45
- });
46
-
47
33
  test('returns flattened array of steps and sub-steps when sub-steps exist', () => {
48
34
  const CustomSubStep = props => <div {...props} />;
49
35