1+ // @flow
2+
13/**
24 * Copyright (c) 2015-present, Facebook, Inc.
35 *
1012
1113'use strict' ; // [macOS]
1214
13- import type { KeyEvent } from 'react-native/Libraries/Types/CoreEventTypes' ;
14-
1515import * as React from 'react' ;
1616
17- import {
18- Pressable ,
19- StyleSheet ,
20- Switch ,
21- Text ,
22- TextInput ,
23- View ,
24- } from 'react-native' ;
17+ import type {
18+ HandledKeyEvent ,
19+ KeyEvent ,
20+ } from 'react-native/Libraries/Types/CoreEventTypes' ;
2521
26- function formatKeyEvent ( event : any ) {
22+ import { Pressable , StyleSheet , Text , TextInput , View } from 'react-native' ;
23+
24+ function formatKeyEvent ( event : KeyEvent ) {
2725 const modifiers = [ ] ;
28- if ( event . ctrlKey ) {
26+ if ( event . nativeEvent . ctrlKey ) {
2927 modifiers . push ( 'Ctrl' ) ;
3028 }
31- if ( event . altKey ) {
29+ if ( event . nativeEvent . altKey ) {
3230 modifiers . push ( 'Alt' ) ;
3331 }
34- if ( event . shiftKey ) {
32+ if ( event . nativeEvent . shiftKey ) {
3533 modifiers . push ( 'Shift' ) ;
3634 }
37- if ( event . metaKey ) {
35+ if ( event . nativeEvent . metaKey ) {
3836 modifiers . push ( 'Meta' ) ;
3937 }
4038
4139 const modifierPrefix = modifiers . length > 0 ? `${ modifiers . join ( '+' ) } +` : '' ;
42- return `${ modifierPrefix } ${ event . key } ` ;
40+ return `${ modifierPrefix } ${ event . nativeEvent . key } ` ;
41+ }
42+
43+ function isKeyBlocked (
44+ event : KeyEvent ,
45+ keyEvents : Array < HandledKeyEvent > ,
46+ ) {
47+ return keyEvents . some ( ( { key, metaKey, ctrlKey, altKey, shiftKey} ) => (
48+ event . nativeEvent . key === key &&
49+ ( metaKey ?? false ) === event . nativeEvent . metaKey &&
50+ ( ctrlKey ?? false ) === event . nativeEvent . ctrlKey &&
51+ ( altKey ?? false ) === event . nativeEvent . altKey &&
52+ ( shiftKey ?? false ) === event . nativeEvent . shiftKey
53+ ) ) ;
4354}
4455
56+ const BOX2_KEY_DOWN_EVENTS = [ { key : 'f' } , { key : 'g' } ] ;
57+
4558function EventLog ( {
4659 eventLog,
4760 onClear,
@@ -74,8 +87,6 @@ function EventLog({
7487function BubblingExample ( ) : React . Node {
7588 const ref = React . useRef < React . ElementRef < typeof Pressable > | null > ( null ) ;
7689 const [ eventLog , setEventLog ] = React . useState < Array < string >> ( [ ] ) ;
77- const [ stopPropagationEnabled , setStopPropagationEnabled ] =
78- React . useState < boolean > ( false ) ;
7990
8091 function appendEvent ( eventName : string , source ?: string ) {
8192 const limit = 12 ;
@@ -92,55 +103,45 @@ function BubblingExample(): React.Node {
92103 Event Bubbling Behavior:
93104 </ Text >
94105 < Text style = { { fontSize : 12 , marginBottom : 3 , color : '#424245' } } >
95- • Pressable won't bubble Space or Enter keys
106+ • Pressable won't bubble Space or Enter keys, it handles those by default
96107 </ Text >
97108 < Text style = { { fontSize : 12 , marginBottom : 3 , color : '#424245' } } >
98109 • Keys 'f' and 'g' won't bubble past Box 2 (handled by keyDownEvents)
99110 </ Text >
100111 < Text style = { { fontSize : 12 , color : '#424245' } } >
101- • If "Stop Propagation" is enabled, no events bubble past 'f' and 'g' in JS
112+ • Shift+f and Shift+g will bubble
102113 </ Text >
103114 </ View >
104- < View
105- style = { { flexDirection : 'row' , alignItems : 'center' , marginBottom : 8 } } >
106- < Text style = { { marginRight : 8 } } > Stop Propagation in Box 2:</ Text >
107- < Switch
108- value = { stopPropagationEnabled }
109- onValueChange = { ( value : boolean ) => setStopPropagationEnabled ( value ) }
110- />
111- </ View >
112115 < View
113116 style = { styles . boxOuter }
114117 nativeID = "Box 3"
115- onKeyDown = { ev => {
116- const keyDisplay = formatKeyEvent ( ev . nativeEvent ) ;
118+ onKeyDown = { event => {
119+ const keyDisplay = formatKeyEvent ( event ) ;
117120 appendEvent ( `keyDown: ${ keyDisplay } ` , 'Box 3' ) ;
118121 } } >
122+ < Text style = { styles . boxLabel } > Box 3</ Text >
119123 < View
120124 style = { styles . boxMiddle }
121125 nativeID = "Box 2"
122- onKeyDown = { ev => {
123- const blockedKeys = [ 'f' , 'g' ] ;
124- const isBlocked = blockedKeys . includes ( ev . nativeEvent . key ) ;
126+ onKeyDown = { event => {
127+ const isBlocked = isKeyBlocked ( event , BOX2_KEY_DOWN_EVENTS ) ;
125128 const suffix = isBlocked ? ' (blocked)' : '' ;
126- const keyDisplay = formatKeyEvent ( ev . nativeEvent ) ;
129+ const keyDisplay = formatKeyEvent ( event ) ;
127130 appendEvent (
128131 `keyDown: ${ keyDisplay } ${ suffix } ` ,
129132 'Box 2 keyDownEvents=[f,g]' ,
130133 ) ;
131- if ( stopPropagationEnabled ) {
132- ev . stopPropagation ( ) ;
133- appendEvent ( 'stopPropagation called' , 'Box 2' ) ;
134- }
135134 } }
136- keyDownEvents = { [ { key : 'f' } , { key : 'g' } ] } >
135+ keyDownEvents = { BOX2_KEY_DOWN_EVENTS } >
136+ < Text style = { styles . boxLabel } > Box 2 (keyDownEvents: f, g)</ Text >
137137 < View
138138 style = { styles . boxInner }
139139 nativeID = "Box 1"
140- onKeyDown = { ev => {
141- const keyDisplay = formatKeyEvent ( ev . nativeEvent ) ;
140+ onKeyDown = { event => {
141+ const keyDisplay = formatKeyEvent ( event ) ;
142142 appendEvent ( `keyDown: ${ keyDisplay } ` , 'Box 1' ) ;
143143 } } >
144+ < Text style = { styles . boxLabel } > Box 1</ Text >
144145 < View style = { [ styles . centered ] } >
145146 < Pressable
146147 ref = { ref }
@@ -153,12 +154,12 @@ function BubblingExample(): React.Node {
153154 onPress = { ( ) => {
154155 ref . current ?. focus ( ) ;
155156 } }
156- onKeyDown = { ev => {
157- const keyDisplay = formatKeyEvent ( ev . nativeEvent ) ;
157+ onKeyDown = { event => {
158+ const keyDisplay = formatKeyEvent ( event ) ;
158159 appendEvent ( `keyDown: ${ keyDisplay } ` , 'Focusable' ) ;
159160 if (
160- ev . nativeEvent . key === 'k' &&
161- ev . nativeEvent . metaKey === true
161+ event . nativeEvent . key === 'k' &&
162+ event . nativeEvent . metaKey === true
162163 ) {
163164 appendEvent ( 'Key command: Clear event log' , 'Focusable' ) ;
164165 setTimeout ( ( ) => {
@@ -189,56 +190,44 @@ function KeyboardEventExample(): React.Node {
189190 } ) ;
190191 }
191192
192- function isKeyBlocked ( event : any , keyEvents : Array < any > ) {
193- return keyEvents . some ( ( { key, metaKey, ctrlKey, altKey, shiftKey} ) => {
194- return (
195- event . key === key &&
196- ( metaKey ?? event . metaKey ) === event . metaKey &&
197- ( ctrlKey ?? event . ctrlKey ) === event . ctrlKey &&
198- ( altKey ?? event . altKey ) === event . altKey &&
199- ( shiftKey ?? event . shiftKey ) === event . shiftKey
200- ) ;
201- } ) ;
202- }
203-
204- const handleSingleLineKeyDown = React . useCallback ( ( e : KeyEvent ) => {
193+ const handleSingleLineKeyDown = React . useCallback ( ( event : KeyEvent ) => {
205194 const keyDownEvents = [
206195 { key : 'g' } ,
207196 { key : 'Escape' } ,
208197 { key : 'Enter' } ,
209198 { key : 'ArrowLeft' } ,
210199 ] ;
211- const isBlocked = isKeyBlocked ( e . nativeEvent , keyDownEvents ) ;
200+ const isBlocked = isKeyBlocked ( event , keyDownEvents ) ;
212201 const suffix = isBlocked ? ' (blocked)' : '' ;
213- const keyDisplay = formatKeyEvent ( e . nativeEvent ) ;
202+ const keyDisplay = formatKeyEvent ( event ) ;
214203 appendEvent ( `keyDown: ${ keyDisplay } ${ suffix } ` , 'Single-line TextInput' ) ;
215204 } , [ ] ) ;
216205
217- const handleSingleLineKeyUp = React . useCallback ( ( e : KeyEvent ) => {
206+ const handleSingleLineKeyUp = React . useCallback ( ( event : KeyEvent ) => {
218207 const keyUpEvents = [ { key : 'c' } , { key : 'd' } ] ;
219- const isBlocked = isKeyBlocked ( e . nativeEvent , keyUpEvents ) ;
208+ const isBlocked = isKeyBlocked ( event , keyUpEvents ) ;
220209 const suffix = isBlocked ? ' (blocked)' : '' ;
221- const keyDisplay = formatKeyEvent ( e . nativeEvent ) ;
210+ const keyDisplay = formatKeyEvent ( event ) ;
222211 appendEvent ( `keyUp: ${ keyDisplay } ${ suffix } ` , 'Single-line TextInput' ) ;
223212 } , [ ] ) ;
224213
225- const handleMultiLineKeyDown = React . useCallback ( ( e : KeyEvent ) => {
214+ const handleMultiLineKeyDown = React . useCallback ( ( event : KeyEvent ) => {
226215 const keyDownEvents = [
227216 { key : 'ArrowRight' } ,
228217 { key : 'ArrowDown' } ,
229218 { key : 'Enter' , metaKey : true } ,
230219 ] ;
231- const isBlocked = isKeyBlocked ( e . nativeEvent , keyDownEvents ) ;
220+ const isBlocked = isKeyBlocked ( event , keyDownEvents ) ;
232221 const suffix = isBlocked ? ' (blocked)' : '' ;
233- const keyDisplay = formatKeyEvent ( e . nativeEvent ) ;
222+ const keyDisplay = formatKeyEvent ( event ) ;
234223 appendEvent ( `keyDown: ${ keyDisplay } ${ suffix } ` , 'Multi-line TextInput' ) ;
235224 } , [ ] ) ;
236225
237- const handleMultiLineKeyUp = React . useCallback ( ( e : KeyEvent ) => {
226+ const handleMultiLineKeyUp = React . useCallback ( ( event : KeyEvent ) => {
238227 const keyUpEvents = [ { key : 'Escape' } , { key : 'Enter' } ] ;
239- const isBlocked = isKeyBlocked ( e . nativeEvent , keyUpEvents ) ;
228+ const isBlocked = isKeyBlocked ( event , keyUpEvents ) ;
240229 const suffix = isBlocked ? ' (blocked)' : '' ;
241- const keyDisplay = formatKeyEvent ( e . nativeEvent ) ;
230+ const keyDisplay = formatKeyEvent ( event ) ;
242231 appendEvent ( `keyUp: ${ keyDisplay } ${ suffix } ` , 'Multi-line TextInput' ) ;
243232 } , [ ] ) ;
244233
@@ -350,6 +339,13 @@ const styles = StyleSheet.create({
350339 borderRadius : 6 ,
351340 backgroundColor : '#f6fff6' ,
352341 } ,
342+ boxLabel : {
343+ fontSize : 12 ,
344+ fontWeight : '600' ,
345+ color : '#8b5e3c' ,
346+ marginHorizontal : 4 ,
347+ marginTop : 4 ,
348+ } ,
353349 row : {
354350 flexDirection : 'row' ,
355351 marginVertical : 10 ,
0 commit comments