/**
 * Copyright (c) 2020 Dell Inc., or its subsidiaries. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 */ import * as React from "react" ; import { ReactElement , ReactNode } from "react" ; import { classNames } from "../utils" ; import { ClassNames , Styles } from "./ClassNames" ; import WizardNavigation , { WizardNavigationStep } from "./WizardNavigation" ; import WizardHeader from "./WizardHeader" ; import WizardStep from "./WizardStep" ; import WizardFooter , { InheritedWizardFooterProps , WizardFooterProps } from "./WizardFooter" ; import { SpinnerSize } from "../spinner/Spinner" ; /**
 * General component description :
 * Wizard :
 * Wizards are used to help users walk through a defined step-by-step process.
 * Each step is in the sidebar on the left. As users complete steps,
 * the steps are marked with a green bar to the left.
 */ param { isInline } if param { style } CSS param { className } CSS param { show } if param { size } enum param { title } wizard param { showNavigation } if param { closable } if param { onClose } callback param { previousText } custom param { showNext } if param { onPrevious } callback param { previousClassName } external param { disablePreviousButton } if param { disableComplet } if param { nextButtonText } custom param { onNext } callback param { nextClassName } external param { completeText } custom param { showComplete } if param { onComplete } callback param { completeClassName } external param { cancelText } custom param { showCancel } if param { cancelClassName } external param { customFooter } custom param { navLinkClasses } external param { dataqa } Quality param { className } custom param { children } child param { currentStepID } The param { dataqa ? } a param { showNavigation ? } indicates param { closable ? } indicates param { completeText ? } test param { isInline ? } indicates param { showPrevious ? } indicates param { previousClassName ? } custom param { nextText ? } text param { nextClassName ? } custom param { onClose ? } event param { onComplete ? } event param { onNext ? } event param { onPrevious ? } event param { onNavigateTo ? } event param { previousText ? } text param { completeClassName ? } custom param { cancelText } text param { showCancel } indicates param { cancelClassName } custom param { customFooter } custom param { navLinkClasses } custom param { showStepTitle } indicates param { showTitle } indicates param { show } indicates param { size } indicates param { style } custom param { title } title param { isLoading } if param { loadingSpinnerSize } size export type WizardProps = { className ? : string ; children : ReactNode ; currentStepID : number ; dataqa ? : string ; showNavigation ? : boolean ; closable ? : boolean ; isInline ? : boolean ; showPrevious ? : boolean ; previousClassName ? : string ; previousText ? : string ; disablePreviousButton ? : boolean ; disableComplete ? : boolean ; nextText ? : string ; showNext ? : boolean ; nextClassName ? : string ; onClose ? : ( evt : React . MouseEvent < HTMLElement , MouseEvent > ) => void ; onComplete ? : ( evt : React . MouseEvent < HTMLElement , MouseEvent > ) => void ; onNext ? : ( evt : React . MouseEvent < HTMLElement , MouseEvent > ) => void ; onPrevious ? : ( evt : React . MouseEvent < HTMLElement , MouseEvent > ) => void ; onNavigateTo ? : ( stepID : number , evt : React . MouseEvent < HTMLElement , MouseEvent > ) => void ; completeText ? : string ; showComplete ? : boolean ; completeClassName ? : string ; cancelText ? : string ; showCancel ? : boolean ; cancelClassName ? : string ; customFooter ? : ( ( wizardState : WizardState , props : WizardFooterProps ) => any ) | any ; navLinkClasses ? : string ; showStepTitle ? : boolean ; showTitle ? : boolean ; show : boolean ; size : WizardSize ; style ? : Object ; title ? : ReactNode ; isLoading ? : boolean ; loadingSpinnerSize ? : SpinnerSize ; } ; /**
 * State for Wizard :
 */ export type WizardState = { } ; type ProgressionStatus = { previousStepExists : boolean ; nextStepExists : boolean ; currentStepTitle : ReactNode ; currentStepIsCompleteAndValid : boolean ; } ; param { MEDIUM } midum param { LARGE } large param { XLARGE } xtra-large export enum WizardSize { MEDIUM = "md" , LARGE = "lg" , XLARGE = "xl" } const modalContentWrapperClassNames = classNames ( [ ClassNames . MODAL_CONTENT_WRAPPER , ClassNames . NG_TNS ] ) ; const modalContentClassNames = classNames ( [ ClassNames . MODAL_CONTENT , ClassNames . NG_TNS ] ) ; export default class Wizard extends React . PureComponent < WizardProps , WizardState > { static defaultProps = { isInline : false , previousText : "BACK" , nextText : "NEXT" , cancelText : "CANCEL" , completeText : "FINISH" , size : WizardSize . MEDIUM , showNavigation : true , showStepTitle : true , showTitle : true , isLoading : false , disablePreviousButton : false , onComplete : ( ) => { } , onPrevious : ( ) => { } , onNext : ( ) => { } , onClose : ( ) => { } , } ; private progressionStatus ( currentStepID , steps ) { const { showNext , showPrevious , showStepTitle } = this . props ; if ( steps . length > 0 && steps [ currentStepID ] ) { const currentStep = steps [ currentStepID ] ; return { previousStepExists : showPrevious !== undefined ? showPrevious : currentStepID !== steps [ 0 ] . props . id , nextStepExists : showNext !== undefined ? showNext : currentStepID !== steps [ steps . length - 1 ] . props . id , currentStepIsCompleteAndValid : ( currentStep . props . valid && currentStep . props . complete ) || false , currentStepTitle : currentStep . props . name , } ; } return { previousStepExists : false , nextStepExists : false , currentStepIsCompleteAndValid : false , currentStepTitle : "" , } ; } scrollToTop ( ) { document . getElementsByClassName ( "modal-body" ) [ 0 ] . scrollTo ( 0 , 0 ) ; } render ( ) { const { children , className , closable , currentStepID , dataqa , isInline , onClose , onPrevious , onNext , onComplete , onNavigateTo , show , showCancel , showComplete , showNavigation , showStepTitle , showTitle , title , size , style , isLoading , loadingSpinnerSize , disablePreviousButton , disableComplete , } = this . props ; const wizardSize = "wizard-" + size ; const modalSize = "modal-" + size ; const wizardClassNames = classNames ( [ isInline && `${ ClassNames . WIZARD_INLINE } ${ ClassNames . WIZARD_NO_SHADOW }` , ClassNames . WIZARD , wizardSize , ClassNames . NG_TNS , ClassNames . WIZARD_OPEN , className , ] ) ; const modalClassNames = classNames ( [ ClassNames . WIZARD_MODAL_DIALOG , modalSize ] ) ; let navigable = true ; const maybeSteps = React . Children . map ( children , child => { if ( React . isValidElement < WizardStep > ( child ) && child . type === WizardStep ) { const step = React . cloneElement < WizardStep > ( child as ReactElement < WizardStep > , Object . assign ( { } , child . props , { currentStepID , navigable , isLoading , loadingSpinnerSize , } ) ) ; navigable = navigable && step . props . valid && step . props . complete ; return step ; } } ) as ReadonlyArray < ReactElement < WizardStep > > ; const allStepsCompleteAndValid = navigable ; const steps = ( maybeSteps ? maybeSteps : [ ] ) . filter ( el => el !== null ) ; const { currentStepTitle , currentStepIsCompleteAndValid , nextStepExists , previousStepExists , } = this . progressionStatus ( currentStepID , steps ) ; const navigationSteps = steps . map ( ( step , index ) => ( < WizardNavigationStep key = { step . key || index } currentStepID = { currentStepID } onSelectStep = { onNavigateTo } isLoading = { isLoading } { ... step . props } / > ) ) ; return ( < React . Fragment > { show && ( < div data - qa = { dataqa } className = { wizardClassNames } style = { style } > < span className = "offscreen-focus-rebounder ng-tns-c167-4 ng-star-inserted" / > < div className = { ClassNames . WIZARD_MODAL } > < div className = { modalClassNames } role = "dialog" aria - hidden = "false" aria - labelledby = "clr-id-3" > < div className = "clr-sr-only ng-tns-c167-4" / > < div className = { ClassNames . WIZARD_OUTER_WRAPPER } style = { Styles . WIZARD_OUTER_WRAPPER } > < div className = { modalContentWrapperClassNames } > < WizardNavigation currentStepID = { currentStepID } show = { showNavigation } showTitle = { showTitle } title = { title } > { navigationSteps } < /WizardNavigation> < div className = { modalContentClassNames } > < WizardHeader title = { currentStepTitle } showTitle = { showStepTitle } onClose = { onClose } closable = { closable } / > < div className = { ClassNames . MODAL_BODY } > < div className = { ClassNames . WIZARD_CONTENT } > { steps } < /div> < /div> < WizardFooter currentStepID = { currentStepID } disableNext = { ! currentStepIsCompleteAndValid } disableComplete = { disableComplete !== undefined ? disableComplete : ! allStepsCompleteAndValid } disablePreviousButton = { disablePreviousButton } showCancel = { showCancel } showComplete = { showComplete !== undefined ? showComplete : ! nextStepExists } showNext = { nextStepExists } showPrevious = { previousStepExists } onClose = { onClose } onComplete = { onComplete } onNext = { onNext } onPrevious = { onPrevious } { ... this . footerProps ( ) } /> < /div> < /div> < div className = { ClassNames . MODAL_GHOST_WRAPPER } > < div className = { ClassNames . MODAL_GHOST_1 } style = { Styles . MODAL_GHOST_1 } / > < div className = { ClassNames . MODAL_GHOST_2 } style = { Styles . MODAL_GHOST_2 } / > < /div> < /div> < /div> < div className = { ClassNames . MODAL_BACKDROP } aria - hidden = "true" / > < /div> < /div>)} < /React.Fragment>); } private footerProps ( ) { const { cancelText , cancelClassName , completeClassName , completeText , customFooter , nextClassName , nextText , previousClassName , previousText , dataqa , showCancel , isLoading , } = this . props ; return { cancelText , cancelClassName , completeClassName , completeText , customFooter , nextClassName , nextText , previousClassName , previousText , dataqa , showCancel , isLoading , } ; } }