Skip to content

Commit 7de717c

Browse files
committed
[website] add draggable rows example
1 parent b786419 commit 7de717c

7 files changed

Lines changed: 314 additions & 4 deletions

File tree

docs/get-started.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@ import 'react-base-table/styles.css'
3030
**`width` and `height` are required to display the table properly**
3131

3232
In the [examples](https://autodesk.github.io/react-base-table/examples)
33-
we are using a wrapper `const Table = props => <BaseTable width={720} height={400} {...props} />` to do that
33+
we are using a wrapper `const Table = props => <BaseTable width={700} height={400} {...props} />` to do that
3434

35-
You can use the [`AutoResizer`](https://autodesk.github.io/react-base-table/api/autoresizer) to make the table fill the container, take the [playground](https://autodesk.github.io/react-base-table/playground) for example
35+
If you want it responsive, you can use the [`AutoResizer`](https://autodesk.github.io/react-base-table/api/autoresizer) to make the table fill the container, checkout the [Auto Resize example](https://autodesk.github.io/react-base-table/examples/auto-resize)
3636

37-
_You have to polyfil `Array.prototype.findIndex` to make it works on IE_
37+
## Browser Support
38+
39+
`BaseTable` is well tested on all modern browsers and IE11. _You have to polyfill `Array.prototype.findIndex` to make it works on IE_
40+
41+
**The [examples](https://autodesk.github.io/react-base-table/examples) don't work on IE as they are powered by [react-runner](https://github.com/nihgwu/react-runner) which is a `react-live` like library but only for modern browsers.**
3842

3943
## Playground
4044

website/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"react-helmet": "^5.2.0",
2929
"react-inspector": "^2.3.1",
3030
"react-live-runner": "^0.7.3",
31+
"react-sortable-hoc": "^1.9.1",
3132
"rehype-react": "^3.1.0",
3233
"sanitize.css": "^10.0.0",
3334
"seamless-immutable": "^7.1.4",

website/siteConfig.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ module.exports = {
7676
title: '10000 Rows',
7777
path: '/examples/10000-rows',
7878
},
79+
{
80+
title: 'Draggable Rows',
81+
path: '/examples/draggable-rows',
82+
},
7983
{
8084
title: 'Disabled',
8185
path: '/examples/disabled',
@@ -160,6 +164,10 @@ module.exports = {
160164
title: 'Multi Sort',
161165
path: '/examples/multi-sort',
162166
},
167+
{
168+
title: 'Selection',
169+
path: '/examples/selection',
170+
},
163171
{
164172
title: 'Expand - Uncontrolled',
165173
path: '/examples/expand-uncontrolled',
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// import { sortableContainer, sortableElement, sortableHandle } from 'react-sortable-hoc'
2+
const { sortableContainer, sortableElement, sortableHandle } = ReactSortableHoc
3+
const DraggableContainer = sortableContainer(({ children }) => children)
4+
const DraggableElement = sortableElement(({ children }) => children)
5+
const DraggableHandle = sortableHandle(({ children }) => children)
6+
7+
const Handle = styled.div`
8+
flex: none;
9+
width: 7.5px;
10+
height: 100%;
11+
background: #888;
12+
`
13+
14+
const Row = ({ key, index, children, ...rest }) => (
15+
<DraggableElement key={key} index={index}>
16+
<div {...rest}>
17+
<DraggableHandle>
18+
<Handle />
19+
</DraggableHandle>
20+
{children}
21+
</div>
22+
</DraggableElement>
23+
)
24+
25+
const rowProps = ({ rowIndex }) => ({
26+
tagName: Row,
27+
index: rowIndex,
28+
})
29+
30+
class DraggableTable extends React.PureComponent {
31+
getContainer() {
32+
return document.querySelector('.BaseTable__body')
33+
}
34+
35+
getHelperContainer() {
36+
return document.querySelector('.BaseTable__table')
37+
}
38+
39+
rowProps = args => {
40+
// don't forget to passing the incoming rowProps
41+
const extraProps = callOrReturn(this.props.rowProps)
42+
return {
43+
...extraProps,
44+
tagName: Row,
45+
index: args.rowIndex,
46+
}
47+
}
48+
49+
render() {
50+
return (
51+
<DraggableContainer
52+
useDragHandle
53+
getContainer={this.getContainer}
54+
helperContainer={this.getHelperContainer}
55+
>
56+
<Table {...this.props} fixed={false} rowProps={this.rowProps} />
57+
</DraggableContainer>
58+
)
59+
}
60+
}
61+
62+
const Hint = styled.div`
63+
font-size: 16px;
64+
font-weight: 700;
65+
color: #336699;
66+
margin-bottom: 10px;
67+
`
68+
69+
const columns = generateColumns(10)
70+
const data = generateData(columns, 200)
71+
72+
export default () => (
73+
<>
74+
<Hint>Drag the gray handles, only works in flex mode(fixed=false)</Hint>
75+
<DraggableTable columns={columns} data={data} />
76+
</>
77+
)

website/src/examples/selection.js

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
const StyledTable = styled(BaseTable)`
2+
.row-selected {
3+
background-color: #e3e3e3;
4+
}
5+
`
6+
7+
class SelectionCell extends React.PureComponent {
8+
_handleChange = e => {
9+
const { rowData, rowIndex, column } = this.props
10+
const { onChange } = column
11+
12+
onChange({ selected: e.target.checked, rowData, rowIndex })
13+
}
14+
15+
render() {
16+
const { rowData, column } = this.props
17+
const { selectedRowKeys, rowKey } = column
18+
const checked = selectedRowKeys.includes(rowData[rowKey])
19+
20+
return (
21+
<input type="checkbox" checked={checked} onChange={this._handleChange} />
22+
)
23+
}
24+
}
25+
26+
class SelectableTable extends React.PureComponent {
27+
constructor(props) {
28+
super(props)
29+
30+
const {
31+
selectedRowKeys,
32+
defaultSelectedRowKeys,
33+
expandedRowKeys,
34+
defaultExpandedRowKeys,
35+
} = props
36+
this.state = {
37+
selectedRowKeys:
38+
(selectedRowKeys !== undefined
39+
? selectedRowKeys
40+
: defaultSelectedRowKeys) || [],
41+
expandedRowKeys:
42+
(expandedRowKeys !== undefined
43+
? expandedRowKeys
44+
: defaultExpandedRowKeys) || [],
45+
}
46+
}
47+
48+
/**
49+
* Set `selectedRowKeys` manually.
50+
* This method is available only if `selectedRowKeys` is uncontrolled.
51+
*
52+
* @param {array} selectedRowKeys
53+
*/
54+
setSelectedRowKeys(selectedRowKeys) {
55+
// if `selectedRowKeys` is controlled
56+
if (this.props.selectedRowKeys !== undefined) return
57+
58+
this.setState({
59+
selectedRowKeys: cloneArray(selectedRowKeys),
60+
})
61+
}
62+
63+
/**
64+
* See BaseTable#setExpandedRowKeys
65+
*/
66+
setExpandedRowKeys(expandedRowKeys) {
67+
// if `expandedRowKeys` is controlled
68+
if (this.props.expandedRowKeys !== undefined) return
69+
70+
this.setState({
71+
expandedRowKeys: cloneArray(expandedRowKeys),
72+
})
73+
}
74+
75+
/* some other custom methods and proxy methods */
76+
77+
/**
78+
* Remove rowKeys from inner state manually, it's useful to purge dirty state after rows removed.
79+
* This method is available only if `selectedRowKeys` or `expandedRowKeys` is uncontrolled.
80+
*
81+
* @param {array} rowKeys
82+
*/
83+
removeRowKeysFromState(rowKeys) {
84+
if (!Array.isArray(rowKeys)) return
85+
86+
const state = {}
87+
if (
88+
this.props.selectedRowKeys === undefined &&
89+
this.state.selectedRowKeys.length > 0
90+
) {
91+
state.selectedRowKeys = this.state.selectedRowKeys.filter(
92+
key => !rowKeys.includes(key)
93+
)
94+
}
95+
if (
96+
this.props.expandedRowKeys === undefined &&
97+
this.state.expandedRowKeys.length > 0
98+
) {
99+
state.expandedRowKeys = this.state.expandedRowKeys.filter(
100+
key => !rowKeys.includes(key)
101+
)
102+
}
103+
if (state.selectedRowKeys || state.expandedRowKeys) {
104+
this.setState(state)
105+
}
106+
}
107+
108+
_handleSelectChange = ({ selected, rowData, rowIndex }) => {
109+
const selectedRowKeys = [...this.state.selectedRowKeys]
110+
const key = rowData[this.props.rowKey]
111+
112+
if (selected) {
113+
if (!selectedRowKeys.includes(key)) selectedRowKeys.push(key)
114+
} else {
115+
const index = selectedRowKeys.indexOf(key)
116+
if (index > -1) {
117+
selectedRowKeys.splice(index, 1)
118+
}
119+
}
120+
121+
// if `selectedRowKeys` is uncontrolled, update internal state
122+
if (this.props.selectedRowKeys === undefined) {
123+
this.setState({ selectedRowKeys })
124+
}
125+
this.props.onRowSelect({ selected, rowData, rowIndex })
126+
this.props.onSelectedRowsChange(selectedRowKeys)
127+
}
128+
129+
_rowClassName = ({ rowData, rowIndex }) => {
130+
const { rowClassName, rowKey } = this.props
131+
const { selectedRowKeys } = this.state
132+
133+
const rowClass = rowClassName
134+
? callOrReturn(rowClassName, { rowData, rowIndex })
135+
: ''
136+
const key = rowData[rowKey]
137+
138+
return [rowClass, selectedRowKeys.includes(key) && 'row-selected']
139+
.filter(Boolean)
140+
.concat(' ')
141+
}
142+
143+
render() {
144+
const {
145+
columns,
146+
children,
147+
selectable,
148+
selectionColumnProps,
149+
...rest
150+
} = this.props
151+
const { selectedRowKeys } = this.state
152+
153+
// you'd better memoize this operation
154+
let _columns = columns || normalizeColumns(children)
155+
if (selectable) {
156+
const selectionColumn = {
157+
width: 40,
158+
flexShrink: 0,
159+
resizable: false,
160+
frozen: Column.FrozenDirection.LEFT,
161+
cellRenderer: SelectionCell,
162+
...selectionColumnProps,
163+
key: '__selection__',
164+
rowKey: this.props.rowKey,
165+
selectedRowKeys: selectedRowKeys,
166+
onChange: this._handleSelectChange,
167+
}
168+
_columns = [selectionColumn, ..._columns]
169+
}
170+
171+
return (
172+
<StyledTable
173+
{...rest}
174+
columns={_columns}
175+
rowClassName={this._rowClassName}
176+
/>
177+
)
178+
}
179+
}
180+
181+
SelectableTable.defaultProps = {
182+
...BaseTable.defaultProps,
183+
onRowSelect: noop,
184+
onSelectedRowsChange: noop,
185+
}
186+
187+
// Use case
188+
const columns = generateColumns(10)
189+
const data = generateData(columns, 200)
190+
191+
export default () => (
192+
<SelectableTable
193+
width={700}
194+
height={400}
195+
selectable
196+
columns={columns}
197+
data={data}
198+
onRowSelect={action('onRowSelect')}
199+
onSelectedRowsChange={action('onSelectedRowsChange')}
200+
/>
201+
)

website/src/utils/baseScope.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react'
22
import ReactDOM from 'react-dom'
33
import styled, { css, keyframes, createGlobalStyle } from 'styled-components'
4+
import * as ReactSortableHoc from 'react-sortable-hoc'
45

56
import BaseTable, {
67
Column,
@@ -53,6 +54,8 @@ export default {
5354
keyframes,
5455
createGlobalStyle,
5556

57+
ReactSortableHoc,
58+
5659
BaseTable,
5760
Column,
5861
SortOrder,

website/yarn.lock

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,13 @@
730730
dependencies:
731731
regenerator-runtime "^0.13.2"
732732

733+
"@babel/runtime@^7.2.0":
734+
version "7.5.4"
735+
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.4.tgz#cb7d1ad7c6d65676e66b47186577930465b5271b"
736+
integrity sha512-Na84uwyImZZc3FKf4aUF1tysApzwf3p2yuFBIyBfbzT5glzKTdvYI4KVW4kcgjrzoGUjC7w3YyCHcJKaRxsr2Q==
737+
dependencies:
738+
regenerator-runtime "^0.13.2"
739+
733740
"@babel/template@^7.1.0", "@babel/template@^7.4.4":
734741
version "7.4.4"
735742
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237"
@@ -8740,7 +8747,7 @@ prompts@^2.1.0:
87408747
kleur "^3.0.2"
87418748
sisteransi "^1.0.0"
87428749

8743-
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
8750+
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
87448751
version "15.7.2"
87458752
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
87468753
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -9089,6 +9096,15 @@ react-simple-code-editor@^0.9.11:
90899096
resolved "https://registry.yarnpkg.com/react-simple-code-editor/-/react-simple-code-editor-0.9.11.tgz#7b363e646546419b377fadbc00f3cc0be3978fd7"
90909097
integrity sha512-kWkFqCOJ0qbiwm7yQsaIcsEG3IBRbet1G+hR/p77O20amPA9eC0yli1lqZdudf6FlUUXfI5gIz31CNNxEMXh4w==
90919098

9099+
react-sortable-hoc@^1.9.1:
9100+
version "1.9.1"
9101+
resolved "https://registry.yarnpkg.com/react-sortable-hoc/-/react-sortable-hoc-1.9.1.tgz#ae3d28c3cff87fb862be3ddcde9c76b5b5bd2152"
9102+
integrity sha512-2VeofjRav8+eZeE5Nm/+b8mrA94rQ+gBsqhXi8pRBSjOWNqslU3ZEm+0XhSlfoXJY2lkgHipfYAUuJbDtCixRg==
9103+
dependencies:
9104+
"@babel/runtime" "^7.2.0"
9105+
invariant "^2.2.4"
9106+
prop-types "^15.5.7"
9107+
90929108
react@^16.8.4, react@^16.8.5:
90939109
version "16.8.6"
90949110
resolved "https://registry.yarnpkg.com/react/-/react-16.8.6.tgz#ad6c3a9614fd3a4e9ef51117f54d888da01f2bbe"

0 commit comments

Comments
 (0)