@react-aria/selection 3.14.0 → 3.15.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/import.mjs +70 -18
- package/dist/main.js +69 -17
- package/dist/main.js.map +1 -1
- package/dist/module.js +70 -18
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +11 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/ListKeyboardDelegate.ts +93 -17
- package/src/useSelectableCollection.ts +6 -0
- package/src/useTypeSelect.ts +1 -1
|
@@ -10,20 +10,42 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {Collection, KeyboardDelegate, Node} from '@react-types/shared';
|
|
13
|
+
import {Collection, Direction, KeyboardDelegate, Node, Orientation} from '@react-types/shared';
|
|
14
|
+
import {isScrollable} from '@react-aria/utils';
|
|
14
15
|
import {Key, RefObject} from 'react';
|
|
15
16
|
|
|
17
|
+
interface ListKeyboardDelegateOptions<T> {
|
|
18
|
+
collection: Collection<Node<T>>,
|
|
19
|
+
ref: RefObject<HTMLElement>,
|
|
20
|
+
orientation?: Orientation,
|
|
21
|
+
direction?: Direction,
|
|
22
|
+
disabledKeys?: Set<Key>
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
export class ListKeyboardDelegate<T> implements KeyboardDelegate {
|
|
17
26
|
private collection: Collection<Node<T>>;
|
|
18
27
|
private disabledKeys: Set<Key>;
|
|
19
28
|
private ref: RefObject<HTMLElement>;
|
|
20
29
|
private collator: Intl.Collator;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
private orientation?: Orientation;
|
|
31
|
+
private direction?: Direction;
|
|
32
|
+
|
|
33
|
+
constructor(collection: Collection<Node<T>>, disabledKeys: Set<Key>, ref: RefObject<HTMLElement>, collator?: Intl.Collator);
|
|
34
|
+
constructor(options: ListKeyboardDelegateOptions<T>);
|
|
35
|
+
constructor(...args: any[]) {
|
|
36
|
+
if (args.length === 1) {
|
|
37
|
+
let opts = args[0] as ListKeyboardDelegateOptions<T>;
|
|
38
|
+
this.collection = opts.collection;
|
|
39
|
+
this.ref = opts.ref;
|
|
40
|
+
this.disabledKeys = opts.disabledKeys || new Set();
|
|
41
|
+
this.orientation = opts.orientation;
|
|
42
|
+
this.direction = opts.direction;
|
|
43
|
+
} else {
|
|
44
|
+
this.collection = args[0];
|
|
45
|
+
this.disabledKeys = args[1];
|
|
46
|
+
this.ref = args[2];
|
|
47
|
+
this.collator = args[3];
|
|
48
|
+
}
|
|
27
49
|
}
|
|
28
50
|
|
|
29
51
|
getKeyBelow(key: Key) {
|
|
@@ -54,6 +76,22 @@ export class ListKeyboardDelegate<T> implements KeyboardDelegate {
|
|
|
54
76
|
return null;
|
|
55
77
|
}
|
|
56
78
|
|
|
79
|
+
getKeyRightOf(key: Key) {
|
|
80
|
+
if (this.orientation === 'horizontal') {
|
|
81
|
+
return this.direction === 'rtl' ? this.getKeyAbove(key) : this.getKeyBelow(key);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
getKeyLeftOf(key: Key) {
|
|
88
|
+
if (this.orientation === 'horizontal') {
|
|
89
|
+
return this.direction === 'rtl' ? this.getKeyBelow(key) : this.getKeyAbove(key);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
57
95
|
getFirstKey() {
|
|
58
96
|
let key = this.collection.getFirstKey();
|
|
59
97
|
while (key != null) {
|
|
@@ -93,14 +131,33 @@ export class ListKeyboardDelegate<T> implements KeyboardDelegate {
|
|
|
93
131
|
return null;
|
|
94
132
|
}
|
|
95
133
|
|
|
96
|
-
|
|
134
|
+
if (!isScrollable(menu)) {
|
|
135
|
+
return this.getFirstKey();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
let containerRect = menu.getBoundingClientRect();
|
|
139
|
+
let itemRect = item.getBoundingClientRect();
|
|
140
|
+
if (this.orientation === 'horizontal') {
|
|
141
|
+
let containerX = containerRect.x - menu.scrollLeft;
|
|
142
|
+
let pageX = Math.max(0, (itemRect.x - containerX) + itemRect.width - containerRect.width);
|
|
97
143
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
144
|
+
while (item && (itemRect.x - containerX) > pageX) {
|
|
145
|
+
key = this.getKeyAbove(key);
|
|
146
|
+
item = key == null ? null : this.getItem(key);
|
|
147
|
+
itemRect = item?.getBoundingClientRect();
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
let containerY = containerRect.y - menu.scrollTop;
|
|
151
|
+
let pageY = Math.max(0, (itemRect.y - containerY) + itemRect.height - containerRect.height);
|
|
152
|
+
|
|
153
|
+
while (item && (itemRect.y - containerY) > pageY) {
|
|
154
|
+
key = this.getKeyAbove(key);
|
|
155
|
+
item = key == null ? null : this.getItem(key);
|
|
156
|
+
itemRect = item?.getBoundingClientRect();
|
|
157
|
+
}
|
|
101
158
|
}
|
|
102
159
|
|
|
103
|
-
return key;
|
|
160
|
+
return key ?? this.getFirstKey();
|
|
104
161
|
}
|
|
105
162
|
|
|
106
163
|
getKeyPageBelow(key: Key) {
|
|
@@ -110,14 +167,33 @@ export class ListKeyboardDelegate<T> implements KeyboardDelegate {
|
|
|
110
167
|
return null;
|
|
111
168
|
}
|
|
112
169
|
|
|
113
|
-
|
|
170
|
+
if (!isScrollable(menu)) {
|
|
171
|
+
return this.getLastKey();
|
|
172
|
+
}
|
|
114
173
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
174
|
+
let containerRect = menu.getBoundingClientRect();
|
|
175
|
+
let itemRect = item.getBoundingClientRect();
|
|
176
|
+
if (this.orientation === 'horizontal') {
|
|
177
|
+
let containerX = containerRect.x - menu.scrollLeft;
|
|
178
|
+
let pageX = Math.min(menu.scrollWidth, (itemRect.x - containerX) - itemRect.width + containerRect.width);
|
|
179
|
+
|
|
180
|
+
while (item && (itemRect.x - containerX) < pageX) {
|
|
181
|
+
key = this.getKeyBelow(key);
|
|
182
|
+
item = key == null ? null : this.getItem(key);
|
|
183
|
+
itemRect = item?.getBoundingClientRect();
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
let containerY = containerRect.y - menu.scrollTop;
|
|
187
|
+
let pageY = Math.min(menu.scrollHeight, (itemRect.y - containerY) - itemRect.height + containerRect.height);
|
|
188
|
+
|
|
189
|
+
while (item && (itemRect.y - containerY) < pageY) {
|
|
190
|
+
key = this.getKeyBelow(key);
|
|
191
|
+
item = key == null ? null : this.getItem(key);
|
|
192
|
+
itemRect = item?.getBoundingClientRect();
|
|
193
|
+
}
|
|
118
194
|
}
|
|
119
195
|
|
|
120
|
-
return key;
|
|
196
|
+
return key ?? this.getLastKey();
|
|
121
197
|
}
|
|
122
198
|
|
|
123
199
|
getKeyForSearch(search: string, fromKey?: Key) {
|
|
@@ -165,6 +165,9 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
|
|
|
165
165
|
if (delegate.getKeyLeftOf) {
|
|
166
166
|
e.preventDefault();
|
|
167
167
|
let nextKey = delegate.getKeyLeftOf(manager.focusedKey);
|
|
168
|
+
if (nextKey == null && shouldFocusWrap) {
|
|
169
|
+
nextKey = direction === 'rtl' ? delegate.getFirstKey?.(manager.focusedKey) : delegate.getLastKey?.(manager.focusedKey);
|
|
170
|
+
}
|
|
168
171
|
navigateToKey(nextKey, direction === 'rtl' ? 'first' : 'last');
|
|
169
172
|
}
|
|
170
173
|
break;
|
|
@@ -173,6 +176,9 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
|
|
|
173
176
|
if (delegate.getKeyRightOf) {
|
|
174
177
|
e.preventDefault();
|
|
175
178
|
let nextKey = delegate.getKeyRightOf(manager.focusedKey);
|
|
179
|
+
if (nextKey == null && shouldFocusWrap) {
|
|
180
|
+
nextKey = direction === 'rtl' ? delegate.getLastKey?.(manager.focusedKey) : delegate.getFirstKey?.(manager.focusedKey);
|
|
181
|
+
}
|
|
176
182
|
navigateToKey(nextKey, direction === 'rtl' ? 'last' : 'first');
|
|
177
183
|
}
|
|
178
184
|
break;
|
package/src/useTypeSelect.ts
CHANGED
|
@@ -53,7 +53,7 @@ export function useTypeSelect(options: AriaTypeSelectOptions): TypeSelectAria {
|
|
|
53
53
|
|
|
54
54
|
let onKeyDown = (e: KeyboardEvent) => {
|
|
55
55
|
let character = getStringForKey(e.key);
|
|
56
|
-
if (!character || e.ctrlKey || e.metaKey) {
|
|
56
|
+
if (!character || e.ctrlKey || e.metaKey || !e.currentTarget.contains(e.target as HTMLElement)) {
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
|