@react-aria/selection 3.8.2 → 3.10.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.
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-aria/selection/src/packages/@react-aria/selection/src/utils.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/useTypeSelect.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/useSelectableCollection.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/useSelectableItem.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/ListKeyboardDelegate.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/useSelectableList.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/index.ts","packages/@react-aria/selection/src/index.ts"],"sourcesContent":[null,null,null,null,null,null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport * from './useSelectableCollection';\nexport * from './useSelectableItem';\nexport * from './useSelectableList';\nexport * from './ListKeyboardDelegate';\nexport * from './useTypeSelect';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
1
+ {"mappings":"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","sources":["packages/@react-aria/selection/src/packages/@react-aria/selection/src/utils.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/useTypeSelect.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/useSelectableCollection.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/useSelectableItem.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/ListKeyboardDelegate.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/useSelectableList.ts","packages/@react-aria/selection/src/packages/@react-aria/selection/src/index.ts","packages/@react-aria/selection/src/index.ts"],"sourcesContent":[null,null,null,null,null,null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport {useSelectableCollection} from './useSelectableCollection';\nexport {useSelectableItem} from './useSelectableItem';\nexport {useSelectableList} from './useSelectableList';\nexport {ListKeyboardDelegate} from './ListKeyboardDelegate';\nexport {useTypeSelect} from './useTypeSelect';\n\nexport type {AriaSelectableCollectionOptions, SelectableCollectionAria} from './useSelectableCollection';\nexport type {AriaSelectableListOptions, SelectableListAria} from './useSelectableList';\nexport type {SelectableItemOptions, SelectableItemStates, SelectableItemAria} from './useSelectableItem';\nexport type {AriaTypeSelectOptions, TypeSelectAria} from './useTypeSelect';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-aria/selection",
3
- "version": "3.8.2",
3
+ "version": "3.10.0",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -18,19 +18,19 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "@babel/runtime": "^7.6.2",
21
- "@react-aria/focus": "^3.5.5",
22
- "@react-aria/i18n": "^3.3.9",
23
- "@react-aria/interactions": "^3.8.4",
24
- "@react-aria/utils": "^3.12.0",
25
- "@react-stately/collections": "^3.3.8",
26
- "@react-stately/selection": "^3.9.4",
27
- "@react-types/shared": "^3.12.0"
21
+ "@react-aria/focus": "^3.7.0",
22
+ "@react-aria/i18n": "^3.5.0",
23
+ "@react-aria/interactions": "^3.10.0",
24
+ "@react-aria/utils": "^3.13.2",
25
+ "@react-stately/collections": "^3.4.2",
26
+ "@react-stately/selection": "^3.10.2",
27
+ "@react-types/shared": "^3.14.0"
28
28
  },
29
29
  "peerDependencies": {
30
- "react": "^16.8.0 || ^17.0.0-rc.1"
30
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
31
31
  },
32
32
  "publishConfig": {
33
33
  "access": "public"
34
34
  },
35
- "gitHead": "6a503b715e0dbbf92038cd7f08b1bcdde4c78e82"
35
+ "gitHead": "cd7c0ec917122c7612f653c22f8ed558f8b66ecd"
36
36
  }
package/src/index.ts CHANGED
@@ -10,8 +10,13 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- export * from './useSelectableCollection';
14
- export * from './useSelectableItem';
15
- export * from './useSelectableList';
16
- export * from './ListKeyboardDelegate';
17
- export * from './useTypeSelect';
13
+ export {useSelectableCollection} from './useSelectableCollection';
14
+ export {useSelectableItem} from './useSelectableItem';
15
+ export {useSelectableList} from './useSelectableList';
16
+ export {ListKeyboardDelegate} from './ListKeyboardDelegate';
17
+ export {useTypeSelect} from './useTypeSelect';
18
+
19
+ export type {AriaSelectableCollectionOptions, SelectableCollectionAria} from './useSelectableCollection';
20
+ export type {AriaSelectableListOptions, SelectableListAria} from './useSelectableList';
21
+ export type {SelectableItemOptions, SelectableItemStates, SelectableItemAria} from './useSelectableItem';
22
+ export type {AriaTypeSelectOptions, TypeSelectAria} from './useTypeSelect';
@@ -10,16 +10,16 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import {FocusEvent, HTMLAttributes, Key, KeyboardEvent, RefObject, useEffect, useRef} from 'react';
13
+ import {DOMAttributes, FocusableElement, FocusStrategy, KeyboardDelegate} from '@react-types/shared';
14
+ import {FocusEvent, Key, KeyboardEvent, RefObject, useEffect, useRef} from 'react';
14
15
  import {focusSafely, getFocusableTreeWalker} from '@react-aria/focus';
15
- import {FocusStrategy, KeyboardDelegate} from '@react-types/shared';
16
16
  import {focusWithoutScrolling, mergeProps, scrollIntoView, useEvent} from '@react-aria/utils';
17
17
  import {isCtrlKeyPressed, isNonContiguousSelectionModifier} from './utils';
18
18
  import {MultipleSelectionManager} from '@react-stately/selection';
19
19
  import {useLocale} from '@react-aria/i18n';
20
20
  import {useTypeSelect} from './useTypeSelect';
21
21
 
22
- interface SelectableCollectionOptions {
22
+ export interface AriaSelectableCollectionOptions {
23
23
  /**
24
24
  * An interface for reading and updating multiple selection state.
25
25
  */
@@ -81,15 +81,15 @@ interface SelectableCollectionOptions {
81
81
  scrollRef?: RefObject<HTMLElement>
82
82
  }
83
83
 
84
- interface SelectableCollectionAria {
84
+ export interface SelectableCollectionAria {
85
85
  /** Props for the collection element. */
86
- collectionProps: HTMLAttributes<HTMLElement>
86
+ collectionProps: DOMAttributes
87
87
  }
88
88
 
89
89
  /**
90
90
  * Handles interactions with selectable collections.
91
91
  */
92
- export function useSelectableCollection(options: SelectableCollectionOptions): SelectableCollectionAria {
92
+ export function useSelectableCollection(options: AriaSelectableCollectionOptions): SelectableCollectionAria {
93
93
  let {
94
94
  selectionManager: manager,
95
95
  keyboardDelegate: delegate,
@@ -117,7 +117,7 @@ export function useSelectableCollection(options: SelectableCollectionOptions): S
117
117
 
118
118
  // Keyboard events bubble through portals. Don't handle keyboard events
119
119
  // for elements outside the collection (e.g. menus).
120
- if (!ref.current.contains(e.target as HTMLElement)) {
120
+ if (!ref.current.contains(e.target as Element)) {
121
121
  return;
122
122
  }
123
123
 
@@ -238,10 +238,10 @@ export function useSelectableCollection(options: SelectableCollectionOptions): S
238
238
  ref.current.focus();
239
239
  } else {
240
240
  let walker = getFocusableTreeWalker(ref.current, {tabbable: true});
241
- let next: HTMLElement;
242
- let last: HTMLElement;
241
+ let next: FocusableElement;
242
+ let last: FocusableElement;
243
243
  do {
244
- last = walker.lastChild() as HTMLElement;
244
+ last = walker.lastChild() as FocusableElement;
245
245
  if (last) {
246
246
  next = last;
247
247
  }
@@ -10,15 +10,15 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
+ import {DOMAttributes, FocusableElement, LongPressEvent, PressEvent} from '@react-types/shared';
13
14
  import {focusSafely} from '@react-aria/focus';
14
- import {HTMLAttributes, Key, RefObject, useEffect, useRef} from 'react';
15
15
  import {isCtrlKeyPressed, isNonContiguousSelectionModifier} from './utils';
16
- import {LongPressEvent, PressEvent} from '@react-types/shared';
16
+ import {Key, RefObject, useEffect, useRef} from 'react';
17
17
  import {mergeProps} from '@react-aria/utils';
18
18
  import {MultipleSelectionManager} from '@react-stately/selection';
19
19
  import {PressProps, useLongPress, usePress} from '@react-aria/interactions';
20
20
 
21
- interface SelectableItemOptions {
21
+ export interface SelectableItemOptions {
22
22
  /**
23
23
  * An interface for reading and updating multiple selection state.
24
24
  */
@@ -30,7 +30,7 @@ interface SelectableItemOptions {
30
30
  /**
31
31
  * Ref to the item.
32
32
  */
33
- ref: RefObject<HTMLElement>,
33
+ ref: RefObject<FocusableElement>,
34
34
  /**
35
35
  * By default, selection occurs on pointer down. This can be strange if selecting an
36
36
  * item causes the UI to disappear immediately (e.g. menus).
@@ -56,19 +56,40 @@ interface SelectableItemOptions {
56
56
  /** Whether the item is disabled. */
57
57
  isDisabled?: boolean,
58
58
  /**
59
- * Handler that is called when a user performs an action on the cell. The exact user event depends on
59
+ * Handler that is called when a user performs an action on the item. The exact user event depends on
60
60
  * the collection's `selectionBehavior` prop and the interaction modality.
61
61
  */
62
62
  onAction?: () => void
63
63
  }
64
64
 
65
- interface SelectableItemAria {
65
+ export interface SelectableItemStates {
66
+ /** Whether the item is currently in a pressed state. */
67
+ isPressed: boolean,
68
+ /** Whether the item is currently selected. */
69
+ isSelected: boolean,
70
+ /**
71
+ * Whether the item is non-interactive, i.e. both selection and actions are disabled and the item may
72
+ * not be focused. Dependent on `disabledKeys` and `disabledBehavior`.
73
+ */
74
+ isDisabled: boolean,
75
+ /**
76
+ * Whether the item may be selected, dependent on `selectionMode`, `disabledKeys`, and `disabledBehavior`.
77
+ */
78
+ allowsSelection: boolean,
79
+ /**
80
+ * Whether the item has an action, dependent on `onAction`, `disabledKeys`,
81
+ * and `disabledBehavior. It may also change depending on the current selection state
82
+ * of the list (e.g. when selection is primary). This can be used to enable or disable hover
83
+ * styles or other visual indications of interactivity.
84
+ */
85
+ hasAction: boolean
86
+ }
87
+
88
+ export interface SelectableItemAria extends SelectableItemStates {
66
89
  /**
67
90
  * Props to be spread on the item root node.
68
91
  */
69
- itemProps: HTMLAttributes<HTMLElement>,
70
- /** Whether the item is currently in a pressed state. */
71
- isPressed: boolean
92
+ itemProps: DOMAttributes
72
93
  }
73
94
 
74
95
  /**
@@ -114,8 +135,8 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
114
135
  };
115
136
 
116
137
  // Focus the associated DOM node when this item becomes the focusedKey
117
- let isFocused = key === manager.focusedKey;
118
138
  useEffect(() => {
139
+ let isFocused = key === manager.focusedKey;
119
140
  if (isFocused && manager.isFocused && !shouldUseVirtualFocus && document.activeElement !== ref.current) {
120
141
  if (focus) {
121
142
  focus();
@@ -123,7 +144,7 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
123
144
  focusSafely(ref.current);
124
145
  }
125
146
  }
126
- }, [ref, isFocused, manager.focusedKey, manager.childFocusStrategy, manager.isFocused, shouldUseVirtualFocus]);
147
+ }, [ref, key, manager.focusedKey, manager.childFocusStrategy, manager.isFocused, shouldUseVirtualFocus]);
127
148
 
128
149
  // Set tabIndex to 0 if the element is focused, or -1 otherwise so that only the last focused
129
150
  // item is tabbable. If using virtual focus, don't set a tabIndex at all so that VoiceOver
@@ -131,7 +152,7 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
131
152
  let itemProps: SelectableItemAria['itemProps'] = {};
132
153
  if (!shouldUseVirtualFocus) {
133
154
  itemProps = {
134
- tabIndex: isFocused ? 0 : -1,
155
+ tabIndex: key === manager.focusedKey ? 0 : -1,
135
156
  onFocus(e) {
136
157
  if (e.target === ref.current) {
137
158
  manager.setFocusedKey(key);
@@ -140,10 +161,26 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
140
161
  };
141
162
  }
142
163
 
143
- let modality = useRef(null);
144
- let hasPrimaryAction = onAction && manager.selectionMode === 'none';
145
- let hasSecondaryAction = onAction && manager.selectionMode !== 'none' && manager.selectionBehavior === 'replace';
164
+
165
+ // With checkbox selection, onAction (i.e. navigation) becomes primary, and occurs on a single click of the row.
166
+ // Clicking the checkbox enters selection mode, after which clicking anywhere on any row toggles selection for that row.
167
+ // With highlight selection, onAction is secondary, and occurs on double click. Single click selects the row.
168
+ // With touch, onAction occurs on single tap, and long press enters selection mode.
169
+ isDisabled = isDisabled || manager.isDisabled(key);
146
170
  let allowsSelection = !isDisabled && manager.canSelectItem(key);
171
+ let allowsActions = onAction && !isDisabled;
172
+ let hasPrimaryAction = allowsActions && (
173
+ manager.selectionBehavior === 'replace'
174
+ ? !allowsSelection
175
+ : manager.isEmpty
176
+ );
177
+ let hasSecondaryAction = allowsActions && allowsSelection && manager.selectionBehavior === 'replace';
178
+ let hasAction = hasPrimaryAction || hasSecondaryAction;
179
+ let modality = useRef(null);
180
+
181
+ let longPressEnabled = hasAction && allowsSelection;
182
+ let longPressEnabledOnPressStart = useRef(false);
183
+ let hadPrimaryActionOnPressStart = useRef(false);
147
184
 
148
185
  // By default, selection occurs on pointer down. This can be strange if selecting an
149
186
  // item causes the UI to disappear immediately (e.g. menus).
@@ -156,7 +193,8 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
156
193
  if (shouldSelectOnPressUp) {
157
194
  itemPressProps.onPressStart = (e) => {
158
195
  modality.current = e.pointerType;
159
- if (e.pointerType === 'keyboard') {
196
+ longPressEnabledOnPressStart.current = longPressEnabled;
197
+ if (e.pointerType === 'keyboard' && (!hasAction || isSelectionKey())) {
160
198
  onSelect(e);
161
199
  }
162
200
  };
@@ -165,12 +203,14 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
165
203
  // Otherwise, have selection happen onPress (prevents listview row selection when clicking on interactable elements in the row)
166
204
  if (!allowsDifferentPressOrigin) {
167
205
  itemPressProps.onPress = (e) => {
168
- if (e.pointerType !== 'keyboard') {
169
- onSelect(e);
170
- }
206
+ if (hasPrimaryAction || (hasSecondaryAction && e.pointerType !== 'mouse')) {
207
+ if (e.pointerType === 'keyboard' && !isActionKey()) {
208
+ return;
209
+ }
171
210
 
172
- if (hasPrimaryAction) {
173
211
  onAction();
212
+ } else if (e.pointerType !== 'keyboard') {
213
+ onSelect(e);
174
214
  }
175
215
  };
176
216
  } else {
@@ -183,19 +223,34 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
183
223
  itemPressProps.onPress = hasPrimaryAction ? () => onAction() : null;
184
224
  }
185
225
  } else {
186
- // On touch, it feels strange to select on touch down, so we special case this.
187
226
  itemPressProps.onPressStart = (e) => {
188
227
  modality.current = e.pointerType;
189
- if (e.pointerType !== 'touch' && e.pointerType !== 'virtual') {
228
+ longPressEnabledOnPressStart.current = longPressEnabled;
229
+ hadPrimaryActionOnPressStart.current = hasPrimaryAction;
230
+
231
+ // Select on mouse down unless there is a primary action which will occur on mouse up.
232
+ // For keyboard, select on key down. If there is an action, the Space key selects on key down,
233
+ // and the Enter key performs onAction on key up.
234
+ if (
235
+ (e.pointerType === 'mouse' && !hasPrimaryAction) ||
236
+ (e.pointerType === 'keyboard' && (!onAction || isSelectionKey()))
237
+ ) {
190
238
  onSelect(e);
191
239
  }
192
240
  };
193
241
 
194
242
  itemPressProps.onPress = (e) => {
195
- if (e.pointerType === 'touch' || e.pointerType === 'virtual' || hasPrimaryAction) {
196
- // Single tap on touch with selectionBehavior = 'replace' performs an action, i.e. navigation.
197
- // Also perform action on press up when selectionMode = 'none'.
198
- if (hasPrimaryAction || hasSecondaryAction) {
243
+ // Selection occurs on touch up. Primary actions always occur on pointer up.
244
+ // Both primary and secondary actions occur on Enter key up. The only exception
245
+ // is secondary actions, which occur on double click with a mouse.
246
+ if (
247
+ e.pointerType === 'touch' ||
248
+ e.pointerType === 'pen' ||
249
+ e.pointerType === 'virtual' ||
250
+ (e.pointerType === 'keyboard' && hasAction && isActionKey()) ||
251
+ (e.pointerType === 'mouse' && hadPrimaryActionOnPressStart.current)
252
+ ) {
253
+ if (hasAction) {
199
254
  onAction();
200
255
  } else {
201
256
  onSelect(e);
@@ -223,9 +278,8 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
223
278
  // Long pressing an item with touch when selectionBehavior = 'replace' switches the selection behavior
224
279
  // to 'toggle'. This changes the single tap behavior from performing an action (i.e. navigating) to
225
280
  // selecting, and may toggle the appearance of a UI affordance like checkboxes on each item.
226
- // TODO: what about when drag and drop is also enabled??
227
281
  let {longPressProps} = useLongPress({
228
- isDisabled: !hasSecondaryAction,
282
+ isDisabled: !longPressEnabled,
229
283
  onLongPress(e) {
230
284
  if (e.pointerType === 'touch') {
231
285
  onSelect(e);
@@ -234,20 +288,35 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
234
288
  }
235
289
  });
236
290
 
237
- // Pressing the Enter key with selectionBehavior = 'replace' performs an action (i.e. navigation).
238
- let onKeyUp = hasSecondaryAction ? (e: KeyboardEvent) => {
239
- if (e.key === 'Enter') {
240
- onAction();
291
+ // Prevent native drag and drop on long press if we also select on long press.
292
+ // Once the user is in selection mode, they can long press again to drag.
293
+ let onDragStart = e => {
294
+ if (modality.current === 'touch' && longPressEnabledOnPressStart.current) {
295
+ e.preventDefault();
241
296
  }
242
- } : undefined;
297
+ };
243
298
 
244
299
  return {
245
300
  itemProps: mergeProps(
246
301
  itemProps,
247
302
  allowsSelection || hasPrimaryAction ? pressProps : {},
248
- hasSecondaryAction ? longPressProps : {},
249
- {onKeyUp, onDoubleClick}
303
+ longPressEnabled ? longPressProps : {},
304
+ {onDoubleClick, onDragStart}
250
305
  ),
251
- isPressed
306
+ isPressed,
307
+ isSelected: manager.isSelected(key),
308
+ isDisabled,
309
+ allowsSelection,
310
+ hasAction
252
311
  };
253
312
  }
313
+
314
+ function isActionKey() {
315
+ let event = window.event as KeyboardEvent;
316
+ return event?.key === 'Enter';
317
+ }
318
+
319
+ function isSelectionKey() {
320
+ let event = window.event as KeyboardEvent;
321
+ return event?.key === ' ' || event?.code === 'Space';
322
+ }
@@ -10,14 +10,14 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import {Collection, FocusStrategy, KeyboardDelegate, Node} from '@react-types/shared';
14
- import {HTMLAttributes, Key, RefObject, useMemo} from 'react';
13
+ import {Collection, DOMAttributes, FocusStrategy, KeyboardDelegate, Node} from '@react-types/shared';
14
+ import {Key, RefObject, useMemo} from 'react';
15
15
  import {ListKeyboardDelegate} from './ListKeyboardDelegate';
16
16
  import {MultipleSelectionManager} from '@react-stately/selection';
17
17
  import {useCollator} from '@react-aria/i18n';
18
18
  import {useSelectableCollection} from './useSelectableCollection';
19
19
 
20
- interface SelectableListOptions {
20
+ export interface AriaSelectableListOptions {
21
21
  /**
22
22
  * An interface for reading and updating multiple selection state.
23
23
  */
@@ -77,17 +77,17 @@ interface SelectableListOptions {
77
77
  allowsTabNavigation?: boolean
78
78
  }
79
79
 
80
- interface SelectableListAria {
80
+ export interface SelectableListAria {
81
81
  /**
82
82
  * Props for the option element.
83
83
  */
84
- listProps: HTMLAttributes<HTMLElement>
84
+ listProps: DOMAttributes
85
85
  }
86
86
 
87
87
  /**
88
88
  * Handles interactions with a selectable list.
89
89
  */
90
- export function useSelectableList(props: SelectableListOptions): SelectableListAria {
90
+ export function useSelectableList(props: AriaSelectableListOptions): SelectableListAria {
91
91
  let {
92
92
  selectionManager,
93
93
  collection,
@@ -98,7 +98,7 @@ export function useSelectableList(props: SelectableListOptions): SelectableListA
98
98
  shouldFocusWrap,
99
99
  isVirtualized,
100
100
  disallowEmptySelection,
101
- selectOnFocus = false,
101
+ selectOnFocus = selectionManager.selectionBehavior === 'replace',
102
102
  disallowTypeAhead,
103
103
  shouldUseVirtualFocus,
104
104
  allowsTabNavigation
@@ -10,11 +10,11 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import {HTMLAttributes, Key, KeyboardEvent, useRef} from 'react';
14
- import {KeyboardDelegate} from '@react-types/shared';
13
+ import {DOMAttributes, KeyboardDelegate} from '@react-types/shared';
14
+ import {Key, KeyboardEvent, useRef} from 'react';
15
15
  import {MultipleSelectionManager} from '@react-stately/selection';
16
16
 
17
- interface TypeSelectOptions {
17
+ export interface AriaTypeSelectOptions {
18
18
  /**
19
19
  * A delegate that returns collection item keys with respect to visual layout.
20
20
  */
@@ -29,17 +29,17 @@ interface TypeSelectOptions {
29
29
  onTypeSelect?: (key: Key) => void
30
30
  }
31
31
 
32
- interface TypeSelectAria {
32
+ export interface TypeSelectAria {
33
33
  /**
34
34
  * Props to be spread on the owner of the options.
35
35
  */
36
- typeSelectProps: HTMLAttributes<HTMLElement>
36
+ typeSelectProps: DOMAttributes
37
37
  }
38
38
 
39
39
  /**
40
40
  * Handles typeahead interactions with collections.
41
41
  */
42
- export function useTypeSelect(options: TypeSelectOptions): TypeSelectAria {
42
+ export function useTypeSelect(options: AriaTypeSelectOptions): TypeSelectAria {
43
43
  let {keyboardDelegate, selectionManager, onTypeSelect} = options;
44
44
  let state = useRef({
45
45
  search: '',