From c06c462eeae1f53114637fc72643eb598f72847d Mon Sep 17 00:00:00 2001 From: fzaninotto Date: Thu, 22 Dec 2022 15:45:01 +0100 Subject: [PATCH] Add ability to pass multiple children to `` and `` --- .../src/detail/Create.spec.tsx | 15 +++++++++++++++ .../ra-ui-materialui/src/detail/Create.tsx | 6 +++--- .../src/detail/CreateView.tsx | 6 +++--- .../ra-ui-materialui/src/list/List.spec.tsx | 17 +++++++++++++++++ packages/ra-ui-materialui/src/list/List.tsx | 2 +- .../ra-ui-materialui/src/list/ListView.tsx | 19 ++++++++++++++----- 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/packages/ra-ui-materialui/src/detail/Create.spec.tsx b/packages/ra-ui-materialui/src/detail/Create.spec.tsx index d267b8bafa3..26d9693d2ef 100644 --- a/packages/ra-ui-materialui/src/detail/Create.spec.tsx +++ b/packages/ra-ui-materialui/src/detail/Create.spec.tsx @@ -25,4 +25,19 @@ describe('', () => { ); expect(screen.queryAllByText('Hello')).toHaveLength(1); }); + + it('should accept more than one child', () => { + const Form = () =>
form
; + const HelpText = () =>
help
; + render( + + +
+ + + + ); + expect(screen.queryAllByText('form')).toHaveLength(1); + expect(screen.queryAllByText('help')).toHaveLength(1); + }); }); diff --git a/packages/ra-ui-materialui/src/detail/Create.tsx b/packages/ra-ui-materialui/src/detail/Create.tsx index 1c6e1e41a26..91de55e4b9e 100644 --- a/packages/ra-ui-materialui/src/detail/Create.tsx +++ b/packages/ra-ui-materialui/src/detail/Create.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { ReactElement } from 'react'; +import { ReactElement, ReactNode } from 'react'; import PropTypes from 'prop-types'; import { RaRecord, useCheckMinimumRequiredProps } from 'ra-core'; @@ -51,7 +51,7 @@ import { CreateBase } from 'ra-core'; * export default App; */ export const Create = ( - props: CreateProps & { children: ReactElement } + props: CreateProps & { children: ReactNode } ): ReactElement => { useCheckMinimumRequiredProps('Create', ['children'], props); const { @@ -84,7 +84,7 @@ export const Create = ( Create.propTypes = { actions: PropTypes.oneOfType([PropTypes.element, PropTypes.bool]), aside: PropTypes.element, - children: PropTypes.element, + children: PropTypes.node, className: PropTypes.string, disableAuthentication: PropTypes.bool, hasEdit: PropTypes.bool, diff --git a/packages/ra-ui-materialui/src/detail/CreateView.tsx b/packages/ra-ui-materialui/src/detail/CreateView.tsx index 8d0a9e39821..f7fe27ca243 100644 --- a/packages/ra-ui-materialui/src/detail/CreateView.tsx +++ b/packages/ra-ui-materialui/src/detail/CreateView.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { ReactElement } from 'react'; +import { ReactNode } from 'react'; import PropTypes from 'prop-types'; import { Card } from '@mui/material'; import { styled } from '@mui/material/styles'; @@ -48,13 +48,13 @@ export const CreateView = (props: CreateViewProps) => { interface CreateViewProps extends CreateProps, Omit, 'resource'> { - children: ReactElement; + children: ReactNode; } CreateView.propTypes = { actions: PropTypes.oneOfType([PropTypes.element, PropTypes.bool]), aside: PropTypes.element, - children: PropTypes.element, + children: PropTypes.node, className: PropTypes.string, defaultTitle: PropTypes.any, hasList: PropTypes.bool, diff --git a/packages/ra-ui-materialui/src/list/List.spec.tsx b/packages/ra-ui-materialui/src/list/List.spec.tsx index 4d7fa7d6b1d..2b8331624b5 100644 --- a/packages/ra-ui-materialui/src/list/List.spec.tsx +++ b/packages/ra-ui-materialui/src/list/List.spec.tsx @@ -50,6 +50,23 @@ describe('', () => { expect(screen.queryAllByText('datagrid')).toHaveLength(1); }); + it('should accept more than one child', () => { + const Filter = () =>
filter
; + const Datagrid = () =>
datagrid
; + render( + + + + + + + + + ); + expect(screen.queryAllByText('filter')).toHaveLength(1); + expect(screen.queryAllByText('datagrid')).toHaveLength(1); + }); + it('should display aside component', () => { const Dummy = () =>
; const Aside = () =>
Hello
; diff --git a/packages/ra-ui-materialui/src/list/List.tsx b/packages/ra-ui-materialui/src/list/List.tsx index 7a85117b636..8cad727b1ef 100644 --- a/packages/ra-ui-materialui/src/list/List.tsx +++ b/packages/ra-ui-materialui/src/list/List.tsx @@ -97,7 +97,7 @@ List.propTypes = { // @ts-ignore-line actions: PropTypes.oneOfType([PropTypes.bool, PropTypes.element]), aside: PropTypes.element, - children: PropTypes.element.isRequired, + children: PropTypes.node.isRequired, className: PropTypes.string, emptyWhileLoading: PropTypes.bool, filter: PropTypes.object, diff --git a/packages/ra-ui-materialui/src/list/ListView.tsx b/packages/ra-ui-materialui/src/list/ListView.tsx index a98bd07e970..9931925b5be 100644 --- a/packages/ra-ui-materialui/src/list/ListView.tsx +++ b/packages/ra-ui-materialui/src/list/ListView.tsx @@ -1,6 +1,12 @@ import * as React from 'react'; import { styled } from '@mui/material/styles'; -import { Children, cloneElement, ReactElement, ElementType } from 'react'; +import { + Children, + cloneElement, + ReactElement, + ReactNode, + ElementType, +} from 'react'; import PropTypes from 'prop-types'; import { SxProps } from '@mui/system'; import Card from '@mui/material/Card'; @@ -61,8 +67,11 @@ export const ListView = ( /> )} - {bulkActionButtons && children - ? cloneElement(Children.only(children), { + {bulkActionButtons && + children && + React.isValidElement(children) + ? // FIXME remove in 5.0 + cloneElement(children, { bulkActionButtons, }) : children} @@ -101,7 +110,7 @@ ListView.propTypes = { // @ts-ignore-line actions: PropTypes.oneOfType([PropTypes.bool, PropTypes.element]), aside: PropTypes.element, - children: PropTypes.element, + children: PropTypes.node, className: PropTypes.string, component: ComponentPropType, // @ts-ignore-line @@ -152,7 +161,7 @@ export interface ListViewProps { */ bulkActionButtons?: ReactElement | false; className?: string; - children: ReactElement; + children: ReactNode; component?: ElementType; empty?: ReactElement | false; emptyWhileLoading?: boolean;