React Events: core API documentation (#15505)

This commit is contained in:
Nicolas Gallagher
2019-04-26 00:11:40 -07:00
committed by Dominic Gannaway
parent 8658611b6c
commit a14e24efab
5 changed files with 362 additions and 200 deletions

View File

@@ -7,251 +7,165 @@ Event components do not render a host node. They listen to native browser events
dispatched on the host node of their child and transform those events into
high-level events for applications.
The core API is documented below. Documentation for individual Event Components
can be found [here](./docs).
## Focus
## EventComponent
The `Focus` module responds to focus and blur events on the element it wraps.
Focus events are dispatched for `mouse`, `pen`, `touch`, and `keyboard`
pointer types.
An Event Component is defined by a module that exports an object of the
following type:
```js
// Example
const TextField = (props) => (
<Focus
onBlur={props.onBlur}
onFocus={props.onFocus}
>
<textarea></textarea>
</Focus>
);
type EventComponent = {|
$$typeof: REACT_EVENT_COMPONENT_TYPE,
displayName?: string,
props: null | Object,
responder: EventResponder,
|};
```
## EventResponder
An Event Responder is defined using an object. Each responder can define DOM
events to listen to, handle the synthetic responder events, dispatch custom
events, and implement a state machine.
```js
// Types
type FocusEvent = {
// types
type ResponderEventType =
| string
| {name: string, passive?: boolean, capture?: boolean};
type ResponderEvent = {|
nativeEvent: any,
target: Element | Document,
type: string,
passive: boolean,
passiveSupported: boolean,
|};
type CustomEvent = {
type: string,
target: Element,
type: 'blur' | 'focus' | 'focuschange'
...
}
```
### disabled: boolean
### createInitialState?: (props: null | Object) => Object
Disables all `Focus` events.
The initial state of that the Event Component is created with.
### onBlur: (e: FocusEvent) => void
### onEvent?: (event: ResponderEvent, context: ResponderContext, props, state)
Called when the element loses focus.
Called during the bubble phase of the `targetEventTypes` dispatched on DOM
elements within the Event Component.
### onFocus: (e: FocusEvent) => void
### onEventCapture?: (event: ResponderEvent, context: ResponderContext, props, state)
Called when the element gains focus.
Called during the capture phase of the `targetEventTypes` dispatched on DOM
elements within the Event Component.
### onFocusChange: boolean => void
### onMount?: (context: ResponderContext, props, state)
Called when the element changes hover state (i.e., after `onBlur` and
`onFocus`).
Called after an Event Component in mounted.
### onOwnershipChange?: (context: ResponderContext, props, state)
Called when responder ownership is granted or terminated for an Event Component instance.
### onRootEvent?: (event: ResponderEvent, context: ResponderContext, props, state)
Called when any of the `rootEventTypes` are dispatched on the root of the app.
### onUnmount?: (context: ResponderContext, props, state)
Called before an Event Component in unmounted.
### rootEventTypes?: Array<ResponderEventType>
Defines the DOM events to listen to on the root of the app.
### stopLocalPropagation: boolean
Defines whether or not synthetic events propagate to other Event Components *of
the same type*. This has no effect on propagation of the source DOM events or
the synthetic events dispatched to Event Components of different types.
### targetEventTypes?: Array<ResponderEventType>
Defines the DOM events to listen to within the Event Component subtree.
## Hover
## ResponderContext
The `Hover` module responds to hover events on the element it wraps. Hover
events are only dispatched for `mouse` pointer types. Hover begins when the
pointer enters the element's bounds and ends when the pointer leaves.
The Event Responder Context is exposed via the `context` argument for certain methods
on the `EventResponder` object.
### addRootEventTypes(eventTypes: Array<ResponderEventType>)
This can be used to dynamically listen to events on the root of the app only
when it is necessary to do so.
### clearTimeout(id: Symbol): void
Clear a timeout defined using `context.setTimeout`.
### dispatchEvent(event: CustomEvent, listener, { discrete: boolean })
Dispatches a custom synthetic event. The `type` and `target` are required
fields, but any other fields can be defined on the `event` that will be passed
to the `listener`. For example:
```js
// Example
const Link = (props) => (
const [ hovered, setHovered ] = useState(false);
return (
<Hover onHoverChange={setHovered}>
<a
{...props}
href={props.href}
style={{
...props.style,
textDecoration: hovered ? 'underline': 'none'
}}
/>
</Hover>
);
);
const event = { type: 'press', target, pointerType, x, y };
context.dispatchEvent(event, props.onPress, { discrete: true });
```
```js
// Types
type HoverEvent = {
pointerType: 'mouse',
target: Element,
type: 'hoverstart' | 'hoverend' | 'hovermove' | 'hoverchange'
}
```
### getFocusableElementsInScope(): Array<Element>
### delayHoverEnd: number
Returns every DOM element that can be focused within the scope of the Event
Component instance.
The duration of the delay between when hover ends and when `onHoverEnd` is
called.
### hasOwnership(): boolean
### delayHoverStart: number
Returns `true` if the instance has taken ownership of the responder.
The duration of the delay between when hover starts and when `onHoverStart` is
called.
### isPositionWithinTouchHitTarget(x: number, y: number): boolean
### disabled: boolean
Returns `true` if the global coordinates lie within the TouchHitTarget.
Disables all `Hover` events.
### isTargetDirectlyWithinEventComponent(target: Element): boolean
### onHoverChange: boolean => void
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.
Called when the element changes hover state (i.e., after `onHoverStart` and
`onHoverEnd`).
### isTargetWithinElement(target: Element, element: Element): boolean
### onHoverEnd: (e: HoverEvent) => void
Returns `true` if `target` is a child of `element`.
Called once the element is no longer hovered. It will be cancelled if the
pointer leaves the element before the `delayHoverStart` threshold is exceeded.
### isTargetWithinEventComponent(target: Element): boolean
### onHoverMove: (e: HoverEvent) => void
Returns `true` is the target element is within the subtree of the Event Component instance.
Called when the pointer moves within the hit bounds of the element. `onHoverMove` is
called immediately and doesn't wait for delayed `onHoverStart`.
### isTargetWithinEventResponderScope(target: Element): boolean
### onHoverStart: (e: HoverEvent) => void
Returns `true` is the target element is within the current responder.
Called once the element is hovered. It will not be called if the pointer leaves
the element before the `delayHoverStart` threshold is exceeded. And it will not
be called more than once before `onHoverEnd` is called.
### releaseOwnership(): boolean
### preventDefault: boolean = true
Returns `true` if the instance released ownership of the responder.
Whether to `preventDefault()` native events.
### removeRootEventTypes(eventTypes: Array<ResponderEventType>)
Remove the root event types added with `addRootEventTypes`.
## Press
### requestGlobalOwnership(): boolean
The `Press` module responds to press events on the element it wraps. Press
events are dispatched for `mouse`, `pen`, `touch`, and `keyboard` pointer types.
Press events are only dispatched for keyboards when pressing the Enter or
Spacebar keys. If neither `onPress` nor `onLongPress` are called, this signifies
that the press ended outside of the element hit bounds (i.e., the user aborted
the press).
Request ownership of the global responder.
```js
// Example
const Button = (props) => (
const [ pressed, setPressed ] = useState(false);
return (
<Press
onPress={props.onPress}
onPressChange={setPressed}
onLongPress={props.onLongPress}
>
<div
{...props}
role="button"
tabIndex={0}
style={
...buttonStyles,
...(pressed && pressedStyles)
}}
/>
</Press>
);
);
```
### requestResponderOwnership(): boolean
```js
// Types
type PressEvent = {
pointerType: 'mouse' | 'touch' | 'pen' | 'keyboard',
target: Element,
type: 'press' | 'pressstart' | 'pressend' | 'presschange' | 'pressmove' | 'longpress' | 'longpresschange'
}
Request ownership of the responder.
type PressOffset = {
top: number,
right: number,
bottom: number,
right: number
};
```
### setTimeout(func: () => void, delay: number): Symbol
### delayLongPress: number = 500ms
The duration of a press before `onLongPress` and `onLongPressChange` are called.
### delayPressEnd: number
The duration of the delay between when the press ends and when `onPressEnd` is
called.
### delayPressStart: number
The duration of a delay between when the press starts and when `onPressStart` is
called. This delay is cut short (and `onPressStart` is called) if the press is
released before the threshold is exceeded.
### disabled: boolean
Disables all `Press` events.
### onLongPress: (e: PressEvent) => void
Called once the element has been pressed for the length of `delayLongPress`. If
the press point moves more than 10px `onLongPress` is cancelled.
### onLongPressChange: boolean => void
Called when the element changes long-press state.
### onLongPressShouldCancelPress: () => boolean
Determines whether calling `onPress` should be cancelled if `onLongPress` or
`onLongPressChange` have already been called. Default is `false`.
### onPress: (e: PressEvent) => void
Called immediately after a press is released, unless either 1) the press is
released outside the hit bounds of the element (accounting for
`pressRetentionOffset` and `TouchHitTarget`), or 2) the press was a long press,
and `onLongPress` or `onLongPressChange` props are provided, and
`onLongPressCancelsPress()` is `true`.
### onPressChange: boolean => void
Called when the element changes press state (i.e., after `onPressStart` and
`onPressEnd`).
### onPressEnd: (e: PressEvent) => void
Called once the element is no longer pressed (because it was released, or moved
beyond the hit bounds). If the press starts again before the `delayPressEnd`
threshold is exceeded then the delay is reset to prevent `onPressEnd` being
called during a press.
### onPressMove: (e: PressEvent) => void
Called when a press moves within the hit bounds of the element. `onPressMove` is
called immediately and doesn't wait for delayed `onPressStart`. Never called for
keyboard-initiated press events.
### onPressStart: (e: PressEvent) => void
Called once the element is pressed down. If the press is released before the
`delayPressStart` threshold is exceeded then the delay is cut short and
`onPressStart` is called immediately.
### pressRetentionOffset: PressOffset
Defines how far the pointer (while held down) may move outside the bounds of the
element before it is deactivated. Once deactivated, the pointer (still held
down) can be moved back within the bounds of the element to reactivate it.
Ensure you pass in a constant to reduce memory allocations.
### preventDefault: boolean = true
Whether to `preventDefault()` native events. Native behavior is prevented by
default. If an anchor is the child of `Press`, internal and external navigation
should be performed in `onPress`/`onLongPress`. To rely on native behavior
instead, set `preventDefault` to `false`, but be aware that native behavior will
take place immediately after interaction without respect for delays or long
press.
This can be used to dispatch async events, e.g., those that fire after a delay.

View File

@@ -0,0 +1,44 @@
## Focus
The `Focus` module responds to focus and blur events on its child. Focus events
are dispatched for `mouse`, `pen`, `touch`, and `keyboard`
pointer types.
Focus events do not propagate between `Focus` event responders.
```js
// Example
const TextField = (props) => (
<Focus
onBlur={props.onBlur}
onFocus={props.onFocus}
>
<textarea></textarea>
</Focus>
);
```
```js
// Types
type FocusEvent = {
target: Element,
type: 'blur' | 'focus' | 'focuschange'
}
```
### disabled: boolean
Disables all `Focus` events.
### onBlur: (e: FocusEvent) => void
Called when the element loses focus.
### onFocus: (e: FocusEvent) => void
Called when the element gains focus.
### onFocusChange: boolean => void
Called when the element changes hover state (i.e., after `onBlur` and
`onFocus`).

View File

View File

@@ -0,0 +1,74 @@
## Hover
The `Hover` module responds to hover events on the element it wraps. Hover
events are only dispatched for `mouse` pointer types. Hover begins when the
pointer enters the element's bounds and ends when the pointer leaves.
Hover events do not propagate between `Hover` event responders.
```js
// Example
const Link = (props) => (
const [ hovered, setHovered ] = useState(false);
return (
<Hover onHoverChange={setHovered}>
<a
{...props}
href={props.href}
style={{
...props.style,
textDecoration: hovered ? 'underline': 'none'
}}
/>
</Hover>
);
);
```
```js
// Types
type HoverEvent = {
pointerType: 'mouse' | 'pen',
target: Element,
type: 'hoverstart' | 'hoverend' | 'hovermove' | 'hoverchange'
}
```
### delayHoverEnd: number
The duration of the delay between when hover ends and when `onHoverEnd` is
called.
### delayHoverStart: number
The duration of the delay between when hover starts and when `onHoverStart` is
called.
### disabled: boolean
Disables all `Hover` events.
### onHoverChange: boolean => void
Called when the element changes hover state (i.e., after `onHoverStart` and
`onHoverEnd`).
### onHoverEnd: (e: HoverEvent) => void
Called once the element is no longer hovered. It will be cancelled if the
pointer leaves the element before the `delayHoverStart` threshold is exceeded.
### onHoverMove: (e: HoverEvent) => void
Called when the pointer moves within the hit bounds of the element. `onHoverMove` is
called immediately and doesn't wait for delayed `onHoverStart`.
### onHoverStart: (e: HoverEvent) => void
Called once the element is hovered. It will not be called if the pointer leaves
the element before the `delayHoverStart` threshold is exceeded. And it will not
be called more than once before `onHoverEnd` is called.
### preventDefault: boolean = true
Whether to `preventDefault()` native events.

View File

@@ -0,0 +1,130 @@
## Press
The `Press` module responds to press events on the element it wraps. Press
events are dispatched for `mouse`, `pen`, `touch`, and `keyboard` pointer types.
Press events are only dispatched for keyboards when pressing the Enter or
Spacebar keys. If neither `onPress` nor `onLongPress` are called, this signifies
that the press ended outside of the element hit bounds (i.e., the user aborted
the press).
Press events do not propagate between `Press` event responders.
```js
// Example
const Button = (props) => (
const [ pressed, setPressed ] = useState(false);
return (
<Press
onPress={props.onPress}
onPressChange={setPressed}
onLongPress={props.onLongPress}
>
<div
{...props}
role="button"
tabIndex={0}
style={
...buttonStyles,
...(pressed && pressedStyles)
}}
/>
</Press>
);
);
```
```js
// Types
type PressEvent = {
pointerType: 'mouse' | 'touch' | 'pen' | 'keyboard',
target: Element,
type: 'press' | 'pressstart' | 'pressend' | 'presschange' | 'pressmove' | 'longpress' | 'longpresschange'
}
type PressOffset = {
top: number,
right: number,
bottom: number,
right: number
};
```
### delayLongPress: number = 500ms
The duration of a press before `onLongPress` and `onLongPressChange` are called.
### delayPressEnd: number
The duration of the delay between when the press ends and when `onPressEnd` is
called.
### delayPressStart: number
The duration of a delay between when the press starts and when `onPressStart` is
called. This delay is cut short (and `onPressStart` is called) if the press is
released before the threshold is exceeded.
### disabled: boolean
Disables all `Press` events.
### onLongPress: (e: PressEvent) => void
Called once the element has been pressed for the length of `delayLongPress`. If
the press point moves more than 10px `onLongPress` is cancelled.
### onLongPressChange: boolean => void
Called when the element changes long-press state.
### onLongPressShouldCancelPress: () => boolean
Determines whether calling `onPress` should be cancelled if `onLongPress` or
`onLongPressChange` have already been called. Default is `false`.
### onPress: (e: PressEvent) => void
Called immediately after a press is released, unless either 1) the press is
released outside the hit bounds of the element (accounting for
`pressRetentionOffset` and `TouchHitTarget`), or 2) the press was a long press,
and `onLongPress` or `onLongPressChange` props are provided, and
`onLongPressCancelsPress()` is `true`.
### onPressChange: boolean => void
Called when the element changes press state (i.e., after `onPressStart` and
`onPressEnd`).
### onPressEnd: (e: PressEvent) => void
Called once the element is no longer pressed (because it was released, or moved
beyond the hit bounds). If the press starts again before the `delayPressEnd`
threshold is exceeded then the delay is reset to prevent `onPressEnd` being
called during a press.
### onPressMove: (e: PressEvent) => void
Called when a press moves within the hit bounds of the element. `onPressMove` is
called immediately and doesn't wait for delayed `onPressStart`. Never called for
keyboard-initiated press events.
### onPressStart: (e: PressEvent) => void
Called once the element is pressed down. If the press is released before the
`delayPressStart` threshold is exceeded then the delay is cut short and
`onPressStart` is called immediately.
### pressRetentionOffset: PressOffset
Defines how far the pointer (while held down) may move outside the bounds of the
element before it is deactivated. Ensure you pass in a constant to reduce memory
allocations.
### preventDefault: boolean = true
Whether to `preventDefault()` native events. Native behavior is prevented by
default. If an anchor is the child of `Press`, internal and external navigation
should be performed in `onPress`/`onLongPress`. To rely on native behavior
instead, set `preventDefault` to `false`, but be aware that native behavior will
take place immediately after interaction without respect for delays or long
press.