@@ -3,8 +3,12 @@ const ReactDOM = require("react-dom");
3
3
const PropTypes = require ( "prop-types" ) ;
4
4
const { styled } = require ( "styletron-react" ) ;
5
5
const TextPlane = require ( "./text_plane" ) ;
6
+ const debounce = require ( '../debounce' ) ;
6
7
const $ = React . createElement ;
7
8
9
+ const CURSOR_BLINK_RESUME_DELAY = 300 ;
10
+ const CURSOR_BLINK_PERIOD = 800 ;
11
+
8
12
const Root = styled ( "div" , {
9
13
width : "100%" ,
10
14
height : "100%" ,
@@ -14,7 +18,12 @@ const Root = styled("div", {
14
18
class TextEditor extends React . Component {
15
19
constructor ( props ) {
16
20
super ( props ) ;
17
- this . onWheel = this . onWheel . bind ( this ) ;
21
+ this . handleMouseWheel = this . handleMouseWheel . bind ( this ) ;
22
+ this . handleKeyDown = this . handleKeyDown . bind ( this ) ;
23
+ this . debouncedStartCursorBlinking = debounce (
24
+ this . startCursorBlinking . bind ( this ) ,
25
+ CURSOR_BLINK_RESUME_DELAY
26
+ ) ;
18
27
19
28
if ( props . initialText ) {
20
29
buffer . splice ( 0 , 0 , props . initialText ) ;
@@ -39,18 +48,16 @@ class TextEditor extends React.Component {
39
48
height : element . offsetHeight
40
49
} ) ;
41
50
42
- element . addEventListener ( 'wheel' , this . onWheel , { passive : true } ) ;
51
+ element . addEventListener ( 'wheel' , this . handleMouseWheel , { passive : true } ) ;
43
52
44
- this . state . cursorBlinkIntervalHandle = window . setInterval ( ( ) => {
45
- this . setState ( { showCursors : ! this . state . showCursors } ) ;
46
- } , 500 ) ;
53
+ this . startCursorBlinking ( ) ;
47
54
}
48
55
49
56
componentWillUnmount ( ) {
57
+ this . stopCursorBlinking ( ) ;
50
58
const element = ReactDOM . findDOMNode ( this ) ;
51
- element . removeEventListener ( 'wheel' , this . onWheel , { passive : true } ) ;
59
+ element . removeEventListener ( 'wheel' , this . handleMouseWheel , { passive : true } ) ;
52
60
this . state . resizeObserver . disconnect ( ) ;
53
- window . clearInterval ( this . state . cursorBlinkIntervalHandle ) ;
54
61
}
55
62
56
63
componentDidResize ( measurements ) {
@@ -64,7 +71,10 @@ class TextEditor extends React.Component {
64
71
render ( ) {
65
72
return $ (
66
73
Root ,
67
- { } ,
74
+ {
75
+ tabIndex : - 1 ,
76
+ onKeyDown : this . handleKeyDown
77
+ } ,
68
78
$ ( TextPlane , {
69
79
showCursors : this . state . showCursors ,
70
80
lineHeight : this . props . line_height ,
@@ -78,9 +88,64 @@ class TextEditor extends React.Component {
78
88
) ;
79
89
}
80
90
81
- onWheel ( event ) {
91
+ handleMouseWheel ( event ) {
82
92
this . props . dispatch ( { type : 'UpdateScrollTop' , delta : event . deltaY } ) ;
83
93
}
94
+
95
+ handleKeyDown ( event ) {
96
+ if ( event . key . length === 1 ) {
97
+ this . props . dispatch ( { type : 'ReplaceSelectedText' , text : event . key } ) ;
98
+ return ;
99
+ }
100
+
101
+ switch ( event . key ) {
102
+ case 'ArrowUp' :
103
+ this . pauseCursorBlinking ( ) ;
104
+ this . props . dispatch ( { type : 'MoveUp' } ) ;
105
+ break ;
106
+ case 'ArrowDown' :
107
+ this . pauseCursorBlinking ( ) ;
108
+ this . props . dispatch ( { type : 'MoveDown' } ) ;
109
+ break ;
110
+ case 'ArrowLeft' :
111
+ this . pauseCursorBlinking ( ) ;
112
+ this . props . dispatch ( { type : 'MoveLeft' } ) ;
113
+ break ;
114
+ case 'ArrowRight' :
115
+ this . pauseCursorBlinking ( ) ;
116
+ this . props . dispatch ( { type : 'MoveRight' } ) ;
117
+ break ;
118
+ }
119
+ }
120
+
121
+ pauseCursorBlinking ( ) {
122
+ this . stopCursorBlinking ( )
123
+ this . debouncedStartCursorBlinking ( )
124
+ }
125
+
126
+ stopCursorBlinking ( ) {
127
+ if ( this . state . cursorsBlinking ) {
128
+ window . clearInterval ( this . cursorBlinkIntervalHandle )
129
+ this . cursorBlinkIntervalHandle = null
130
+ this . setState ( {
131
+ showCursors : true ,
132
+ cursorsBlinking : false
133
+ } ) ;
134
+ }
135
+ }
136
+
137
+ startCursorBlinking ( ) {
138
+ if ( ! this . state . cursorsBlinking ) {
139
+ this . cursorBlinkIntervalHandle = window . setInterval ( ( ) => {
140
+ this . setState ( { showCursors : ! this . state . showCursors } ) ;
141
+ } , CURSOR_BLINK_PERIOD / 2 ) ;
142
+
143
+ this . setState ( {
144
+ cursorsBlinking : true ,
145
+ showCursors : false
146
+ } ) ;
147
+ }
148
+ }
84
149
}
85
150
86
151
TextEditor . contextTypes = {
0 commit comments