-
Notifications
You must be signed in to change notification settings - Fork 3k
Expand file tree
/
Copy pathArrowKeyStepper.js
More file actions
92 lines (81 loc) · 2.45 KB
/
ArrowKeyStepper.js
File metadata and controls
92 lines (81 loc) · 2.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/** @flow */
import React, { Component, PropTypes } from 'react'
import shouldPureComponentUpdate from 'react-pure-render/function'
/**
* This HOC decorates a virtualized component and responds to arrow-key events by scrolling one row or column at a time.
*/
export default class ArrowKeyStepper extends Component {
shouldComponentUpdate = shouldPureComponentUpdate
static propTypes = {
children: PropTypes.func.isRequired,
className: PropTypes.string,
columnsCount: PropTypes.number.isRequired,
rowsCount: PropTypes.number.isRequired
}
constructor (props, context) {
super(props, context)
this.state = {
scrollToColumn: 0,
scrollToRow: 0
}
this._columnStartIndex = 0
this._columnStopIndex = 0
this._rowStartIndex = 0
this._rowStopIndex = 0
this._onKeyDown = this._onKeyDown.bind(this)
this._onSectionRendered = this._onSectionRendered.bind(this)
}
render () {
const { className, children } = this.props
const { scrollToColumn, scrollToRow } = this.state
return (
<div
className={className}
onKeyDown={this._onKeyDown}
>
{children({
onSectionRendered: this._onSectionRendered,
scrollToColumn,
scrollToRow
})}
</div>
)
}
_onKeyDown (event) {
const { columnsCount, rowsCount } = this.props
// The above cases all prevent default event event behavior.
// This is to keep the grid from scrolling after the snap-to update.
switch (event.key) {
case 'ArrowDown':
event.preventDefault()
this.setState({
scrollToRow: Math.min(this._rowStopIndex + 1, rowsCount - 1)
})
break
case 'ArrowLeft':
event.preventDefault()
this.setState({
scrollToColumn: Math.max(this._columnStartIndex - 1, 0)
})
break
case 'ArrowRight':
event.preventDefault()
this.setState({
scrollToColumn: Math.min(this._columnStopIndex + 1, columnsCount - 1)
})
break
case 'ArrowUp':
event.preventDefault()
this.setState({
scrollToRow: Math.max(this._rowStartIndex - 1, 0)
})
break
}
}
_onSectionRendered ({ columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex }) {
this._columnStartIndex = columnStartIndex
this._columnStopIndex = columnStopIndex
this._rowStartIndex = rowStartIndex
this._rowStopIndex = rowStopIndex
}
}