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‎

Lines changed: 117 additions & 40 deletions
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‎

Lines changed: 22 additions & 14 deletions
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)