React Events: core API documentation (#15505)
Nicolas Gallagher committed
Apr 26, 2019 at 00:11 UTC
a14e24efabe8fa37d9b488cd97b116eaab04a702
5 files changed
+344
-182
packages/react-events/README.md
+96
-182
@@ -7,251 +7,165 @@ Event components do not render a host node. They listen to native browser events
7
dispatched on the host node of their child and transform those events into
8
high-level events for applications.
9
10
+The core API is documented below. Documentation for individual Event Components
11
+can be found [here](./docs).
12
11
-## Focus
13
+## EventComponent
14
13
-The `Focus` module responds to focus and blur events on the element it wraps.
14
-Focus events are dispatched for `mouse`, `pen`, `touch`, and `keyboard`
15
-pointer types.
15
+An Event Component is defined by a module that exports an object of the
16
+following type:
17
18
```js
18
-// Example
19
-const TextField = (props) => (
20
- <Focus
21
- onBlur={props.onBlur}
22
- onFocus={props.onFocus}
23
- >
24
- <textarea></textarea>
25
- </Focus>
26
-);
19
+type EventComponent = {|
20
+ $$typeof: REACT_EVENT_COMPONENT_TYPE,
21
+ displayName?: string,
22
+ props: null | Object,
23
+ responder: EventResponder,
24
+|};
25
```
26
27
+## EventResponder
28
+
29
+An Event Responder is defined using an object. Each responder can define DOM
30
+events to listen to, handle the synthetic responder events, dispatch custom
31
+events, and implement a state machine.
32
+
33
```js
30
-// Types
31
-type FocusEvent = {
34
+// types
35
+type ResponderEventType =
36
+ | string
37
+ | {name: string, passive?: boolean, capture?: boolean};
38
+
39
+type ResponderEvent = {|
40
+ nativeEvent: any,
41
+ target: Element | Document,
42
+ type: string,
43
+ passive: boolean,
44
+ passiveSupported: boolean,
45
+|};
46
+
47
+type CustomEvent = {
48
+ type: string,
49
target: Element,
33
- type: 'blur' | 'focus' | 'focuschange'
50
+ ...
51
}
52
```
53
37
-### disabled: boolean
38
-
39
-Disables all `Focus` events.
54
+### createInitialState?: (props: null | Object) => Object
55
41
-### onBlur: (e: FocusEvent) => void
56
+The initial state of that the Event Component is created with.
57
43
-Called when the element loses focus.
58
+### onEvent?: (event: ResponderEvent, context: ResponderContext, props, state)
59
45
-### onFocus: (e: FocusEvent) => void
60
+Called during the bubble phase of the `targetEventTypes` dispatched on DOM
61
+elements within the Event Component.
62
47
-Called when the element gains focus.
63
+### onEventCapture?: (event: ResponderEvent, context: ResponderContext, props, state)
64
49
-### onFocusChange: boolean => void
65
+Called during the capture phase of the `targetEventTypes` dispatched on DOM
66
+elements within the Event Component.
67
51
-Called when the element changes hover state (i.e., after `onBlur` and
52
-`onFocus`).
68
+### onMount?: (context: ResponderContext, props, state)
69
70
+Called after an Event Component in mounted.
71
55
-## Hover
72
+### onOwnershipChange?: (context: ResponderContext, props, state)
73
57
-The `Hover` module responds to hover events on the element it wraps. Hover
58
-events are only dispatched for `mouse` pointer types. Hover begins when the
59
-pointer enters the element's bounds and ends when the pointer leaves.
60
-
61
-```js
62
-// Example
63
-const Link = (props) => (
64
- const [ hovered, setHovered ] = useState(false);
65
- return (
66
- <Hover onHoverChange={setHovered}>
67
- <a
68
- {...props}
69
- href={props.href}
70
- style={{
71
- ...props.style,
72
- textDecoration: hovered ? 'underline': 'none'
73
- }}
74
- />
75
- </Hover>
76
- );
77
-);
78
-```
79
-
80
-```js
81
-// Types
82
-type HoverEvent = {
83
- pointerType: 'mouse',
84
- target: Element,
85
- type: 'hoverstart' | 'hoverend' | 'hovermove' | 'hoverchange'
86
-}
87
-```
74
+Called when responder ownership is granted or terminated for an Event Component instance.
75
89
-### delayHoverEnd: number
76
+### onRootEvent?: (event: ResponderEvent, context: ResponderContext, props, state)
77
91
-The duration of the delay between when hover ends and when `onHoverEnd` is
92
-called.
78
+Called when any of the `rootEventTypes` are dispatched on the root of the app.
79
94
-### delayHoverStart: number
80
+### onUnmount?: (context: ResponderContext, props, state)
81
96
-The duration of the delay between when hover starts and when `onHoverStart` is
97
-called.
82
+Called before an Event Component in unmounted.
83
99
-### disabled: boolean
84
+### rootEventTypes?: Array<ResponderEventType>
85
101
-Disables all `Hover` events.
86
+Defines the DOM events to listen to on the root of the app.
87
103
-### onHoverChange: boolean => void
88
+### stopLocalPropagation: boolean
89
105
-Called when the element changes hover state (i.e., after `onHoverStart` and
106
-`onHoverEnd`).
90
+Defines whether or not synthetic events propagate to other Event Components *of
91
+the same type*. This has no effect on propagation of the source DOM events or
92
+the synthetic events dispatched to Event Components of different types.
93
108
-### onHoverEnd: (e: HoverEvent) => void
94
+### targetEventTypes?: Array<ResponderEventType>
95
110
-Called once the element is no longer hovered. It will be cancelled if the
111
-pointer leaves the element before the `delayHoverStart` threshold is exceeded.
96
+Defines the DOM events to listen to within the Event Component subtree.
97
113
-### onHoverMove: (e: HoverEvent) => void
98
115
-Called when the pointer moves within the hit bounds of the element. `onHoverMove` is
116
-called immediately and doesn't wait for delayed `onHoverStart`.
99
+## ResponderContext
100
118
-### onHoverStart: (e: HoverEvent) => void
101
+The Event Responder Context is exposed via the `context` argument for certain methods
102
+on the `EventResponder` object.
103
120
-Called once the element is hovered. It will not be called if the pointer leaves
121
-the element before the `delayHoverStart` threshold is exceeded. And it will not
122
-be called more than once before `onHoverEnd` is called.
104
+### addRootEventTypes(eventTypes: Array<ResponderEventType>)
105
124
-### preventDefault: boolean = true
106
+This can be used to dynamically listen to events on the root of the app only
107
+when it is necessary to do so.
108
126
-Whether to `preventDefault()` native events.
109
+### clearTimeout(id: Symbol): void
110
111
+Clear a timeout defined using `context.setTimeout`.
112
129
-## Press
113
+### dispatchEvent(event: CustomEvent, listener, { discrete: boolean })
114
131
-The `Press` module responds to press events on the element it wraps. Press
132
-events are dispatched for `mouse`, `pen`, `touch`, and `keyboard` pointer types.
133
-Press events are only dispatched for keyboards when pressing the Enter or
134
-Spacebar keys. If neither `onPress` nor `onLongPress` are called, this signifies
135
-that the press ended outside of the element hit bounds (i.e., the user aborted
136
-the press).
115
+Dispatches a custom synthetic event. The `type` and `target` are required
116
+fields, but any other fields can be defined on the `event` that will be passed
117
+to the `listener`. For example:
118
119
```js
139
-// Example
140
-const Button = (props) => (
141
- const [ pressed, setPressed ] = useState(false);
142
- return (
143
- <Press
144
- onPress={props.onPress}
145
- onPressChange={setPressed}
146
- onLongPress={props.onLongPress}
147
- >
148
- <div
149
- {...props}
150
- role="button"
151
- tabIndex={0}
152
- style={
153
- ...buttonStyles,
154
- ...(pressed && pressedStyles)
155
- }}
156
- />
157
- </Press>
158
- );
159
-);
120
+const event = { type: 'press', target, pointerType, x, y };
121
+context.dispatchEvent(event, props.onPress, { discrete: true });
122
```
123
162
-```js
163
-// Types
164
-type PressEvent = {
165
- pointerType: 'mouse' | 'touch' | 'pen' | 'keyboard',
166
- target: Element,
167
- type: 'press' | 'pressstart' | 'pressend' | 'presschange' | 'pressmove' | 'longpress' | 'longpresschange'
168
-}
169
-
170
-type PressOffset = {
171
- top: number,
172
- right: number,
173
- bottom: number,
174
- right: number
175
-};
176
-```
177
-
178
-### delayLongPress: number = 500ms
179
-
180
-The duration of a press before `onLongPress` and `onLongPressChange` are called.
181
-
182
-### delayPressEnd: number
183
-
184
-The duration of the delay between when the press ends and when `onPressEnd` is
185
-called.
186
-
187
-### delayPressStart: number
124
+### getFocusableElementsInScope(): Array<Element>
125
189
-The duration of a delay between when the press starts and when `onPressStart` is
190
-called. This delay is cut short (and `onPressStart` is called) if the press is
191
-released before the threshold is exceeded.
126
+Returns every DOM element that can be focused within the scope of the Event
127
+Component instance.
128
193
-### disabled: boolean
129
+### hasOwnership(): boolean
130
195
-Disables all `Press` events.
131
+Returns `true` if the instance has taken ownership of the responder.
132
197
-### onLongPress: (e: PressEvent) => void
133
+### isPositionWithinTouchHitTarget(x: number, y: number): boolean
134
199
-Called once the element has been pressed for the length of `delayLongPress`. If
200
-the press point moves more than 10px `onLongPress` is cancelled.
135
+Returns `true` if the global coordinates lie within the TouchHitTarget.
136
202
-### onLongPressChange: boolean => void
137
+### isTargetDirectlyWithinEventComponent(target: Element): boolean
138
204
-Called when the element changes long-press state.
139
+Returns `true` is the target element is within the direct subtree of the Event Component instance, i.e., the target is not nested within an Event Component instance that is a descendant of the current instance.
140
206
-### onLongPressShouldCancelPress: () => boolean
141
+### isTargetWithinElement(target: Element, element: Element): boolean
142
208
-Determines whether calling `onPress` should be cancelled if `onLongPress` or
209
-`onLongPressChange` have already been called. Default is `false`.
143
+Returns `true` if `target` is a child of `element`.
144
211
-### onPress: (e: PressEvent) => void
145
+### isTargetWithinEventComponent(target: Element): boolean
146
213
-Called immediately after a press is released, unless either 1) the press is
214
-released outside the hit bounds of the element (accounting for
215
-`pressRetentionOffset` and `TouchHitTarget`), or 2) the press was a long press,
216
-and `onLongPress` or `onLongPressChange` props are provided, and
217
-`onLongPressCancelsPress()` is `true`.
147
+Returns `true` is the target element is within the subtree of the Event Component instance.
148
219
-### onPressChange: boolean => void
149
+### isTargetWithinEventResponderScope(target: Element): boolean
150
221
-Called when the element changes press state (i.e., after `onPressStart` and
222
-`onPressEnd`).
151
+Returns `true` is the target element is within the current responder.
152
224
-### onPressEnd: (e: PressEvent) => void
153
+### releaseOwnership(): boolean
154
226
-Called once the element is no longer pressed (because it was released, or moved
227
-beyond the hit bounds). If the press starts again before the `delayPressEnd`
228
-threshold is exceeded then the delay is reset to prevent `onPressEnd` being
229
-called during a press.
155
+Returns `true` if the instance released ownership of the responder.
156
231
-### onPressMove: (e: PressEvent) => void
157
+### removeRootEventTypes(eventTypes: Array<ResponderEventType>)
158
233
-Called when a press moves within the hit bounds of the element. `onPressMove` is
234
-called immediately and doesn't wait for delayed `onPressStart`. Never called for
235
-keyboard-initiated press events.
159
+Remove the root event types added with `addRootEventTypes`.
160
237
-### onPressStart: (e: PressEvent) => void
161
+### requestGlobalOwnership(): boolean
162
239
-Called once the element is pressed down. If the press is released before the
240
-`delayPressStart` threshold is exceeded then the delay is cut short and
241
-`onPressStart` is called immediately.
163
+Request ownership of the global responder.
164
243
-### pressRetentionOffset: PressOffset
165
+### requestResponderOwnership(): boolean
166
245
-Defines how far the pointer (while held down) may move outside the bounds of the
246
-element before it is deactivated. Once deactivated, the pointer (still held
247
-down) can be moved back within the bounds of the element to reactivate it.
248
-Ensure you pass in a constant to reduce memory allocations.
167
+Request ownership of the responder.
168
250
-### preventDefault: boolean = true
169
+### setTimeout(func: () => void, delay: number): Symbol
170
252
-Whether to `preventDefault()` native events. Native behavior is prevented by
253
-default. If an anchor is the child of `Press`, internal and external navigation
254
-should be performed in `onPress`/`onLongPress`. To rely on native behavior
255
-instead, set `preventDefault` to `false`, but be aware that native behavior will
256
-take place immediately after interaction without respect for delays or long
257
-press.
171
+This can be used to dispatch async events, e.g., those that fire after a delay.
packages/react-events/docs/Focus.md
new
+44
@@ -0,0 +1,44 @@
1
+## Focus
2
+
3
+The `Focus` module responds to focus and blur events on its child. Focus events
4
+are dispatched for `mouse`, `pen`, `touch`, and `keyboard`
5
+pointer types.
6
+
7
+Focus events do not propagate between `Focus` event responders.
8
+
9
+```js
10
+// Example
11
+const TextField = (props) => (
12
+ <Focus
13
+ onBlur={props.onBlur}
14
+ onFocus={props.onFocus}
15
+ >
16
+ <textarea></textarea>
17
+ </Focus>
18
+);
19
+```
20
+
21
+```js
22
+// Types
23
+type FocusEvent = {
24
+ target: Element,
25
+ type: 'blur' | 'focus' | 'focuschange'
26
+}
27
+```
28
+
29
+### disabled: boolean
30
+
31
+Disables all `Focus` events.
32
+
33
+### onBlur: (e: FocusEvent) => void
34
+
35
+Called when the element loses focus.
36
+
37
+### onFocus: (e: FocusEvent) => void
38
+
39
+Called when the element gains focus.
40
+
41
+### onFocusChange: boolean => void
42
+
43
+Called when the element changes hover state (i.e., after `onBlur` and
44
+`onFocus`).
packages/react-events/docs/FocusScope.md
packages/react-events/docs/Hover.md
new
+74
@@ -0,0 +1,74 @@
1
+## Hover
2
+
3
+The `Hover` module responds to hover events on the element it wraps. Hover
4
+events are only dispatched for `mouse` pointer types. Hover begins when the
5
+pointer enters the element's bounds and ends when the pointer leaves.
6
+
7
+Hover events do not propagate between `Hover` event responders.
8
+
9
+```js
10
+// Example
11
+const Link = (props) => (
12
+ const [ hovered, setHovered ] = useState(false);
13
+ return (
14
+ <Hover onHoverChange={setHovered}>
15
+ <a
16
+ {...props}
17
+ href={props.href}
18
+ style={{
19
+ ...props.style,
20
+ textDecoration: hovered ? 'underline': 'none'
21
+ }}
22
+ />
23
+ </Hover>
24
+ );
25
+);
26
+```
27
+
28
+```js
29
+// Types
30
+type HoverEvent = {
31
+ pointerType: 'mouse' | 'pen',
32
+ target: Element,
33
+ type: 'hoverstart' | 'hoverend' | 'hovermove' | 'hoverchange'
34
+}
35
+```
36
+
37
+### delayHoverEnd: number
38
+
39
+The duration of the delay between when hover ends and when `onHoverEnd` is
40
+called.
41
+
42
+### delayHoverStart: number
43
+
44
+The duration of the delay between when hover starts and when `onHoverStart` is
45
+called.
46
+
47
+### disabled: boolean
48
+
49
+Disables all `Hover` events.
50
+
51
+### onHoverChange: boolean => void
52
+
53
+Called when the element changes hover state (i.e., after `onHoverStart` and
54
+`onHoverEnd`).
55
+
56
+### onHoverEnd: (e: HoverEvent) => void
57
+
58
+Called once the element is no longer hovered. It will be cancelled if the
59
+pointer leaves the element before the `delayHoverStart` threshold is exceeded.
60
+
61
+### onHoverMove: (e: HoverEvent) => void
62
+
63
+Called when the pointer moves within the hit bounds of the element. `onHoverMove` is
64
+called immediately and doesn't wait for delayed `onHoverStart`.
65
+
66
+### onHoverStart: (e: HoverEvent) => void
67
+
68
+Called once the element is hovered. It will not be called if the pointer leaves
69
+the element before the `delayHoverStart` threshold is exceeded. And it will not
70
+be called more than once before `onHoverEnd` is called.
71
+
72
+### preventDefault: boolean = true
73
+
74
+Whether to `preventDefault()` native events.
packages/react-events/docs/Press.md
new
+130
@@ -0,0 +1,130 @@
1
+## Press
2
+
3
+The `Press` module responds to press events on the element it wraps. Press
4
+events are dispatched for `mouse`, `pen`, `touch`, and `keyboard` pointer types.
5
+Press events are only dispatched for keyboards when pressing the Enter or
6
+Spacebar keys. If neither `onPress` nor `onLongPress` are called, this signifies
7
+that the press ended outside of the element hit bounds (i.e., the user aborted
8
+the press).
9
+
10
+Press events do not propagate between `Press` event responders.
11
+
12
+```js
13
+// Example
14
+const Button = (props) => (
15
+ const [ pressed, setPressed ] = useState(false);
16
+ return (
17
+ <Press
18
+ onPress={props.onPress}
19
+ onPressChange={setPressed}
20
+ onLongPress={props.onLongPress}
21
+ >
22
+ <div
23
+ {...props}
24
+ role="button"
25
+ tabIndex={0}
26
+ style={
27
+ ...buttonStyles,
28
+ ...(pressed && pressedStyles)
29
+ }}
30
+ />
31
+ </Press>
32
+ );
33
+);
34
+```
35
+
36
+```js
37
+// Types
38
+type PressEvent = {
39
+ pointerType: 'mouse' | 'touch' | 'pen' | 'keyboard',
40
+ target: Element,
41
+ type: 'press' | 'pressstart' | 'pressend' | 'presschange' | 'pressmove' | 'longpress' | 'longpresschange'
42
+}
43
+
44
+type PressOffset = {
45
+ top: number,
46
+ right: number,
47
+ bottom: number,
48
+ right: number
49
+};
50
+```
51
+
52
+### delayLongPress: number = 500ms
53
+
54
+The duration of a press before `onLongPress` and `onLongPressChange` are called.
55
+
56
+### delayPressEnd: number
57
+
58
+The duration of the delay between when the press ends and when `onPressEnd` is
59
+called.
60
+
61
+### delayPressStart: number
62
+
63
+The duration of a delay between when the press starts and when `onPressStart` is
64
+called. This delay is cut short (and `onPressStart` is called) if the press is
65
+released before the threshold is exceeded.
66
+
67
+### disabled: boolean
68
+
69
+Disables all `Press` events.
70
+
71
+### onLongPress: (e: PressEvent) => void
72
+
73
+Called once the element has been pressed for the length of `delayLongPress`. If
74
+the press point moves more than 10px `onLongPress` is cancelled.
75
+
76
+### onLongPressChange: boolean => void
77
+
78
+Called when the element changes long-press state.
79
+
80
+### onLongPressShouldCancelPress: () => boolean
81
+
82
+Determines whether calling `onPress` should be cancelled if `onLongPress` or
83
+`onLongPressChange` have already been called. Default is `false`.
84
+
85
+### onPress: (e: PressEvent) => void
86
+
87
+Called immediately after a press is released, unless either 1) the press is
88
+released outside the hit bounds of the element (accounting for
89
+`pressRetentionOffset` and `TouchHitTarget`), or 2) the press was a long press,
90
+and `onLongPress` or `onLongPressChange` props are provided, and
91
+`onLongPressCancelsPress()` is `true`.
92
+
93
+### onPressChange: boolean => void
94
+
95
+Called when the element changes press state (i.e., after `onPressStart` and
96
+`onPressEnd`).
97
+
98
+### onPressEnd: (e: PressEvent) => void
99
+
100
+Called once the element is no longer pressed (because it was released, or moved
101
+beyond the hit bounds). If the press starts again before the `delayPressEnd`
102
+threshold is exceeded then the delay is reset to prevent `onPressEnd` being
103
+called during a press.
104
+
105
+### onPressMove: (e: PressEvent) => void
106
+
107
+Called when a press moves within the hit bounds of the element. `onPressMove` is
108
+called immediately and doesn't wait for delayed `onPressStart`. Never called for
109
+keyboard-initiated press events.
110
+
111
+### onPressStart: (e: PressEvent) => void
112
+
113
+Called once the element is pressed down. If the press is released before the
114
+`delayPressStart` threshold is exceeded then the delay is cut short and
115
+`onPressStart` is called immediately.
116
+
117
+### pressRetentionOffset: PressOffset
118
+
119
+Defines how far the pointer (while held down) may move outside the bounds of the
120
+element before it is deactivated. Ensure you pass in a constant to reduce memory
121
+allocations.
122
+
123
+### preventDefault: boolean = true
124
+
125
+Whether to `preventDefault()` native events. Native behavior is prevented by
126
+default. If an anchor is the child of `Press`, internal and external navigation
127
+should be performed in `onPress`/`onLongPress`. To rely on native behavior
128
+instead, set `preventDefault` to `false`, but be aware that native behavior will
129
+take place immediately after interaction without respect for delays or long
130
+press.