@react-aria/selection 3.4.1 → 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 +288 -168
- package/dist/main.js.map +1 -1
- package/dist/module.js +279 -166
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +19 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +9 -9
- package/src/useSelectableCollection.ts +160 -93
- package/src/useSelectableItem.ts +106 -15
- package/src/useSelectableList.ts +4 -43
- package/src/utils.ts +34 -0
package/dist/main.js
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
+
var {
|
|
2
|
+
useLongPress,
|
|
3
|
+
usePress
|
|
4
|
+
} = require("@react-aria/interactions");
|
|
5
|
+
|
|
1
6
|
var {
|
|
2
7
|
useLocale,
|
|
3
8
|
useCollator
|
|
4
9
|
} = require("@react-aria/i18n");
|
|
5
10
|
|
|
6
11
|
var {
|
|
7
|
-
|
|
8
|
-
mergeProps
|
|
12
|
+
focusWithoutScrolling,
|
|
13
|
+
mergeProps,
|
|
14
|
+
useEvent,
|
|
15
|
+
isAppleDevice,
|
|
16
|
+
isMac
|
|
9
17
|
} = require("@react-aria/utils");
|
|
10
18
|
|
|
11
19
|
var {
|
|
@@ -25,6 +33,20 @@ function $parcel$interopDefault(a) {
|
|
|
25
33
|
return a && a.__esModule ? a.default : a;
|
|
26
34
|
}
|
|
27
35
|
|
|
36
|
+
function $d220314dfe032b5c2a0f0c46ec981e5$export$isNonContiguousSelectionModifier(e) {
|
|
37
|
+
// Ctrl + Arrow Up/Arrow Down has a system wide meaning on macOS, so use Alt instead.
|
|
38
|
+
// On Windows and Ubuntu, Alt + Space has a system wide meaning.
|
|
39
|
+
return isAppleDevice() ? e.altKey : e.ctrlKey;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function $d220314dfe032b5c2a0f0c46ec981e5$export$isCtrlKeyPressed(e) {
|
|
43
|
+
if (isMac()) {
|
|
44
|
+
return e.metaKey;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return e.ctrlKey;
|
|
48
|
+
}
|
|
49
|
+
|
|
28
50
|
/**
|
|
29
51
|
* Handles typeahead interactions with collections.
|
|
30
52
|
*/
|
|
@@ -104,14 +126,6 @@ function $c2e740eb44846c887b3b88306c61$var$getStringForKey(key) {
|
|
|
104
126
|
return '';
|
|
105
127
|
}
|
|
106
128
|
|
|
107
|
-
function $f791fefd7189e0e4d903034fb2925$var$isCtrlKeyPressed(e) {
|
|
108
|
-
if (isMac()) {
|
|
109
|
-
return e.metaKey;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return e.ctrlKey;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
129
|
/**
|
|
116
130
|
* Handles interactions with selectable collections.
|
|
117
131
|
*/
|
|
@@ -124,48 +138,54 @@ function useSelectableCollection(options) {
|
|
|
124
138
|
shouldFocusWrap = false,
|
|
125
139
|
disallowEmptySelection = false,
|
|
126
140
|
disallowSelectAll = false,
|
|
127
|
-
selectOnFocus =
|
|
141
|
+
selectOnFocus = manager.selectionBehavior === 'replace',
|
|
128
142
|
disallowTypeAhead = false,
|
|
129
143
|
shouldUseVirtualFocus,
|
|
130
|
-
allowsTabNavigation = false
|
|
144
|
+
allowsTabNavigation = false,
|
|
145
|
+
isVirtualized,
|
|
146
|
+
// If no scrollRef is provided, assume the collection ref is the scrollable region
|
|
147
|
+
scrollRef = ref
|
|
131
148
|
} = options;
|
|
132
149
|
let {
|
|
133
150
|
direction
|
|
134
151
|
} = useLocale();
|
|
135
152
|
|
|
136
153
|
let onKeyDown = e => {
|
|
137
|
-
//
|
|
138
|
-
|
|
154
|
+
// Prevent option + tab from doing anything since it doesn't move focus to the cells, only buttons/checkboxes
|
|
155
|
+
if (e.altKey && e.key === 'Tab') {
|
|
156
|
+
e.preventDefault();
|
|
157
|
+
} // Keyboard events bubble through portals. Don't handle keyboard events
|
|
139
158
|
// for elements outside the collection (e.g. menus).
|
|
140
|
-
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
if (!ref.current.contains(e.target)) {
|
|
141
162
|
return;
|
|
142
163
|
}
|
|
143
164
|
|
|
165
|
+
const navigateToKey = (key, childFocus) => {
|
|
166
|
+
if (key != null) {
|
|
167
|
+
manager.setFocusedKey(key, childFocus);
|
|
168
|
+
|
|
169
|
+
if (e.shiftKey && manager.selectionMode === 'multiple') {
|
|
170
|
+
manager.extendSelection(key);
|
|
171
|
+
} else if (selectOnFocus && !$d220314dfe032b5c2a0f0c46ec981e5$export$isNonContiguousSelectionModifier(e)) {
|
|
172
|
+
manager.replaceSelection(key);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
144
177
|
switch (e.key) {
|
|
145
178
|
case 'ArrowDown':
|
|
146
179
|
{
|
|
147
180
|
if (delegate.getKeyBelow) {
|
|
148
181
|
e.preventDefault();
|
|
149
|
-
let nextKey = manager.focusedKey != null ? delegate.getKeyBelow(manager.focusedKey) : delegate.getFirstKey();
|
|
150
|
-
|
|
151
|
-
if (nextKey != null) {
|
|
152
|
-
manager.setFocusedKey(nextKey);
|
|
182
|
+
let nextKey = manager.focusedKey != null ? delegate.getKeyBelow(manager.focusedKey) : delegate.getFirstKey == null ? void 0 : delegate.getFirstKey();
|
|
153
183
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
} else if (shouldFocusWrap) {
|
|
158
|
-
let wrapKey = delegate.getFirstKey(manager.focusedKey);
|
|
159
|
-
manager.setFocusedKey(wrapKey);
|
|
160
|
-
|
|
161
|
-
if (manager.selectionMode === 'single' && selectOnFocus) {
|
|
162
|
-
manager.replaceSelection(wrapKey);
|
|
163
|
-
}
|
|
184
|
+
if (nextKey == null && shouldFocusWrap) {
|
|
185
|
+
nextKey = delegate.getFirstKey == null ? void 0 : delegate.getFirstKey(manager.focusedKey);
|
|
164
186
|
}
|
|
165
187
|
|
|
166
|
-
|
|
167
|
-
manager.extendSelection(nextKey);
|
|
168
|
-
}
|
|
188
|
+
navigateToKey(nextKey);
|
|
169
189
|
}
|
|
170
190
|
|
|
171
191
|
break;
|
|
@@ -175,26 +195,13 @@ function useSelectableCollection(options) {
|
|
|
175
195
|
{
|
|
176
196
|
if (delegate.getKeyAbove) {
|
|
177
197
|
e.preventDefault();
|
|
178
|
-
let nextKey = manager.focusedKey != null ? delegate.getKeyAbove(manager.focusedKey) : delegate.getLastKey();
|
|
179
|
-
|
|
180
|
-
if (nextKey != null) {
|
|
181
|
-
manager.setFocusedKey(nextKey);
|
|
182
|
-
|
|
183
|
-
if (manager.selectionMode === 'single' && selectOnFocus) {
|
|
184
|
-
manager.replaceSelection(nextKey);
|
|
185
|
-
}
|
|
186
|
-
} else if (shouldFocusWrap) {
|
|
187
|
-
let wrapKey = delegate.getLastKey(manager.focusedKey);
|
|
188
|
-
manager.setFocusedKey(wrapKey);
|
|
198
|
+
let nextKey = manager.focusedKey != null ? delegate.getKeyAbove(manager.focusedKey) : delegate.getLastKey == null ? void 0 : delegate.getLastKey();
|
|
189
199
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
200
|
+
if (nextKey == null && shouldFocusWrap) {
|
|
201
|
+
nextKey = delegate.getLastKey == null ? void 0 : delegate.getLastKey(manager.focusedKey);
|
|
193
202
|
}
|
|
194
203
|
|
|
195
|
-
|
|
196
|
-
manager.extendSelection(nextKey);
|
|
197
|
-
}
|
|
204
|
+
navigateToKey(nextKey);
|
|
198
205
|
}
|
|
199
206
|
|
|
200
207
|
break;
|
|
@@ -205,18 +212,7 @@ function useSelectableCollection(options) {
|
|
|
205
212
|
if (delegate.getKeyLeftOf) {
|
|
206
213
|
e.preventDefault();
|
|
207
214
|
let nextKey = delegate.getKeyLeftOf(manager.focusedKey);
|
|
208
|
-
|
|
209
|
-
if (nextKey != null) {
|
|
210
|
-
manager.setFocusedKey(nextKey, direction === 'rtl' ? 'first' : 'last');
|
|
211
|
-
|
|
212
|
-
if (manager.selectionMode === 'single' && selectOnFocus) {
|
|
213
|
-
manager.replaceSelection(nextKey);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (e.shiftKey && manager.selectionMode === 'multiple') {
|
|
218
|
-
manager.extendSelection(nextKey);
|
|
219
|
-
}
|
|
215
|
+
navigateToKey(nextKey, direction === 'rtl' ? 'first' : 'last');
|
|
220
216
|
}
|
|
221
217
|
|
|
222
218
|
break;
|
|
@@ -227,18 +223,7 @@ function useSelectableCollection(options) {
|
|
|
227
223
|
if (delegate.getKeyRightOf) {
|
|
228
224
|
e.preventDefault();
|
|
229
225
|
let nextKey = delegate.getKeyRightOf(manager.focusedKey);
|
|
230
|
-
|
|
231
|
-
if (nextKey != null) {
|
|
232
|
-
manager.setFocusedKey(nextKey, direction === 'rtl' ? 'last' : 'first');
|
|
233
|
-
|
|
234
|
-
if (manager.selectionMode === 'single' && selectOnFocus) {
|
|
235
|
-
manager.replaceSelection(nextKey);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (e.shiftKey && manager.selectionMode === 'multiple') {
|
|
240
|
-
manager.extendSelection(nextKey);
|
|
241
|
-
}
|
|
226
|
+
navigateToKey(nextKey, direction === 'rtl' ? 'last' : 'first');
|
|
242
227
|
}
|
|
243
228
|
|
|
244
229
|
break;
|
|
@@ -247,15 +232,13 @@ function useSelectableCollection(options) {
|
|
|
247
232
|
case 'Home':
|
|
248
233
|
if (delegate.getFirstKey) {
|
|
249
234
|
e.preventDefault();
|
|
250
|
-
let firstKey = delegate.getFirstKey(manager.focusedKey, $
|
|
235
|
+
let firstKey = delegate.getFirstKey(manager.focusedKey, $d220314dfe032b5c2a0f0c46ec981e5$export$isCtrlKeyPressed(e));
|
|
251
236
|
manager.setFocusedKey(firstKey);
|
|
252
237
|
|
|
253
|
-
if (manager.selectionMode === '
|
|
254
|
-
manager.replaceSelection(firstKey);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if ($f791fefd7189e0e4d903034fb2925$var$isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {
|
|
238
|
+
if ($d220314dfe032b5c2a0f0c46ec981e5$export$isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {
|
|
258
239
|
manager.extendSelection(firstKey);
|
|
240
|
+
} else if (selectOnFocus) {
|
|
241
|
+
manager.replaceSelection(firstKey);
|
|
259
242
|
}
|
|
260
243
|
}
|
|
261
244
|
|
|
@@ -264,15 +247,13 @@ function useSelectableCollection(options) {
|
|
|
264
247
|
case 'End':
|
|
265
248
|
if (delegate.getLastKey) {
|
|
266
249
|
e.preventDefault();
|
|
267
|
-
let lastKey = delegate.getLastKey(manager.focusedKey, $
|
|
250
|
+
let lastKey = delegate.getLastKey(manager.focusedKey, $d220314dfe032b5c2a0f0c46ec981e5$export$isCtrlKeyPressed(e));
|
|
268
251
|
manager.setFocusedKey(lastKey);
|
|
269
252
|
|
|
270
|
-
if (manager.selectionMode === '
|
|
271
|
-
manager.replaceSelection(lastKey);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if ($f791fefd7189e0e4d903034fb2925$var$isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {
|
|
253
|
+
if ($d220314dfe032b5c2a0f0c46ec981e5$export$isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {
|
|
275
254
|
manager.extendSelection(lastKey);
|
|
255
|
+
} else if (selectOnFocus) {
|
|
256
|
+
manager.replaceSelection(lastKey);
|
|
276
257
|
}
|
|
277
258
|
}
|
|
278
259
|
|
|
@@ -282,14 +263,7 @@ function useSelectableCollection(options) {
|
|
|
282
263
|
if (delegate.getKeyPageBelow) {
|
|
283
264
|
e.preventDefault();
|
|
284
265
|
let nextKey = delegate.getKeyPageBelow(manager.focusedKey);
|
|
285
|
-
|
|
286
|
-
if (nextKey != null) {
|
|
287
|
-
manager.setFocusedKey(nextKey);
|
|
288
|
-
|
|
289
|
-
if (e.shiftKey && manager.selectionMode === 'multiple') {
|
|
290
|
-
manager.extendSelection(nextKey);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
266
|
+
navigateToKey(nextKey);
|
|
293
267
|
}
|
|
294
268
|
|
|
295
269
|
break;
|
|
@@ -298,20 +272,13 @@ function useSelectableCollection(options) {
|
|
|
298
272
|
if (delegate.getKeyPageAbove) {
|
|
299
273
|
e.preventDefault();
|
|
300
274
|
let nextKey = delegate.getKeyPageAbove(manager.focusedKey);
|
|
301
|
-
|
|
302
|
-
if (nextKey != null) {
|
|
303
|
-
manager.setFocusedKey(nextKey);
|
|
304
|
-
|
|
305
|
-
if (e.shiftKey && manager.selectionMode === 'multiple') {
|
|
306
|
-
manager.extendSelection(nextKey);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
275
|
+
navigateToKey(nextKey);
|
|
309
276
|
}
|
|
310
277
|
|
|
311
278
|
break;
|
|
312
279
|
|
|
313
280
|
case 'a':
|
|
314
|
-
if ($
|
|
281
|
+
if ($d220314dfe032b5c2a0f0c46ec981e5$export$isCtrlKeyPressed(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {
|
|
315
282
|
e.preventDefault();
|
|
316
283
|
manager.selectAll();
|
|
317
284
|
}
|
|
@@ -354,7 +321,7 @@ function useSelectableCollection(options) {
|
|
|
354
321
|
} while (last);
|
|
355
322
|
|
|
356
323
|
if (next && !next.contains(document.activeElement)) {
|
|
357
|
-
next
|
|
324
|
+
focusWithoutScrolling(next);
|
|
358
325
|
}
|
|
359
326
|
}
|
|
360
327
|
|
|
@@ -362,7 +329,19 @@ function useSelectableCollection(options) {
|
|
|
362
329
|
}
|
|
363
330
|
}
|
|
364
331
|
}
|
|
365
|
-
};
|
|
332
|
+
}; // Store the scroll position so we can restore it later.
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
let scrollPos = useRef({
|
|
336
|
+
top: 0,
|
|
337
|
+
left: 0
|
|
338
|
+
});
|
|
339
|
+
useEvent(scrollRef, 'scroll', isVirtualized ? null : () => {
|
|
340
|
+
scrollPos.current = {
|
|
341
|
+
top: scrollRef.current.scrollTop,
|
|
342
|
+
left: scrollRef.current.scrollLeft
|
|
343
|
+
};
|
|
344
|
+
});
|
|
366
345
|
|
|
367
346
|
let onFocus = e => {
|
|
368
347
|
if (manager.isFocused) {
|
|
@@ -382,19 +361,41 @@ function useSelectableCollection(options) {
|
|
|
382
361
|
manager.setFocused(true);
|
|
383
362
|
|
|
384
363
|
if (manager.focusedKey == null) {
|
|
385
|
-
|
|
364
|
+
let navigateToFirstKey = key => {
|
|
365
|
+
if (key != null) {
|
|
366
|
+
manager.setFocusedKey(key);
|
|
367
|
+
|
|
368
|
+
if (selectOnFocus) {
|
|
369
|
+
manager.replaceSelection(key);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}; // If the user hasn't yet interacted with the collection, there will be no focusedKey set.
|
|
386
373
|
// Attempt to detect whether the user is tabbing forward or backward into the collection
|
|
387
374
|
// and either focus the first or last item accordingly.
|
|
375
|
+
|
|
376
|
+
|
|
388
377
|
let relatedTarget = e.relatedTarget;
|
|
389
378
|
|
|
390
379
|
if (relatedTarget && e.currentTarget.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
391
380
|
var _manager$lastSelected;
|
|
392
381
|
|
|
393
|
-
|
|
382
|
+
navigateToFirstKey((_manager$lastSelected = manager.lastSelectedKey) != null ? _manager$lastSelected : delegate.getLastKey());
|
|
394
383
|
} else {
|
|
395
384
|
var _manager$firstSelecte;
|
|
396
385
|
|
|
397
|
-
|
|
386
|
+
navigateToFirstKey((_manager$firstSelecte = manager.firstSelectedKey) != null ? _manager$firstSelecte : delegate.getFirstKey());
|
|
387
|
+
}
|
|
388
|
+
} else if (!isVirtualized) {
|
|
389
|
+
// Restore the scroll position to what it was before.
|
|
390
|
+
scrollRef.current.scrollTop = scrollPos.current.top;
|
|
391
|
+
scrollRef.current.scrollLeft = scrollPos.current.left; // Refocus and scroll the focused item into view if it exists within the scrollable region.
|
|
392
|
+
|
|
393
|
+
let element = scrollRef.current.querySelector("[data-key=\"" + manager.focusedKey + "\"]");
|
|
394
|
+
|
|
395
|
+
if (element) {
|
|
396
|
+
// This prevents a flash of focus on the first/last element in the collection
|
|
397
|
+
focusWithoutScrolling(element);
|
|
398
|
+
$f791fefd7189e0e4d903034fb2925$var$scrollIntoView(scrollRef.current, element);
|
|
398
399
|
}
|
|
399
400
|
}
|
|
400
401
|
};
|
|
@@ -406,8 +407,9 @@ function useSelectableCollection(options) {
|
|
|
406
407
|
}
|
|
407
408
|
};
|
|
408
409
|
|
|
410
|
+
const autoFocusRef = useRef(autoFocus);
|
|
409
411
|
useEffect(() => {
|
|
410
|
-
if (
|
|
412
|
+
if (autoFocusRef.current) {
|
|
411
413
|
let focusedKey = null; // Check focus strategy to determine which item to focus
|
|
412
414
|
|
|
413
415
|
if (autoFocus === 'first') {
|
|
@@ -431,17 +433,32 @@ function useSelectableCollection(options) {
|
|
|
431
433
|
if (focusedKey == null && !shouldUseVirtualFocus) {
|
|
432
434
|
focusSafely(ref.current);
|
|
433
435
|
}
|
|
434
|
-
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
autoFocusRef.current = false; // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
439
|
+
}, []); // If not virtualized, scroll the focused element into view when the focusedKey changes.
|
|
440
|
+
// When virtualized, Virtualizer handles this internally.
|
|
435
441
|
|
|
436
|
-
|
|
442
|
+
useEffect(() => {
|
|
443
|
+
if (!isVirtualized && manager.focusedKey && scrollRef != null && scrollRef.current) {
|
|
444
|
+
let element = scrollRef.current.querySelector("[data-key=\"" + manager.focusedKey + "\"]");
|
|
445
|
+
|
|
446
|
+
if (element) {
|
|
447
|
+
$f791fefd7189e0e4d903034fb2925$var$scrollIntoView(scrollRef.current, element);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}, [isVirtualized, scrollRef, manager.focusedKey]);
|
|
437
451
|
let handlers = {
|
|
438
452
|
onKeyDown,
|
|
439
453
|
onFocus,
|
|
440
454
|
onBlur,
|
|
441
455
|
|
|
442
456
|
onMouseDown(e) {
|
|
443
|
-
//
|
|
444
|
-
e.
|
|
457
|
+
// Ignore events that bubbled through portals.
|
|
458
|
+
if (e.currentTarget.contains(e.target)) {
|
|
459
|
+
// Prevent focus going to the collection when clicking on the scrollbar.
|
|
460
|
+
e.preventDefault();
|
|
461
|
+
}
|
|
445
462
|
}
|
|
446
463
|
|
|
447
464
|
};
|
|
@@ -472,9 +489,70 @@ function useSelectableCollection(options) {
|
|
|
472
489
|
})
|
|
473
490
|
};
|
|
474
491
|
}
|
|
492
|
+
/**
|
|
493
|
+
* Scrolls `scrollView` so that `element` is visible.
|
|
494
|
+
* Similar to `element.scrollIntoView({block: 'nearest'})` (not supported in Edge),
|
|
495
|
+
* but doesn't affect parents above `scrollView`.
|
|
496
|
+
*/
|
|
497
|
+
|
|
475
498
|
|
|
476
499
|
exports.useSelectableCollection = useSelectableCollection;
|
|
477
500
|
|
|
501
|
+
function $f791fefd7189e0e4d903034fb2925$var$scrollIntoView(scrollView, element) {
|
|
502
|
+
let offsetX = $f791fefd7189e0e4d903034fb2925$var$relativeOffset(scrollView, element, 'left');
|
|
503
|
+
let offsetY = $f791fefd7189e0e4d903034fb2925$var$relativeOffset(scrollView, element, 'top');
|
|
504
|
+
let width = element.offsetWidth;
|
|
505
|
+
let height = element.offsetHeight;
|
|
506
|
+
let x = scrollView.scrollLeft;
|
|
507
|
+
let y = scrollView.scrollTop;
|
|
508
|
+
let maxX = x + scrollView.offsetWidth;
|
|
509
|
+
let maxY = y + scrollView.offsetHeight;
|
|
510
|
+
|
|
511
|
+
if (offsetX <= x) {
|
|
512
|
+
x = offsetX;
|
|
513
|
+
} else if (offsetX + width > maxX) {
|
|
514
|
+
x += offsetX + width - maxX;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (offsetY <= y) {
|
|
518
|
+
y = offsetY;
|
|
519
|
+
} else if (offsetY + height > maxY) {
|
|
520
|
+
y += offsetY + height - maxY;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
scrollView.scrollLeft = x;
|
|
524
|
+
scrollView.scrollTop = y;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Computes the offset left or top from child to ancestor by accumulating
|
|
528
|
+
* offsetLeft or offsetTop through intervening offsetParents.
|
|
529
|
+
*/
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
function $f791fefd7189e0e4d903034fb2925$var$relativeOffset(ancestor, child, axis) {
|
|
533
|
+
const prop = axis === 'left' ? 'offsetLeft' : 'offsetTop';
|
|
534
|
+
let sum = 0;
|
|
535
|
+
|
|
536
|
+
while (child.offsetParent) {
|
|
537
|
+
sum += child[prop];
|
|
538
|
+
|
|
539
|
+
if (child.offsetParent === ancestor) {
|
|
540
|
+
// Stop once we have found the ancestor we are interested in.
|
|
541
|
+
break;
|
|
542
|
+
} else if (child.offsetParent.contains(ancestor)) {
|
|
543
|
+
// If the ancestor is not `position:relative`, then we stop at
|
|
544
|
+
// _its_ offset parent, and we subtract off _its_ offset, so that
|
|
545
|
+
// we end up with the proper offset from child to ancestor.
|
|
546
|
+
sum -= ancestor[prop];
|
|
547
|
+
break;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
child = child.offsetParent;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
return sum;
|
|
554
|
+
}
|
|
555
|
+
|
|
478
556
|
/**
|
|
479
557
|
* Handles interactions with an item in a selectable collection.
|
|
480
558
|
*/
|
|
@@ -486,10 +564,35 @@ function useSelectableItem(options) {
|
|
|
486
564
|
shouldSelectOnPressUp,
|
|
487
565
|
isVirtualized,
|
|
488
566
|
shouldUseVirtualFocus,
|
|
489
|
-
focus
|
|
567
|
+
focus,
|
|
568
|
+
isDisabled,
|
|
569
|
+
onAction
|
|
490
570
|
} = options;
|
|
491
571
|
|
|
492
|
-
let onSelect = e =>
|
|
572
|
+
let onSelect = e => {
|
|
573
|
+
if (e.pointerType === 'keyboard' && $d220314dfe032b5c2a0f0c46ec981e5$export$isNonContiguousSelectionModifier(e)) {
|
|
574
|
+
manager.toggleSelection(key);
|
|
575
|
+
} else {
|
|
576
|
+
if (manager.selectionMode === 'none') {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (manager.selectionMode === 'single') {
|
|
581
|
+
if (manager.isSelected(key) && !manager.disallowEmptySelection) {
|
|
582
|
+
manager.toggleSelection(key);
|
|
583
|
+
} else {
|
|
584
|
+
manager.replaceSelection(key);
|
|
585
|
+
}
|
|
586
|
+
} else if (e && e.shiftKey) {
|
|
587
|
+
manager.extendSelection(key);
|
|
588
|
+
} else if (manager.selectionBehavior === 'toggle' || e && ($d220314dfe032b5c2a0f0c46ec981e5$export$isCtrlKeyPressed(e) || e.pointerType === 'touch' || e.pointerType === 'virtual')) {
|
|
589
|
+
// if touch or virtual (VO) then we just want to toggle, otherwise it's impossible to multi select because they don't have modifier keys
|
|
590
|
+
manager.toggleSelection(key);
|
|
591
|
+
} else {
|
|
592
|
+
manager.replaceSelection(key);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}; // Focus the associated DOM node when this item becomes the focusedKey
|
|
493
596
|
|
|
494
597
|
|
|
495
598
|
let isFocused = key === manager.focusedKey;
|
|
@@ -518,7 +621,12 @@ function useSelectableItem(options) {
|
|
|
518
621
|
}
|
|
519
622
|
|
|
520
623
|
};
|
|
521
|
-
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
let modality = useRef(null);
|
|
627
|
+
let hasPrimaryAction = onAction && manager.selectionMode === 'none';
|
|
628
|
+
let hasSecondaryAction = onAction && manager.selectionMode !== 'none' && manager.selectionBehavior === 'replace';
|
|
629
|
+
let allowsSelection = !isDisabled && manager.canSelectItem(key); // By default, selection occurs on pointer down. This can be strange if selecting an
|
|
522
630
|
// item causes the UI to disappear immediately (e.g. menus).
|
|
523
631
|
// If shouldSelectOnPressUp is true, we use onPressUp instead of onPressStart.
|
|
524
632
|
// onPress requires a pointer down event on the same element as pointer up. For menus,
|
|
@@ -526,30 +634,43 @@ function useSelectableItem(options) {
|
|
|
526
634
|
// the pointer up on the menu item rather than requiring a separate press.
|
|
527
635
|
// For keyboard events, selection still occurs on key down.
|
|
528
636
|
|
|
637
|
+
let itemPressProps = {};
|
|
529
638
|
|
|
530
639
|
if (shouldSelectOnPressUp) {
|
|
531
|
-
|
|
640
|
+
itemPressProps.onPressStart = e => {
|
|
641
|
+
modality.current = e.pointerType;
|
|
642
|
+
|
|
532
643
|
if (e.pointerType === 'keyboard') {
|
|
533
644
|
onSelect(e);
|
|
534
645
|
}
|
|
535
646
|
};
|
|
536
647
|
|
|
537
|
-
|
|
648
|
+
itemPressProps.onPressUp = e => {
|
|
538
649
|
if (e.pointerType !== 'keyboard') {
|
|
539
650
|
onSelect(e);
|
|
540
651
|
}
|
|
541
652
|
};
|
|
653
|
+
|
|
654
|
+
itemPressProps.onPress = hasPrimaryAction ? () => onAction() : null;
|
|
542
655
|
} else {
|
|
543
656
|
// On touch, it feels strange to select on touch down, so we special case this.
|
|
544
|
-
|
|
545
|
-
|
|
657
|
+
itemPressProps.onPressStart = e => {
|
|
658
|
+
modality.current = e.pointerType;
|
|
659
|
+
|
|
660
|
+
if (e.pointerType !== 'touch' && e.pointerType !== 'virtual') {
|
|
546
661
|
onSelect(e);
|
|
547
662
|
}
|
|
548
663
|
};
|
|
549
664
|
|
|
550
|
-
|
|
551
|
-
if (e.pointerType === 'touch') {
|
|
552
|
-
|
|
665
|
+
itemPressProps.onPress = e => {
|
|
666
|
+
if (e.pointerType === 'touch' || e.pointerType === 'virtual' || hasPrimaryAction) {
|
|
667
|
+
// Single tap on touch with selectionBehavior = 'replace' performs an action, i.e. navigation.
|
|
668
|
+
// Also perform action on press up when selectionMode = 'none'.
|
|
669
|
+
if (hasPrimaryAction || hasSecondaryAction) {
|
|
670
|
+
onAction();
|
|
671
|
+
} else {
|
|
672
|
+
onSelect(e);
|
|
673
|
+
}
|
|
553
674
|
}
|
|
554
675
|
};
|
|
555
676
|
}
|
|
@@ -558,8 +679,48 @@ function useSelectableItem(options) {
|
|
|
558
679
|
itemProps['data-key'] = key;
|
|
559
680
|
}
|
|
560
681
|
|
|
682
|
+
itemPressProps.preventFocusOnPress = shouldUseVirtualFocus;
|
|
683
|
+
let {
|
|
684
|
+
pressProps,
|
|
685
|
+
isPressed
|
|
686
|
+
} = usePress(itemPressProps); // Double clicking with a mouse with selectionBehavior = 'replace' performs an action.
|
|
687
|
+
|
|
688
|
+
let onDoubleClick = hasSecondaryAction ? e => {
|
|
689
|
+
if (modality.current === 'mouse') {
|
|
690
|
+
e.stopPropagation();
|
|
691
|
+
e.preventDefault();
|
|
692
|
+
onAction();
|
|
693
|
+
}
|
|
694
|
+
} : undefined; // Long pressing an item with touch when selectionBehavior = 'replace' switches the selection behavior
|
|
695
|
+
// to 'toggle'. This changes the single tap behavior from performing an action (i.e. navigating) to
|
|
696
|
+
// selecting, and may toggle the appearance of a UI affordance like checkboxes on each item.
|
|
697
|
+
// TODO: what about when drag and drop is also enabled??
|
|
698
|
+
|
|
699
|
+
let {
|
|
700
|
+
longPressProps
|
|
701
|
+
} = useLongPress({
|
|
702
|
+
isDisabled: !hasSecondaryAction,
|
|
703
|
+
|
|
704
|
+
onLongPress(e) {
|
|
705
|
+
if (e.pointerType === 'touch') {
|
|
706
|
+
onSelect(e);
|
|
707
|
+
manager.setSelectionBehavior('toggle');
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
}); // Pressing the Enter key with selectionBehavior = 'replace' performs an action (i.e. navigation).
|
|
712
|
+
|
|
713
|
+
let onKeyUp = hasSecondaryAction ? e => {
|
|
714
|
+
if (e.key === 'Enter') {
|
|
715
|
+
onAction();
|
|
716
|
+
}
|
|
717
|
+
} : undefined;
|
|
561
718
|
return {
|
|
562
|
-
itemProps
|
|
719
|
+
itemProps: mergeProps(itemProps, allowsSelection || hasPrimaryAction ? pressProps : {}, hasSecondaryAction ? longPressProps : {}, {
|
|
720
|
+
onKeyUp,
|
|
721
|
+
onDoubleClick
|
|
722
|
+
}),
|
|
723
|
+
isPressed
|
|
563
724
|
};
|
|
564
725
|
}
|
|
565
726
|
|
|
@@ -735,18 +896,7 @@ function useSelectableList(props) {
|
|
|
735
896
|
usage: 'search',
|
|
736
897
|
sensitivity: 'base'
|
|
737
898
|
});
|
|
738
|
-
let delegate = useMemo(() => keyboardDelegate || new ListKeyboardDelegate(collection, disabledKeys, ref, collator), [keyboardDelegate, collection, disabledKeys, ref, collator]);
|
|
739
|
-
// When virtualized, Virtualizer handles this internally.
|
|
740
|
-
|
|
741
|
-
useEffect(() => {
|
|
742
|
-
if (!isVirtualized && selectionManager.focusedKey && (ref == null ? void 0 : ref.current)) {
|
|
743
|
-
let element = ref.current.querySelector("[data-key=\"" + selectionManager.focusedKey + "\"]");
|
|
744
|
-
|
|
745
|
-
if (element) {
|
|
746
|
-
$e85d8307c59fae2ab45d73201aa19$var$scrollIntoView(ref.current, element);
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
}, [isVirtualized, ref, selectionManager.focusedKey]);
|
|
899
|
+
let delegate = useMemo(() => keyboardDelegate || new ListKeyboardDelegate(collection, disabledKeys, ref, collator), [keyboardDelegate, collection, disabledKeys, ref, collator]);
|
|
750
900
|
let {
|
|
751
901
|
collectionProps
|
|
752
902
|
} = useSelectableCollection({
|
|
@@ -759,44 +909,14 @@ function useSelectableList(props) {
|
|
|
759
909
|
selectOnFocus,
|
|
760
910
|
disallowTypeAhead,
|
|
761
911
|
shouldUseVirtualFocus,
|
|
762
|
-
allowsTabNavigation
|
|
912
|
+
allowsTabNavigation,
|
|
913
|
+
isVirtualized,
|
|
914
|
+
scrollRef: ref
|
|
763
915
|
});
|
|
764
916
|
return {
|
|
765
917
|
listProps: collectionProps
|
|
766
918
|
};
|
|
767
919
|
}
|
|
768
|
-
/**
|
|
769
|
-
* Scrolls `scrollView` so that `element` is visible.
|
|
770
|
-
* Similar to `element.scrollIntoView({block: 'nearest'})` (not supported in Edge),
|
|
771
|
-
* but doesn't affect parents above `scrollView`.
|
|
772
|
-
*/
|
|
773
|
-
|
|
774
920
|
|
|
775
921
|
exports.useSelectableList = useSelectableList;
|
|
776
|
-
|
|
777
|
-
function $e85d8307c59fae2ab45d73201aa19$var$scrollIntoView(scrollView, element) {
|
|
778
|
-
let offsetX = element.offsetLeft - scrollView.offsetLeft;
|
|
779
|
-
let offsetY = element.offsetTop - scrollView.offsetTop;
|
|
780
|
-
let width = element.offsetWidth;
|
|
781
|
-
let height = element.offsetHeight;
|
|
782
|
-
let x = scrollView.scrollLeft;
|
|
783
|
-
let y = scrollView.scrollTop;
|
|
784
|
-
let maxX = x + scrollView.offsetWidth;
|
|
785
|
-
let maxY = y + scrollView.offsetHeight;
|
|
786
|
-
|
|
787
|
-
if (offsetX <= x) {
|
|
788
|
-
x = offsetX;
|
|
789
|
-
} else if (offsetX + width > maxX) {
|
|
790
|
-
x += offsetX + width - maxX;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
if (offsetY <= y) {
|
|
794
|
-
y = offsetY;
|
|
795
|
-
} else if (offsetY + height > maxY) {
|
|
796
|
-
y += offsetY + height - maxY;
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
scrollView.scrollLeft = x;
|
|
800
|
-
scrollView.scrollTop = y;
|
|
801
|
-
}
|
|
802
922
|
//# sourceMappingURL=main.js.map
|