Skip to content

Commit 81a61b1

Browse files
authored
React events: add delay props to Press module (#15340)
* Add delay props to Press event module * Minor naming changes to Hover events * Add examples to react-events README
1 parent 4064ea9 commit 81a61b1

File tree

5 files changed

+537
-132
lines changed

5 files changed

+537
-132
lines changed

packages/react-events/README.md

+117-40
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,31 @@
33
*This package is experimental. It is intended for use with the experimental React
44
events API that is not available in open source builds.*
55

6+
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+
610

711
## Focus
812

913
The `Focus` module responds to focus and blur events on the element it wraps.
1014
Focus events are dispatched for `mouse`, `pen`, `touch`, and `keyboard`
1115
pointer types.
1216

17+
```js
18+
// Example
19+
const TextField = (props) => (
20+
<Focus
21+
onBlur={props.onBlur}
22+
onFocus={props.onFocus}
23+
>
24+
<textarea></textarea>
25+
</Focus>
26+
);
1327
```
28+
29+
```js
30+
// Types
1431
type FocusEvent = {}
1532
```
1633

@@ -38,69 +55,124 @@ The `Hover` module responds to hover events on the element it wraps. Hover
3855
events are only dispatched for `mouse` pointer types. Hover begins when the
3956
pointer enters the element's bounds and ends when the pointer leaves.
4057

58+
```js
59+
// Example
60+
const Link = (props) => (
61+
const [ hovered, setHovered ] = useState(false);
62+
return (
63+
<Hover onHoverChange={setHovered}>
64+
<a
65+
{...props}
66+
href={props.href}
67+
style={{
68+
...props.style,
69+
textDecoration: hovered ? 'underline': 'none'
70+
}}
71+
/>
72+
</Hover>
73+
);
74+
);
4175
```
76+
77+
```js
78+
// Types
4279
type HoverEvent = {}
4380
```
4481

45-
### disabled: boolean
82+
### delayHoverEnd: number
4683

47-
Disables all `Hover` events.
84+
The duration of the delay between when hover ends and when `onHoverEnd` is
85+
called.
4886

49-
### onHoverStart: (e: HoverEvent) => void
87+
### delayHoverStart: number
5088

51-
Called once the element is hovered. It will not be called if the pointer leaves
52-
the element before the `delayHoverStart` threshold is exceeded. And it will not
53-
be called more than once before `onHoverEnd` is called.
89+
The duration of the delay between when hover starts and when `onHoverStart` is
90+
called.
5491

55-
### onHoverEnd: (e: HoverEvent) => void
92+
### disabled: boolean
5693

57-
Called once the element is no longer hovered. It will be cancelled if the
58-
pointer leaves the element before the `delayHoverStart` threshold is exceeded.
94+
Disables all `Hover` events.
5995

6096
### onHoverChange: boolean => void
6197

6298
Called when the element changes hover state (i.e., after `onHoverStart` and
6399
`onHoverEnd`).
64100

65-
### delayHoverStart: number
101+
### onHoverEnd: (e: HoverEvent) => void
66102

67-
The duration of the delay between when hover starts and when `onHoverStart` is
68-
called.
103+
Called once the element is no longer hovered. It will be cancelled if the
104+
pointer leaves the element before the `delayHoverStart` threshold is exceeded.
69105

70-
### delayHoverEnd: number
106+
### onHoverStart: (e: HoverEvent) => void
71107

72-
The duration of the delay between when hover ends and when `onHoverEnd` is
73-
called.
108+
Called once the element is hovered. It will not be called if the pointer leaves
109+
the element before the `delayHoverStart` threshold is exceeded. And it will not
110+
be called more than once before `onHoverEnd` is called.
74111

75112

76113
## Press
77114

78115
The `Press` module responds to press events on the element it wraps. Press
79116
events are dispatched for `mouse`, `pen`, `touch`, and `keyboard` pointer types.
80-
117+
Press events are only dispatched for keyboards when pressing the Enter or
118+
Spacebar keys. If neither `onPress` nor `onLongPress` are called, this signifies
119+
that the press ended outside of the element hit bounds (i.e., the user aborted
120+
the press).
121+
122+
```js
123+
// Example
124+
const Button = (props) => (
125+
const [ pressed, setPressed ] = useState(false);
126+
return (
127+
<Press
128+
onPress={props.onPress}
129+
onPressChange={setPressed}
130+
onLongPress={props.onLongPress}
131+
>
132+
<div
133+
{...props}
134+
role="button"
135+
tabIndex={0}
136+
style={
137+
...buttonStyles,
138+
...(pressed && pressedStyles)
139+
}}
140+
/>
141+
</Press>
142+
);
143+
);
81144
```
145+
146+
```js
147+
// Types
82148
type PressEvent = {}
149+
150+
type PressOffset = {
151+
top: number,
152+
right: number,
153+
bottom: number,
154+
right: number
155+
};
83156
```
84157

85-
### disabled: boolean
158+
### delayLongPress: number = 500ms
86159

87-
Disables all `Press` events.
160+
The duration of a press before `onLongPress` and `onLongPressChange` are called.
88161

89-
### onPressStart: (e: PressEvent) => void
162+
### delayPressEnd: number
90163

91-
Called once the element is pressed down. If the press is released before the
92-
`delayPressStart` threshold is exceeded then the delay is cut short and
93-
`onPressStart` is called immediately.
164+
The duration of the delay between when the press ends and when `onPressEnd` is
165+
called.
94166

95-
### onPressEnd: (e: PressEvent) => void
167+
### delayPressStart: number
96168

97-
Called once the element is no longer pressed. It will be cancelled if the press
98-
starts again before the `delayPressEnd` threshold is exceeded.
169+
The duration of a delay between when the press starts and when `onPressStart` is
170+
called. This delay is cut short (and `onPressStart` is called) if the press is
171+
released before the threshold is exceeded.
99172

100-
### onPressChange: boolean => void
173+
### disabled: boolean
101174

102-
Called when the element changes press state (i.e., after `onPressStart` and
103-
`onPressEnd`).
175+
Disables all `Press` events.
104176

105177
### onLongPress: (e: PressEvent) => void
106178

@@ -117,25 +189,30 @@ Determines whether calling `onPress` should be cancelled if `onLongPress` or
117189

118190
### onPress: (e: PressEvent) => void
119191

120-
Called after `onPressEnd` only if `onLongPressShouldCancelPress` returns
121-
`false`.
192+
Called immediately after a press is released, unless either 1) the press is
193+
released outside the hit bounds of the element (accounting for
194+
`pressRetentionOffset` and `TouchHitTarget`), or 2) the press was a long press,
195+
and `onLongPress` or `onLongPressChange` props are provided, and
196+
`onLongPressCancelsPress()` is `true`.
122197

123-
### delayPressStart: number
198+
### onPressChange: boolean => void
124199

125-
The duration of a delay between when the press starts and when `onPressStart` is
126-
called. This delay is cut short if the press ends released before the threshold
127-
is exceeded.
200+
Called when the element changes press state (i.e., after `onPressStart` and
201+
`onPressEnd`).
128202

129-
### delayPressEnd: number
203+
### onPressEnd: (e: PressEvent) => void
130204

131-
The duration of the delay between when the press ends and when `onPressEnd` is
132-
called.
205+
Called once the element is no longer pressed. If the press starts again before
206+
the `delayPressEnd` threshold is exceeded then the delay is reset to prevent
207+
`onPressEnd` being called during a press.
133208

134-
### delayLongPress: number = 500ms
209+
### onPressStart: (e: PressEvent) => void
135210

136-
The duration of a press before `onLongPress` and `onLongPressChange` are called.
211+
Called once the element is pressed down. If the press is released before the
212+
`delayPressStart` threshold is exceeded then the delay is cut short and
213+
`onPressStart` is called immediately.
137214

138-
### pressRententionOffset: { top: number, right: number, bottom: number, right: number }
215+
### pressRententionOffset: PressOffset
139216

140217
Defines how far the pointer (while held down) may move outside the bounds of the
141218
element before it is deactivated. Once deactivated, the pointer (still held

packages/react-events/src/Hover.js

+22-14
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ type HoverEvent = {|
3636
type: HoverEventType,
3737
|};
3838

39-
// const DEFAULT_HOVER_END_DELAY_MS = 0;
40-
// const DEFAULT_HOVER_START_DELAY_MS = 0;
39+
const DEFAULT_HOVER_END_DELAY_MS = 0;
40+
const DEFAULT_HOVER_START_DELAY_MS = 0;
4141

4242
const targetEventTypes = [
4343
'pointerover',
@@ -98,7 +98,7 @@ function dispatchHoverStartEvents(
9898
state.hoverEndTimeout = null;
9999
}
100100

101-
const dispatch = () => {
101+
const activate = () => {
102102
state.isActiveHovered = true;
103103

104104
if (props.onHoverStart) {
@@ -115,14 +115,18 @@ function dispatchHoverStartEvents(
115115
};
116116

117117
if (!state.isActiveHovered) {
118-
const delay = calculateDelayMS(props.delayHoverStart, 0, 0);
119-
if (delay > 0) {
118+
const delayHoverStart = calculateDelayMS(
119+
props.delayHoverStart,
120+
0,
121+
DEFAULT_HOVER_START_DELAY_MS,
122+
);
123+
if (delayHoverStart > 0) {
120124
state.hoverStartTimeout = context.setTimeout(() => {
121125
state.hoverStartTimeout = null;
122-
dispatch();
123-
}, delay);
126+
activate();
127+
}, delayHoverStart);
124128
} else {
125-
dispatch();
129+
activate();
126130
}
127131
}
128132
}
@@ -145,7 +149,7 @@ function dispatchHoverEndEvents(
145149
state.hoverStartTimeout = null;
146150
}
147151

148-
const dispatch = () => {
152+
const deactivate = () => {
149153
state.isActiveHovered = false;
150154

151155
if (props.onHoverEnd) {
@@ -162,13 +166,17 @@ function dispatchHoverEndEvents(
162166
};
163167

164168
if (state.isActiveHovered) {
165-
const delay = calculateDelayMS(props.delayHoverEnd, 0, 0);
166-
if (delay > 0) {
169+
const delayHoverEnd = calculateDelayMS(
170+
props.delayHoverEnd,
171+
0,
172+
DEFAULT_HOVER_END_DELAY_MS,
173+
);
174+
if (delayHoverEnd > 0) {
167175
state.hoverEndTimeout = context.setTimeout(() => {
168-
dispatch();
169-
}, delay);
176+
deactivate();
177+
}, delayHoverEnd);
170178
} else {
171-
dispatch();
179+
deactivate();
172180
}
173181
}
174182
}

0 commit comments

Comments
 (0)