@instructure/ui-table 9.1.1-pr-snapshot-1720014507835 → 9.1.1-pr-snapshot-1720186232821

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -873,118 +873,6 @@ render(
873
873
  )
874
874
  ```
875
875
 
876
- ### Using Custom Components as Children
877
-
878
- 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.
879
-
880
- ```javascript
881
- ---
882
- type: example
883
- ---
884
- class CustomTableCell extends React.Component {
885
- render () {
886
- return (
887
- <Table.Cell {...this.props}>{this.props.children}</Table.Cell>
888
- )
889
- }
890
- }
891
-
892
- class CustomTableRow extends React.Component {
893
- render () {
894
- return (
895
- <Table.Row {...this.props}>
896
- <Table.RowHeader>1</Table.RowHeader>
897
- <Table.Cell>The Shawshank Redemption</Table.Cell>
898
- <Table.Cell>1994</Table.Cell>
899
- <CustomTableCell>9.3</CustomTableCell>
900
- </Table.Row>
901
- )
902
- }
903
- }
904
-
905
- class Example extends React.Component {
906
- state = {
907
- layout: 'auto',
908
- hover: false,
909
- }
910
-
911
- handleChange = (field, value) => {
912
- this.setState({
913
- [field]: value,
914
- })
915
- }
916
-
917
- renderOptions () {
918
- const { layout, hover } = this.state
919
-
920
- return (
921
- <Flex alignItems="start">
922
- <Flex.Item margin="small">
923
- <RadioInputGroup
924
- name="layout2"
925
- description="layout2"
926
- value={layout}
927
- onChange={(e, value) => this.handleChange('layout', value)}
928
- >
929
- <RadioInput label="auto" value="auto" />
930
- <RadioInput label="fixed" value="fixed" />
931
- <RadioInput label="stacked" value="stacked" />
932
- </RadioInputGroup>
933
- </Flex.Item>
934
- <Flex.Item margin="small">
935
- <Checkbox
936
- label="hover"
937
- checked={hover}
938
- onChange={(e, value) => this.handleChange('hover', !hover)}
939
- />
940
- </Flex.Item>
941
- </Flex>
942
- )
943
- }
944
-
945
- render() {
946
- const { layout, hover } = this.state
947
-
948
- return (
949
- <div>
950
- {this.renderOptions()}
951
- <Table
952
- caption='Top rated movies'
953
- layout={layout}
954
- hover={hover}
955
- >
956
- <Table.Head>
957
- <Table.Row>
958
- <Table.ColHeader id="Rank">Rank</Table.ColHeader>
959
- <Table.ColHeader id="Title">Title</Table.ColHeader>
960
- <Table.ColHeader id="Year">Year</Table.ColHeader>
961
- <Table.ColHeader id="Rating">Rating</Table.ColHeader>
962
- </Table.Row>
963
- </Table.Head>
964
- <Table.Body>
965
- <CustomTableRow/>
966
- <Table.Row>
967
- <Table.RowHeader>2</Table.RowHeader>
968
- <Table.Cell>The Godfather</Table.Cell>
969
- <Table.Cell>1972</Table.Cell>
970
- <Table.Cell>9.2</Table.Cell>
971
- </Table.Row>
972
- <Table.Row>
973
- <Table.RowHeader>3</Table.RowHeader>
974
- <Table.Cell>The Godfather: Part II</Table.Cell>
975
- <Table.Cell>1974</Table.Cell>
976
- <Table.Cell>9.0</Table.Cell>
977
- </Table.Row>
978
- </Table.Body>
979
- </Table>
980
- </div>
981
- )
982
- }
983
- }
984
-
985
- render(<Example />)
986
- ```
987
-
988
876
  ### Guidelines
989
877
 
990
878
  ```js
@@ -25,7 +25,11 @@
25
25
  /** @jsx jsx */
26
26
  import { Component, Children } from 'react'
27
27
 
28
- import { omitProps, safeCloneElement } from '@instructure/ui-react-utils'
28
+ import {
29
+ omitProps,
30
+ matchComponentTypes,
31
+ safeCloneElement
32
+ } from '@instructure/ui-react-utils'
29
33
  import { View } from '@instructure/ui-view'
30
34
 
31
35
  import { withStyle, jsx } from '@instructure/emotion'
@@ -33,7 +37,11 @@ import { withStyle, jsx } from '@instructure/emotion'
33
37
  import generateStyle from './styles'
34
38
  import generateComponentTheme from './theme'
35
39
 
40
+ import { ColHeader } from '../ColHeader'
41
+ import { RowHeader } from '../RowHeader'
42
+ import { Cell } from '../Cell'
36
43
  import type { TableRowProps } from './props'
44
+ import type { ColHeaderChild, RowHeaderChild, CellChild } from '../props'
37
45
  import { allowedProps, propTypes } from './props'
38
46
 
39
47
  /**
@@ -71,14 +79,32 @@ class Row extends Component<TableRowProps> {
71
79
  css={styles?.row}
72
80
  role={isStacked ? 'row' : undefined}
73
81
  >
74
- {Children.toArray(children)
82
+ {(
83
+ Children.toArray(children) as (
84
+ | ColHeaderChild
85
+ | RowHeaderChild
86
+ | CellChild
87
+ )[]
88
+ )
75
89
  .filter(Boolean)
76
- .map((child: any, index) => {
77
- return safeCloneElement(child, {
78
- key: child.props.name,
79
- isStacked,
80
- header: headers && headers[index]
81
- })
90
+ .map((child, index) => {
91
+ if (matchComponentTypes<ColHeaderChild>(child, [ColHeader])) {
92
+ return child
93
+ }
94
+ if (matchComponentTypes<RowHeaderChild>(child, [RowHeader])) {
95
+ return safeCloneElement(child, {
96
+ key: child.props.name,
97
+ isStacked
98
+ })
99
+ }
100
+ if (matchComponentTypes<CellChild>(child, [Cell])) {
101
+ return safeCloneElement(child, {
102
+ key: child.props.name,
103
+ isStacked,
104
+ header: headers && headers[index]
105
+ })
106
+ }
107
+ return null
82
108
  })}
83
109
  </View>
84
110
  )
@@ -25,6 +25,11 @@
25
25
  import React from 'react'
26
26
  import PropTypes from 'prop-types'
27
27
 
28
+ import { Children as ChildrenPropTypes } from '@instructure/ui-prop-types'
29
+
30
+ import { ColHeader } from '../ColHeader'
31
+ import { RowHeader } from '../RowHeader'
32
+ import { Cell } from '../Cell'
28
33
  import type { TableCellProps } from '../Cell/props'
29
34
 
30
35
  import type {
@@ -55,7 +60,7 @@ type TableRowProps = TableRowOwnProps &
55
60
  type TableRowStyle = ComponentStyle<'row'>
56
61
 
57
62
  const propTypes: PropValidators<PropKeys> = {
58
- children: PropTypes.node,
63
+ children: ChildrenPropTypes.oneOf([ColHeader, RowHeader, Cell]),
59
64
  hover: PropTypes.bool,
60
65
  isStacked: PropTypes.bool,
61
66
  headers: PropTypes.arrayOf(
@@ -25,7 +25,11 @@
25
25
  /** @jsx jsx */
26
26
  import { Component, Children } from 'react'
27
27
 
28
- import { safeCloneElement, omitProps } from '@instructure/ui-react-utils'
28
+ import {
29
+ matchComponentTypes,
30
+ safeCloneElement,
31
+ omitProps
32
+ } from '@instructure/ui-react-utils'
29
33
  import { View } from '@instructure/ui-view'
30
34
  import { ScreenReaderContent } from '@instructure/ui-a11y-content'
31
35
 
@@ -44,6 +48,8 @@ import { Cell } from './Cell'
44
48
  import type {
45
49
  TableProps,
46
50
  HeadChild,
51
+ BodyChild,
52
+ RowChild,
47
53
  ColHeaderChild,
48
54
  RowHeaderChild,
49
55
  CellChild
@@ -99,15 +105,22 @@ class Table extends Component<TableProps> {
99
105
  getHeaders() {
100
106
  const { children } = this.props
101
107
  const [head] = Children.toArray(children) as HeadChild[]
102
- const [row]: any = Children.toArray(head.props.children)
103
- if (!row) return undefined
104
108
 
105
- return Children.map(
106
- row.props.children as (ColHeaderChild | RowHeaderChild | CellChild)[],
107
- (colHeader) => {
108
- return colHeader.props.children
109
+ if (matchComponentTypes<HeadChild>(head, [Head])) {
110
+ const [row] = Children.toArray(head.props.children)
111
+
112
+ if (matchComponentTypes<RowChild>(row, [Row])) {
113
+ return Children.map(
114
+ row.props.children as (ColHeaderChild | RowHeaderChild | CellChild)[],
115
+ (colHeader) => {
116
+ return matchComponentTypes<ColHeaderChild>(colHeader, [ColHeader])
117
+ ? colHeader.props.children
118
+ : undefined
119
+ }
120
+ )
109
121
  }
110
- )
122
+ }
123
+ return undefined
111
124
  }
112
125
 
113
126
  render() {
@@ -133,13 +146,22 @@ class Table extends Component<TableProps> {
133
146
  <ScreenReaderContent>{caption}</ScreenReaderContent>
134
147
  </caption>
135
148
  )}
136
- {Children.map(children, (child: any) => {
137
- return safeCloneElement(child, {
138
- key: child.props.name,
139
- isStacked,
140
- hover,
141
- headers
142
- })
149
+ {Children.map(children, (child) => {
150
+ if (matchComponentTypes<HeadChild>(child, [Head])) {
151
+ return safeCloneElement(child, {
152
+ key: child.props.name,
153
+ isStacked
154
+ })
155
+ }
156
+ if (matchComponentTypes<BodyChild>(child, [Body])) {
157
+ return safeCloneElement(child, {
158
+ key: child.props.name,
159
+ isStacked,
160
+ hover,
161
+ headers
162
+ })
163
+ }
164
+ return null
143
165
  })}
144
166
  </View>
145
167
  )
@@ -24,6 +24,7 @@
24
24
  import React from 'react'
25
25
  import PropTypes from 'prop-types'
26
26
 
27
+ import { Children as ChildrenPropTypes } from '@instructure/ui-prop-types'
27
28
  import { ThemeablePropTypes } from '@instructure/emotion'
28
29
 
29
30
  import type {
@@ -101,7 +102,7 @@ type TableStyle = ComponentStyle<'table'>
101
102
 
102
103
  const propTypes: PropValidators<PropKeys> = {
103
104
  caption: PropTypes.node.isRequired,
104
- children: PropTypes.node,
105
+ children: ChildrenPropTypes.oneOf([Head, Body]),
105
106
  margin: ThemeablePropTypes.spacing,
106
107
  elementRef: PropTypes.func,
107
108
  hover: PropTypes.bool,