import * as React from 'react' ; import { ChangeEvent , Children , cloneElement , isValidElement , ReactElement , ReactNode , useState , } from 'react' ; import PropTypes from 'prop-types' ; import classnames from 'classnames' ; import { Route , useRouteMatch , useLocation } from 'react-router-dom' ; import { Divider } from '@material-ui/core' ; import { makeStyles } from '@material-ui/core/styles' ; import { escapePath , FormWithRedirectRenderProps , MutationMode , Record , } from 'ra-core' ; import Toolbar from './Toolbar' ; import TabbedFormTabs , { getTabFullPath } from './TabbedFormTabs' ; import { ClassesOverride } from '../types' ; export const TabbedFormView = ( props ) : ReactElement => { const { basePath , children , className , classes : classesOverride , formRootPathname , handleSubmit , handleSubmitWithRedirect , invalid , mutationMode , pristine , record , redirect : defaultRedirect , resource , saving , submitOnEnter , syncWithLocation = true , tabs , toolbar , undoable , variant , margin , validating , ... rest } = props ; const classes = useTabbedFormViewStyles ( props ) ; const match = useRouteMatch ( ) ; const location = useLocation ( ) ; const url = match ? match . url : location . pathname ; const [ tabValue , setTabValue ] = useState ( 0 ) ; const handleTabChange = ( event , value ) : void => { if ( ! syncWithLocation ) { setTabValue ( value ) ; } } ; return ( < form className = { classnames ( 'tabbed-form' , className ) } { ... sanitizeRestProps ( rest ) } > { cloneElement ( tabs , { classes , url , syncWithLocation , onChange : handleTabChange , value : tabValue , } , children ) } < Divider / > < div className = { classes . content } > { } { Children . map ( children , ( tab , index ) => { if ( ! tab ) { return ; } const tabPath = getTabFullPath ( tab , index , url ) ; return ( < Route exact path = { escapePath ( tabPath ) } > { routeProps => isValidElement < any > ( tab ) ? React . cloneElement ( tab , { intent : 'content' , classes , resource , record , basePath , hidden : syncWithLocation ? ! routeProps . match : tabValue !== index , variant : tab . props . variant || variant , margin : tab . props . margin || margin , value : syncWithLocation ? tabPath : index , } ) : null } < /Route>); } ) } < /div> { toolbar && React . cloneElement ( toolbar , { basePath , className : 'toolbar' , handleSubmitWithRedirect , handleSubmit , invalid , mutationMode , pristine , record , redirect : defaultRedirect , resource , saving , submitOnEnter , validating , undoable , } ) } < /form>); } ; export const useTabbedFormViewStyles = makeStyles ( theme => ( { errorTabButton : { color : theme . palette . error . main } , content : { paddingTop : theme . spacing ( 1 ) , paddingLeft : theme . spacing ( 2 ) , paddingRight : theme . spacing ( 2 ) , } , } ) , { name : 'RaTabbedForm' } ) ; TabbedFormView . propTypes = { basePath : PropTypes . string , children : PropTypes . node , className : PropTypes . string , classes : PropTypes . object , defaultValue : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . func ] ) , handleSubmit : PropTypes . func , initialValues : PropTypes . oneOfType ( [ PropTypes . object , PropTypes . func ] ) , invalid : PropTypes . bool , location : PropTypes . object , match : PropTypes . object , mutationMode : PropTypes . oneOf ( [ 'pessimistic' , 'optimistic' , 'undoable' ] ) , pristine : PropTypes . bool , record : PropTypes . object , redirect : PropTypes . oneOfType ( [ PropTypes . string , PropTypes . bool , PropTypes . func , ] ) , resource : PropTypes . string , save : PropTypes . func , saving : PropTypes . bool , submitOnEnter : PropTypes . bool , tabs : PropTypes . element . isRequired , toolbar : PropTypes . element , translate : PropTypes . func , undoable : PropTypes . bool , validate : PropTypes . func , value : PropTypes . number , version : PropTypes . number , } ; TabbedFormView . defaultProps = { submitOnEnter : true , tabs : < TabbedFormTabs />, toolbar : < Toolbar />, } ; export interface TabbedFormViewProps extends FormWithRedirectRenderProps { basePath ? : string ; children ? : ReactNode ; classes ? : ClassesOverride < typeof useTabbedFormViewStyles > ; className ? : string ; margin ? : 'none' | 'normal' | 'dense' ; mutationMode ? : MutationMode ; record ? : Partial < Record > ; resource ? : string ; syncWithLocation ? : boolean ; tabs ? : ReactElement ; toolbar ? : ReactElement ; deprecated undoable ? : boolean ; variant ? : 'standard' | 'outlined' | 'filled' ; submitOnEnter ? : boolean ; __versions ? : any ; } const sanitizeRestProps = ( { active , dirty , dirtyFields , dirtyFieldsSinceLastSubmit , dirtySinceLastSubmit , error , errors , form , hasSubmitErrors , hasValidationErrors , initialValues , modified = null , modifiedSinceLastSubmit , save = null , submitError , submitErrors , submitFailed , submitSucceeded , submitting , touched = null , valid , values , visited = null , __versions = null , ... props } ) => props ;