diff --git a/packages/ui-table/src/Table/Body/index.tsx b/packages/ui-table/src/Table/Body/index.tsx index 2454bb7541..2bd9dcaa2c 100644 --- a/packages/ui-table/src/Table/Body/index.tsx +++ b/packages/ui-table/src/Table/Body/index.tsx @@ -25,17 +25,12 @@ /** @jsx jsx */ import { Component, Children } from 'react' -import { - matchComponentTypes, - safeCloneElement, - omitProps -} from '@instructure/ui-react-utils' +import { safeCloneElement, omitProps } from '@instructure/ui-react-utils' import { View } from '@instructure/ui-view' import { withStyle, jsx } from '@instructure/emotion' import generateStyle from './styles' import generateComponentTheme from './theme' -import { Row } from '../Row' import type { TableBodyProps } from './props' import type { RowChild } from '../props' import { allowedProps, propTypes } from './props' @@ -76,14 +71,12 @@ class Body extends Component { role={isStacked ? 'rowgroup' : undefined} > {Children.map(children as RowChild[], (child) => - matchComponentTypes(child, [Row]) - ? safeCloneElement(child, { - key: child.props.name, - hover, - isStacked, - headers - }) - : null + safeCloneElement(child, { + key: child.props.name, + hover, + isStacked, + headers + }) )} ) diff --git a/packages/ui-table/src/Table/Body/props.ts b/packages/ui-table/src/Table/Body/props.ts index 132c927f73..e58ffb07e3 100644 --- a/packages/ui-table/src/Table/Body/props.ts +++ b/packages/ui-table/src/Table/Body/props.ts @@ -24,9 +24,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { Children as ChildrenPropTypes } from '@instructure/ui-prop-types' - -import { Row } from '../Row' import type { TableRowProps } from '../Row/props' import type { @@ -57,7 +54,7 @@ type TableBodyProps = TableBodyOwnProps & type TableBodyStyle = ComponentStyle<'body'> const propTypes: PropValidators = { - children: ChildrenPropTypes.oneOf([Row]), + children: PropTypes.node, hover: PropTypes.bool, isStacked: PropTypes.bool, headers: PropTypes.arrayOf( diff --git a/packages/ui-table/src/Table/Head/props.ts b/packages/ui-table/src/Table/Head/props.ts index 54504584ea..63603e5361 100644 --- a/packages/ui-table/src/Table/Head/props.ts +++ b/packages/ui-table/src/Table/Head/props.ts @@ -25,10 +25,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { Children as ChildrenPropTypes } from '@instructure/ui-prop-types' - -import { Row } from '../Row' - import type { OtherHTMLAttributes, PropValidators, @@ -56,7 +52,7 @@ type TableHeadProps = TableHeadOwnProps & type TableHeadStyle = ComponentStyle<'head'> const propTypes: PropValidators = { - children: ChildrenPropTypes.oneOf([Row]), + children: PropTypes.node, isStacked: PropTypes.bool, renderSortLabel: PropTypes.oneOfType([PropTypes.node, PropTypes.func]) } diff --git a/packages/ui-table/src/Table/README.md b/packages/ui-table/src/Table/README.md index 5b92ae04b0..2ab5038cd9 100644 --- a/packages/ui-table/src/Table/README.md +++ b/packages/ui-table/src/Table/README.md @@ -873,6 +873,118 @@ render( ) ``` +### Using Custom Components as Children + +In some cases you might want to use custom components in a `Table`, e.g. a HOC for `Table.Row` or `Table.Cell`. This is generally not recommended but sometimes it could be beneficial for codesplitting or writing cleaner code for larger and more complex Tables. In those cases you have to pay attention to always pass down the appropriate props manually. + +```javascript +--- +type: example +--- +class CustomTableCell extends React.Component { + render () { + return ( + {this.props.children} + ) + } +} + +class CustomTableRow extends React.Component { + render () { + return ( + + 1 + The Shawshank Redemption + 1994 + 9.3 + + ) + } +} + +class Example extends React.Component { + state = { + layout: 'auto', + hover: false, + } + + handleChange = (field, value) => { + this.setState({ + [field]: value, + }) + } + + renderOptions () { + const { layout, hover } = this.state + + return ( + + + this.handleChange('layout', value)} + > + + + + + + + this.handleChange('hover', !hover)} + /> + + + ) + } + + render() { + const { layout, hover } = this.state + + return ( +
+ {this.renderOptions()} + + + + Rank + Title + Year + Rating + + + + + + 2 + The Godfather + 1972 + 9.2 + + + 3 + The Godfather: Part II + 1974 + 9.0 + + +
+
+ ) + } +} + +render() +``` + ### Guidelines ```js diff --git a/packages/ui-table/src/Table/Row/index.tsx b/packages/ui-table/src/Table/Row/index.tsx index 05cf57df75..65b19e3eca 100644 --- a/packages/ui-table/src/Table/Row/index.tsx +++ b/packages/ui-table/src/Table/Row/index.tsx @@ -25,11 +25,7 @@ /** @jsx jsx */ import { Component, Children } from 'react' -import { - omitProps, - matchComponentTypes, - safeCloneElement -} from '@instructure/ui-react-utils' +import { omitProps, safeCloneElement } from '@instructure/ui-react-utils' import { View } from '@instructure/ui-view' import { withStyle, jsx } from '@instructure/emotion' @@ -37,11 +33,7 @@ import { withStyle, jsx } from '@instructure/emotion' import generateStyle from './styles' import generateComponentTheme from './theme' -import { ColHeader } from '../ColHeader' -import { RowHeader } from '../RowHeader' -import { Cell } from '../Cell' import type { TableRowProps } from './props' -import type { ColHeaderChild, RowHeaderChild, CellChild } from '../props' import { allowedProps, propTypes } from './props' /** @@ -79,32 +71,14 @@ class Row extends Component { css={styles?.row} role={isStacked ? 'row' : undefined} > - {( - Children.toArray(children) as ( - | ColHeaderChild - | RowHeaderChild - | CellChild - )[] - ) + {Children.toArray(children) .filter(Boolean) - .map((child, index) => { - if (matchComponentTypes(child, [ColHeader])) { - return child - } - if (matchComponentTypes(child, [RowHeader])) { - return safeCloneElement(child, { - key: child.props.name, - isStacked - }) - } - if (matchComponentTypes(child, [Cell])) { - return safeCloneElement(child, { - key: child.props.name, - isStacked, - header: headers && headers[index] - }) - } - return null + .map((child: any, index) => { + return safeCloneElement(child, { + key: child.props.name, + isStacked, + header: headers && headers[index] + }) })} ) diff --git a/packages/ui-table/src/Table/Row/props.ts b/packages/ui-table/src/Table/Row/props.ts index 6982b418ab..32eeb36b6c 100644 --- a/packages/ui-table/src/Table/Row/props.ts +++ b/packages/ui-table/src/Table/Row/props.ts @@ -25,11 +25,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { Children as ChildrenPropTypes } from '@instructure/ui-prop-types' - -import { ColHeader } from '../ColHeader' -import { RowHeader } from '../RowHeader' -import { Cell } from '../Cell' import type { TableCellProps } from '../Cell/props' import type { @@ -60,7 +55,7 @@ type TableRowProps = TableRowOwnProps & type TableRowStyle = ComponentStyle<'row'> const propTypes: PropValidators = { - children: ChildrenPropTypes.oneOf([ColHeader, RowHeader, Cell]), + children: PropTypes.node, hover: PropTypes.bool, isStacked: PropTypes.bool, headers: PropTypes.arrayOf( diff --git a/packages/ui-table/src/Table/__tests__/Table.test.tsx b/packages/ui-table/src/Table/__tests__/Table.test.tsx index c86fb04dcf..b99bb2f3ff 100644 --- a/packages/ui-table/src/Table/__tests__/Table.test.tsx +++ b/packages/ui-table/src/Table/__tests__/Table.test.tsx @@ -23,14 +23,7 @@ */ import React from 'react' -import { - expect, - mount, - stub, - find, - findAll, - within -} from '@instructure/ui-test-utils' +import { expect, mount, stub, find, within } from '@instructure/ui-test-utils' //TODO /* eslint-disable no-restricted-imports */ // @ts-ignore: Cannot find module @@ -115,30 +108,6 @@ describe('', async () => { expect(stackedTable).to.exist() }) - it('can ignore invalid children', async () => { - await mount( -
- - {null} - - Foo - {null} - - - {null} - - {null} - - -
- ) - const th = await findAll('th') - const tr = await findAll('tr') - - expect(th).to.have.length(1) - expect(tr).to.have.length(2) - }) - it('can handle non-existent head in stacked layout', async () => { const stackedTable = await mount( diff --git a/packages/ui-table/src/Table/index.tsx b/packages/ui-table/src/Table/index.tsx index 8493fbe507..f3581d2dad 100644 --- a/packages/ui-table/src/Table/index.tsx +++ b/packages/ui-table/src/Table/index.tsx @@ -25,11 +25,7 @@ /** @jsx jsx */ import { Component, Children } from 'react' -import { - matchComponentTypes, - safeCloneElement, - omitProps -} from '@instructure/ui-react-utils' +import { safeCloneElement, omitProps } from '@instructure/ui-react-utils' import { View } from '@instructure/ui-view' import { ScreenReaderContent } from '@instructure/ui-a11y-content' @@ -48,8 +44,6 @@ import { Cell } from './Cell' import type { TableProps, HeadChild, - BodyChild, - RowChild, ColHeaderChild, RowHeaderChild, CellChild @@ -105,22 +99,15 @@ class Table extends Component { getHeaders() { const { children } = this.props const [head] = Children.toArray(children) as HeadChild[] + const [row]: any = Children.toArray(head.props.children) + if (!row) return undefined - if (matchComponentTypes(head, [Head])) { - const [row] = Children.toArray(head.props.children) - - if (matchComponentTypes(row, [Row])) { - return Children.map( - row.props.children as (ColHeaderChild | RowHeaderChild | CellChild)[], - (colHeader) => { - return matchComponentTypes(colHeader, [ColHeader]) - ? colHeader.props.children - : undefined - } - ) + return Children.map( + row.props.children as (ColHeaderChild | RowHeaderChild | CellChild)[], + (colHeader) => { + return colHeader.props.children } - } - return undefined + ) } render() { @@ -146,22 +133,13 @@ class Table extends Component { {caption} )} - {Children.map(children, (child) => { - if (matchComponentTypes(child, [Head])) { - return safeCloneElement(child, { - key: child.props.name, - isStacked - }) - } - if (matchComponentTypes(child, [Body])) { - return safeCloneElement(child, { - key: child.props.name, - isStacked, - hover, - headers - }) - } - return null + {Children.map(children, (child: any) => { + return safeCloneElement(child, { + key: child.props.name, + isStacked, + hover, + headers + }) })} ) diff --git a/packages/ui-table/src/Table/props.ts b/packages/ui-table/src/Table/props.ts index 8c33fdf171..68a6e0328c 100644 --- a/packages/ui-table/src/Table/props.ts +++ b/packages/ui-table/src/Table/props.ts @@ -24,7 +24,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { Children as ChildrenPropTypes } from '@instructure/ui-prop-types' import { ThemeablePropTypes } from '@instructure/emotion' import type { @@ -102,7 +101,7 @@ type TableStyle = ComponentStyle<'table'> const propTypes: PropValidators = { caption: PropTypes.node.isRequired, - children: ChildrenPropTypes.oneOf([Head, Body]), + children: PropTypes.node, margin: ThemeablePropTypes.spacing, elementRef: PropTypes.func, hover: PropTypes.bool,