@samitouri / QOS-React / commits / a14e24efab

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.