1
1
import React from 'react'
2
2
import styled from 'styled-components'
3
- import { useTable , useResizeColumns , useFlexLayout } from 'react-table'
3
+ import {
4
+ useTable ,
5
+ useResizeColumns ,
6
+ useFlexLayout ,
7
+ useRowSelect ,
8
+ } from 'react-table'
4
9
5
10
import makeData from './makeData'
6
11
@@ -35,13 +40,13 @@ const Styles = styled.div`
35
40
border-bottom: 0;
36
41
}
37
42
}
43
+ border-bottom: 1px solid black;
38
44
}
39
45
40
46
.th,
41
47
.td {
42
48
margin: 0;
43
49
padding: 0.5rem;
44
- border-bottom: 1px solid black;
45
50
border-right: 1px solid black;
46
51
47
52
${ '' /* In this example we use an absolutely position resizer,
@@ -53,12 +58,11 @@ const Styles = styled.div`
53
58
}
54
59
55
60
.resizer {
56
- display: inline-block ;
61
+ right: -5px ;
57
62
background: blue;
58
63
width: 10px;
59
64
height: 100%;
60
65
position: absolute;
61
- right: 0;
62
66
top: 0;
63
67
z-index: 1;
64
68
${ '' /* prevents from scrolling while dragging on touch devices */ }
@@ -69,9 +73,51 @@ const Styles = styled.div`
69
73
}
70
74
}
71
75
}
76
+
77
+ .th {
78
+ &:last-of-type {
79
+ .resizer {
80
+ ${ '' /* note that the 15 is the scroll width and if also referenced in the getHeaderGroupProps for the header row below */ }
81
+ ${ '' /* todo: resolve this value dynamicaly from element.scrollWidth to account for OS/Browser differences */ }
82
+ right: -15px;
83
+ }
84
+ }
85
+ }
72
86
}
73
87
`
74
88
89
+ const headerProps = ( props , { column } ) => getStyles ( props , column . align )
90
+
91
+ const cellProps = ( props , { cell } ) => getStyles ( props , cell . column . align )
92
+
93
+ const getStyles = ( props , align = 'left' ) => [
94
+ props ,
95
+ {
96
+ style : {
97
+ justifyContent : align === 'right' ? 'flex-end' : 'flex-start' ,
98
+ alignItems : 'flex-start' ,
99
+ display : 'flex' ,
100
+ } ,
101
+ } ,
102
+ ]
103
+
104
+ const IndeterminateCheckbox = React . forwardRef (
105
+ ( { indeterminate, ...rest } , ref ) => {
106
+ const defaultRef = React . useRef ( )
107
+ const resolvedRef = ref || defaultRef
108
+
109
+ React . useEffect ( ( ) => {
110
+ resolvedRef . current . indeterminate = indeterminate
111
+ } , [ resolvedRef , indeterminate ] )
112
+
113
+ return (
114
+ < >
115
+ < input type = "checkbox" ref = { resolvedRef } { ...rest } />
116
+ </ >
117
+ )
118
+ }
119
+ )
120
+
75
121
function Table ( { columns, data } ) {
76
122
const defaultColumn = React . useMemo (
77
123
( ) => ( {
@@ -96,36 +142,77 @@ function Table({ columns, data }) {
96
142
defaultColumn,
97
143
} ,
98
144
useResizeColumns ,
99
- useFlexLayout
145
+ useFlexLayout ,
146
+ useRowSelect ,
147
+ hooks => {
148
+ hooks . flatColumns . push ( columns => [
149
+ // Let's make a column for selection
150
+ {
151
+ id : 'selection' ,
152
+ disableResizing : true ,
153
+ minWidth : 35 ,
154
+ width : 35 ,
155
+ maxWidth : 35 ,
156
+ // The header can use the table's getToggleAllRowsSelectedProps method
157
+ // to render a checkbox
158
+ Header : ( { getToggleAllRowsSelectedProps } ) => (
159
+ < div >
160
+ < IndeterminateCheckbox { ...getToggleAllRowsSelectedProps ( ) } />
161
+ </ div >
162
+ ) ,
163
+ // The cell can use the individual row's getToggleRowSelectedProps method
164
+ // to the render a checkbox
165
+ Cell : ( { row } ) => (
166
+ < div >
167
+ < IndeterminateCheckbox { ...row . getToggleRowSelectedProps ( ) } />
168
+ </ div >
169
+ ) ,
170
+ } ,
171
+ ...columns ,
172
+ ] )
173
+ hooks . useInstanceBeforeDimensions . push ( ( { headerGroups } ) => {
174
+ // fix the parent group of the selection button to not be resizable
175
+ const selectionGroupHeader = headerGroups [ 0 ] . headers [ 0 ]
176
+ selectionGroupHeader . canResize = false
177
+ } )
178
+ }
100
179
)
101
180
102
181
return (
103
182
< div { ...getTableProps ( ) } className = "table" >
104
183
< div >
105
184
{ headerGroups . map ( headerGroup => (
106
- < div { ...headerGroup . getHeaderGroupProps ( ) } className = "tr" >
185
+ < div
186
+ { ...headerGroup . getHeaderGroupProps ( {
187
+ style : { paddingRight : '15px' } ,
188
+ } ) }
189
+ className = "tr"
190
+ >
107
191
{ headerGroup . headers . map ( column => (
108
- < div { ...column . getHeaderProps ( ) } className = "th" >
192
+ < div { ...column . getHeaderProps ( headerProps ) } className = "th" >
109
193
{ column . render ( 'Header' ) }
110
194
{ /* Use column.getResizerProps to hook up the events correctly */ }
111
- < div
112
- { ...column . getResizerProps ( ) }
113
- className = { `resizer ${ column . isResizing ? 'isResizing' : '' } ` }
114
- />
195
+ { column . canResize && (
196
+ < div
197
+ { ...column . getResizerProps ( ) }
198
+ className = { `resizer ${
199
+ column . isResizing ? 'isResizing' : ''
200
+ } `}
201
+ />
202
+ ) }
115
203
</ div >
116
204
) ) }
117
205
</ div >
118
206
) ) }
119
207
</ div >
120
-
121
208
< div { ...getTableBodyProps ( ) } className = "tbody" >
122
209
{ rows . map ( ( row , i ) => {
123
210
prepareRow ( row )
124
211
return (
125
212
< div { ...row . getRowProps ( ) } className = "tr" >
126
213
{ row . cells . map ( cell => {
127
214
return (
128
- < div { ...cell . getCellProps ( ) } className = "td" >
215
+ < div { ...cell . getCellProps ( cellProps ) } className = "td" >
129
216
{ cell . render ( 'Cell' ) }
130
217
</ div >
131
218
)
@@ -161,11 +248,13 @@ function App() {
161
248
Header : 'Age' ,
162
249
accessor : 'age' ,
163
250
width : 50 ,
251
+ align : 'right' ,
164
252
} ,
165
253
{
166
254
Header : 'Visits' ,
167
255
accessor : 'visits' ,
168
256
width : 50 ,
257
+ align : 'right' ,
169
258
} ,
170
259
{
171
260
Header : 'Status' ,
0 commit comments