@react-aria/interactions 3.4.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +440 -152
- package/dist/main.js.map +1 -1
- package/dist/module.js +429 -149
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +53 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/PressResponder.tsx +4 -2
- package/src/index.ts +1 -0
- package/src/textSelection.ts +59 -28
- package/src/useFocusVisible.ts +33 -16
- package/src/useHover.ts +28 -9
- package/src/useInteractOutside.ts +46 -44
- package/src/useLongPress.ts +128 -0
- package/src/usePress.ts +181 -38
- package/src/useScrollWheel.ts +3 -12
package/dist/module.js
CHANGED
|
@@ -1,44 +1,72 @@
|
|
|
1
1
|
import _react, { useContext, useEffect, useMemo, useRef, useState, useCallback } from "react";
|
|
2
|
-
import { mergeProps, runAfterTransition, focusWithoutScrolling, useGlobalListeners, useSyncRef, isMac } from "@react-aria/utils";
|
|
2
|
+
import { mergeProps, isIOS, runAfterTransition, focusWithoutScrolling, useGlobalListeners, useSyncRef, isMac, useEvent, useDescription } from "@react-aria/utils";
|
|
3
3
|
import _babelRuntimeHelpersEsmObjectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
4
4
|
import _babelRuntimeHelpersEsmExtends from "@babel/runtime/helpers/esm/extends";
|
|
5
|
+
// Note that state only matters here for iOS. Non-iOS gets user-select: none applied to the target element
|
|
6
|
+
// rather than at the document level so we just need to apply/remove user-select: none for each pressed element individually
|
|
5
7
|
let $e17c9db826984f8ab8e5d837bf0b8$var$state = 'default';
|
|
6
8
|
let $e17c9db826984f8ab8e5d837bf0b8$var$savedUserSelect = '';
|
|
9
|
+
let $e17c9db826984f8ab8e5d837bf0b8$var$modifiedElementMap = new WeakMap();
|
|
7
10
|
|
|
8
|
-
function $e17c9db826984f8ab8e5d837bf0b8$export$disableTextSelection() {
|
|
9
|
-
if (
|
|
10
|
-
$e17c9db826984f8ab8e5d837bf0b8$var$
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
function $e17c9db826984f8ab8e5d837bf0b8$export$disableTextSelection(target) {
|
|
12
|
+
if (isIOS()) {
|
|
13
|
+
if ($e17c9db826984f8ab8e5d837bf0b8$var$state === 'default') {
|
|
14
|
+
$e17c9db826984f8ab8e5d837bf0b8$var$savedUserSelect = document.documentElement.style.webkitUserSelect;
|
|
15
|
+
document.documentElement.style.webkitUserSelect = 'none';
|
|
16
|
+
}
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
$e17c9db826984f8ab8e5d837bf0b8$var$state = 'disabled';
|
|
19
|
+
} else if (target) {
|
|
20
|
+
// If not iOS, store the target's original user-select and change to user-select: none
|
|
21
|
+
// Ignore state since it doesn't apply for non iOS
|
|
22
|
+
$e17c9db826984f8ab8e5d837bf0b8$var$modifiedElementMap.set(target, target.style.userSelect);
|
|
23
|
+
target.style.userSelect = 'none';
|
|
24
|
+
}
|
|
15
25
|
}
|
|
16
26
|
|
|
17
|
-
function $e17c9db826984f8ab8e5d837bf0b8$export$restoreTextSelection() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
function $e17c9db826984f8ab8e5d837bf0b8$export$restoreTextSelection(target) {
|
|
28
|
+
if (isIOS()) {
|
|
29
|
+
// If the state is already default, there's nothing to do.
|
|
30
|
+
// If it is restoring, then there's no need to queue a second restore.
|
|
31
|
+
if ($e17c9db826984f8ab8e5d837bf0b8$var$state !== 'disabled') {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
23
34
|
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
$e17c9db826984f8ab8e5d837bf0b8$var$state = 'restoring'; // There appears to be a delay on iOS where selection still might occur
|
|
36
|
+
// after pointer up, so wait a bit before removing user-select.
|
|
37
|
+
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
// Wait for any CSS transitions to complete so we don't recompute style
|
|
40
|
+
// for the whole page in the middle of the animation and cause jank.
|
|
41
|
+
runAfterTransition(() => {
|
|
42
|
+
// Avoid race conditions
|
|
43
|
+
if ($e17c9db826984f8ab8e5d837bf0b8$var$state === 'restoring') {
|
|
44
|
+
if (document.documentElement.style.webkitUserSelect === 'none') {
|
|
45
|
+
document.documentElement.style.webkitUserSelect = $e17c9db826984f8ab8e5d837bf0b8$var$savedUserSelect || '';
|
|
46
|
+
}
|
|
26
47
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// for the whole page in the middle of the animation and cause jank.
|
|
30
|
-
runAfterTransition(() => {
|
|
31
|
-
// Avoid race conditions
|
|
32
|
-
if ($e17c9db826984f8ab8e5d837bf0b8$var$state === 'restoring') {
|
|
33
|
-
if (document.documentElement.style.webkitUserSelect === 'none') {
|
|
34
|
-
document.documentElement.style.webkitUserSelect = $e17c9db826984f8ab8e5d837bf0b8$var$savedUserSelect || '';
|
|
48
|
+
$e17c9db826984f8ab8e5d837bf0b8$var$savedUserSelect = '';
|
|
49
|
+
$e17c9db826984f8ab8e5d837bf0b8$var$state = 'default';
|
|
35
50
|
}
|
|
51
|
+
});
|
|
52
|
+
}, 300);
|
|
53
|
+
} else {
|
|
54
|
+
// If not iOS, restore the target's original user-select if any
|
|
55
|
+
// Ignore state since it doesn't apply for non iOS
|
|
56
|
+
if (target && $e17c9db826984f8ab8e5d837bf0b8$var$modifiedElementMap.has(target)) {
|
|
57
|
+
let targetOldUserSelect = $e17c9db826984f8ab8e5d837bf0b8$var$modifiedElementMap.get(target);
|
|
36
58
|
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
if (target.style.userSelect === 'none') {
|
|
60
|
+
target.style.userSelect = targetOldUserSelect;
|
|
39
61
|
}
|
|
40
|
-
|
|
41
|
-
|
|
62
|
+
|
|
63
|
+
if (target.getAttribute('style') === '') {
|
|
64
|
+
target.removeAttribute('style');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
$e17c9db826984f8ab8e5d837bf0b8$var$modifiedElementMap.delete(target);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
42
70
|
}
|
|
43
71
|
|
|
44
72
|
/*
|
|
@@ -108,9 +136,11 @@ export function usePress(props) {
|
|
|
108
136
|
onPressUp,
|
|
109
137
|
isDisabled,
|
|
110
138
|
isPressed: isPressedProp,
|
|
111
|
-
preventFocusOnPress
|
|
139
|
+
preventFocusOnPress,
|
|
140
|
+
shouldCancelOnPointerExit,
|
|
141
|
+
allowTextSelectionOnPress
|
|
112
142
|
} = _usePressResponderCon,
|
|
113
|
-
domProps = _babelRuntimeHelpersEsmObjectWithoutPropertiesLoose(_usePressResponderCon, ["onPress", "onPressChange", "onPressStart", "onPressEnd", "onPressUp", "isDisabled", "isPressed", "preventFocusOnPress", "ref"]);
|
|
143
|
+
domProps = _babelRuntimeHelpersEsmObjectWithoutPropertiesLoose(_usePressResponderCon, ["onPress", "onPressChange", "onPressStart", "onPressEnd", "onPressUp", "isDisabled", "isPressed", "preventFocusOnPress", "shouldCancelOnPointerExit", "allowTextSelectionOnPress", "ref"]);
|
|
114
144
|
|
|
115
145
|
let propsRef = useRef(null);
|
|
116
146
|
propsRef.current = {
|
|
@@ -119,7 +149,8 @@ export function usePress(props) {
|
|
|
119
149
|
onPressStart,
|
|
120
150
|
onPressEnd,
|
|
121
151
|
onPressUp,
|
|
122
|
-
isDisabled
|
|
152
|
+
isDisabled,
|
|
153
|
+
shouldCancelOnPointerExit
|
|
123
154
|
};
|
|
124
155
|
let [isPressed, setPressed] = useState(false);
|
|
125
156
|
let ref = useRef({
|
|
@@ -157,7 +188,8 @@ export function usePress(props) {
|
|
|
157
188
|
target: originalEvent.currentTarget,
|
|
158
189
|
shiftKey: originalEvent.shiftKey,
|
|
159
190
|
metaKey: originalEvent.metaKey,
|
|
160
|
-
ctrlKey: originalEvent.ctrlKey
|
|
191
|
+
ctrlKey: originalEvent.ctrlKey,
|
|
192
|
+
altKey: originalEvent.altKey
|
|
161
193
|
});
|
|
162
194
|
}
|
|
163
195
|
|
|
@@ -195,7 +227,8 @@ export function usePress(props) {
|
|
|
195
227
|
target: originalEvent.currentTarget,
|
|
196
228
|
shiftKey: originalEvent.shiftKey,
|
|
197
229
|
metaKey: originalEvent.metaKey,
|
|
198
|
-
ctrlKey: originalEvent.ctrlKey
|
|
230
|
+
ctrlKey: originalEvent.ctrlKey,
|
|
231
|
+
altKey: originalEvent.altKey
|
|
199
232
|
});
|
|
200
233
|
}
|
|
201
234
|
|
|
@@ -212,7 +245,8 @@ export function usePress(props) {
|
|
|
212
245
|
target: originalEvent.currentTarget,
|
|
213
246
|
shiftKey: originalEvent.shiftKey,
|
|
214
247
|
metaKey: originalEvent.metaKey,
|
|
215
|
-
ctrlKey: originalEvent.ctrlKey
|
|
248
|
+
ctrlKey: originalEvent.ctrlKey,
|
|
249
|
+
altKey: originalEvent.altKey
|
|
216
250
|
});
|
|
217
251
|
}
|
|
218
252
|
};
|
|
@@ -234,7 +268,8 @@ export function usePress(props) {
|
|
|
234
268
|
target: originalEvent.currentTarget,
|
|
235
269
|
shiftKey: originalEvent.shiftKey,
|
|
236
270
|
metaKey: originalEvent.metaKey,
|
|
237
|
-
ctrlKey: originalEvent.ctrlKey
|
|
271
|
+
ctrlKey: originalEvent.ctrlKey,
|
|
272
|
+
altKey: originalEvent.altKey
|
|
238
273
|
});
|
|
239
274
|
}
|
|
240
275
|
};
|
|
@@ -250,13 +285,16 @@ export function usePress(props) {
|
|
|
250
285
|
state.activePointerId = null;
|
|
251
286
|
state.pointerType = null;
|
|
252
287
|
removeAllGlobalListeners();
|
|
253
|
-
|
|
288
|
+
|
|
289
|
+
if (!allowTextSelectionOnPress) {
|
|
290
|
+
$e17c9db826984f8ab8e5d837bf0b8$export$restoreTextSelection(state.target);
|
|
291
|
+
}
|
|
254
292
|
}
|
|
255
293
|
};
|
|
256
294
|
|
|
257
295
|
let pressProps = {
|
|
258
296
|
onKeyDown(e) {
|
|
259
|
-
if ($ffc54430b1dbeee65879852feaaff07d$var$isValidKeyboardEvent(e.nativeEvent)) {
|
|
297
|
+
if ($ffc54430b1dbeee65879852feaaff07d$var$isValidKeyboardEvent(e.nativeEvent) && e.currentTarget.contains(e.target)) {
|
|
260
298
|
e.preventDefault();
|
|
261
299
|
e.stopPropagation(); // If the event is repeating, it may have started on a different element
|
|
262
300
|
// after which focus moved to the current element. Ignore these events and
|
|
@@ -274,12 +312,16 @@ export function usePress(props) {
|
|
|
274
312
|
},
|
|
275
313
|
|
|
276
314
|
onKeyUp(e) {
|
|
277
|
-
if ($ffc54430b1dbeee65879852feaaff07d$var$isValidKeyboardEvent(e.nativeEvent) && !e.repeat) {
|
|
315
|
+
if ($ffc54430b1dbeee65879852feaaff07d$var$isValidKeyboardEvent(e.nativeEvent) && !e.repeat && e.currentTarget.contains(e.target)) {
|
|
278
316
|
triggerPressUp($ffc54430b1dbeee65879852feaaff07d$var$createEvent(state.target, e), 'keyboard');
|
|
279
317
|
}
|
|
280
318
|
},
|
|
281
319
|
|
|
282
320
|
onClick(e) {
|
|
321
|
+
if (e && !e.currentTarget.contains(e.target)) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
|
|
283
325
|
if (e && e.button === 0) {
|
|
284
326
|
e.stopPropagation();
|
|
285
327
|
|
|
@@ -289,7 +331,7 @@ export function usePress(props) {
|
|
|
289
331
|
// trigger as if it were a keyboard click.
|
|
290
332
|
|
|
291
333
|
|
|
292
|
-
if (!state.ignoreClickAfterPress && !state.ignoreEmulatedMouseEvents && $f67ef9f1b8ed09b4b00fd0840cd8b94b$export$isVirtualClick(e.nativeEvent)) {
|
|
334
|
+
if (!state.ignoreClickAfterPress && !state.ignoreEmulatedMouseEvents && (state.pointerType === 'virtual' || $f67ef9f1b8ed09b4b00fd0840cd8b94b$export$isVirtualClick(e.nativeEvent))) {
|
|
293
335
|
// Ensure the element receives focus (VoiceOver on iOS does not do this)
|
|
294
336
|
if (!isDisabled && !preventFocusOnPress) {
|
|
295
337
|
focusWithoutScrolling(e.currentTarget);
|
|
@@ -312,11 +354,12 @@ export function usePress(props) {
|
|
|
312
354
|
e.preventDefault();
|
|
313
355
|
e.stopPropagation();
|
|
314
356
|
state.isPressed = false;
|
|
315
|
-
|
|
357
|
+
let target = e.target;
|
|
358
|
+
triggerPressEnd($ffc54430b1dbeee65879852feaaff07d$var$createEvent(state.target, e), 'keyboard', state.target.contains(target));
|
|
316
359
|
removeAllGlobalListeners(); // If the target is a link, trigger the click method to open the URL,
|
|
317
360
|
// but defer triggering pressEnd until onClick event handler.
|
|
318
361
|
|
|
319
|
-
if (
|
|
362
|
+
if (state.target.contains(target) && $ffc54430b1dbeee65879852feaaff07d$var$isHTMLAnchorLink(state.target) || state.target.getAttribute('role') === 'link') {
|
|
320
363
|
state.target.click();
|
|
321
364
|
}
|
|
322
365
|
}
|
|
@@ -324,8 +367,17 @@ export function usePress(props) {
|
|
|
324
367
|
|
|
325
368
|
if (typeof PointerEvent !== 'undefined') {
|
|
326
369
|
pressProps.onPointerDown = e => {
|
|
327
|
-
// Only handle left clicks
|
|
328
|
-
if (e.button !== 0) {
|
|
370
|
+
// Only handle left clicks, and ignore events that bubbled through portals.
|
|
371
|
+
if (e.button !== 0 || !e.currentTarget.contains(e.target)) {
|
|
372
|
+
return;
|
|
373
|
+
} // iOS safari fires pointer events from VoiceOver with incorrect coordinates/target.
|
|
374
|
+
// Ignore and let the onClick handler take care of it instead.
|
|
375
|
+
// https://bugs.webkit.org/show_bug.cgi?id=222627
|
|
376
|
+
// https://bugs.webkit.org/show_bug.cgi?id=223202
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
if ($ffc54430b1dbeee65879852feaaff07d$var$isVirtualPointerEvent(e.nativeEvent)) {
|
|
380
|
+
state.pointerType = 'virtual';
|
|
329
381
|
return;
|
|
330
382
|
} // Due to browser inconsistencies, especially on mobile browsers, we prevent
|
|
331
383
|
// default on pointer down and handle focusing the pressable element ourselves.
|
|
@@ -333,11 +385,9 @@ export function usePress(props) {
|
|
|
333
385
|
|
|
334
386
|
if ($ffc54430b1dbeee65879852feaaff07d$var$shouldPreventDefault(e.target)) {
|
|
335
387
|
e.preventDefault();
|
|
336
|
-
}
|
|
337
|
-
// https://bugs.webkit.org/show_bug.cgi?id=222627
|
|
338
|
-
|
|
388
|
+
}
|
|
339
389
|
|
|
340
|
-
state.pointerType =
|
|
390
|
+
state.pointerType = e.pointerType;
|
|
341
391
|
e.stopPropagation();
|
|
342
392
|
|
|
343
393
|
if (!state.isPressed) {
|
|
@@ -350,7 +400,10 @@ export function usePress(props) {
|
|
|
350
400
|
focusWithoutScrolling(e.currentTarget);
|
|
351
401
|
}
|
|
352
402
|
|
|
353
|
-
|
|
403
|
+
if (!allowTextSelectionOnPress) {
|
|
404
|
+
$e17c9db826984f8ab8e5d837bf0b8$export$disableTextSelection(state.target);
|
|
405
|
+
}
|
|
406
|
+
|
|
354
407
|
triggerPressStart(e, state.pointerType);
|
|
355
408
|
addGlobalListener(document, 'pointermove', onPointerMove, false);
|
|
356
409
|
addGlobalListener(document, 'pointerup', onPointerUp, false);
|
|
@@ -359,6 +412,10 @@ export function usePress(props) {
|
|
|
359
412
|
};
|
|
360
413
|
|
|
361
414
|
pressProps.onMouseDown = e => {
|
|
415
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
362
419
|
if (e.button === 0) {
|
|
363
420
|
// Chrome and Firefox on touch Windows devices require mouse down events
|
|
364
421
|
// to be canceled in addition to pointer events, or an extra asynchronous
|
|
@@ -372,11 +429,16 @@ export function usePress(props) {
|
|
|
372
429
|
};
|
|
373
430
|
|
|
374
431
|
pressProps.onPointerUp = e => {
|
|
375
|
-
//
|
|
432
|
+
// iOS fires pointerup with zero width and height, so check the pointerType recorded during pointerdown.
|
|
433
|
+
if (!e.currentTarget.contains(e.target) || state.pointerType === 'virtual') {
|
|
434
|
+
return;
|
|
435
|
+
} // Only handle left clicks
|
|
376
436
|
// Safari on iOS sometimes fires pointerup events, even
|
|
377
437
|
// when the touch isn't over the target, so double check.
|
|
438
|
+
|
|
439
|
+
|
|
378
440
|
if (e.button === 0 && $ffc54430b1dbeee65879852feaaff07d$var$isOverTarget(e, e.currentTarget)) {
|
|
379
|
-
triggerPressUp(e, state.pointerType);
|
|
441
|
+
triggerPressUp(e, state.pointerType || e.pointerType);
|
|
380
442
|
}
|
|
381
443
|
}; // Safari on iOS < 13.2 does not implement pointerenter/pointerleave events correctly.
|
|
382
444
|
// Use pointer move events instead to implement our own hit testing.
|
|
@@ -396,6 +458,10 @@ export function usePress(props) {
|
|
|
396
458
|
} else if (state.isOverTarget) {
|
|
397
459
|
state.isOverTarget = false;
|
|
398
460
|
triggerPressEnd($ffc54430b1dbeee65879852feaaff07d$var$createEvent(state.target, e), state.pointerType, false);
|
|
461
|
+
|
|
462
|
+
if (propsRef.current.shouldCancelOnPointerExit) {
|
|
463
|
+
cancel(e);
|
|
464
|
+
}
|
|
399
465
|
}
|
|
400
466
|
};
|
|
401
467
|
|
|
@@ -412,7 +478,10 @@ export function usePress(props) {
|
|
|
412
478
|
state.activePointerId = null;
|
|
413
479
|
state.pointerType = null;
|
|
414
480
|
removeAllGlobalListeners();
|
|
415
|
-
|
|
481
|
+
|
|
482
|
+
if (!allowTextSelectionOnPress) {
|
|
483
|
+
$e17c9db826984f8ab8e5d837bf0b8$export$restoreTextSelection(state.target);
|
|
484
|
+
}
|
|
416
485
|
}
|
|
417
486
|
};
|
|
418
487
|
|
|
@@ -421,13 +490,17 @@ export function usePress(props) {
|
|
|
421
490
|
};
|
|
422
491
|
|
|
423
492
|
pressProps.onDragStart = e => {
|
|
424
|
-
|
|
493
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
494
|
+
return;
|
|
495
|
+
} // Safari does not call onPointerCancel when a drag starts, whereas Chrome and Firefox do.
|
|
496
|
+
|
|
497
|
+
|
|
425
498
|
cancel(e);
|
|
426
499
|
};
|
|
427
500
|
} else {
|
|
428
501
|
pressProps.onMouseDown = e => {
|
|
429
502
|
// Only handle left clicks
|
|
430
|
-
if (e.button !== 0) {
|
|
503
|
+
if (e.button !== 0 || !e.currentTarget.contains(e.target)) {
|
|
431
504
|
return;
|
|
432
505
|
} // Due to browser inconsistencies, especially on mobile browsers, we prevent
|
|
433
506
|
// default on mouse down and handle focusing the pressable element ourselves.
|
|
@@ -457,6 +530,10 @@ export function usePress(props) {
|
|
|
457
530
|
};
|
|
458
531
|
|
|
459
532
|
pressProps.onMouseEnter = e => {
|
|
533
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
|
|
460
537
|
e.stopPropagation();
|
|
461
538
|
|
|
462
539
|
if (state.isPressed && !state.ignoreEmulatedMouseEvents) {
|
|
@@ -466,15 +543,27 @@ export function usePress(props) {
|
|
|
466
543
|
};
|
|
467
544
|
|
|
468
545
|
pressProps.onMouseLeave = e => {
|
|
546
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
|
|
469
550
|
e.stopPropagation();
|
|
470
551
|
|
|
471
552
|
if (state.isPressed && !state.ignoreEmulatedMouseEvents) {
|
|
472
553
|
state.isOverTarget = false;
|
|
473
554
|
triggerPressEnd(e, state.pointerType, false);
|
|
555
|
+
|
|
556
|
+
if (propsRef.current.shouldCancelOnPointerExit) {
|
|
557
|
+
cancel(e);
|
|
558
|
+
}
|
|
474
559
|
}
|
|
475
560
|
};
|
|
476
561
|
|
|
477
562
|
pressProps.onMouseUp = e => {
|
|
563
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
|
|
478
567
|
if (!state.ignoreEmulatedMouseEvents && e.button === 0) {
|
|
479
568
|
triggerPressUp(e, state.pointerType);
|
|
480
569
|
}
|
|
@@ -504,6 +593,10 @@ export function usePress(props) {
|
|
|
504
593
|
};
|
|
505
594
|
|
|
506
595
|
pressProps.onTouchStart = e => {
|
|
596
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
|
|
507
600
|
e.stopPropagation();
|
|
508
601
|
let touch = $ffc54430b1dbeee65879852feaaff07d$var$getTouchFromEvent(e.nativeEvent);
|
|
509
602
|
|
|
@@ -523,12 +616,19 @@ export function usePress(props) {
|
|
|
523
616
|
focusWithoutScrolling(e.currentTarget);
|
|
524
617
|
}
|
|
525
618
|
|
|
526
|
-
|
|
619
|
+
if (!allowTextSelectionOnPress) {
|
|
620
|
+
$e17c9db826984f8ab8e5d837bf0b8$export$disableTextSelection(state.target);
|
|
621
|
+
}
|
|
622
|
+
|
|
527
623
|
triggerPressStart(e, state.pointerType);
|
|
528
624
|
addGlobalListener(window, 'scroll', onScroll, true);
|
|
529
625
|
};
|
|
530
626
|
|
|
531
627
|
pressProps.onTouchMove = e => {
|
|
628
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
|
|
532
632
|
e.stopPropagation();
|
|
533
633
|
|
|
534
634
|
if (!state.isPressed) {
|
|
@@ -545,10 +645,18 @@ export function usePress(props) {
|
|
|
545
645
|
} else if (state.isOverTarget) {
|
|
546
646
|
state.isOverTarget = false;
|
|
547
647
|
triggerPressEnd(e, state.pointerType, false);
|
|
648
|
+
|
|
649
|
+
if (propsRef.current.shouldCancelOnPointerExit) {
|
|
650
|
+
cancel(e);
|
|
651
|
+
}
|
|
548
652
|
}
|
|
549
653
|
};
|
|
550
654
|
|
|
551
655
|
pressProps.onTouchEnd = e => {
|
|
656
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
|
|
552
660
|
e.stopPropagation();
|
|
553
661
|
|
|
554
662
|
if (!state.isPressed) {
|
|
@@ -568,11 +676,19 @@ export function usePress(props) {
|
|
|
568
676
|
state.activePointerId = null;
|
|
569
677
|
state.isOverTarget = false;
|
|
570
678
|
state.ignoreEmulatedMouseEvents = true;
|
|
571
|
-
|
|
679
|
+
|
|
680
|
+
if (!allowTextSelectionOnPress) {
|
|
681
|
+
$e17c9db826984f8ab8e5d837bf0b8$export$restoreTextSelection(state.target);
|
|
682
|
+
}
|
|
683
|
+
|
|
572
684
|
removeAllGlobalListeners();
|
|
573
685
|
};
|
|
574
686
|
|
|
575
687
|
pressProps.onTouchCancel = e => {
|
|
688
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
|
|
576
692
|
e.stopPropagation();
|
|
577
693
|
|
|
578
694
|
if (state.isPressed) {
|
|
@@ -586,23 +702,32 @@ export function usePress(props) {
|
|
|
586
702
|
currentTarget: state.target,
|
|
587
703
|
shiftKey: false,
|
|
588
704
|
ctrlKey: false,
|
|
589
|
-
metaKey: false
|
|
705
|
+
metaKey: false,
|
|
706
|
+
altKey: false
|
|
590
707
|
});
|
|
591
708
|
}
|
|
592
709
|
};
|
|
593
710
|
|
|
594
711
|
pressProps.onDragStart = e => {
|
|
712
|
+
if (!e.currentTarget.contains(e.target)) {
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
|
|
595
716
|
cancel(e);
|
|
596
717
|
};
|
|
597
718
|
}
|
|
598
719
|
|
|
599
720
|
return pressProps;
|
|
600
|
-
}, [addGlobalListener, isDisabled, preventFocusOnPress, removeAllGlobalListeners]); // Remove user-select: none in case component unmounts immediately after pressStart
|
|
721
|
+
}, [addGlobalListener, isDisabled, preventFocusOnPress, removeAllGlobalListeners, allowTextSelectionOnPress]); // Remove user-select: none in case component unmounts immediately after pressStart
|
|
601
722
|
// eslint-disable-next-line arrow-body-style
|
|
602
723
|
|
|
603
724
|
useEffect(() => {
|
|
604
|
-
return () =>
|
|
605
|
-
|
|
725
|
+
return () => {
|
|
726
|
+
if (!allowTextSelectionOnPress) {
|
|
727
|
+
$e17c9db826984f8ab8e5d837bf0b8$export$restoreTextSelection(ref.current.target);
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
}, [allowTextSelectionOnPress]);
|
|
606
731
|
return {
|
|
607
732
|
isPressed: isPressedProp || isPressed,
|
|
608
733
|
pressProps: mergeProps(domProps, pressProps)
|
|
@@ -616,6 +741,7 @@ function $ffc54430b1dbeee65879852feaaff07d$var$isHTMLAnchorLink(target) {
|
|
|
616
741
|
function $ffc54430b1dbeee65879852feaaff07d$var$isValidKeyboardEvent(event) {
|
|
617
742
|
const {
|
|
618
743
|
key,
|
|
744
|
+
code,
|
|
619
745
|
target
|
|
620
746
|
} = event;
|
|
621
747
|
const element = target;
|
|
@@ -626,7 +752,7 @@ function $ffc54430b1dbeee65879852feaaff07d$var$isValidKeyboardEvent(event) {
|
|
|
626
752
|
const role = element.getAttribute('role'); // Accessibility for keyboards. Space and Enter only.
|
|
627
753
|
// "Spacebar" is for IE 11
|
|
628
754
|
|
|
629
|
-
return (key === 'Enter' || key === ' ' || key === 'Spacebar') && tagName !== 'INPUT' && tagName !== 'TEXTAREA' && isContentEditable !== true && ( // A link with a valid href should be handled natively,
|
|
755
|
+
return (key === 'Enter' || key === ' ' || key === 'Spacebar' || code === 'Space') && tagName !== 'INPUT' && tagName !== 'TEXTAREA' && isContentEditable !== true && ( // A link with a valid href should be handled natively,
|
|
630
756
|
// unless it also has role='button' and was triggered using Space.
|
|
631
757
|
!$ffc54430b1dbeee65879852feaaff07d$var$isHTMLAnchorLink(element) || role === 'button' && key !== 'Enter') && // An element with role='link' should only trigger with Enter key
|
|
632
758
|
!(role === 'link' && key !== 'Enter');
|
|
@@ -663,13 +789,40 @@ function $ffc54430b1dbeee65879852feaaff07d$var$createEvent(target, e) {
|
|
|
663
789
|
currentTarget: target,
|
|
664
790
|
shiftKey: e.shiftKey,
|
|
665
791
|
ctrlKey: e.ctrlKey,
|
|
666
|
-
metaKey: e.metaKey
|
|
792
|
+
metaKey: e.metaKey,
|
|
793
|
+
altKey: e.altKey
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
function $ffc54430b1dbeee65879852feaaff07d$var$getPointClientRect(point) {
|
|
798
|
+
let offsetX = point.width / 2 || point.radiusX || 0;
|
|
799
|
+
let offsetY = point.height / 2 || point.radiusY || 0;
|
|
800
|
+
return {
|
|
801
|
+
top: point.clientY - offsetY,
|
|
802
|
+
right: point.clientX + offsetX,
|
|
803
|
+
bottom: point.clientY + offsetY,
|
|
804
|
+
left: point.clientX - offsetX
|
|
667
805
|
};
|
|
668
806
|
}
|
|
669
807
|
|
|
808
|
+
function $ffc54430b1dbeee65879852feaaff07d$var$areRectanglesOverlapping(a, b) {
|
|
809
|
+
// check if they cannot overlap on x axis
|
|
810
|
+
if (a.left > b.right || b.left > a.right) {
|
|
811
|
+
return false;
|
|
812
|
+
} // check if they cannot overlap on y axis
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
if (a.top > b.bottom || b.top > a.bottom) {
|
|
816
|
+
return false;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
return true;
|
|
820
|
+
}
|
|
821
|
+
|
|
670
822
|
function $ffc54430b1dbeee65879852feaaff07d$var$isOverTarget(point, target) {
|
|
671
823
|
let rect = target.getBoundingClientRect();
|
|
672
|
-
|
|
824
|
+
let pointRect = $ffc54430b1dbeee65879852feaaff07d$var$getPointClientRect(point);
|
|
825
|
+
return $ffc54430b1dbeee65879852feaaff07d$var$areRectanglesOverlapping(rect, pointRect);
|
|
673
826
|
}
|
|
674
827
|
|
|
675
828
|
function $ffc54430b1dbeee65879852feaaff07d$var$shouldPreventDefault(target) {
|
|
@@ -679,7 +832,11 @@ function $ffc54430b1dbeee65879852feaaff07d$var$shouldPreventDefault(target) {
|
|
|
679
832
|
|
|
680
833
|
function $ffc54430b1dbeee65879852feaaff07d$var$isVirtualPointerEvent(event) {
|
|
681
834
|
// If the pointer size is zero, then we assume it's from a screen reader.
|
|
682
|
-
return event
|
|
835
|
+
// Android TalkBack double tap will sometimes return a event with width and height of 1
|
|
836
|
+
// and pointerType === 'mouse' so we need to check for a specific combination of event attributes.
|
|
837
|
+
// Cannot use "event.pressure === 0" as the sole check due to Safari pointer events always returning pressure === 0
|
|
838
|
+
// instead of .5, see https://bugs.webkit.org/show_bug.cgi?id=206216
|
|
839
|
+
return event.width === 0 && event.height === 0 || event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0;
|
|
683
840
|
}
|
|
684
841
|
|
|
685
842
|
export const Pressable = /*#__PURE__*/_react.forwardRef((_ref, ref) => {
|
|
@@ -714,7 +871,7 @@ export const PressResponder = /*#__PURE__*/_react.forwardRef((_ref, ref) => {
|
|
|
714
871
|
let isRegistered = useRef(false);
|
|
715
872
|
let prevContext = useContext($a3ff51240de6f955c79cf17a88e349$export$PressResponderContext);
|
|
716
873
|
let context = mergeProps(prevContext || {}, _babelRuntimeHelpersEsmExtends({}, props, {
|
|
717
|
-
ref,
|
|
874
|
+
ref: ref || (prevContext == null ? void 0 : prevContext.ref),
|
|
718
875
|
|
|
719
876
|
register() {
|
|
720
877
|
isRegistered.current = true;
|
|
@@ -725,6 +882,7 @@ export const PressResponder = /*#__PURE__*/_react.forwardRef((_ref, ref) => {
|
|
|
725
882
|
}
|
|
726
883
|
|
|
727
884
|
}));
|
|
885
|
+
useSyncRef(prevContext, ref);
|
|
728
886
|
useEffect(() => {
|
|
729
887
|
if (!isRegistered.current) {
|
|
730
888
|
console.warn('A PressResponder was rendered without a pressable child. ' + 'Either call the usePress hook, or wrap your DOM node with <Pressable> component.');
|
|
@@ -788,7 +946,8 @@ export function useFocus(props) {
|
|
|
788
946
|
let $d01f69bb2ab5f70dfd0005370a2a2cbc$var$currentModality = null;
|
|
789
947
|
let $d01f69bb2ab5f70dfd0005370a2a2cbc$var$changeHandlers = new Set();
|
|
790
948
|
let $d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasSetupGlobalListeners = false;
|
|
791
|
-
let $d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasEventBeforeFocus = false;
|
|
949
|
+
let $d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasEventBeforeFocus = false;
|
|
950
|
+
let $d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasBlurredWindowRecently = false; // Only Tab or Esc keys will make focus visible on text input elements
|
|
792
951
|
|
|
793
952
|
const $d01f69bb2ab5f70dfd0005370a2a2cbc$var$FOCUS_VISIBLE_INPUT_KEYS = {
|
|
794
953
|
Tab: true,
|
|
@@ -806,7 +965,8 @@ function $d01f69bb2ab5f70dfd0005370a2a2cbc$var$triggerChangeHandlers(modality, e
|
|
|
806
965
|
|
|
807
966
|
|
|
808
967
|
function $d01f69bb2ab5f70dfd0005370a2a2cbc$var$isValidKey(e) {
|
|
809
|
-
|
|
968
|
+
// Control and Shift keys trigger when navigating back to the tab with keyboard.
|
|
969
|
+
return !(e.metaKey || !isMac() && e.altKey || e.ctrlKey || e.key === 'Control' || e.key === 'Shift' || e.key === 'Meta');
|
|
810
970
|
}
|
|
811
971
|
|
|
812
972
|
function $d01f69bb2ab5f70dfd0005370a2a2cbc$var$handleKeyboardEvent(e) {
|
|
@@ -844,18 +1004,20 @@ function $d01f69bb2ab5f70dfd0005370a2a2cbc$var$handleFocusEvent(e) {
|
|
|
844
1004
|
// This occurs, for example, when navigating a form with the next/previous buttons on iOS.
|
|
845
1005
|
|
|
846
1006
|
|
|
847
|
-
if (!$d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasEventBeforeFocus) {
|
|
1007
|
+
if (!$d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasEventBeforeFocus && !$d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasBlurredWindowRecently) {
|
|
848
1008
|
$d01f69bb2ab5f70dfd0005370a2a2cbc$var$currentModality = 'virtual';
|
|
849
1009
|
$d01f69bb2ab5f70dfd0005370a2a2cbc$var$triggerChangeHandlers('virtual', e);
|
|
850
1010
|
}
|
|
851
1011
|
|
|
852
1012
|
$d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasEventBeforeFocus = false;
|
|
1013
|
+
$d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasBlurredWindowRecently = false;
|
|
853
1014
|
}
|
|
854
1015
|
|
|
855
1016
|
function $d01f69bb2ab5f70dfd0005370a2a2cbc$var$handleWindowBlur() {
|
|
856
1017
|
// When the window is blurred, reset state. This is necessary when tabbing out of the window,
|
|
857
1018
|
// for example, since a subsequent focus event won't be fired.
|
|
858
1019
|
$d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasEventBeforeFocus = false;
|
|
1020
|
+
$d01f69bb2ab5f70dfd0005370a2a2cbc$var$hasBlurredWindowRecently = true;
|
|
859
1021
|
}
|
|
860
1022
|
/**
|
|
861
1023
|
* Setup global event listeners to control when keyboard focus style should be visible.
|
|
@@ -940,40 +1102,56 @@ export function useInteractionModality() {
|
|
|
940
1102
|
}, []);
|
|
941
1103
|
return modality;
|
|
942
1104
|
}
|
|
1105
|
+
/**
|
|
1106
|
+
* If this is attached to text input component, return if the event is a focus event (Tab/Escape keys pressed) so that
|
|
1107
|
+
* focus visible style can be properly set.
|
|
1108
|
+
*/
|
|
1109
|
+
|
|
1110
|
+
function $d01f69bb2ab5f70dfd0005370a2a2cbc$var$isKeyboardFocusEvent(isTextInput, modality, e) {
|
|
1111
|
+
return !(isTextInput && modality === 'keyboard' && e instanceof KeyboardEvent && !$d01f69bb2ab5f70dfd0005370a2a2cbc$var$FOCUS_VISIBLE_INPUT_KEYS[e.key]);
|
|
1112
|
+
}
|
|
943
1113
|
/**
|
|
944
1114
|
* Manages focus visible state for the page, and subscribes individual components for updates.
|
|
945
1115
|
*/
|
|
946
1116
|
|
|
1117
|
+
|
|
947
1118
|
export function useFocusVisible(props) {
|
|
948
1119
|
if (props === void 0) {
|
|
949
1120
|
props = {};
|
|
950
1121
|
}
|
|
951
1122
|
|
|
952
|
-
$d01f69bb2ab5f70dfd0005370a2a2cbc$var$setupGlobalFocusEvents();
|
|
953
1123
|
let {
|
|
954
1124
|
isTextInput,
|
|
955
1125
|
autoFocus
|
|
956
1126
|
} = props;
|
|
957
1127
|
let [isFocusVisibleState, setFocusVisible] = useState(autoFocus || isFocusVisible());
|
|
1128
|
+
useFocusVisibleListener(isFocusVisible => {
|
|
1129
|
+
setFocusVisible(isFocusVisible);
|
|
1130
|
+
}, [isTextInput], {
|
|
1131
|
+
isTextInput
|
|
1132
|
+
});
|
|
1133
|
+
return {
|
|
1134
|
+
isFocusVisible: isFocusVisibleState
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Listens for trigger change and reports if focus is visible (i.e., modality is not pointer).
|
|
1139
|
+
*/
|
|
1140
|
+
|
|
1141
|
+
export function useFocusVisibleListener(fn, deps, opts) {
|
|
1142
|
+
$d01f69bb2ab5f70dfd0005370a2a2cbc$var$setupGlobalFocusEvents();
|
|
958
1143
|
useEffect(() => {
|
|
959
1144
|
let handler = (modality, e) => {
|
|
960
|
-
|
|
961
|
-
// typing except for when the Tab and Escape keys are pressed.
|
|
962
|
-
if (isTextInput && modality === 'keyboard' && e instanceof KeyboardEvent && !$d01f69bb2ab5f70dfd0005370a2a2cbc$var$FOCUS_VISIBLE_INPUT_KEYS[e.key]) {
|
|
1145
|
+
if (!$d01f69bb2ab5f70dfd0005370a2a2cbc$var$isKeyboardFocusEvent(opts == null ? void 0 : opts.isTextInput, modality, e)) {
|
|
963
1146
|
return;
|
|
964
1147
|
}
|
|
965
1148
|
|
|
966
|
-
|
|
1149
|
+
fn(isFocusVisible());
|
|
967
1150
|
};
|
|
968
1151
|
|
|
969
1152
|
$d01f69bb2ab5f70dfd0005370a2a2cbc$var$changeHandlers.add(handler);
|
|
970
|
-
return () =>
|
|
971
|
-
|
|
972
|
-
};
|
|
973
|
-
}, [isTextInput]);
|
|
974
|
-
return {
|
|
975
|
-
isFocusVisible: isFocusVisibleState
|
|
976
|
-
};
|
|
1153
|
+
return () => $d01f69bb2ab5f70dfd0005370a2a2cbc$var$changeHandlers.delete(handler);
|
|
1154
|
+
}, deps);
|
|
977
1155
|
}
|
|
978
1156
|
|
|
979
1157
|
/**
|
|
@@ -1093,17 +1271,25 @@ export function useHover(props) {
|
|
|
1093
1271
|
let [isHovered, setHovered] = useState(false);
|
|
1094
1272
|
let state = useRef({
|
|
1095
1273
|
isHovered: false,
|
|
1096
|
-
ignoreEmulatedMouseEvents: false
|
|
1274
|
+
ignoreEmulatedMouseEvents: false,
|
|
1275
|
+
pointerType: '',
|
|
1276
|
+
target: null
|
|
1097
1277
|
}).current;
|
|
1098
1278
|
useEffect($b1a784c66b81d90efa4f74e05b$var$setupGlobalTouchEvents, []);
|
|
1099
|
-
let
|
|
1279
|
+
let {
|
|
1280
|
+
hoverProps,
|
|
1281
|
+
triggerHoverEnd
|
|
1282
|
+
} = useMemo(() => {
|
|
1100
1283
|
let triggerHoverStart = (event, pointerType) => {
|
|
1101
|
-
|
|
1284
|
+
state.pointerType = pointerType;
|
|
1285
|
+
|
|
1286
|
+
if (isDisabled || pointerType === 'touch' || state.isHovered || !event.currentTarget.contains(event.target)) {
|
|
1102
1287
|
return;
|
|
1103
1288
|
}
|
|
1104
1289
|
|
|
1105
1290
|
state.isHovered = true;
|
|
1106
|
-
let target = event.
|
|
1291
|
+
let target = event.currentTarget;
|
|
1292
|
+
state.target = target;
|
|
1107
1293
|
|
|
1108
1294
|
if (onHoverStart) {
|
|
1109
1295
|
onHoverStart({
|
|
@@ -1121,12 +1307,15 @@ export function useHover(props) {
|
|
|
1121
1307
|
};
|
|
1122
1308
|
|
|
1123
1309
|
let triggerHoverEnd = (event, pointerType) => {
|
|
1310
|
+
state.pointerType = '';
|
|
1311
|
+
state.target = null;
|
|
1312
|
+
|
|
1124
1313
|
if (pointerType === 'touch' || !state.isHovered) {
|
|
1125
1314
|
return;
|
|
1126
1315
|
}
|
|
1127
1316
|
|
|
1128
1317
|
state.isHovered = false;
|
|
1129
|
-
let target = event.
|
|
1318
|
+
let target = event.currentTarget;
|
|
1130
1319
|
|
|
1131
1320
|
if (onHoverEnd) {
|
|
1132
1321
|
onHoverEnd({
|
|
@@ -1155,7 +1344,9 @@ export function useHover(props) {
|
|
|
1155
1344
|
};
|
|
1156
1345
|
|
|
1157
1346
|
hoverProps.onPointerLeave = e => {
|
|
1158
|
-
|
|
1347
|
+
if (!isDisabled && e.currentTarget.contains(e.target)) {
|
|
1348
|
+
triggerHoverEnd(e, e.pointerType);
|
|
1349
|
+
}
|
|
1159
1350
|
};
|
|
1160
1351
|
} else {
|
|
1161
1352
|
hoverProps.onTouchStart = () => {
|
|
@@ -1171,12 +1362,26 @@ export function useHover(props) {
|
|
|
1171
1362
|
};
|
|
1172
1363
|
|
|
1173
1364
|
hoverProps.onMouseLeave = e => {
|
|
1174
|
-
|
|
1365
|
+
if (!isDisabled && e.currentTarget.contains(e.target)) {
|
|
1366
|
+
triggerHoverEnd(e, 'mouse');
|
|
1367
|
+
}
|
|
1175
1368
|
};
|
|
1176
1369
|
}
|
|
1177
1370
|
|
|
1178
|
-
return
|
|
1371
|
+
return {
|
|
1372
|
+
hoverProps,
|
|
1373
|
+
triggerHoverEnd
|
|
1374
|
+
};
|
|
1179
1375
|
}, [onHoverStart, onHoverChange, onHoverEnd, isDisabled, state]);
|
|
1376
|
+
useEffect(() => {
|
|
1377
|
+
// Call the triggerHoverEnd as soon as isDisabled changes to true
|
|
1378
|
+
// Safe to call triggerHoverEnd, it will early return if we aren't currently hovering
|
|
1379
|
+
if (isDisabled) {
|
|
1380
|
+
triggerHoverEnd({
|
|
1381
|
+
currentTarget: state.target
|
|
1382
|
+
}, state.pointerType);
|
|
1383
|
+
}
|
|
1384
|
+
}, [isDisabled]);
|
|
1180
1385
|
return {
|
|
1181
1386
|
hoverProps,
|
|
1182
1387
|
isHovered
|
|
@@ -1191,81 +1396,80 @@ export function useInteractOutside(props) {
|
|
|
1191
1396
|
let {
|
|
1192
1397
|
ref,
|
|
1193
1398
|
onInteractOutside,
|
|
1194
|
-
isDisabled
|
|
1399
|
+
isDisabled,
|
|
1400
|
+
onInteractOutsideStart
|
|
1195
1401
|
} = props;
|
|
1196
1402
|
let stateRef = useRef({
|
|
1197
1403
|
isPointerDown: false,
|
|
1198
|
-
ignoreEmulatedMouseEvents: false
|
|
1404
|
+
ignoreEmulatedMouseEvents: false,
|
|
1405
|
+
onInteractOutside,
|
|
1406
|
+
onInteractOutsideStart
|
|
1199
1407
|
});
|
|
1200
1408
|
let state = stateRef.current;
|
|
1409
|
+
state.onInteractOutside = onInteractOutside;
|
|
1410
|
+
state.onInteractOutsideStart = onInteractOutsideStart;
|
|
1201
1411
|
useEffect(() => {
|
|
1412
|
+
if (isDisabled) {
|
|
1413
|
+
return;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1202
1416
|
let onPointerDown = e => {
|
|
1203
|
-
if (
|
|
1204
|
-
|
|
1205
|
-
|
|
1417
|
+
if ($e415bb64ab27cb8fbfac2f417412022f$var$isValidEvent(e, ref) && state.onInteractOutside) {
|
|
1418
|
+
if (state.onInteractOutsideStart) {
|
|
1419
|
+
state.onInteractOutsideStart(e);
|
|
1420
|
+
}
|
|
1206
1421
|
|
|
1207
|
-
if ($e415bb64ab27cb8fbfac2f417412022f$var$isValidEvent(e, ref)) {
|
|
1208
1422
|
state.isPointerDown = true;
|
|
1209
1423
|
}
|
|
1210
|
-
};
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
// once it's fixed we can uncomment
|
|
1214
|
-
// Use pointer events if available. Otherwise, fall back to mouse and touch events.
|
|
1424
|
+
}; // Use pointer events if available. Otherwise, fall back to mouse and touch events.
|
|
1425
|
+
|
|
1426
|
+
|
|
1215
1427
|
if (typeof PointerEvent !== 'undefined') {
|
|
1216
|
-
let onPointerUp =
|
|
1217
|
-
if (state.isPointerDown && onInteractOutside && isValidEvent(e, ref)) {
|
|
1428
|
+
let onPointerUp = e => {
|
|
1429
|
+
if (state.isPointerDown && state.onInteractOutside && $e415bb64ab27cb8fbfac2f417412022f$var$isValidEvent(e, ref)) {
|
|
1218
1430
|
state.isPointerDown = false;
|
|
1219
|
-
onInteractOutside(e);
|
|
1431
|
+
state.onInteractOutside(e);
|
|
1220
1432
|
}
|
|
1221
|
-
};
|
|
1222
|
-
|
|
1433
|
+
}; // changing these to capture phase fixed combobox
|
|
1434
|
+
|
|
1435
|
+
|
|
1223
1436
|
document.addEventListener('pointerdown', onPointerDown, true);
|
|
1224
1437
|
document.addEventListener('pointerup', onPointerUp, true);
|
|
1225
|
-
|
|
1438
|
+
return () => {
|
|
1226
1439
|
document.removeEventListener('pointerdown', onPointerDown, true);
|
|
1227
1440
|
document.removeEventListener('pointerup', onPointerUp, true);
|
|
1228
1441
|
};
|
|
1229
|
-
} else {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
state.ignoreEmulatedMouseEvents = false;
|
|
1239
|
-
} else if (state.isPointerDown && onInteractOutside && $e415bb64ab27cb8fbfac2f417412022f$var$isValidEvent(e, ref)) {
|
|
1240
|
-
state.isPointerDown = false;
|
|
1241
|
-
onInteractOutside(e);
|
|
1242
|
-
}
|
|
1243
|
-
};
|
|
1244
|
-
|
|
1245
|
-
let onTouchEnd = e => {
|
|
1246
|
-
if (isDisabled) {
|
|
1247
|
-
return;
|
|
1248
|
-
}
|
|
1442
|
+
} else {
|
|
1443
|
+
let onMouseUp = e => {
|
|
1444
|
+
if (state.ignoreEmulatedMouseEvents) {
|
|
1445
|
+
state.ignoreEmulatedMouseEvents = false;
|
|
1446
|
+
} else if (state.isPointerDown && state.onInteractOutside && $e415bb64ab27cb8fbfac2f417412022f$var$isValidEvent(e, ref)) {
|
|
1447
|
+
state.isPointerDown = false;
|
|
1448
|
+
state.onInteractOutside(e);
|
|
1449
|
+
}
|
|
1450
|
+
};
|
|
1249
1451
|
|
|
1250
|
-
|
|
1452
|
+
let onTouchEnd = e => {
|
|
1453
|
+
state.ignoreEmulatedMouseEvents = true;
|
|
1251
1454
|
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1455
|
+
if (state.onInteractOutside && state.isPointerDown && $e415bb64ab27cb8fbfac2f417412022f$var$isValidEvent(e, ref)) {
|
|
1456
|
+
state.isPointerDown = false;
|
|
1457
|
+
state.onInteractOutside(e);
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1257
1460
|
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1461
|
+
document.addEventListener('mousedown', onPointerDown, true);
|
|
1462
|
+
document.addEventListener('mouseup', onMouseUp, true);
|
|
1463
|
+
document.addEventListener('touchstart', onPointerDown, true);
|
|
1464
|
+
document.addEventListener('touchend', onTouchEnd, true);
|
|
1465
|
+
return () => {
|
|
1466
|
+
document.removeEventListener('mousedown', onPointerDown, true);
|
|
1467
|
+
document.removeEventListener('mouseup', onMouseUp, true);
|
|
1468
|
+
document.removeEventListener('touchstart', onPointerDown, true);
|
|
1469
|
+
document.removeEventListener('touchend', onTouchEnd, true);
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1472
|
+
}, [ref, state, isDisabled]);
|
|
1269
1473
|
}
|
|
1270
1474
|
|
|
1271
1475
|
function $e415bb64ab27cb8fbfac2f417412022f$var$isValidEvent(event, ref) {
|
|
@@ -1601,17 +1805,93 @@ export function useScrollWheel(props, ref) {
|
|
|
1601
1805
|
});
|
|
1602
1806
|
}
|
|
1603
1807
|
}, [onScroll]);
|
|
1604
|
-
|
|
1605
|
-
|
|
1808
|
+
useEvent(ref, 'wheel', isDisabled ? null : onScrollHandler);
|
|
1809
|
+
}
|
|
1810
|
+
const $cd8e0096d064b4c36af8a188dfbda75c$var$DEFAULT_THRESHOLD = 500;
|
|
1811
|
+
/**
|
|
1812
|
+
* Handles long press interactions across mouse and touch devices. Supports a customizable time threshold,
|
|
1813
|
+
* accessibility description, and normalizes behavior across browsers and devices.
|
|
1814
|
+
*/
|
|
1606
1815
|
|
|
1607
|
-
|
|
1608
|
-
|
|
1816
|
+
export function useLongPress(props) {
|
|
1817
|
+
let {
|
|
1818
|
+
isDisabled,
|
|
1819
|
+
onLongPressStart,
|
|
1820
|
+
onLongPressEnd,
|
|
1821
|
+
onLongPress,
|
|
1822
|
+
threshold = $cd8e0096d064b4c36af8a188dfbda75c$var$DEFAULT_THRESHOLD,
|
|
1823
|
+
accessibilityDescription
|
|
1824
|
+
} = props;
|
|
1825
|
+
const timeRef = useRef(null);
|
|
1826
|
+
let {
|
|
1827
|
+
addGlobalListener,
|
|
1828
|
+
removeGlobalListener
|
|
1829
|
+
} = useGlobalListeners();
|
|
1830
|
+
let {
|
|
1831
|
+
pressProps
|
|
1832
|
+
} = usePress({
|
|
1833
|
+
isDisabled,
|
|
1834
|
+
|
|
1835
|
+
onPressStart(e) {
|
|
1836
|
+
if (e.pointerType === 'mouse' || e.pointerType === 'touch') {
|
|
1837
|
+
if (onLongPressStart) {
|
|
1838
|
+
onLongPressStart(_babelRuntimeHelpersEsmExtends({}, e, {
|
|
1839
|
+
type: 'longpressstart'
|
|
1840
|
+
}));
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
timeRef.current = setTimeout(() => {
|
|
1844
|
+
// Prevent other usePress handlers from also handling this event.
|
|
1845
|
+
e.target.dispatchEvent(new PointerEvent('pointercancel', {
|
|
1846
|
+
bubbles: true
|
|
1847
|
+
}));
|
|
1848
|
+
|
|
1849
|
+
if (onLongPress) {
|
|
1850
|
+
onLongPress(_babelRuntimeHelpersEsmExtends({}, e, {
|
|
1851
|
+
type: 'longpress'
|
|
1852
|
+
}));
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
timeRef.current = null;
|
|
1856
|
+
}, threshold); // Prevent context menu, which may be opened on long press on touch devices
|
|
1857
|
+
|
|
1858
|
+
if (e.pointerType === 'touch') {
|
|
1859
|
+
let onContextMenu = e => {
|
|
1860
|
+
e.preventDefault();
|
|
1861
|
+
};
|
|
1862
|
+
|
|
1863
|
+
addGlobalListener(e.target, 'contextmenu', onContextMenu, {
|
|
1864
|
+
once: true
|
|
1865
|
+
});
|
|
1866
|
+
addGlobalListener(window, 'pointerup', () => {
|
|
1867
|
+
// If no contextmenu event is fired quickly after pointerup, remove the handler
|
|
1868
|
+
// so future context menu events outside a long press are not prevented.
|
|
1869
|
+
setTimeout(() => {
|
|
1870
|
+
removeGlobalListener(e.target, 'contextmenu', onContextMenu);
|
|
1871
|
+
}, 30);
|
|
1872
|
+
}, {
|
|
1873
|
+
once: true
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
},
|
|
1878
|
+
|
|
1879
|
+
onPressEnd(e) {
|
|
1880
|
+
if (timeRef.current) {
|
|
1881
|
+
clearTimeout(timeRef.current);
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
if (onLongPressEnd && (e.pointerType === 'mouse' || e.pointerType === 'touch')) {
|
|
1885
|
+
onLongPressEnd(_babelRuntimeHelpersEsmExtends({}, e, {
|
|
1886
|
+
type: 'longpressend'
|
|
1887
|
+
}));
|
|
1888
|
+
}
|
|
1609
1889
|
}
|
|
1610
1890
|
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
}
|
|
1891
|
+
});
|
|
1892
|
+
let descriptionProps = useDescription(onLongPress && !isDisabled ? accessibilityDescription : null);
|
|
1893
|
+
return {
|
|
1894
|
+
longPressProps: mergeProps(pressProps, descriptionProps)
|
|
1895
|
+
};
|
|
1616
1896
|
}
|
|
1617
1897
|
//# sourceMappingURL=module.js.map
|