@react-aria/selection 3.23.1 → 3.24.1
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/ListKeyboardDelegate.main.js.map +1 -1
- package/dist/ListKeyboardDelegate.module.js.map +1 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/useSelectableCollection.main.js +12 -3
- package/dist/useSelectableCollection.main.js.map +1 -1
- package/dist/useSelectableCollection.mjs +12 -3
- package/dist/useSelectableCollection.module.js +12 -3
- package/dist/useSelectableCollection.module.js.map +1 -1
- package/dist/useSelectableItem.main.js +4 -2
- package/dist/useSelectableItem.main.js.map +1 -1
- package/dist/useSelectableItem.mjs +4 -2
- package/dist/useSelectableItem.module.js +4 -2
- package/dist/useSelectableItem.module.js.map +1 -1
- package/dist/utils.main.js.map +1 -1
- package/dist/utils.module.js.map +1 -1
- package/package.json +8 -8
- package/src/ListKeyboardDelegate.ts +11 -11
- package/src/useSelectableCollection.ts +25 -2
- package/src/useSelectableItem.ts +3 -3
- package/src/utils.ts +5 -5
|
@@ -54,6 +54,11 @@ export interface AriaSelectableCollectionOptions {
|
|
|
54
54
|
* @default false
|
|
55
55
|
*/
|
|
56
56
|
disallowSelectAll?: boolean,
|
|
57
|
+
/**
|
|
58
|
+
* Whether pressing the Escape should clear selection in the collection or not.
|
|
59
|
+
* @default 'clearSelection'
|
|
60
|
+
*/
|
|
61
|
+
escapeKeyBehavior?: 'clearSelection' | 'none',
|
|
57
62
|
/**
|
|
58
63
|
* Whether selection should occur automatically on focus.
|
|
59
64
|
* @default false
|
|
@@ -108,6 +113,7 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
|
|
|
108
113
|
shouldFocusWrap = false,
|
|
109
114
|
disallowEmptySelection = false,
|
|
110
115
|
disallowSelectAll = false,
|
|
116
|
+
escapeKeyBehavior = 'clearSelection',
|
|
111
117
|
selectOnFocus = manager.selectionBehavior === 'replace',
|
|
112
118
|
disallowTypeAhead = false,
|
|
113
119
|
shouldUseVirtualFocus,
|
|
@@ -279,7 +285,7 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
|
|
|
279
285
|
}
|
|
280
286
|
break;
|
|
281
287
|
case 'Escape':
|
|
282
|
-
if (!disallowEmptySelection && manager.selectedKeys.size !== 0) {
|
|
288
|
+
if (escapeKeyBehavior === 'clearSelection' && !disallowEmptySelection && manager.selectedKeys.size !== 0) {
|
|
283
289
|
e.stopPropagation();
|
|
284
290
|
e.preventDefault();
|
|
285
291
|
manager.clearSelection();
|
|
@@ -499,6 +505,7 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
|
|
|
499
505
|
|
|
500
506
|
// Scroll the focused element into view when the focusedKey changes.
|
|
501
507
|
let lastFocusedKey = useRef(manager.focusedKey);
|
|
508
|
+
let raf = useRef<number | null>(null);
|
|
502
509
|
useEffect(() => {
|
|
503
510
|
if (manager.isFocused && manager.focusedKey != null && (manager.focusedKey !== lastFocusedKey.current || didAutoFocusRef.current) && scrollRef.current && ref.current) {
|
|
504
511
|
let modality = getInteractionModality();
|
|
@@ -510,8 +517,16 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
|
|
|
510
517
|
}
|
|
511
518
|
|
|
512
519
|
if (modality === 'keyboard' || didAutoFocusRef.current) {
|
|
513
|
-
scrollIntoView(scrollRef.current, element);
|
|
514
520
|
|
|
521
|
+
if (raf.current) {
|
|
522
|
+
cancelAnimationFrame(raf.current);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
raf.current = requestAnimationFrame(() => {
|
|
526
|
+
if (scrollRef.current) {
|
|
527
|
+
scrollIntoView(scrollRef.current, element);
|
|
528
|
+
}
|
|
529
|
+
});
|
|
515
530
|
// Avoid scroll in iOS VO, since it may cause overlay to close (i.e. RAC submenu)
|
|
516
531
|
if (modality !== 'virtual') {
|
|
517
532
|
scrollIntoViewport(element, {containingElement: ref.current});
|
|
@@ -528,6 +543,14 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
|
|
|
528
543
|
didAutoFocusRef.current = false;
|
|
529
544
|
});
|
|
530
545
|
|
|
546
|
+
useEffect(() => {
|
|
547
|
+
return () => {
|
|
548
|
+
if (raf.current) {
|
|
549
|
+
cancelAnimationFrame(raf.current);
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
}, []);
|
|
553
|
+
|
|
531
554
|
// Intercept FocusScope restoration since virtualized collections can reuse DOM nodes.
|
|
532
555
|
useEvent(ref, 'react-aria-focus-scope-restore', e => {
|
|
533
556
|
e.preventDefault();
|
package/src/useSelectableItem.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import {DOMAttributes, DOMProps, FocusableElement, Key, LongPressEvent, PointerType, PressEvent, RefObject} from '@react-types/shared';
|
|
14
|
-
import {focusSafely,
|
|
14
|
+
import {focusSafely, PressHookProps, useLongPress, usePress} from '@react-aria/interactions';
|
|
15
15
|
import {getCollectionId, isNonContiguousSelectionModifier} from './utils';
|
|
16
16
|
import {isCtrlKeyPressed, mergeProps, openLink, useId, useRouter} from '@react-aria/utils';
|
|
17
17
|
import {moveVirtualFocus} from '@react-aria/focus';
|
|
@@ -239,7 +239,7 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
|
|
|
239
239
|
// we want to be able to have the pointer down on the trigger that opens the menu and
|
|
240
240
|
// the pointer up on the menu item rather than requiring a separate press.
|
|
241
241
|
// For keyboard events, selection still occurs on key down.
|
|
242
|
-
let itemPressProps:
|
|
242
|
+
let itemPressProps: PressHookProps = {ref};
|
|
243
243
|
if (shouldSelectOnPressUp) {
|
|
244
244
|
itemPressProps.onPressStart = (e) => {
|
|
245
245
|
modality.current = e.pointerType;
|
|
@@ -382,7 +382,7 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
|
|
|
382
382
|
return {
|
|
383
383
|
itemProps: mergeProps(
|
|
384
384
|
itemProps,
|
|
385
|
-
allowsSelection || hasPrimaryAction || shouldUseVirtualFocus ? pressProps : {},
|
|
385
|
+
allowsSelection || hasPrimaryAction || (shouldUseVirtualFocus && !isDisabled) ? pressProps : {},
|
|
386
386
|
longPressEnabled ? longPressProps : {},
|
|
387
387
|
{onDoubleClick, onDragStartCapture, onClick, id},
|
|
388
388
|
// Prevent DOM focus from moving on mouse down when using virtual focus
|
package/src/utils.ts
CHANGED
|
@@ -20,13 +20,13 @@ interface Event {
|
|
|
20
20
|
metaKey: boolean
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export function isNonContiguousSelectionModifier(e: Event) {
|
|
23
|
+
export function isNonContiguousSelectionModifier(e: Event): boolean {
|
|
24
24
|
// Ctrl + Arrow Up/Arrow Down has a system wide meaning on macOS, so use Alt instead.
|
|
25
25
|
// On Windows and Ubuntu, Alt + Space has a system wide meaning.
|
|
26
26
|
return isAppleDevice() ? e.altKey : e.ctrlKey;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export function getItemElement(collectionRef: RefObject<HTMLElement | null>, key: Key) {
|
|
29
|
+
export function getItemElement(collectionRef: RefObject<HTMLElement | null>, key: Key): Element | null | undefined {
|
|
30
30
|
let selector = `[data-key="${CSS.escape(String(key))}"]`;
|
|
31
31
|
let collection = collectionRef.current?.dataset.collection;
|
|
32
32
|
if (collection) {
|
|
@@ -35,13 +35,13 @@ export function getItemElement(collectionRef: RefObject<HTMLElement | null>, key
|
|
|
35
35
|
return collectionRef.current?.querySelector(selector);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const collectionMap = new WeakMap();
|
|
39
|
-
export function useCollectionId(collection: Collection<any>) {
|
|
38
|
+
const collectionMap = new WeakMap<Collection<any>, string>();
|
|
39
|
+
export function useCollectionId(collection: Collection<any>): string {
|
|
40
40
|
let id = useId();
|
|
41
41
|
collectionMap.set(collection, id);
|
|
42
42
|
return id;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export function getCollectionId(collection: Collection<any>) {
|
|
45
|
+
export function getCollectionId(collection: Collection<any>): string {
|
|
46
46
|
return collectionMap.get(collection)!;
|
|
47
47
|
}
|