Skip to content

Commit a14e24e

Browse files
necolastrueadm
authored andcommitted
React Events: core API documentation (#15505)
1 parent 8658611 commit a14e24e

File tree

5 files changed

+344
-182
lines changed

5 files changed

+344
-182
lines changed

packages/react-events/README.md

Lines changed: 96 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -7,251 +7,165 @@ Event components do not render a host node. They listen to native browser events
77
dispatched on the host node of their child and transform those events into
88
high-level events for applications.
99

10+
The core API is documented below. Documentation for individual Event Components
11+
can be found [here](./docs).
1012

11-
## Focus
13+
## EventComponent
1214

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:
1617

1718
```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+
|};
2725
```
2826

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+
2933
```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,
3249
target: Element,
33-
type: 'blur' | 'focus' | 'focuschange'
50+
...
3451
}
3552
```
3653

37-
### disabled: boolean
38-
39-
Disables all `Focus` events.
54+
### createInitialState?: (props: null | Object) => Object
4055

41-
### onBlur: (e: FocusEvent) => void
56+
The initial state of that the Event Component is created with.
4257

43-
Called when the element loses focus.
58+
### onEvent?: (event: ResponderEvent, context: ResponderContext, props, state)
4459

45-
### onFocus: (e: FocusEvent) => void
60+
Called during the bubble phase of the `targetEventTypes` dispatched on DOM
61+
elements within the Event Component.
4662

47-
Called when the element gains focus.
63+
### onEventCapture?: (event: ResponderEvent, context: ResponderContext, props, state)
4864

49-
### onFocusChange: boolean => void
65+
Called during the capture phase of the `targetEventTypes` dispatched on DOM
66+
elements within the Event Component.
5067

51-
Called when the element changes hover state (i.e., after `onBlur` and
52-
`onFocus`).
68+
### onMount?: (context: ResponderContext, props, state)
5369

70+
Called after an Event Component in mounted.
5471

55-
## Hover
72+
### onOwnershipChange?: (context: ResponderContext, props, state)
5673

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.
8875

89-
### delayHoverEnd: number
76+
### onRootEvent?: (event: ResponderEvent, context: ResponderContext, props, state)
9077

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.
9379

94-
### delayHoverStart: number
80+
### onUnmount?: (context: ResponderContext, props, state)
9581

96-
The duration of the delay between when hover starts and when `onHoverStart` is
97-
called.
82+
Called before an Event Component in unmounted.
9883

99-
### disabled: boolean
84+
### rootEventTypes?: Array<ResponderEventType>
10085

101-
Disables all `Hover` events.
86+
Defines the DOM events to listen to on the root of the app.
10287

103-
### onHoverChange: boolean => void
88+
### stopLocalPropagation: boolean
10489

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.
10793

108-
### onHoverEnd: (e: HoverEvent) => void
94+
### targetEventTypes?: Array<ResponderEventType>
10995

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.
11297

113-
### onHoverMove: (e: HoverEvent) => void
11498

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
117100

118-
### onHoverStart: (e: HoverEvent) => void
101+
The Event Responder Context is exposed via the `context` argument for certain methods
102+
on the `EventResponder` object.
119103

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>)
123105

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.
125108

126-
Whether to `preventDefault()` native events.
109+
### clearTimeout(id: Symbol): void
127110

111+
Clear a timeout defined using `context.setTimeout`.
128112

129-
## Press
113+
### dispatchEvent(event: CustomEvent, listener, { discrete: boolean })
130114

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:
137118

138119
```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 });
160122
```
161123

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>
188125

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.
192128

193-
### disabled: boolean
129+
### hasOwnership(): boolean
194130

195-
Disables all `Press` events.
131+
Returns `true` if the instance has taken ownership of the responder.
196132

197-
### onLongPress: (e: PressEvent) => void
133+
### isPositionWithinTouchHitTarget(x: number, y: number): boolean
198134

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.
201136

202-
### onLongPressChange: boolean => void
137+
### isTargetDirectlyWithinEventComponent(target: Element): boolean
203138

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.
205140

206-
### onLongPressShouldCancelPress: () => boolean
141+
### isTargetWithinElement(target: Element, element: Element): boolean
207142

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`.
210144

211-
### onPress: (e: PressEvent) => void
145+
### isTargetWithinEventComponent(target: Element): boolean
212146

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.
218148

219-
### onPressChange: boolean => void
149+
### isTargetWithinEventResponderScope(target: Element): boolean
220150

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.
223152

224-
### onPressEnd: (e: PressEvent) => void
153+
### releaseOwnership(): boolean
225154

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.
230156

231-
### onPressMove: (e: PressEvent) => void
157+
### removeRootEventTypes(eventTypes: Array<ResponderEventType>)
232158

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`.
236160

237-
### onPressStart: (e: PressEvent) => void
161+
### requestGlobalOwnership(): boolean
238162

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.
242164

243-
### pressRetentionOffset: PressOffset
165+
### requestResponderOwnership(): boolean
244166

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.
249168

250-
### preventDefault: boolean = true
169+
### setTimeout(func: () => void, delay: number): Symbol
251170

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Whitespace-only changes.

0 commit comments

Comments
 (0)