1
1
import React , {
2
2
ChangeEvent ,
3
- FormEvent ,
3
+ KeyboardEvent ,
4
4
MouseEvent ,
5
5
useCallback ,
6
6
useEffect ,
@@ -84,18 +84,21 @@ export function SearchForm({ view }: SearchFormProps) {
84
84
setSelectedIndex ( null ) ;
85
85
} , [ query , view ] ) ;
86
86
87
- const updateFindCount = useCallback ( ( ) => {
88
- const cursor = query . getCursor ( view . state . doc ) ;
89
- let count = 0 ;
90
- let result = cursor . next ( ) ;
87
+ const updateFindCount = useCallback (
88
+ ( searchQuery : SearchQuery ) => {
89
+ const cursor = searchQuery . getCursor ( view . state . doc ) ;
90
+ let count = 0 ;
91
+ let result = cursor . next ( ) ;
91
92
92
- while ( ! result . done ) {
93
- count ++ ;
94
- result = cursor . next ( ) ;
95
- }
93
+ while ( ! result . done ) {
94
+ count ++ ;
95
+ result = cursor . next ( ) ;
96
+ }
96
97
97
- setFindCount ( count ) ;
98
- } , [ query , view ] ) ;
98
+ setFindCount ( count ) ;
99
+ } ,
100
+ [ view ] ,
101
+ ) ;
99
102
100
103
useEffect ( ( ) => {
101
104
const newQuery = new SearchQuery ( {
@@ -107,8 +110,8 @@ export function SearchForm({ view }: SearchFormProps) {
107
110
} ) ;
108
111
109
112
setQuery ( newQuery ) ;
110
- view . dispatch ( { effects : setSearchQuery . of ( query ) } ) ;
111
- updateFindCount ( ) ;
113
+ view . dispatch ( { effects : setSearchQuery . of ( newQuery ) } ) ;
114
+ updateFindCount ( newQuery ) ;
112
115
} , [
113
116
replaceString ,
114
117
searchString ,
@@ -117,7 +120,6 @@ export function SearchForm({ view }: SearchFormProps) {
117
120
isWholeWord ,
118
121
view ,
119
122
updateFindCount ,
120
- query ,
121
123
] ) ;
122
124
123
125
const handleToggleButtonClick = useCallback (
@@ -148,43 +150,56 @@ export function SearchForm({ view }: SearchFormProps) {
148
150
[ ] ,
149
151
) ;
150
152
151
- const handleFindFormSubmit = useCallback (
152
- ( e : FormEvent < HTMLFormElement > ) => {
153
- e . preventDefault ( ) ;
154
- findNext ( view ) ;
155
- updateSelectedIndex ( ) ;
156
- } ,
157
- [ view , updateSelectedIndex ] ,
158
- ) ;
159
-
160
- const handleNextClick = useCallback ( ( ) => {
153
+ const handleFindNext = useCallback ( ( ) => {
161
154
findNext ( view ) ;
162
155
updateSelectedIndex ( ) ;
163
156
} , [ view , updateSelectedIndex ] ) ;
164
157
165
- const handlePreviousClick = useCallback ( ( ) => {
158
+ const handleFindPrevious = useCallback ( ( ) => {
166
159
findPrevious ( view ) ;
167
160
updateSelectedIndex ( ) ;
168
161
} , [ view , updateSelectedIndex ] ) ;
169
162
170
163
const handleReplace = useCallback ( ( ) => {
171
164
replaceNext ( view ) ;
172
165
updateSelectedIndex ( ) ;
173
- updateFindCount ( ) ;
174
- } , [ view , updateSelectedIndex , updateFindCount ] ) ;
166
+ updateFindCount ( query ) ;
167
+ } , [ view , updateSelectedIndex , updateFindCount , query ] ) ;
175
168
176
169
const handleReplaceAll = useCallback ( ( ) => {
177
170
replaceAll ( view ) ;
178
171
updateSelectedIndex ( ) ;
179
- updateFindCount ( ) ;
180
- } , [ view , updateSelectedIndex , updateFindCount ] ) ;
172
+ updateFindCount ( query ) ;
173
+ } , [ view , updateSelectedIndex , updateFindCount , query ] ) ;
181
174
182
- const handleReplaceFormSubmit = useCallback (
183
- ( e : FormEvent < HTMLFormElement > ) => {
184
- e . preventDefault ( ) ;
185
- handleReplace ( ) ;
175
+ const handleFindInputKeyDown = useCallback (
176
+ ( e : KeyboardEvent < HTMLInputElement > ) => {
177
+ if ( e . key === 'Enter' ) {
178
+ e . preventDefault ( ) ;
179
+ if ( e . shiftKey ) {
180
+ handleFindPrevious ( ) ;
181
+ } else {
182
+ handleFindNext ( ) ;
183
+ }
184
+ } else if ( e . key === 'Escape' ) {
185
+ e . preventDefault ( ) ;
186
+ closeSearchPanel ( view ) ;
187
+ }
188
+ } ,
189
+ [ handleFindNext , handleFindPrevious , view ] ,
190
+ ) ;
191
+
192
+ const handleReplaceInputKeyDown = useCallback (
193
+ ( e : KeyboardEvent < HTMLInputElement > ) => {
194
+ if ( e . key === 'Enter' ) {
195
+ e . preventDefault ( ) ;
196
+ handleReplace ( ) ;
197
+ } else if ( e . key === 'Escape' ) {
198
+ e . preventDefault ( ) ;
199
+ closeSearchPanel ( view ) ;
200
+ }
186
201
} ,
187
- [ handleReplace ] ,
202
+ [ handleReplace , view ] ,
188
203
) ;
189
204
190
205
return (
@@ -202,17 +217,16 @@ export function SearchForm({ view }: SearchFormProps) {
202
217
< Icon glyph = "ChevronDown" className = { getToggleIconStyles ( isOpen ) } />
203
218
</ IconButton >
204
219
< div className = { findInputContainerStyles } >
205
- < form onSubmit = { handleFindFormSubmit } >
206
- < TextInput
207
- placeholder = "Find"
208
- aria-labelledby = "find"
209
- onChange = { handleSearchQueryChange }
210
- className = { findInputStyles }
211
- // eslint-disable-next-line jsx-a11y/no-autofocus
212
- autoFocus
213
- value = { searchString }
214
- />
215
- </ form >
220
+ < TextInput
221
+ placeholder = "Find"
222
+ aria-labelledby = "find"
223
+ onChange = { handleSearchQueryChange }
224
+ onKeyDown = { handleFindInputKeyDown }
225
+ className = { findInputStyles }
226
+ // eslint-disable-next-line jsx-a11y/no-autofocus
227
+ autoFocus
228
+ value = { searchString }
229
+ />
216
230
< div className = { findOptionsContainerStyles } >
217
231
{ searchString && (
218
232
< Body >
@@ -227,14 +241,14 @@ export function SearchForm({ view }: SearchFormProps) {
227
241
< IconButton
228
242
aria-label = "previous item button"
229
243
disabled = { ! searchString || findCount === 0 }
230
- onClick = { handlePreviousClick }
244
+ onClick = { handleFindPrevious }
231
245
>
232
246
< Icon glyph = "ArrowUp" />
233
247
</ IconButton >
234
248
< IconButton
235
249
aria-label = "next item button"
236
250
disabled = { ! searchString || findCount === 0 }
237
- onClick = { handleNextClick }
251
+ onClick = { handleFindNext }
238
252
>
239
253
< Icon glyph = "ArrowDown" />
240
254
</ IconButton >
@@ -263,15 +277,14 @@ export function SearchForm({ view }: SearchFormProps) {
263
277
aria-hidden = { ! isOpen }
264
278
>
265
279
< div className = { getReplaceInnerSectionStyles ( theme ) } >
266
- < form onSubmit = { handleReplaceFormSubmit } >
267
- < TextInput
268
- placeholder = "Replace"
269
- aria-labelledby = "replace"
270
- className = { replaceInputContainerStyles }
271
- value = { replaceString }
272
- onChange = { handleReplaceQueryChange }
273
- />
274
- </ form >
280
+ < TextInput
281
+ placeholder = "Replace"
282
+ aria-labelledby = "replace"
283
+ className = { replaceInputContainerStyles }
284
+ value = { replaceString }
285
+ onChange = { handleReplaceQueryChange }
286
+ onKeyDown = { handleReplaceInputKeyDown }
287
+ />
275
288
< Button
276
289
aria-label = "replace button"
277
290
className = { replaceButtonStyles }
0 commit comments