import * as React from 'react' ; import { Children , cloneElement , FC , memo , ReactElement } from 'react' ; import PropTypes from 'prop-types' ; import { makeStyles } from '@material-ui/core/styles' ; import { useSelector } from 'react-redux' ; import { ListContextProvider , useListContext , ListControllerProps , useReferenceArrayFieldController , SortPayload , FilterPayload , ResourceContextProvider , useRecordContext , ReduxState , } from 'ra-core' ; import { fieldPropTypes , PublicFieldProps , InjectedFieldProps } from './types' ; import { ClassesOverride } from '../types' ; import sanitizeFieldRestProps from './sanitizeFieldRestProps' ; import { LinearProgress } from '../layout' ; example example example example example const ReferenceArrayField = props => { const { basePath , children , filter , page = 1 , perPage , reference , resource , sort , source , } = props ; const record = useRecordContext ( props ) ; if ( React . Children . count ( children ) !== 1 ) { throw new Error ( '<ReferenceArrayField> only accepts a single child (like <Datagrid>)' ) ; } const isReferenceDeclared = useSelector < ReduxState , boolean > ( state => typeof state . admin . resources [ props . reference ] !== 'undefined' ) ; if ( ! isReferenceDeclared ) { throw new Error ( `You must declare a <Resource name="${ props . reference }"> in order to use a <ReferenceArrayField reference="${ props . reference }">` ) ; } const controllerProps = useReferenceArrayFieldController ( { basePath , filter , page , perPage , record , reference , resource , sort , source , } ) ; return ( < ResourceContextProvider value = { reference } > < ListContextProvider value = { controllerProps } > < PureReferenceArrayFieldView { ... props } { ... controllerProps } /> < /ListContextProvider> < /ResourceContextProvider>); } ; ReferenceArrayField . propTypes = { ... fieldPropTypes , addLabel : PropTypes . bool , basePath : PropTypes . string , classes : PropTypes . object , className : PropTypes . string , children : PropTypes . element . isRequired , label : PropTypes . string , record : PropTypes . any , reference : PropTypes . string . isRequired , resource : PropTypes . string , sortBy : PropTypes . string , sortByOrder : fieldPropTypes . sortByOrder , source : PropTypes . string . isRequired , } ; ReferenceArrayField . defaultProps = { addLabel : true , } ; export interface ReferenceArrayFieldProps extends PublicFieldProps , InjectedFieldProps { children : ReactElement ; classes ? : ClassesOverride < typeof useStyles > ; filter ? : FilterPayload ; page ? : number ; pagination ? : ReactElement ; perPage ? : number ; reference : string ; resource ? : string ; sort ? : SortPayload ; } const useStyles = makeStyles ( theme => ( { progress : { marginTop : theme . spacing ( 2 ) } , } ) , { name : 'RaReferenceArrayField' } ) ; export interface ReferenceArrayFieldViewProps extends Omit < ReferenceArrayFieldProps , 'basePath' | 'resource' | 'page' | 'perPage' > , ListControllerProps { classes ? : ClassesOverride < typeof useStyles > ; } export const ReferenceArrayFieldView = props => { const { children , pagination , className , resource , reference , ... rest } = props ; const classes = useStyles ( props ) ; const { loaded } = useListContext ( props ) ; if ( ! loaded ) { return < LinearProgress className = { classes . progress } />; } return ( < > { cloneElement ( Children . only ( children ) , { ... sanitizeFieldRestProps ( rest ) , className , resource , } ) } { ' ' } { pagination && props . total !== undefined && cloneElement ( pagination , sanitizeFieldRestProps ( rest ) ) } < />); } ; ReferenceArrayFieldView . propTypes = { basePath : PropTypes . string , classes : PropTypes . any , className : PropTypes . string , data : PropTypes . any , ids : PropTypes . array , loaded : PropTypes . bool , children : PropTypes . element . isRequired , reference : PropTypes . string . isRequired , } ; const PureReferenceArrayFieldView = memo ( ReferenceArrayFieldView ) ; export default ReferenceArrayField ;