diff --git a/package.json b/package.json index 6066f2dfb0a..e19af5bd6f3 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@babel/preset-react": "^7.0.0", "@babel/preset-typescript": "^7.9.0", "@octokit/rest": "^16.43.2", + "@testing-library/react-hooks": "^8.0.1", "@testing-library/jest-dom": "^5.16.2", "@testing-library/react": "^12.1.5", "@testing-library/user-event": "14.4.3", diff --git a/packages/react-core/src/next/components/Wizard/Wizard.tsx b/packages/react-core/src/next/components/Wizard/Wizard.tsx index 040a8061335..ceae05460d3 100644 --- a/packages/react-core/src/next/components/Wizard/Wizard.tsx +++ b/packages/react-core/src/next/components/Wizard/Wizard.tsx @@ -6,16 +6,14 @@ import styles from '@patternfly/react-styles/css/components/Wizard/wizard'; import { DefaultWizardFooterProps, DefaultWizardNavProps, - isCustomWizardFooter, isWizardParentStep, WizardNavStepFunction, CustomWizardNavFunction } from './types'; import { buildSteps, normalizeNavStep } from './utils'; -import { useWizardContext, WizardContextProvider } from './WizardContext'; +import { WizardContextProvider } from './WizardContext'; import { WizardStepProps } from './WizardStep'; -import { WizardFooter } from './WizardFooter'; -import { WizardToggle } from './WizardToggle'; +import { WizardToggleInternal } from './WizardToggle'; /** * Wrapper for all steps and hosts state, including navigation helpers, within context. @@ -29,7 +27,7 @@ export interface WizardProps extends React.HTMLProps { header?: React.ReactNode; /** Wizard footer */ footer?: DefaultWizardFooterProps | React.ReactElement; - /** Default wizard nav props or a custom WizardNav (with callback) */ + /** Wizard nav */ nav?: DefaultWizardNavProps | CustomWizardNavFunction; /** The initial index the wizard is to start on (1 or higher). Defaults to 1. */ startIndex?: number; @@ -39,6 +37,8 @@ export interface WizardProps extends React.HTMLProps { width?: number | string; /** Custom height of the wizard */ height?: number | string; + /** Flag to unmount inactive steps instead of hiding. Defaults to true */ + unmountInactiveSteps?: boolean; /** Callback function when a step in the nav is clicked */ onNavByIndex?: WizardNavStepFunction; /** Callback function after next button is clicked */ @@ -51,8 +51,23 @@ export interface WizardProps extends React.HTMLProps { onClose?: () => void; } -export const Wizard = (props: WizardProps) => { - const { startIndex = 1, children, footer, onNavByIndex, onNext, onBack, onSave, onClose, ...internalProps } = props; +export const Wizard = ({ + startIndex = 1, + children, + footer, + height, + width, + className, + header, + nav, + unmountInactiveSteps, + onNavByIndex, + onNext, + onBack, + onSave, + onClose, + ...wrapperProps +}: WizardProps) => { const [currentStepIndex, setCurrentStepIndex] = React.useState(startIndex); const steps = buildSteps(children); @@ -130,7 +145,7 @@ export const Wizard = (props: WizardProps) => { { goToStepByName={goToStepByName} goToStepByIndex={goToStepByIndex} > - - {children} - +
+ {header} + +
); }; -// eslint-disable-next-line patternfly-react/no-anonymous-functions -const WizardInternal = ({ height, width, className, header, footer, nav, ...divProps }: WizardProps) => { - const { activeStep, steps, footer: customFooter, onNext, onBack, onClose, goToStepByIndex } = useWizardContext(); - - const wizardFooter = customFooter || ( - - ); - - return ( -
- {header} - -
- ); -}; - Wizard.displayName = 'Wizard'; diff --git a/packages/react-core/src/next/components/Wizard/WizardBody.tsx b/packages/react-core/src/next/components/Wizard/WizardBody.tsx index 51cd195facc..c9d4e3c40bb 100644 --- a/packages/react-core/src/next/components/Wizard/WizardBody.tsx +++ b/packages/react-core/src/next/components/Wizard/WizardBody.tsx @@ -8,7 +8,7 @@ import { css } from '@patternfly/react-styles'; */ export interface WizardBodyProps { - children?: React.ReactNode | React.ReactNode[]; + children: React.ReactNode | React.ReactNode[]; /** Set to true to remove the default body padding */ hasNoBodyPadding?: boolean; /** An aria-label to use for the wrapper element */ diff --git a/packages/react-core/src/next/components/Wizard/WizardContext.tsx b/packages/react-core/src/next/components/Wizard/WizardContext.tsx index 8859d1b5879..d9a934203de 100644 --- a/packages/react-core/src/next/components/Wizard/WizardContext.tsx +++ b/packages/react-core/src/next/components/Wizard/WizardContext.tsx @@ -1,6 +1,11 @@ import React from 'react'; -import { WizardControlStep } from './types'; + +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/react-styles/css/components/Wizard/wizard'; + +import { DefaultWizardFooterProps, isCustomWizardFooter, WizardControlStep } from './types'; import { getActiveStep } from './utils'; +import { WizardFooter } from './WizardFooter'; export interface WizardContextProps { /** List of steps */ @@ -22,7 +27,7 @@ export interface WizardContextProps { /** Navigate to step by index */ goToStepByIndex: (index: number) => void; /** Update the footer with any react element */ - setFooter: (footer: React.ReactElement) => void; + setFooter: (footer: DefaultWizardFooterProps | React.ReactElement) => void; } export const WizardContext = React.createContext({} as WizardContextProps); @@ -39,7 +44,7 @@ interface WizardContextRenderProps { export interface WizardContextProviderProps { steps: WizardControlStep[]; currentStepIndex: number; - footer: React.ReactElement; + footer: DefaultWizardFooterProps | React.ReactElement; children: React.ReactElement | ((props: WizardContextRenderProps) => React.ReactElement); onNext(): void; onBack(): void; @@ -66,6 +71,23 @@ export const WizardContextProvider: React.FunctionComponent + isCustomWizardFooter(footer) ? ( +
{footer}
+ ) : ( + + ), + [activeStep, footer, onBack, onClose, onNext, steps] + ); + // When the active step changes and the newly active step isn't visited, set the visited flag to true. React.useEffect(() => { if (activeStep && !activeStep?.visited) { @@ -86,7 +108,7 @@ export const WizardContextProvider: React.FunctionComponent - {typeof children === 'function' ? children({ activeStep, steps, footer, onNext, onBack, onClose }) : children} + {typeof children === 'function' + ? children({ activeStep, steps, footer: wizardFooter, onNext, onBack, onClose }) + : children} ); }; diff --git a/packages/react-core/src/next/components/Wizard/WizardNav.tsx b/packages/react-core/src/next/components/Wizard/WizardNav.tsx index 9cdfcb86ab2..76e8f6cd58b 100644 --- a/packages/react-core/src/next/components/Wizard/WizardNav.tsx +++ b/packages/react-core/src/next/components/Wizard/WizardNav.tsx @@ -10,7 +10,7 @@ export interface WizardNavProps { /** Sets the aria-labelledby attribute on the nav element */ 'aria-labelledby'?: string; /** Whether the nav is expanded */ - isOpen?: boolean; + isExpanded?: boolean; /** True to return the inner list without the wrapping nav element */ returnList?: boolean; } @@ -19,7 +19,7 @@ export const WizardNav: React.FunctionComponent = ({ children, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, - isOpen = false, + isExpanded = false, returnList = false }: WizardNavProps) => { const innerList =
    {children}
; @@ -30,7 +30,7 @@ export const WizardNav: React.FunctionComponent = ({ return (