@react-aria/selection 3.0.0-nightly-4dd0993da-250106 → 3.0.0-nightly-e7053dd8f-250108

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":";;ACqBA;IACE;;OAEG;IACH,gBAAgB,EAAE,gBAAgB,CAAC;IACnC;;OAEG;IACH,gBAAgB,EAAE,wBAAwB,CAAC;IAC3C;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;CAClC;AAED;IACE;;OAEG;IACH,eAAe,EAAE,aAAa,CAAA;CAC/B;AAED;;GAEG;AACH,8BAA8B,OAAO,EAAE,qBAAqB,GAAG,cAAc,CAyD5E;AChFD;IACE;;OAEG;IACH,gBAAgB,EAAE,wBAAwB,CAAC;IAC3C;;OAEG;IACH,gBAAgB,EAAE,gBAAgB,CAAC;IACnC;;OAEG;IACH,GAAG,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,CAAC;IACnC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,aAAa,CAAC;IACpC;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,CAAC;IAC1C;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAA;CACnD;AAED;IACE,wCAAwC;IACxC,eAAe,EAAE,aAAa,CAAA;CAC/B;AAED;;GAEG;AACH,wCAAwC,OAAO,EAAE,+BAA+B,GAAG,wBAAwB,CA+a1G;AChgBD,sCAAuC,SAAQ,QAAQ;IACrD;;OAEG;IACH,gBAAgB,EAAE,wBAAwB,CAAC;IAC3C;;OAEG;IACH,GAAG,EAAE,GAAG,CAAC;IACT;;OAEG;IACH,GAAG,EAAE,UAAU,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACxC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;OAGG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IACnB;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,oCAAoC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAA;CAC5D;AAED;IACE,wDAAwD;IACxD,SAAS,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,UAAU,EAAE,OAAO,CAAC;IACpB,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,eAAe,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,mCAAoC,SAAQ,oBAAoB;IAC9D;;OAEG;IACH,SAAS,EAAE,aAAa,CAAA;CACzB;AAED;;GAEG;AACH,kCAAkC,OAAO,EAAE,qBAAqB,GAAG,kBAAkB,CA6QpF;AC3WD,8BAA+B,YAAW,cAAc;gBAG1C,GAAG,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC;IAI9C,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI;IAqBlC,cAAc,IAAI,IAAI;IAQtB,cAAc,IAAI,IAAI;CASvB;AC3CD,sCAAsC,CAAC;IACrC,UAAU,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC;IAChC,GAAG,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,KAAK,QAAQ,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,YAAY,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC;AAED,kCAAkC,CAAC,CAAE,YAAW,gBAAgB;gBAWlD,UAAU,EAAE,WAAW,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,UAAU,WAAW,GAAG,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,KAAK,QAAQ;gBACrH,OAAO,EAAE,4BAA4B,CAAC,CAAC;IAkDnD,UAAU,CAAC,GAAG,EAAE,GAAG;IAMnB,cAAc,CAAC,GAAG,EAAE,GAAG;IAsCvB,WAAW,CAAC,GAAG,EAAE,GAAG;IAQpB,WAAW,CAAC,GAAG,EAAE,GAAG;IAYpB,aAAa,CAAC,CAAC,GAAG,EAAE,GAAG;IAsBvB,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG;IAoBtB,WAAW;IAKX,UAAU;IAKV,eAAe,CAAC,GAAG,EAAE,GAAG;IA+BxB,eAAe,CAAC,GAAG,EAAE,GAAG;IA+BxB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG;CAsB9C;AChRD,0CAA2C,SAAQ,IAAI,CAAC,+BAA+B,EAAE,kBAAkB,CAAC;IAC1G;;OAEG;IACH,UAAU,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC;IACtC;;OAEG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;OAEG;IACH,YAAY,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;CACvB;AAED;IACE;;OAEG;IACH,SAAS,EAAE,aAAa,CAAA;CACzB;AAED;;GAEG;AACH,kCAAkC,KAAK,EAAE,yBAAyB,GAAG,kBAAkB,CAmCtF","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/DOMLayoutDelegate.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,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 {DOMLayoutDelegate} from './DOMLayoutDelegate';\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"}
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/DOMLayoutDelegate.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,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 {DOMLayoutDelegate} from './DOMLayoutDelegate';\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"}
@@ -111,10 +111,10 @@ function $b6837c2f80a3c32f$export$d6daf82dcd84e87c(options) {
111
111
  if (delegate.getFirstKey) {
112
112
  if (manager.focusedKey === null && e.shiftKey) return;
113
113
  e.preventDefault();
114
- let firstKey = delegate.getFirstKey(manager.focusedKey, (0, $ee0bdf4faa47f2a8$exports.isCtrlKeyPressed)(e));
114
+ let firstKey = delegate.getFirstKey(manager.focusedKey, (0, $bT8Bh$reactariautils.isCtrlKeyPressed)(e));
115
115
  manager.setFocusedKey(firstKey);
116
116
  if (firstKey != null) {
117
- if ((0, $ee0bdf4faa47f2a8$exports.isCtrlKeyPressed)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(firstKey);
117
+ if ((0, $bT8Bh$reactariautils.isCtrlKeyPressed)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(firstKey);
118
118
  else if (selectOnFocus) manager.replaceSelection(firstKey);
119
119
  }
120
120
  }
@@ -123,10 +123,10 @@ function $b6837c2f80a3c32f$export$d6daf82dcd84e87c(options) {
123
123
  if (delegate.getLastKey) {
124
124
  if (manager.focusedKey === null && e.shiftKey) return;
125
125
  e.preventDefault();
126
- let lastKey = delegate.getLastKey(manager.focusedKey, (0, $ee0bdf4faa47f2a8$exports.isCtrlKeyPressed)(e));
126
+ let lastKey = delegate.getLastKey(manager.focusedKey, (0, $bT8Bh$reactariautils.isCtrlKeyPressed)(e));
127
127
  manager.setFocusedKey(lastKey);
128
128
  if (lastKey != null) {
129
- if ((0, $ee0bdf4faa47f2a8$exports.isCtrlKeyPressed)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(lastKey);
129
+ if ((0, $bT8Bh$reactariautils.isCtrlKeyPressed)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(lastKey);
130
130
  else if (selectOnFocus) manager.replaceSelection(lastKey);
131
131
  }
132
132
  }
@@ -150,7 +150,7 @@ function $b6837c2f80a3c32f$export$d6daf82dcd84e87c(options) {
150
150
  }
151
151
  break;
152
152
  case 'a':
153
- if ((0, $ee0bdf4faa47f2a8$exports.isCtrlKeyPressed)(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {
153
+ if ((0, $bT8Bh$reactariautils.isCtrlKeyPressed)(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {
154
154
  e.preventDefault();
155
155
  manager.selectAll();
156
156
  }
@@ -247,6 +247,10 @@ function $b6837c2f80a3c32f$export$d6daf82dcd84e87c(options) {
247
247
  // Don't set blurred and then focused again if moving focus within the collection.
248
248
  if (!e.currentTarget.contains(e.relatedTarget)) manager.setFocused(false);
249
249
  };
250
+ // Ref to track whether the first item in the collection should be automatically focused. Specifically used for autocomplete when user types
251
+ // to focus the first key AFTER the collection updates.
252
+ // TODO: potentially expand the usage of this
253
+ let shouldVirtualFocusFirst = (0, $bT8Bh$react.useRef)(false);
250
254
  // Add event listeners for custom virtual events. These handle updating the focused key in response to various keyboard events
251
255
  // at the autocomplete level
252
256
  // TODO: fix type later
@@ -255,18 +259,43 @@ function $b6837c2f80a3c32f$export$d6daf82dcd84e87c(options) {
255
259
  e.stopPropagation();
256
260
  manager.setFocused(true);
257
261
  // If the user is typing forwards, autofocus the first option in the list.
258
- if ((detail === null || detail === void 0 ? void 0 : detail.focusStrategy) === 'first') {
259
- var _delegate_getFirstKey, _ref_current;
260
- var _delegate_getFirstKey1;
261
- let keyToFocus = (_delegate_getFirstKey1 = (_delegate_getFirstKey = delegate.getFirstKey) === null || _delegate_getFirstKey === void 0 ? void 0 : _delegate_getFirstKey.call(delegate)) !== null && _delegate_getFirstKey1 !== void 0 ? _delegate_getFirstKey1 : null;
262
- // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist
263
- if (keyToFocus == null) (_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.dispatchEvent(new CustomEvent((0, $bT8Bh$reactariautils.UPDATE_ACTIVEDESCENDANT), {
264
- cancelable: true,
265
- bubbles: true
266
- }));
262
+ if ((detail === null || detail === void 0 ? void 0 : detail.focusStrategy) === 'first') shouldVirtualFocusFirst.current = true;
263
+ });
264
+ let updateActiveDescendant = (0, $bT8Bh$reactariautils.useEffectEvent)(()=>{
265
+ var _delegate_getFirstKey, _ref_current;
266
+ var _delegate_getFirstKey1;
267
+ let keyToFocus = (_delegate_getFirstKey1 = (_delegate_getFirstKey = delegate.getFirstKey) === null || _delegate_getFirstKey === void 0 ? void 0 : _delegate_getFirstKey.call(delegate)) !== null && _delegate_getFirstKey1 !== void 0 ? _delegate_getFirstKey1 : null;
268
+ // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist
269
+ if (keyToFocus == null) (_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.dispatchEvent(new CustomEvent((0, $bT8Bh$reactariautils.UPDATE_ACTIVEDESCENDANT), {
270
+ cancelable: true,
271
+ bubbles: true
272
+ }));
273
+ else {
267
274
  manager.setFocusedKey(keyToFocus);
275
+ // Only set shouldVirtualFocusFirst to false if we've successfully set the first key as the focused key
276
+ // If there wasn't a key to focus, we might be in a temporary loading state so we'll want to still focus the first key
277
+ // after the collection updates after load
278
+ shouldVirtualFocusFirst.current = false;
268
279
  }
269
280
  });
281
+ (0, $bT8Bh$reactariautils.useUpdateLayoutEffect)(()=>{
282
+ if (shouldVirtualFocusFirst.current) updateActiveDescendant();
283
+ }, [
284
+ manager.collection,
285
+ updateActiveDescendant
286
+ ]);
287
+ let resetFocusFirstFlag = (0, $bT8Bh$reactariautils.useEffectEvent)(()=>{
288
+ // If user causes the focused key to change in any other way, clear shouldVirtualFocusFirst so we don't
289
+ // accidentally move focus from under them. Skip this if the collection was empty because we might be in a load
290
+ // state and will still want to focus the first item after load
291
+ if (manager.collection.size > 0) shouldVirtualFocusFirst.current = false;
292
+ });
293
+ (0, $bT8Bh$reactariautils.useUpdateLayoutEffect)(()=>{
294
+ resetFocusFirstFlag();
295
+ }, [
296
+ manager.focusedKey,
297
+ resetFocusFirstFlag
298
+ ]);
270
299
  (0, $bT8Bh$reactariautils.useEvent)(ref, (0, $bT8Bh$reactariautils.CLEAR_FOCUS_EVENT), !shouldUseVirtualFocus ? undefined : (e)=>{
271
300
  e.stopPropagation();
272
301
  manager.setFocused(false);
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-aria/selection/src/useSelectableCollection.ts"],"sourcesContent":["/*\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\nimport {CLEAR_FOCUS_EVENT, FOCUS_EVENT, focusWithoutScrolling, mergeProps, scrollIntoView, scrollIntoViewport, UPDATE_ACTIVEDESCENDANT, useEvent, useRouter} from '@react-aria/utils';\nimport {DOMAttributes, FocusableElement, FocusStrategy, Key, KeyboardDelegate, RefObject} from '@react-types/shared';\nimport {flushSync} from 'react-dom';\nimport {FocusEvent, KeyboardEvent, useEffect, useRef} from 'react';\nimport {focusSafely, getFocusableTreeWalker} from '@react-aria/focus';\nimport {getInteractionModality} from '@react-aria/interactions';\nimport {isCtrlKeyPressed, isNonContiguousSelectionModifier} from './utils';\nimport {MultipleSelectionManager} from '@react-stately/selection';\nimport {useLocale} from '@react-aria/i18n';\nimport {useTypeSelect} from './useTypeSelect';\n\nexport interface AriaSelectableCollectionOptions {\n /**\n * An interface for reading and updating multiple selection state.\n */\n selectionManager: MultipleSelectionManager,\n /**\n * A delegate object that implements behavior for keyboard focus movement.\n */\n keyboardDelegate: KeyboardDelegate,\n /**\n * The ref attached to the element representing the collection.\n */\n ref: RefObject<HTMLElement | null>,\n /**\n * Whether the collection or one of its items should be automatically focused upon render.\n * @default false\n */\n autoFocus?: boolean | FocusStrategy,\n /**\n * Whether focus should wrap around when the end/start is reached.\n * @default false\n */\n shouldFocusWrap?: boolean,\n /**\n * Whether the collection allows empty selection.\n * @default false\n */\n disallowEmptySelection?: boolean,\n /**\n * Whether the collection allows the user to select all items via keyboard shortcut.\n * @default false\n */\n disallowSelectAll?: boolean,\n /**\n * Whether selection should occur automatically on focus.\n * @default false\n */\n selectOnFocus?: boolean,\n /**\n * Whether typeahead is disabled.\n * @default false\n */\n disallowTypeAhead?: boolean,\n /**\n * Whether the collection items should use virtual focus instead of being focused directly.\n */\n shouldUseVirtualFocus?: boolean,\n /**\n * Whether navigation through tab key is enabled.\n */\n allowsTabNavigation?: boolean,\n /**\n * Whether the collection items are contained in a virtual scroller.\n */\n isVirtualized?: boolean,\n /**\n * The ref attached to the scrollable body. Used to provide automatic scrolling on item focus for non-virtualized collections.\n * If not provided, defaults to the collection ref.\n */\n scrollRef?: RefObject<HTMLElement | null>,\n /**\n * The behavior of links in the collection.\n * - 'action': link behaves like onAction.\n * - 'selection': link follows selection interactions (e.g. if URL drives selection).\n * - 'override': links override all other interactions (link items are not selectable).\n * @default 'action'\n */\n linkBehavior?: 'action' | 'selection' | 'override'\n}\n\nexport interface SelectableCollectionAria {\n /** Props for the collection element. */\n collectionProps: DOMAttributes\n}\n\n/**\n * Handles interactions with selectable collections.\n */\nexport function useSelectableCollection(options: AriaSelectableCollectionOptions): SelectableCollectionAria {\n let {\n selectionManager: manager,\n keyboardDelegate: delegate,\n ref,\n autoFocus = false,\n shouldFocusWrap = false,\n disallowEmptySelection = false,\n disallowSelectAll = false,\n selectOnFocus = manager.selectionBehavior === 'replace',\n disallowTypeAhead = false,\n shouldUseVirtualFocus,\n allowsTabNavigation = false,\n isVirtualized,\n // If no scrollRef is provided, assume the collection ref is the scrollable region\n scrollRef = ref,\n linkBehavior = 'action'\n } = options;\n let {direction} = useLocale();\n let router = useRouter();\n\n let onKeyDown = (e: KeyboardEvent) => {\n // Prevent option + tab from doing anything since it doesn't move focus to the cells, only buttons/checkboxes\n if (e.altKey && e.key === 'Tab') {\n e.preventDefault();\n }\n\n // Keyboard events bubble through portals. Don't handle keyboard events\n // for elements outside the collection (e.g. menus).\n if (!ref.current?.contains(e.target as Element)) {\n return;\n }\n\n const navigateToKey = (key: Key | undefined, childFocus?: FocusStrategy) => {\n if (key != null) {\n if (manager.isLink(key) && linkBehavior === 'selection' && selectOnFocus && !isNonContiguousSelectionModifier(e)) {\n // Set focused key and re-render synchronously to bring item into view if needed.\n flushSync(() => {\n manager.setFocusedKey(key, childFocus);\n });\n\n let item = scrollRef.current?.querySelector(`[data-key=\"${CSS.escape(key.toString())}\"]`);\n let itemProps = manager.getItemProps(key);\n if (item) {\n router.open(item, e, itemProps.href, itemProps.routerOptions);\n }\n\n return;\n }\n\n manager.setFocusedKey(key, childFocus);\n\n if (manager.isLink(key) && linkBehavior === 'override') {\n return;\n }\n\n if (e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(key);\n } else if (selectOnFocus && !isNonContiguousSelectionModifier(e)) {\n manager.replaceSelection(key);\n }\n }\n };\n\n switch (e.key) {\n case 'ArrowDown': {\n if (delegate.getKeyBelow) {\n let nextKey = manager.focusedKey != null\n ? delegate.getKeyBelow?.(manager.focusedKey)\n : delegate.getFirstKey?.();\n if (nextKey == null && shouldFocusWrap) {\n nextKey = delegate.getFirstKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n }\n case 'ArrowUp': {\n if (delegate.getKeyAbove) {\n let nextKey = manager.focusedKey != null\n ? delegate.getKeyAbove?.(manager.focusedKey)\n : delegate.getLastKey?.();\n if (nextKey == null && shouldFocusWrap) {\n nextKey = delegate.getLastKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n }\n case 'ArrowLeft': {\n if (delegate.getKeyLeftOf) {\n let nextKey: Key | undefined | null = manager.focusedKey != null ? delegate.getKeyLeftOf?.(manager.focusedKey) : null;\n if (nextKey == null && shouldFocusWrap) {\n nextKey = direction === 'rtl' ? delegate.getFirstKey?.(manager.focusedKey) : delegate.getLastKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey, direction === 'rtl' ? 'first' : 'last');\n }\n }\n break;\n }\n case 'ArrowRight': {\n if (delegate.getKeyRightOf) {\n let nextKey: Key | undefined | null = manager.focusedKey != null ? delegate.getKeyRightOf?.(manager.focusedKey) : null;\n if (nextKey == null && shouldFocusWrap) {\n nextKey = direction === 'rtl' ? delegate.getLastKey?.(manager.focusedKey) : delegate.getFirstKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey, direction === 'rtl' ? 'last' : 'first');\n }\n }\n break;\n }\n case 'Home':\n if (delegate.getFirstKey) {\n if (manager.focusedKey === null && e.shiftKey) {\n return;\n }\n e.preventDefault();\n let firstKey: Key | null = delegate.getFirstKey(manager.focusedKey, isCtrlKeyPressed(e));\n manager.setFocusedKey(firstKey);\n if (firstKey != null) {\n if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(firstKey);\n } else if (selectOnFocus) {\n manager.replaceSelection(firstKey);\n }\n }\n }\n break;\n case 'End':\n if (delegate.getLastKey) {\n if (manager.focusedKey === null && e.shiftKey) {\n return;\n }\n e.preventDefault();\n let lastKey = delegate.getLastKey(manager.focusedKey, isCtrlKeyPressed(e));\n manager.setFocusedKey(lastKey);\n if (lastKey != null) {\n if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(lastKey);\n } else if (selectOnFocus) {\n manager.replaceSelection(lastKey);\n }\n }\n }\n break;\n case 'PageDown':\n if (delegate.getKeyPageBelow && manager.focusedKey != null) {\n let nextKey = delegate.getKeyPageBelow(manager.focusedKey);\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n case 'PageUp':\n if (delegate.getKeyPageAbove && manager.focusedKey != null) {\n let nextKey = delegate.getKeyPageAbove(manager.focusedKey);\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n case 'a':\n if (isCtrlKeyPressed(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {\n e.preventDefault();\n manager.selectAll();\n }\n break;\n case 'Escape':\n if (!disallowEmptySelection && manager.selectedKeys.size !== 0) {\n e.stopPropagation();\n e.preventDefault();\n manager.clearSelection();\n }\n break;\n case 'Tab': {\n if (!allowsTabNavigation) {\n // There may be elements that are \"tabbable\" inside a collection (e.g. in a grid cell).\n // However, collections should be treated as a single tab stop, with arrow key navigation internally.\n // We don't control the rendering of these, so we can't override the tabIndex to prevent tabbing.\n // Instead, we handle the Tab key, and move focus manually to the first/last tabbable element\n // in the collection, so that the browser default behavior will apply starting from that element\n // rather than the currently focused one.\n if (e.shiftKey) {\n ref.current.focus();\n } else {\n let walker = getFocusableTreeWalker(ref.current, {tabbable: true});\n let next: FocusableElement | undefined = undefined;\n let last: FocusableElement;\n do {\n last = walker.lastChild() as FocusableElement;\n if (last) {\n next = last;\n }\n } while (last);\n\n if (next && !next.contains(document.activeElement)) {\n focusWithoutScrolling(next);\n }\n }\n break;\n }\n }\n }\n };\n\n // Store the scroll position so we can restore it later.\n /// TODO: should this happen all the time??\n let scrollPos = useRef({top: 0, left: 0});\n useEvent(scrollRef, 'scroll', isVirtualized ? undefined : () => {\n scrollPos.current = {\n top: scrollRef.current?.scrollTop ?? 0,\n left: scrollRef.current?.scrollLeft ?? 0\n };\n });\n\n let onFocus = (e: FocusEvent) => {\n if (manager.isFocused) {\n // If a focus event bubbled through a portal, reset focus state.\n if (!e.currentTarget.contains(e.target)) {\n manager.setFocused(false);\n }\n\n return;\n }\n\n // Focus events can bubble through portals. Ignore these events.\n if (!e.currentTarget.contains(e.target)) {\n return;\n }\n\n manager.setFocused(true);\n\n if (manager.focusedKey == null) {\n let navigateToFirstKey = (key: Key | undefined | null) => {\n if (key != null) {\n manager.setFocusedKey(key);\n if (selectOnFocus) {\n manager.replaceSelection(key);\n }\n }\n };\n // If the user hasn't yet interacted with the collection, there will be no focusedKey set.\n // Attempt to detect whether the user is tabbing forward or backward into the collection\n // and either focus the first or last item accordingly.\n let relatedTarget = e.relatedTarget as Element;\n if (relatedTarget && (e.currentTarget.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING)) {\n navigateToFirstKey(manager.lastSelectedKey ?? delegate.getLastKey?.());\n } else {\n navigateToFirstKey(manager.firstSelectedKey ?? delegate.getFirstKey?.());\n }\n } else if (!isVirtualized && scrollRef.current) {\n // Restore the scroll position to what it was before.\n scrollRef.current.scrollTop = scrollPos.current.top;\n scrollRef.current.scrollLeft = scrollPos.current.left;\n }\n\n if (manager.focusedKey != null && scrollRef.current) {\n // Refocus and scroll the focused item into view if it exists within the scrollable region.\n let element = scrollRef.current.querySelector(`[data-key=\"${CSS.escape(manager.focusedKey.toString())}\"]`) as HTMLElement;\n if (element) {\n // This prevents a flash of focus on the first/last element in the collection, or the collection itself.\n if (!element.contains(document.activeElement)) {\n focusWithoutScrolling(element);\n }\n\n let modality = getInteractionModality();\n if (modality === 'keyboard') {\n scrollIntoViewport(element, {containingElement: ref.current});\n }\n }\n }\n };\n\n let onBlur = (e) => {\n // Don't set blurred and then focused again if moving focus within the collection.\n if (!e.currentTarget.contains(e.relatedTarget as HTMLElement)) {\n manager.setFocused(false);\n }\n };\n\n // Add event listeners for custom virtual events. These handle updating the focused key in response to various keyboard events\n // at the autocomplete level\n // TODO: fix type later\n useEvent(ref, FOCUS_EVENT, !shouldUseVirtualFocus ? undefined : (e: any) => {\n let {detail} = e;\n e.stopPropagation();\n manager.setFocused(true);\n\n // If the user is typing forwards, autofocus the first option in the list.\n if (detail?.focusStrategy === 'first') {\n let keyToFocus = delegate.getFirstKey?.() ?? null;\n // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist\n if (keyToFocus == null) {\n ref.current?.dispatchEvent(\n new CustomEvent(UPDATE_ACTIVEDESCENDANT, {\n cancelable: true,\n bubbles: true\n })\n );\n }\n\n manager.setFocusedKey(keyToFocus);\n }\n });\n\n useEvent(ref, CLEAR_FOCUS_EVENT, !shouldUseVirtualFocus ? undefined : (e) => {\n e.stopPropagation();\n manager.setFocused(false);\n manager.setFocusedKey(null);\n });\n\n const autoFocusRef = useRef(autoFocus);\n useEffect(() => {\n if (autoFocusRef.current) {\n let focusedKey: Key | null = null;\n\n // Check focus strategy to determine which item to focus\n if (autoFocus === 'first') {\n focusedKey = delegate.getFirstKey?.() ?? null;\n } if (autoFocus === 'last') {\n focusedKey = delegate.getLastKey?.() ?? null;\n }\n\n // If there are any selected keys, make the first one the new focus target\n let selectedKeys = manager.selectedKeys;\n if (selectedKeys.size) {\n for (let key of selectedKeys) {\n if (manager.canSelectItem(key)) {\n focusedKey = key;\n break;\n }\n }\n }\n\n manager.setFocused(true);\n manager.setFocusedKey(focusedKey);\n\n // If no default focus key is selected, focus the collection itself.\n if (focusedKey == null && !shouldUseVirtualFocus && ref.current) {\n focusSafely(ref.current);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Scroll the focused element into view when the focusedKey changes.\n let lastFocusedKey = useRef(manager.focusedKey);\n useEffect(() => {\n if (manager.isFocused && manager.focusedKey != null && (manager.focusedKey !== lastFocusedKey.current || autoFocusRef.current) && scrollRef.current && ref.current) {\n let modality = getInteractionModality();\n let element = ref.current.querySelector(`[data-key=\"${CSS.escape(manager.focusedKey.toString())}\"]`) as HTMLElement;\n if (!element) {\n // If item element wasn't found, return early (don't update autoFocusRef and lastFocusedKey).\n // The collection may initially be empty (e.g. virtualizer), so wait until the element exists.\n return;\n }\n\n if (modality === 'keyboard' || autoFocusRef.current) {\n scrollIntoView(scrollRef.current, element);\n\n // Avoid scroll in iOS VO, since it may cause overlay to close (i.e. RAC submenu)\n if (modality !== 'virtual') {\n scrollIntoViewport(element, {containingElement: ref.current});\n }\n }\n }\n\n // If the focused key becomes null (e.g. the last item is deleted), focus the whole collection.\n if (!shouldUseVirtualFocus && manager.isFocused && manager.focusedKey == null && lastFocusedKey.current != null && ref.current) {\n focusSafely(ref.current);\n }\n\n lastFocusedKey.current = manager.focusedKey;\n autoFocusRef.current = false;\n });\n\n // Intercept FocusScope restoration since virtualized collections can reuse DOM nodes.\n useEvent(ref, 'react-aria-focus-scope-restore', e => {\n e.preventDefault();\n manager.setFocused(true);\n });\n\n let handlers = {\n onKeyDown,\n onFocus,\n onBlur,\n onMouseDown(e) {\n // Ignore events that bubbled through portals.\n if (scrollRef.current === e.target) {\n // Prevent focus going to the collection when clicking on the scrollbar.\n e.preventDefault();\n }\n }\n };\n\n let {typeSelectProps} = useTypeSelect({\n keyboardDelegate: delegate,\n selectionManager: manager\n });\n\n if (!disallowTypeAhead) {\n handlers = mergeProps(typeSelectProps, handlers);\n }\n\n // If nothing is focused within the collection, make the collection itself tabbable.\n // This will be marshalled to either the first or last item depending on where focus came from.\n let tabIndex: number | undefined = undefined;\n if (!shouldUseVirtualFocus) {\n tabIndex = manager.focusedKey == null ? 0 : -1;\n } else {\n tabIndex = -1;\n }\n\n return {\n collectionProps: {\n ...handlers,\n tabIndex\n }\n };\n}\n"],"names":[],"version":3,"file":"useSelectableCollection.main.js.map"}
1
+ {"mappings":";;;;;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;;;;AA2FM,SAAS,0CAAwB,OAAwC;IAC9E,IAAI,EACF,kBAAkB,OAAO,EACzB,kBAAkB,QAAQ,OAC1B,GAAG,aACH,YAAY,wBACZ,kBAAkB,+BAClB,yBAAyB,0BACzB,oBAAoB,sBACpB,gBAAgB,QAAQ,iBAAiB,KAAK,8BAC9C,oBAAoB,8BACpB,qBAAqB,uBACrB,sBAAsB,sBACtB,aAAa,aACb,kFAAkF;IAClF,YAAY,mBACZ,eAAe,UAChB,GAAG;IACJ,IAAI,aAAC,SAAS,EAAC,GAAG,CAAA,GAAA,8BAAQ;IAC1B,IAAI,SAAS,CAAA,GAAA,+BAAQ;IAErB,IAAI,YAAY,CAAC;YAQV;QAPL,6GAA6G;QAC7G,IAAI,EAAE,MAAM,IAAI,EAAE,GAAG,KAAK,OACxB,EAAE,cAAc;QAGlB,uEAAuE;QACvE,oDAAoD;QACpD,IAAI,GAAC,eAAA,IAAI,OAAO,cAAX,mCAAA,aAAa,QAAQ,CAAC,EAAE,MAAM,IACjC;QAGF,MAAM,gBAAgB,CAAC,KAAsB;YAC3C,IAAI,OAAO,MAAM;gBACf,IAAI,QAAQ,MAAM,CAAC,QAAQ,iBAAiB,eAAe,iBAAiB,CAAC,CAAA,GAAA,0DAA+B,EAAE,IAAI;wBAMrG;oBALX,iFAAiF;oBACjF,CAAA,GAAA,yBAAQ,EAAE;wBACR,QAAQ,aAAa,CAAC,KAAK;oBAC7B;oBAEA,IAAI,QAAO,qBAAA,UAAU,OAAO,cAAjB,yCAAA,mBAAmB,aAAa,CAAC,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,IAAI,QAAQ,IAAI,EAAE,CAAC;oBACxF,IAAI,YAAY,QAAQ,YAAY,CAAC;oBACrC,IAAI,MACF,OAAO,IAAI,CAAC,MAAM,GAAG,UAAU,IAAI,EAAE,UAAU,aAAa;oBAG9D;gBACF;gBAEA,QAAQ,aAAa,CAAC,KAAK;gBAE3B,IAAI,QAAQ,MAAM,CAAC,QAAQ,iBAAiB,YAC1C;gBAGF,IAAI,EAAE,QAAQ,IAAI,QAAQ,aAAa,KAAK,YAC1C,QAAQ,eAAe,CAAC;qBACnB,IAAI,iBAAiB,CAAC,CAAA,GAAA,0DAA+B,EAAE,IAC5D,QAAQ,gBAAgB,CAAC;YAE7B;QACF;QAEA,OAAQ,EAAE,GAAG;YACX,KAAK;gBACH,IAAI,SAAS,WAAW,EAAE;wBAElB,uBACA,uBAEM;oBAJZ,IAAI,UAAU,QAAQ,UAAU,IAAI,QAC9B,wBAAA,SAAS,WAAW,cAApB,4CAAA,2BAAA,UAAuB,QAAQ,UAAU,KACzC,wBAAA,SAAS,WAAW,cAApB,4CAAA,2BAAA;oBACN,IAAI,WAAW,QAAQ,iBACrB,WAAU,yBAAA,SAAS,WAAW,cAApB,6CAAA,4BAAA,UAAuB,QAAQ,UAAU;oBAErD,IAAI,WAAW,MAAM;wBACnB,EAAE,cAAc;wBAChB,cAAc;oBAChB;gBACF;gBACA;YAEF,KAAK;gBACH,IAAI,SAAS,WAAW,EAAE;wBAElB,uBACA,sBAEM;oBAJZ,IAAI,UAAU,QAAQ,UAAU,IAAI,QAC9B,wBAAA,SAAS,WAAW,cAApB,4CAAA,2BAAA,UAAuB,QAAQ,UAAU,KACzC,uBAAA,SAAS,UAAU,cAAnB,2CAAA,0BAAA;oBACN,IAAI,WAAW,QAAQ,iBACrB,WAAU,wBAAA,SAAS,UAAU,cAAnB,4CAAA,2BAAA,UAAsB,QAAQ,UAAU;oBAEpD,IAAI,WAAW,MAAM;wBACnB,EAAE,cAAc;wBAChB,cAAc;oBAChB;gBACF;gBACA;YAEF,KAAK;gBACH,IAAI,SAAS,YAAY,EAAE;wBAC0C,wBAEjC,wBAA6C;oBAF/E,IAAI,UAAkC,QAAQ,UAAU,IAAI,QAAO,yBAAA,SAAS,YAAY,cAArB,6CAAA,4BAAA,UAAwB,QAAQ,UAAU,IAAI;oBACjH,IAAI,WAAW,QAAQ,iBACrB,UAAU,cAAc,SAAQ,yBAAA,SAAS,WAAW,cAApB,6CAAA,4BAAA,UAAuB,QAAQ,UAAU,KAAI,wBAAA,SAAS,UAAU,cAAnB,4CAAA,2BAAA,UAAsB,QAAQ,UAAU;oBAEvH,IAAI,WAAW,MAAM;wBACnB,EAAE,cAAc;wBAChB,cAAc,SAAS,cAAc,QAAQ,UAAU;oBACzD;gBACF;gBACA;YAEF,KAAK;gBACH,IAAI,SAAS,aAAa,EAAE;wBACyC,yBAEjC,uBAA4C;oBAF9E,IAAI,UAAkC,QAAQ,UAAU,IAAI,QAAO,0BAAA,SAAS,aAAa,cAAtB,8CAAA,6BAAA,UAAyB,QAAQ,UAAU,IAAI;oBAClH,IAAI,WAAW,QAAQ,iBACrB,UAAU,cAAc,SAAQ,wBAAA,SAAS,UAAU,cAAnB,4CAAA,2BAAA,UAAsB,QAAQ,UAAU,KAAI,yBAAA,SAAS,WAAW,cAApB,6CAAA,4BAAA,UAAuB,QAAQ,UAAU;oBAEvH,IAAI,WAAW,MAAM;wBACnB,EAAE,cAAc;wBAChB,cAAc,SAAS,cAAc,QAAQ,SAAS;oBACxD;gBACF;gBACA;YAEF,KAAK;gBACH,IAAI,SAAS,WAAW,EAAE;oBACxB,IAAI,QAAQ,UAAU,KAAK,QAAQ,EAAE,QAAQ,EAC3C;oBAEF,EAAE,cAAc;oBAChB,IAAI,WAAuB,SAAS,WAAW,CAAC,QAAQ,UAAU,EAAE,CAAA,GAAA,sCAAe,EAAE;oBACrF,QAAQ,aAAa,CAAC;oBACtB,IAAI,YAAY,MAAM;wBACpB,IAAI,CAAA,GAAA,sCAAe,EAAE,MAAM,EAAE,QAAQ,IAAI,QAAQ,aAAa,KAAK,YACjE,QAAQ,eAAe,CAAC;6BACnB,IAAI,eACT,QAAQ,gBAAgB,CAAC;oBAE7B;gBACF;gBACA;YACF,KAAK;gBACH,IAAI,SAAS,UAAU,EAAE;oBACvB,IAAI,QAAQ,UAAU,KAAK,QAAQ,EAAE,QAAQ,EAC3C;oBAEF,EAAE,cAAc;oBAChB,IAAI,UAAU,SAAS,UAAU,CAAC,QAAQ,UAAU,EAAE,CAAA,GAAA,sCAAe,EAAE;oBACvE,QAAQ,aAAa,CAAC;oBACtB,IAAI,WAAW,MAAM;wBACnB,IAAI,CAAA,GAAA,sCAAe,EAAE,MAAM,EAAE,QAAQ,IAAI,QAAQ,aAAa,KAAK,YACjE,QAAQ,eAAe,CAAC;6BACnB,IAAI,eACT,QAAQ,gBAAgB,CAAC;oBAE7B;gBACF;gBACA;YACF,KAAK;gBACH,IAAI,SAAS,eAAe,IAAI,QAAQ,UAAU,IAAI,MAAM;oBAC1D,IAAI,UAAU,SAAS,eAAe,CAAC,QAAQ,UAAU;oBACzD,IAAI,WAAW,MAAM;wBACnB,EAAE,cAAc;wBAChB,cAAc;oBAChB;gBACF;gBACA;YACF,KAAK;gBACH,IAAI,SAAS,eAAe,IAAI,QAAQ,UAAU,IAAI,MAAM;oBAC1D,IAAI,UAAU,SAAS,eAAe,CAAC,QAAQ,UAAU;oBACzD,IAAI,WAAW,MAAM;wBACnB,EAAE,cAAc;wBAChB,cAAc;oBAChB;gBACF;gBACA;YACF,KAAK;gBACH,IAAI,CAAA,GAAA,sCAAe,EAAE,MAAM,QAAQ,aAAa,KAAK,cAAc,sBAAsB,MAAM;oBAC7F,EAAE,cAAc;oBAChB,QAAQ,SAAS;gBACnB;gBACA;YACF,KAAK;gBACH,IAAI,CAAC,0BAA0B,QAAQ,YAAY,CAAC,IAAI,KAAK,GAAG;oBAC9D,EAAE,eAAe;oBACjB,EAAE,cAAc;oBAChB,QAAQ,cAAc;gBACxB;gBACA;YACF,KAAK;gBACH,IAAI,CAAC,qBAAqB;oBACxB,uFAAuF;oBACvF,qGAAqG;oBACrG,iGAAiG;oBACjG,6FAA6F;oBAC7F,gGAAgG;oBAChG,yCAAyC;oBACzC,IAAI,EAAE,QAAQ,EACZ,IAAI,OAAO,CAAC,KAAK;yBACZ;wBACL,IAAI,SAAS,CAAA,GAAA,4CAAqB,EAAE,IAAI,OAAO,EAAE;4BAAC,UAAU;wBAAI;wBAChE,IAAI,OAAqC;wBACzC,IAAI;wBACJ,GAAG;4BACD,OAAO,OAAO,SAAS;4BACvB,IAAI,MACF,OAAO;wBAEX,QAAS,MAAM;wBAEf,IAAI,QAAQ,CAAC,KAAK,QAAQ,CAAC,SAAS,aAAa,GAC/C,CAAA,GAAA,2CAAoB,EAAE;oBAE1B;oBACA;gBACF;QAEJ;IACF;IAEA,wDAAwD;IACxD,2CAA2C;IAC3C,IAAI,YAAY,CAAA,GAAA,mBAAK,EAAE;QAAC,KAAK;QAAG,MAAM;IAAC;IACvC,CAAA,GAAA,8BAAO,EAAE,WAAW,UAAU,gBAAgB,YAAY;YAEjD,oBACC;YADD,8BACC;QAFR,UAAU,OAAO,GAAG;YAClB,KAAK,CAAA,gCAAA,qBAAA,UAAU,OAAO,cAAjB,yCAAA,mBAAmB,SAAS,cAA5B,0CAAA,+BAAgC;YACrC,MAAM,CAAA,iCAAA,sBAAA,UAAU,OAAO,cAAjB,0CAAA,oBAAmB,UAAU,cAA7B,2CAAA,gCAAiC;QACzC;IACF;IAEA,IAAI,UAAU,CAAC;QACb,IAAI,QAAQ,SAAS,EAAE;YACrB,gEAAgE;YAChE,IAAI,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GACpC,QAAQ,UAAU,CAAC;YAGrB;QACF;QAEA,gEAAgE;QAChE,IAAI,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GACpC;QAGF,QAAQ,UAAU,CAAC;QAEnB,IAAI,QAAQ,UAAU,IAAI,MAAM;gBAckB,sBAEC;YAfjD,IAAI,qBAAqB,CAAC;gBACxB,IAAI,OAAO,MAAM;oBACf,QAAQ,aAAa,CAAC;oBACtB,IAAI,eACF,QAAQ,gBAAgB,CAAC;gBAE7B;YACF;YACA,0FAA0F;YAC1F,wFAAwF;YACxF,uDAAuD;YACvD,IAAI,gBAAgB,EAAE,aAAa;gBAEd,0BAEA;YAHrB,IAAI,iBAAkB,EAAE,aAAa,CAAC,uBAAuB,CAAC,iBAAiB,KAAK,2BAA2B,EAC7G,mBAAmB,CAAA,2BAAA,QAAQ,eAAe,cAAvB,sCAAA,4BAA2B,uBAAA,SAAS,UAAU,cAAnB,2CAAA,0BAAA;iBAE9C,mBAAmB,CAAA,4BAAA,QAAQ,gBAAgB,cAAxB,uCAAA,6BAA4B,wBAAA,SAAS,WAAW,cAApB,4CAAA,2BAAA;QAEnD,OAAO,IAAI,CAAC,iBAAiB,UAAU,OAAO,EAAE;YAC9C,qDAAqD;YACrD,UAAU,OAAO,CAAC,SAAS,GAAG,UAAU,OAAO,CAAC,GAAG;YACnD,UAAU,OAAO,CAAC,UAAU,GAAG,UAAU,OAAO,CAAC,IAAI;QACvD;QAEA,IAAI,QAAQ,UAAU,IAAI,QAAQ,UAAU,OAAO,EAAE;YACnD,2FAA2F;YAC3F,IAAI,UAAU,UAAU,OAAO,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,QAAQ,UAAU,CAAC,QAAQ,IAAI,EAAE,CAAC;YACzG,IAAI,SAAS;gBACX,wGAAwG;gBACxG,IAAI,CAAC,QAAQ,QAAQ,CAAC,SAAS,aAAa,GAC1C,CAAA,GAAA,2CAAoB,EAAE;gBAGxB,IAAI,WAAW,CAAA,GAAA,mDAAqB;gBACpC,IAAI,aAAa,YACf,CAAA,GAAA,wCAAiB,EAAE,SAAS;oBAAC,mBAAmB,IAAI,OAAO;gBAAA;YAE/D;QACF;IACF;IAEA,IAAI,SAAS,CAAC;QACZ,kFAAkF;QAClF,IAAI,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,EAAE,aAAa,GAC3C,QAAQ,UAAU,CAAC;IAEvB;IAEA,4IAA4I;IAC5I,uDAAuD;IACvD,6CAA6C;IAC7C,IAAI,0BAA0B,CAAA,GAAA,mBAAK,EAAE;IACrC,8HAA8H;IAC9H,4BAA4B;IAC5B,uBAAuB;IACvB,CAAA,GAAA,8BAAO,EAAE,KAAK,CAAA,GAAA,iCAAU,GAAG,CAAC,wBAAwB,YAAY,CAAC;QAC/D,IAAI,UAAC,MAAM,EAAC,GAAG;QACf,EAAE,eAAe;QACjB,QAAQ,UAAU,CAAC;QAEnB,0EAA0E;QAC1E,IAAI,CAAA,mBAAA,6BAAA,OAAQ,aAAa,MAAK,SAC5B,wBAAwB,OAAO,GAAG;IAEtC;IAEA,IAAI,yBAAyB,CAAA,GAAA,oCAAa,EAAE;YACzB,uBAIf;YAJe;QAAjB,IAAI,aAAa,CAAA,0BAAA,wBAAA,SAAS,WAAW,cAApB,4CAAA,2BAAA,uBAAA,oCAAA,yBAA4B;QAE7C,wGAAwG;QACxG,IAAI,cAAc,OAChB,eAAA,IAAI,OAAO,cAAX,mCAAA,aAAa,aAAa,CACxB,IAAI,YAAY,CAAA,GAAA,6CAAsB,GAAG;YACvC,YAAY;YACZ,SAAS;QACX;aAEG;YACL,QAAQ,aAAa,CAAC;YACtB,uGAAuG;YACvG,sHAAsH;YACtH,0CAA0C;YAC1C,wBAAwB,OAAO,GAAG;QACpC;IACF;IAEA,CAAA,GAAA,2CAAoB,EAAE;QACpB,IAAI,wBAAwB,OAAO,EACjC;IAGJ,GAAG;QAAC,QAAQ,UAAU;QAAE;KAAuB;IAE/C,IAAI,sBAAsB,CAAA,GAAA,oCAAa,EAAE;QACvC,uGAAuG;QACvG,+GAA+G;QAC/G,+DAA+D;QAC/D,IAAI,QAAQ,UAAU,CAAC,IAAI,GAAG,GAC5B,wBAAwB,OAAO,GAAG;IAEtC;IAEA,CAAA,GAAA,2CAAoB,EAAE;QACpB;IACF,GAAG;QAAC,QAAQ,UAAU;QAAE;KAAoB;IAE5C,CAAA,GAAA,8BAAO,EAAE,KAAK,CAAA,GAAA,uCAAgB,GAAG,CAAC,wBAAwB,YAAY,CAAC;QACrE,EAAE,eAAe;QACjB,QAAQ,UAAU,CAAC;QACnB,QAAQ,aAAa,CAAC;IACxB;IAEA,MAAM,eAAe,CAAA,GAAA,mBAAK,EAAE;IAC5B,CAAA,GAAA,sBAAQ,EAAE;QACR,IAAI,aAAa,OAAO,EAAE;gBAKT,uBAEA;YANf,IAAI,aAAyB;gBAId;YAFf,wDAAwD;YACxD,IAAI,cAAc,SAChB,aAAa,CAAA,0BAAA,wBAAA,SAAS,WAAW,cAApB,4CAAA,2BAAA,uBAAA,oCAAA,yBAA4B;gBAE5B;YADb,IAAI,cAAc,QAClB,aAAa,CAAA,yBAAA,uBAAA,SAAS,UAAU,cAAnB,2CAAA,0BAAA,uBAAA,mCAAA,wBAA2B;YAG1C,0EAA0E;YAC1E,IAAI,eAAe,QAAQ,YAAY;YACvC,IAAI,aAAa,IAAI,EAAE;gBACrB,KAAK,IAAI,OAAO,aACd,IAAI,QAAQ,aAAa,CAAC,MAAM;oBAC9B,aAAa;oBACb;gBACF;YAEJ;YAEA,QAAQ,UAAU,CAAC;YACnB,QAAQ,aAAa,CAAC;YAEtB,oEAAoE;YACpE,IAAI,cAAc,QAAQ,CAAC,yBAAyB,IAAI,OAAO,EAC7D,CAAA,GAAA,iCAAU,EAAE,IAAI,OAAO;QAE3B;IACF,uDAAuD;IACvD,GAAG,EAAE;IAEL,oEAAoE;IACpE,IAAI,iBAAiB,CAAA,GAAA,mBAAK,EAAE,QAAQ,UAAU;IAC9C,CAAA,GAAA,sBAAQ,EAAE;QACR,IAAI,QAAQ,SAAS,IAAI,QAAQ,UAAU,IAAI,QAAS,CAAA,QAAQ,UAAU,KAAK,eAAe,OAAO,IAAI,aAAa,OAAO,AAAD,KAAM,UAAU,OAAO,IAAI,IAAI,OAAO,EAAE;YAClK,IAAI,WAAW,CAAA,GAAA,mDAAqB;YACpC,IAAI,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,QAAQ,UAAU,CAAC,QAAQ,IAAI,EAAE,CAAC;YACnG,IAAI,CAAC,SACH,6FAA6F;YAC7F,8FAA8F;YAC9F;YAGF,IAAI,aAAa,cAAc,aAAa,OAAO,EAAE;gBACnD,CAAA,GAAA,oCAAa,EAAE,UAAU,OAAO,EAAE;gBAElC,iFAAiF;gBACjF,IAAI,aAAa,WACf,CAAA,GAAA,wCAAiB,EAAE,SAAS;oBAAC,mBAAmB,IAAI,OAAO;gBAAA;YAE/D;QACF;QAEA,+FAA+F;QAC/F,IAAI,CAAC,yBAAyB,QAAQ,SAAS,IAAI,QAAQ,UAAU,IAAI,QAAQ,eAAe,OAAO,IAAI,QAAQ,IAAI,OAAO,EAC5H,CAAA,GAAA,iCAAU,EAAE,IAAI,OAAO;QAGzB,eAAe,OAAO,GAAG,QAAQ,UAAU;QAC3C,aAAa,OAAO,GAAG;IACzB;IAEA,sFAAsF;IACtF,CAAA,GAAA,8BAAO,EAAE,KAAK,kCAAkC,CAAA;QAC9C,EAAE,cAAc;QAChB,QAAQ,UAAU,CAAC;IACrB;IAEA,IAAI,WAAW;mBACb;iBACA;gBACA;QACA,aAAY,CAAC;YACX,8CAA8C;YAC9C,IAAI,UAAU,OAAO,KAAK,EAAE,MAAM,EAChC,wEAAwE;YACxE,EAAE,cAAc;QAEpB;IACF;IAEA,IAAI,mBAAC,eAAe,EAAC,GAAG,CAAA,GAAA,uCAAY,EAAE;QACpC,kBAAkB;QAClB,kBAAkB;IACpB;IAEA,IAAI,CAAC,mBACH,WAAW,CAAA,GAAA,gCAAS,EAAE,iBAAiB;IAGzC,oFAAoF;IACpF,+FAA+F;IAC/F,IAAI,WAA+B;IACnC,IAAI,CAAC,uBACH,WAAW,QAAQ,UAAU,IAAI,OAAO,IAAI;SAE5C,WAAW;IAGb,OAAO;QACL,iBAAiB;YACf,GAAG,QAAQ;sBACX;QACF;IACF;AACF","sources":["packages/@react-aria/selection/src/useSelectableCollection.ts"],"sourcesContent":["/*\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\nimport {CLEAR_FOCUS_EVENT, FOCUS_EVENT, focusWithoutScrolling, isCtrlKeyPressed, mergeProps, scrollIntoView, scrollIntoViewport, UPDATE_ACTIVEDESCENDANT, useEffectEvent, useEvent, useRouter, useUpdateLayoutEffect} from '@react-aria/utils';\nimport {DOMAttributes, FocusableElement, FocusStrategy, Key, KeyboardDelegate, RefObject} from '@react-types/shared';\nimport {flushSync} from 'react-dom';\nimport {FocusEvent, KeyboardEvent, useEffect, useRef} from 'react';\nimport {focusSafely, getFocusableTreeWalker} from '@react-aria/focus';\nimport {getInteractionModality} from '@react-aria/interactions';\nimport {isNonContiguousSelectionModifier} from './utils';\nimport {MultipleSelectionManager} from '@react-stately/selection';\nimport {useLocale} from '@react-aria/i18n';\nimport {useTypeSelect} from './useTypeSelect';\n\nexport interface AriaSelectableCollectionOptions {\n /**\n * An interface for reading and updating multiple selection state.\n */\n selectionManager: MultipleSelectionManager,\n /**\n * A delegate object that implements behavior for keyboard focus movement.\n */\n keyboardDelegate: KeyboardDelegate,\n /**\n * The ref attached to the element representing the collection.\n */\n ref: RefObject<HTMLElement | null>,\n /**\n * Whether the collection or one of its items should be automatically focused upon render.\n * @default false\n */\n autoFocus?: boolean | FocusStrategy,\n /**\n * Whether focus should wrap around when the end/start is reached.\n * @default false\n */\n shouldFocusWrap?: boolean,\n /**\n * Whether the collection allows empty selection.\n * @default false\n */\n disallowEmptySelection?: boolean,\n /**\n * Whether the collection allows the user to select all items via keyboard shortcut.\n * @default false\n */\n disallowSelectAll?: boolean,\n /**\n * Whether selection should occur automatically on focus.\n * @default false\n */\n selectOnFocus?: boolean,\n /**\n * Whether typeahead is disabled.\n * @default false\n */\n disallowTypeAhead?: boolean,\n /**\n * Whether the collection items should use virtual focus instead of being focused directly.\n */\n shouldUseVirtualFocus?: boolean,\n /**\n * Whether navigation through tab key is enabled.\n */\n allowsTabNavigation?: boolean,\n /**\n * Whether the collection items are contained in a virtual scroller.\n */\n isVirtualized?: boolean,\n /**\n * The ref attached to the scrollable body. Used to provide automatic scrolling on item focus for non-virtualized collections.\n * If not provided, defaults to the collection ref.\n */\n scrollRef?: RefObject<HTMLElement | null>,\n /**\n * The behavior of links in the collection.\n * - 'action': link behaves like onAction.\n * - 'selection': link follows selection interactions (e.g. if URL drives selection).\n * - 'override': links override all other interactions (link items are not selectable).\n * @default 'action'\n */\n linkBehavior?: 'action' | 'selection' | 'override'\n}\n\nexport interface SelectableCollectionAria {\n /** Props for the collection element. */\n collectionProps: DOMAttributes\n}\n\n/**\n * Handles interactions with selectable collections.\n */\nexport function useSelectableCollection(options: AriaSelectableCollectionOptions): SelectableCollectionAria {\n let {\n selectionManager: manager,\n keyboardDelegate: delegate,\n ref,\n autoFocus = false,\n shouldFocusWrap = false,\n disallowEmptySelection = false,\n disallowSelectAll = false,\n selectOnFocus = manager.selectionBehavior === 'replace',\n disallowTypeAhead = false,\n shouldUseVirtualFocus,\n allowsTabNavigation = false,\n isVirtualized,\n // If no scrollRef is provided, assume the collection ref is the scrollable region\n scrollRef = ref,\n linkBehavior = 'action'\n } = options;\n let {direction} = useLocale();\n let router = useRouter();\n\n let onKeyDown = (e: KeyboardEvent) => {\n // Prevent option + tab from doing anything since it doesn't move focus to the cells, only buttons/checkboxes\n if (e.altKey && e.key === 'Tab') {\n e.preventDefault();\n }\n\n // Keyboard events bubble through portals. Don't handle keyboard events\n // for elements outside the collection (e.g. menus).\n if (!ref.current?.contains(e.target as Element)) {\n return;\n }\n\n const navigateToKey = (key: Key | undefined, childFocus?: FocusStrategy) => {\n if (key != null) {\n if (manager.isLink(key) && linkBehavior === 'selection' && selectOnFocus && !isNonContiguousSelectionModifier(e)) {\n // Set focused key and re-render synchronously to bring item into view if needed.\n flushSync(() => {\n manager.setFocusedKey(key, childFocus);\n });\n\n let item = scrollRef.current?.querySelector(`[data-key=\"${CSS.escape(key.toString())}\"]`);\n let itemProps = manager.getItemProps(key);\n if (item) {\n router.open(item, e, itemProps.href, itemProps.routerOptions);\n }\n\n return;\n }\n\n manager.setFocusedKey(key, childFocus);\n\n if (manager.isLink(key) && linkBehavior === 'override') {\n return;\n }\n\n if (e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(key);\n } else if (selectOnFocus && !isNonContiguousSelectionModifier(e)) {\n manager.replaceSelection(key);\n }\n }\n };\n\n switch (e.key) {\n case 'ArrowDown': {\n if (delegate.getKeyBelow) {\n let nextKey = manager.focusedKey != null\n ? delegate.getKeyBelow?.(manager.focusedKey)\n : delegate.getFirstKey?.();\n if (nextKey == null && shouldFocusWrap) {\n nextKey = delegate.getFirstKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n }\n case 'ArrowUp': {\n if (delegate.getKeyAbove) {\n let nextKey = manager.focusedKey != null\n ? delegate.getKeyAbove?.(manager.focusedKey)\n : delegate.getLastKey?.();\n if (nextKey == null && shouldFocusWrap) {\n nextKey = delegate.getLastKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n }\n case 'ArrowLeft': {\n if (delegate.getKeyLeftOf) {\n let nextKey: Key | undefined | null = manager.focusedKey != null ? delegate.getKeyLeftOf?.(manager.focusedKey) : null;\n if (nextKey == null && shouldFocusWrap) {\n nextKey = direction === 'rtl' ? delegate.getFirstKey?.(manager.focusedKey) : delegate.getLastKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey, direction === 'rtl' ? 'first' : 'last');\n }\n }\n break;\n }\n case 'ArrowRight': {\n if (delegate.getKeyRightOf) {\n let nextKey: Key | undefined | null = manager.focusedKey != null ? delegate.getKeyRightOf?.(manager.focusedKey) : null;\n if (nextKey == null && shouldFocusWrap) {\n nextKey = direction === 'rtl' ? delegate.getLastKey?.(manager.focusedKey) : delegate.getFirstKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey, direction === 'rtl' ? 'last' : 'first');\n }\n }\n break;\n }\n case 'Home':\n if (delegate.getFirstKey) {\n if (manager.focusedKey === null && e.shiftKey) {\n return;\n }\n e.preventDefault();\n let firstKey: Key | null = delegate.getFirstKey(manager.focusedKey, isCtrlKeyPressed(e));\n manager.setFocusedKey(firstKey);\n if (firstKey != null) {\n if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(firstKey);\n } else if (selectOnFocus) {\n manager.replaceSelection(firstKey);\n }\n }\n }\n break;\n case 'End':\n if (delegate.getLastKey) {\n if (manager.focusedKey === null && e.shiftKey) {\n return;\n }\n e.preventDefault();\n let lastKey = delegate.getLastKey(manager.focusedKey, isCtrlKeyPressed(e));\n manager.setFocusedKey(lastKey);\n if (lastKey != null) {\n if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(lastKey);\n } else if (selectOnFocus) {\n manager.replaceSelection(lastKey);\n }\n }\n }\n break;\n case 'PageDown':\n if (delegate.getKeyPageBelow && manager.focusedKey != null) {\n let nextKey = delegate.getKeyPageBelow(manager.focusedKey);\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n case 'PageUp':\n if (delegate.getKeyPageAbove && manager.focusedKey != null) {\n let nextKey = delegate.getKeyPageAbove(manager.focusedKey);\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n case 'a':\n if (isCtrlKeyPressed(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {\n e.preventDefault();\n manager.selectAll();\n }\n break;\n case 'Escape':\n if (!disallowEmptySelection && manager.selectedKeys.size !== 0) {\n e.stopPropagation();\n e.preventDefault();\n manager.clearSelection();\n }\n break;\n case 'Tab': {\n if (!allowsTabNavigation) {\n // There may be elements that are \"tabbable\" inside a collection (e.g. in a grid cell).\n // However, collections should be treated as a single tab stop, with arrow key navigation internally.\n // We don't control the rendering of these, so we can't override the tabIndex to prevent tabbing.\n // Instead, we handle the Tab key, and move focus manually to the first/last tabbable element\n // in the collection, so that the browser default behavior will apply starting from that element\n // rather than the currently focused one.\n if (e.shiftKey) {\n ref.current.focus();\n } else {\n let walker = getFocusableTreeWalker(ref.current, {tabbable: true});\n let next: FocusableElement | undefined = undefined;\n let last: FocusableElement;\n do {\n last = walker.lastChild() as FocusableElement;\n if (last) {\n next = last;\n }\n } while (last);\n\n if (next && !next.contains(document.activeElement)) {\n focusWithoutScrolling(next);\n }\n }\n break;\n }\n }\n }\n };\n\n // Store the scroll position so we can restore it later.\n /// TODO: should this happen all the time??\n let scrollPos = useRef({top: 0, left: 0});\n useEvent(scrollRef, 'scroll', isVirtualized ? undefined : () => {\n scrollPos.current = {\n top: scrollRef.current?.scrollTop ?? 0,\n left: scrollRef.current?.scrollLeft ?? 0\n };\n });\n\n let onFocus = (e: FocusEvent) => {\n if (manager.isFocused) {\n // If a focus event bubbled through a portal, reset focus state.\n if (!e.currentTarget.contains(e.target)) {\n manager.setFocused(false);\n }\n\n return;\n }\n\n // Focus events can bubble through portals. Ignore these events.\n if (!e.currentTarget.contains(e.target)) {\n return;\n }\n\n manager.setFocused(true);\n\n if (manager.focusedKey == null) {\n let navigateToFirstKey = (key: Key | undefined | null) => {\n if (key != null) {\n manager.setFocusedKey(key);\n if (selectOnFocus) {\n manager.replaceSelection(key);\n }\n }\n };\n // If the user hasn't yet interacted with the collection, there will be no focusedKey set.\n // Attempt to detect whether the user is tabbing forward or backward into the collection\n // and either focus the first or last item accordingly.\n let relatedTarget = e.relatedTarget as Element;\n if (relatedTarget && (e.currentTarget.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING)) {\n navigateToFirstKey(manager.lastSelectedKey ?? delegate.getLastKey?.());\n } else {\n navigateToFirstKey(manager.firstSelectedKey ?? delegate.getFirstKey?.());\n }\n } else if (!isVirtualized && scrollRef.current) {\n // Restore the scroll position to what it was before.\n scrollRef.current.scrollTop = scrollPos.current.top;\n scrollRef.current.scrollLeft = scrollPos.current.left;\n }\n\n if (manager.focusedKey != null && scrollRef.current) {\n // Refocus and scroll the focused item into view if it exists within the scrollable region.\n let element = scrollRef.current.querySelector(`[data-key=\"${CSS.escape(manager.focusedKey.toString())}\"]`) as HTMLElement;\n if (element) {\n // This prevents a flash of focus on the first/last element in the collection, or the collection itself.\n if (!element.contains(document.activeElement)) {\n focusWithoutScrolling(element);\n }\n\n let modality = getInteractionModality();\n if (modality === 'keyboard') {\n scrollIntoViewport(element, {containingElement: ref.current});\n }\n }\n }\n };\n\n let onBlur = (e) => {\n // Don't set blurred and then focused again if moving focus within the collection.\n if (!e.currentTarget.contains(e.relatedTarget as HTMLElement)) {\n manager.setFocused(false);\n }\n };\n\n // Ref to track whether the first item in the collection should be automatically focused. Specifically used for autocomplete when user types\n // to focus the first key AFTER the collection updates.\n // TODO: potentially expand the usage of this\n let shouldVirtualFocusFirst = useRef(false);\n // Add event listeners for custom virtual events. These handle updating the focused key in response to various keyboard events\n // at the autocomplete level\n // TODO: fix type later\n useEvent(ref, FOCUS_EVENT, !shouldUseVirtualFocus ? undefined : (e: any) => {\n let {detail} = e;\n e.stopPropagation();\n manager.setFocused(true);\n\n // If the user is typing forwards, autofocus the first option in the list.\n if (detail?.focusStrategy === 'first') {\n shouldVirtualFocusFirst.current = true;\n }\n });\n\n let updateActiveDescendant = useEffectEvent(() => {\n let keyToFocus = delegate.getFirstKey?.() ?? null;\n\n // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist\n if (keyToFocus == null) {\n ref.current?.dispatchEvent(\n new CustomEvent(UPDATE_ACTIVEDESCENDANT, {\n cancelable: true,\n bubbles: true\n })\n );\n } else {\n manager.setFocusedKey(keyToFocus);\n // Only set shouldVirtualFocusFirst to false if we've successfully set the first key as the focused key\n // If there wasn't a key to focus, we might be in a temporary loading state so we'll want to still focus the first key\n // after the collection updates after load\n shouldVirtualFocusFirst.current = false;\n }\n });\n\n useUpdateLayoutEffect(() => {\n if (shouldVirtualFocusFirst.current) {\n updateActiveDescendant();\n }\n\n }, [manager.collection, updateActiveDescendant]);\n\n let resetFocusFirstFlag = useEffectEvent(() => {\n // If user causes the focused key to change in any other way, clear shouldVirtualFocusFirst so we don't\n // accidentally move focus from under them. Skip this if the collection was empty because we might be in a load\n // state and will still want to focus the first item after load\n if (manager.collection.size > 0) {\n shouldVirtualFocusFirst.current = false;\n }\n });\n\n useUpdateLayoutEffect(() => {\n resetFocusFirstFlag();\n }, [manager.focusedKey, resetFocusFirstFlag]);\n\n useEvent(ref, CLEAR_FOCUS_EVENT, !shouldUseVirtualFocus ? undefined : (e) => {\n e.stopPropagation();\n manager.setFocused(false);\n manager.setFocusedKey(null);\n });\n\n const autoFocusRef = useRef(autoFocus);\n useEffect(() => {\n if (autoFocusRef.current) {\n let focusedKey: Key | null = null;\n\n // Check focus strategy to determine which item to focus\n if (autoFocus === 'first') {\n focusedKey = delegate.getFirstKey?.() ?? null;\n } if (autoFocus === 'last') {\n focusedKey = delegate.getLastKey?.() ?? null;\n }\n\n // If there are any selected keys, make the first one the new focus target\n let selectedKeys = manager.selectedKeys;\n if (selectedKeys.size) {\n for (let key of selectedKeys) {\n if (manager.canSelectItem(key)) {\n focusedKey = key;\n break;\n }\n }\n }\n\n manager.setFocused(true);\n manager.setFocusedKey(focusedKey);\n\n // If no default focus key is selected, focus the collection itself.\n if (focusedKey == null && !shouldUseVirtualFocus && ref.current) {\n focusSafely(ref.current);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Scroll the focused element into view when the focusedKey changes.\n let lastFocusedKey = useRef(manager.focusedKey);\n useEffect(() => {\n if (manager.isFocused && manager.focusedKey != null && (manager.focusedKey !== lastFocusedKey.current || autoFocusRef.current) && scrollRef.current && ref.current) {\n let modality = getInteractionModality();\n let element = ref.current.querySelector(`[data-key=\"${CSS.escape(manager.focusedKey.toString())}\"]`) as HTMLElement;\n if (!element) {\n // If item element wasn't found, return early (don't update autoFocusRef and lastFocusedKey).\n // The collection may initially be empty (e.g. virtualizer), so wait until the element exists.\n return;\n }\n\n if (modality === 'keyboard' || autoFocusRef.current) {\n scrollIntoView(scrollRef.current, element);\n\n // Avoid scroll in iOS VO, since it may cause overlay to close (i.e. RAC submenu)\n if (modality !== 'virtual') {\n scrollIntoViewport(element, {containingElement: ref.current});\n }\n }\n }\n\n // If the focused key becomes null (e.g. the last item is deleted), focus the whole collection.\n if (!shouldUseVirtualFocus && manager.isFocused && manager.focusedKey == null && lastFocusedKey.current != null && ref.current) {\n focusSafely(ref.current);\n }\n\n lastFocusedKey.current = manager.focusedKey;\n autoFocusRef.current = false;\n });\n\n // Intercept FocusScope restoration since virtualized collections can reuse DOM nodes.\n useEvent(ref, 'react-aria-focus-scope-restore', e => {\n e.preventDefault();\n manager.setFocused(true);\n });\n\n let handlers = {\n onKeyDown,\n onFocus,\n onBlur,\n onMouseDown(e) {\n // Ignore events that bubbled through portals.\n if (scrollRef.current === e.target) {\n // Prevent focus going to the collection when clicking on the scrollbar.\n e.preventDefault();\n }\n }\n };\n\n let {typeSelectProps} = useTypeSelect({\n keyboardDelegate: delegate,\n selectionManager: manager\n });\n\n if (!disallowTypeAhead) {\n handlers = mergeProps(typeSelectProps, handlers);\n }\n\n // If nothing is focused within the collection, make the collection itself tabbable.\n // This will be marshalled to either the first or last item depending on where focus came from.\n let tabIndex: number | undefined = undefined;\n if (!shouldUseVirtualFocus) {\n tabIndex = manager.focusedKey == null ? 0 : -1;\n } else {\n tabIndex = -1;\n }\n\n return {\n collectionProps: {\n ...handlers,\n tabIndex\n }\n };\n}\n"],"names":[],"version":3,"file":"useSelectableCollection.main.js.map"}
@@ -1,6 +1,6 @@
1
- import {isCtrlKeyPressed as $feb5ffebff200149$export$16792effe837dba3, isNonContiguousSelectionModifier as $feb5ffebff200149$export$d3e3bd3e26688c04} from "./utils.mjs";
1
+ import {isNonContiguousSelectionModifier as $feb5ffebff200149$export$d3e3bd3e26688c04} from "./utils.mjs";
2
2
  import {useTypeSelect as $fb3050f43d946246$export$e32c88dfddc6e1d8} from "./useTypeSelect.mjs";
3
- import {useRouter as $3H3GQ$useRouter, focusWithoutScrolling as $3H3GQ$focusWithoutScrolling, useEvent as $3H3GQ$useEvent, scrollIntoViewport as $3H3GQ$scrollIntoViewport, FOCUS_EVENT as $3H3GQ$FOCUS_EVENT, UPDATE_ACTIVEDESCENDANT as $3H3GQ$UPDATE_ACTIVEDESCENDANT, CLEAR_FOCUS_EVENT as $3H3GQ$CLEAR_FOCUS_EVENT, scrollIntoView as $3H3GQ$scrollIntoView, mergeProps as $3H3GQ$mergeProps} from "@react-aria/utils";
3
+ import {useRouter as $3H3GQ$useRouter, isCtrlKeyPressed as $3H3GQ$isCtrlKeyPressed, focusWithoutScrolling as $3H3GQ$focusWithoutScrolling, useEvent as $3H3GQ$useEvent, scrollIntoViewport as $3H3GQ$scrollIntoViewport, FOCUS_EVENT as $3H3GQ$FOCUS_EVENT, useEffectEvent as $3H3GQ$useEffectEvent, UPDATE_ACTIVEDESCENDANT as $3H3GQ$UPDATE_ACTIVEDESCENDANT, useUpdateLayoutEffect as $3H3GQ$useUpdateLayoutEffect, CLEAR_FOCUS_EVENT as $3H3GQ$CLEAR_FOCUS_EVENT, scrollIntoView as $3H3GQ$scrollIntoView, mergeProps as $3H3GQ$mergeProps} from "@react-aria/utils";
4
4
  import {flushSync as $3H3GQ$flushSync} from "react-dom";
5
5
  import {useRef as $3H3GQ$useRef, useEffect as $3H3GQ$useEffect} from "react";
6
6
  import {getFocusableTreeWalker as $3H3GQ$getFocusableTreeWalker, focusSafely as $3H3GQ$focusSafely} from "@react-aria/focus";
@@ -105,10 +105,10 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
105
105
  if (delegate.getFirstKey) {
106
106
  if (manager.focusedKey === null && e.shiftKey) return;
107
107
  e.preventDefault();
108
- let firstKey = delegate.getFirstKey(manager.focusedKey, (0, $feb5ffebff200149$export$16792effe837dba3)(e));
108
+ let firstKey = delegate.getFirstKey(manager.focusedKey, (0, $3H3GQ$isCtrlKeyPressed)(e));
109
109
  manager.setFocusedKey(firstKey);
110
110
  if (firstKey != null) {
111
- if ((0, $feb5ffebff200149$export$16792effe837dba3)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(firstKey);
111
+ if ((0, $3H3GQ$isCtrlKeyPressed)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(firstKey);
112
112
  else if (selectOnFocus) manager.replaceSelection(firstKey);
113
113
  }
114
114
  }
@@ -117,10 +117,10 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
117
117
  if (delegate.getLastKey) {
118
118
  if (manager.focusedKey === null && e.shiftKey) return;
119
119
  e.preventDefault();
120
- let lastKey = delegate.getLastKey(manager.focusedKey, (0, $feb5ffebff200149$export$16792effe837dba3)(e));
120
+ let lastKey = delegate.getLastKey(manager.focusedKey, (0, $3H3GQ$isCtrlKeyPressed)(e));
121
121
  manager.setFocusedKey(lastKey);
122
122
  if (lastKey != null) {
123
- if ((0, $feb5ffebff200149$export$16792effe837dba3)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(lastKey);
123
+ if ((0, $3H3GQ$isCtrlKeyPressed)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(lastKey);
124
124
  else if (selectOnFocus) manager.replaceSelection(lastKey);
125
125
  }
126
126
  }
@@ -144,7 +144,7 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
144
144
  }
145
145
  break;
146
146
  case 'a':
147
- if ((0, $feb5ffebff200149$export$16792effe837dba3)(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {
147
+ if ((0, $3H3GQ$isCtrlKeyPressed)(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {
148
148
  e.preventDefault();
149
149
  manager.selectAll();
150
150
  }
@@ -241,6 +241,10 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
241
241
  // Don't set blurred and then focused again if moving focus within the collection.
242
242
  if (!e.currentTarget.contains(e.relatedTarget)) manager.setFocused(false);
243
243
  };
244
+ // Ref to track whether the first item in the collection should be automatically focused. Specifically used for autocomplete when user types
245
+ // to focus the first key AFTER the collection updates.
246
+ // TODO: potentially expand the usage of this
247
+ let shouldVirtualFocusFirst = (0, $3H3GQ$useRef)(false);
244
248
  // Add event listeners for custom virtual events. These handle updating the focused key in response to various keyboard events
245
249
  // at the autocomplete level
246
250
  // TODO: fix type later
@@ -249,18 +253,43 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
249
253
  e.stopPropagation();
250
254
  manager.setFocused(true);
251
255
  // If the user is typing forwards, autofocus the first option in the list.
252
- if ((detail === null || detail === void 0 ? void 0 : detail.focusStrategy) === 'first') {
253
- var _delegate_getFirstKey, _ref_current;
254
- var _delegate_getFirstKey1;
255
- let keyToFocus = (_delegate_getFirstKey1 = (_delegate_getFirstKey = delegate.getFirstKey) === null || _delegate_getFirstKey === void 0 ? void 0 : _delegate_getFirstKey.call(delegate)) !== null && _delegate_getFirstKey1 !== void 0 ? _delegate_getFirstKey1 : null;
256
- // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist
257
- if (keyToFocus == null) (_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.dispatchEvent(new CustomEvent((0, $3H3GQ$UPDATE_ACTIVEDESCENDANT), {
258
- cancelable: true,
259
- bubbles: true
260
- }));
256
+ if ((detail === null || detail === void 0 ? void 0 : detail.focusStrategy) === 'first') shouldVirtualFocusFirst.current = true;
257
+ });
258
+ let updateActiveDescendant = (0, $3H3GQ$useEffectEvent)(()=>{
259
+ var _delegate_getFirstKey, _ref_current;
260
+ var _delegate_getFirstKey1;
261
+ let keyToFocus = (_delegate_getFirstKey1 = (_delegate_getFirstKey = delegate.getFirstKey) === null || _delegate_getFirstKey === void 0 ? void 0 : _delegate_getFirstKey.call(delegate)) !== null && _delegate_getFirstKey1 !== void 0 ? _delegate_getFirstKey1 : null;
262
+ // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist
263
+ if (keyToFocus == null) (_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.dispatchEvent(new CustomEvent((0, $3H3GQ$UPDATE_ACTIVEDESCENDANT), {
264
+ cancelable: true,
265
+ bubbles: true
266
+ }));
267
+ else {
261
268
  manager.setFocusedKey(keyToFocus);
269
+ // Only set shouldVirtualFocusFirst to false if we've successfully set the first key as the focused key
270
+ // If there wasn't a key to focus, we might be in a temporary loading state so we'll want to still focus the first key
271
+ // after the collection updates after load
272
+ shouldVirtualFocusFirst.current = false;
262
273
  }
263
274
  });
275
+ (0, $3H3GQ$useUpdateLayoutEffect)(()=>{
276
+ if (shouldVirtualFocusFirst.current) updateActiveDescendant();
277
+ }, [
278
+ manager.collection,
279
+ updateActiveDescendant
280
+ ]);
281
+ let resetFocusFirstFlag = (0, $3H3GQ$useEffectEvent)(()=>{
282
+ // If user causes the focused key to change in any other way, clear shouldVirtualFocusFirst so we don't
283
+ // accidentally move focus from under them. Skip this if the collection was empty because we might be in a load
284
+ // state and will still want to focus the first item after load
285
+ if (manager.collection.size > 0) shouldVirtualFocusFirst.current = false;
286
+ });
287
+ (0, $3H3GQ$useUpdateLayoutEffect)(()=>{
288
+ resetFocusFirstFlag();
289
+ }, [
290
+ manager.focusedKey,
291
+ resetFocusFirstFlag
292
+ ]);
264
293
  (0, $3H3GQ$useEvent)(ref, (0, $3H3GQ$CLEAR_FOCUS_EVENT), !shouldUseVirtualFocus ? undefined : (e)=>{
265
294
  e.stopPropagation();
266
295
  manager.setFocused(false);
@@ -1,6 +1,6 @@
1
- import {isCtrlKeyPressed as $feb5ffebff200149$export$16792effe837dba3, isNonContiguousSelectionModifier as $feb5ffebff200149$export$d3e3bd3e26688c04} from "./utils.module.js";
1
+ import {isNonContiguousSelectionModifier as $feb5ffebff200149$export$d3e3bd3e26688c04} from "./utils.module.js";
2
2
  import {useTypeSelect as $fb3050f43d946246$export$e32c88dfddc6e1d8} from "./useTypeSelect.module.js";
3
- import {useRouter as $3H3GQ$useRouter, focusWithoutScrolling as $3H3GQ$focusWithoutScrolling, useEvent as $3H3GQ$useEvent, scrollIntoViewport as $3H3GQ$scrollIntoViewport, FOCUS_EVENT as $3H3GQ$FOCUS_EVENT, UPDATE_ACTIVEDESCENDANT as $3H3GQ$UPDATE_ACTIVEDESCENDANT, CLEAR_FOCUS_EVENT as $3H3GQ$CLEAR_FOCUS_EVENT, scrollIntoView as $3H3GQ$scrollIntoView, mergeProps as $3H3GQ$mergeProps} from "@react-aria/utils";
3
+ import {useRouter as $3H3GQ$useRouter, isCtrlKeyPressed as $3H3GQ$isCtrlKeyPressed, focusWithoutScrolling as $3H3GQ$focusWithoutScrolling, useEvent as $3H3GQ$useEvent, scrollIntoViewport as $3H3GQ$scrollIntoViewport, FOCUS_EVENT as $3H3GQ$FOCUS_EVENT, useEffectEvent as $3H3GQ$useEffectEvent, UPDATE_ACTIVEDESCENDANT as $3H3GQ$UPDATE_ACTIVEDESCENDANT, useUpdateLayoutEffect as $3H3GQ$useUpdateLayoutEffect, CLEAR_FOCUS_EVENT as $3H3GQ$CLEAR_FOCUS_EVENT, scrollIntoView as $3H3GQ$scrollIntoView, mergeProps as $3H3GQ$mergeProps} from "@react-aria/utils";
4
4
  import {flushSync as $3H3GQ$flushSync} from "react-dom";
5
5
  import {useRef as $3H3GQ$useRef, useEffect as $3H3GQ$useEffect} from "react";
6
6
  import {getFocusableTreeWalker as $3H3GQ$getFocusableTreeWalker, focusSafely as $3H3GQ$focusSafely} from "@react-aria/focus";
@@ -105,10 +105,10 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
105
105
  if (delegate.getFirstKey) {
106
106
  if (manager.focusedKey === null && e.shiftKey) return;
107
107
  e.preventDefault();
108
- let firstKey = delegate.getFirstKey(manager.focusedKey, (0, $feb5ffebff200149$export$16792effe837dba3)(e));
108
+ let firstKey = delegate.getFirstKey(manager.focusedKey, (0, $3H3GQ$isCtrlKeyPressed)(e));
109
109
  manager.setFocusedKey(firstKey);
110
110
  if (firstKey != null) {
111
- if ((0, $feb5ffebff200149$export$16792effe837dba3)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(firstKey);
111
+ if ((0, $3H3GQ$isCtrlKeyPressed)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(firstKey);
112
112
  else if (selectOnFocus) manager.replaceSelection(firstKey);
113
113
  }
114
114
  }
@@ -117,10 +117,10 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
117
117
  if (delegate.getLastKey) {
118
118
  if (manager.focusedKey === null && e.shiftKey) return;
119
119
  e.preventDefault();
120
- let lastKey = delegate.getLastKey(manager.focusedKey, (0, $feb5ffebff200149$export$16792effe837dba3)(e));
120
+ let lastKey = delegate.getLastKey(manager.focusedKey, (0, $3H3GQ$isCtrlKeyPressed)(e));
121
121
  manager.setFocusedKey(lastKey);
122
122
  if (lastKey != null) {
123
- if ((0, $feb5ffebff200149$export$16792effe837dba3)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(lastKey);
123
+ if ((0, $3H3GQ$isCtrlKeyPressed)(e) && e.shiftKey && manager.selectionMode === 'multiple') manager.extendSelection(lastKey);
124
124
  else if (selectOnFocus) manager.replaceSelection(lastKey);
125
125
  }
126
126
  }
@@ -144,7 +144,7 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
144
144
  }
145
145
  break;
146
146
  case 'a':
147
- if ((0, $feb5ffebff200149$export$16792effe837dba3)(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {
147
+ if ((0, $3H3GQ$isCtrlKeyPressed)(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {
148
148
  e.preventDefault();
149
149
  manager.selectAll();
150
150
  }
@@ -241,6 +241,10 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
241
241
  // Don't set blurred and then focused again if moving focus within the collection.
242
242
  if (!e.currentTarget.contains(e.relatedTarget)) manager.setFocused(false);
243
243
  };
244
+ // Ref to track whether the first item in the collection should be automatically focused. Specifically used for autocomplete when user types
245
+ // to focus the first key AFTER the collection updates.
246
+ // TODO: potentially expand the usage of this
247
+ let shouldVirtualFocusFirst = (0, $3H3GQ$useRef)(false);
244
248
  // Add event listeners for custom virtual events. These handle updating the focused key in response to various keyboard events
245
249
  // at the autocomplete level
246
250
  // TODO: fix type later
@@ -249,18 +253,43 @@ function $ae20dd8cbca75726$export$d6daf82dcd84e87c(options) {
249
253
  e.stopPropagation();
250
254
  manager.setFocused(true);
251
255
  // If the user is typing forwards, autofocus the first option in the list.
252
- if ((detail === null || detail === void 0 ? void 0 : detail.focusStrategy) === 'first') {
253
- var _delegate_getFirstKey, _ref_current;
254
- var _delegate_getFirstKey1;
255
- let keyToFocus = (_delegate_getFirstKey1 = (_delegate_getFirstKey = delegate.getFirstKey) === null || _delegate_getFirstKey === void 0 ? void 0 : _delegate_getFirstKey.call(delegate)) !== null && _delegate_getFirstKey1 !== void 0 ? _delegate_getFirstKey1 : null;
256
- // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist
257
- if (keyToFocus == null) (_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.dispatchEvent(new CustomEvent((0, $3H3GQ$UPDATE_ACTIVEDESCENDANT), {
258
- cancelable: true,
259
- bubbles: true
260
- }));
256
+ if ((detail === null || detail === void 0 ? void 0 : detail.focusStrategy) === 'first') shouldVirtualFocusFirst.current = true;
257
+ });
258
+ let updateActiveDescendant = (0, $3H3GQ$useEffectEvent)(()=>{
259
+ var _delegate_getFirstKey, _ref_current;
260
+ var _delegate_getFirstKey1;
261
+ let keyToFocus = (_delegate_getFirstKey1 = (_delegate_getFirstKey = delegate.getFirstKey) === null || _delegate_getFirstKey === void 0 ? void 0 : _delegate_getFirstKey.call(delegate)) !== null && _delegate_getFirstKey1 !== void 0 ? _delegate_getFirstKey1 : null;
262
+ // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist
263
+ if (keyToFocus == null) (_ref_current = ref.current) === null || _ref_current === void 0 ? void 0 : _ref_current.dispatchEvent(new CustomEvent((0, $3H3GQ$UPDATE_ACTIVEDESCENDANT), {
264
+ cancelable: true,
265
+ bubbles: true
266
+ }));
267
+ else {
261
268
  manager.setFocusedKey(keyToFocus);
269
+ // Only set shouldVirtualFocusFirst to false if we've successfully set the first key as the focused key
270
+ // If there wasn't a key to focus, we might be in a temporary loading state so we'll want to still focus the first key
271
+ // after the collection updates after load
272
+ shouldVirtualFocusFirst.current = false;
262
273
  }
263
274
  });
275
+ (0, $3H3GQ$useUpdateLayoutEffect)(()=>{
276
+ if (shouldVirtualFocusFirst.current) updateActiveDescendant();
277
+ }, [
278
+ manager.collection,
279
+ updateActiveDescendant
280
+ ]);
281
+ let resetFocusFirstFlag = (0, $3H3GQ$useEffectEvent)(()=>{
282
+ // If user causes the focused key to change in any other way, clear shouldVirtualFocusFirst so we don't
283
+ // accidentally move focus from under them. Skip this if the collection was empty because we might be in a load
284
+ // state and will still want to focus the first item after load
285
+ if (manager.collection.size > 0) shouldVirtualFocusFirst.current = false;
286
+ });
287
+ (0, $3H3GQ$useUpdateLayoutEffect)(()=>{
288
+ resetFocusFirstFlag();
289
+ }, [
290
+ manager.focusedKey,
291
+ resetFocusFirstFlag
292
+ ]);
264
293
  (0, $3H3GQ$useEvent)(ref, (0, $3H3GQ$CLEAR_FOCUS_EVENT), !shouldUseVirtualFocus ? undefined : (e)=>{
265
294
  e.stopPropagation();
266
295
  manager.setFocused(false);
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-aria/selection/src/useSelectableCollection.ts"],"sourcesContent":["/*\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\nimport {CLEAR_FOCUS_EVENT, FOCUS_EVENT, focusWithoutScrolling, mergeProps, scrollIntoView, scrollIntoViewport, UPDATE_ACTIVEDESCENDANT, useEvent, useRouter} from '@react-aria/utils';\nimport {DOMAttributes, FocusableElement, FocusStrategy, Key, KeyboardDelegate, RefObject} from '@react-types/shared';\nimport {flushSync} from 'react-dom';\nimport {FocusEvent, KeyboardEvent, useEffect, useRef} from 'react';\nimport {focusSafely, getFocusableTreeWalker} from '@react-aria/focus';\nimport {getInteractionModality} from '@react-aria/interactions';\nimport {isCtrlKeyPressed, isNonContiguousSelectionModifier} from './utils';\nimport {MultipleSelectionManager} from '@react-stately/selection';\nimport {useLocale} from '@react-aria/i18n';\nimport {useTypeSelect} from './useTypeSelect';\n\nexport interface AriaSelectableCollectionOptions {\n /**\n * An interface for reading and updating multiple selection state.\n */\n selectionManager: MultipleSelectionManager,\n /**\n * A delegate object that implements behavior for keyboard focus movement.\n */\n keyboardDelegate: KeyboardDelegate,\n /**\n * The ref attached to the element representing the collection.\n */\n ref: RefObject<HTMLElement | null>,\n /**\n * Whether the collection or one of its items should be automatically focused upon render.\n * @default false\n */\n autoFocus?: boolean | FocusStrategy,\n /**\n * Whether focus should wrap around when the end/start is reached.\n * @default false\n */\n shouldFocusWrap?: boolean,\n /**\n * Whether the collection allows empty selection.\n * @default false\n */\n disallowEmptySelection?: boolean,\n /**\n * Whether the collection allows the user to select all items via keyboard shortcut.\n * @default false\n */\n disallowSelectAll?: boolean,\n /**\n * Whether selection should occur automatically on focus.\n * @default false\n */\n selectOnFocus?: boolean,\n /**\n * Whether typeahead is disabled.\n * @default false\n */\n disallowTypeAhead?: boolean,\n /**\n * Whether the collection items should use virtual focus instead of being focused directly.\n */\n shouldUseVirtualFocus?: boolean,\n /**\n * Whether navigation through tab key is enabled.\n */\n allowsTabNavigation?: boolean,\n /**\n * Whether the collection items are contained in a virtual scroller.\n */\n isVirtualized?: boolean,\n /**\n * The ref attached to the scrollable body. Used to provide automatic scrolling on item focus for non-virtualized collections.\n * If not provided, defaults to the collection ref.\n */\n scrollRef?: RefObject<HTMLElement | null>,\n /**\n * The behavior of links in the collection.\n * - 'action': link behaves like onAction.\n * - 'selection': link follows selection interactions (e.g. if URL drives selection).\n * - 'override': links override all other interactions (link items are not selectable).\n * @default 'action'\n */\n linkBehavior?: 'action' | 'selection' | 'override'\n}\n\nexport interface SelectableCollectionAria {\n /** Props for the collection element. */\n collectionProps: DOMAttributes\n}\n\n/**\n * Handles interactions with selectable collections.\n */\nexport function useSelectableCollection(options: AriaSelectableCollectionOptions): SelectableCollectionAria {\n let {\n selectionManager: manager,\n keyboardDelegate: delegate,\n ref,\n autoFocus = false,\n shouldFocusWrap = false,\n disallowEmptySelection = false,\n disallowSelectAll = false,\n selectOnFocus = manager.selectionBehavior === 'replace',\n disallowTypeAhead = false,\n shouldUseVirtualFocus,\n allowsTabNavigation = false,\n isVirtualized,\n // If no scrollRef is provided, assume the collection ref is the scrollable region\n scrollRef = ref,\n linkBehavior = 'action'\n } = options;\n let {direction} = useLocale();\n let router = useRouter();\n\n let onKeyDown = (e: KeyboardEvent) => {\n // Prevent option + tab from doing anything since it doesn't move focus to the cells, only buttons/checkboxes\n if (e.altKey && e.key === 'Tab') {\n e.preventDefault();\n }\n\n // Keyboard events bubble through portals. Don't handle keyboard events\n // for elements outside the collection (e.g. menus).\n if (!ref.current?.contains(e.target as Element)) {\n return;\n }\n\n const navigateToKey = (key: Key | undefined, childFocus?: FocusStrategy) => {\n if (key != null) {\n if (manager.isLink(key) && linkBehavior === 'selection' && selectOnFocus && !isNonContiguousSelectionModifier(e)) {\n // Set focused key and re-render synchronously to bring item into view if needed.\n flushSync(() => {\n manager.setFocusedKey(key, childFocus);\n });\n\n let item = scrollRef.current?.querySelector(`[data-key=\"${CSS.escape(key.toString())}\"]`);\n let itemProps = manager.getItemProps(key);\n if (item) {\n router.open(item, e, itemProps.href, itemProps.routerOptions);\n }\n\n return;\n }\n\n manager.setFocusedKey(key, childFocus);\n\n if (manager.isLink(key) && linkBehavior === 'override') {\n return;\n }\n\n if (e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(key);\n } else if (selectOnFocus && !isNonContiguousSelectionModifier(e)) {\n manager.replaceSelection(key);\n }\n }\n };\n\n switch (e.key) {\n case 'ArrowDown': {\n if (delegate.getKeyBelow) {\n let nextKey = manager.focusedKey != null\n ? delegate.getKeyBelow?.(manager.focusedKey)\n : delegate.getFirstKey?.();\n if (nextKey == null && shouldFocusWrap) {\n nextKey = delegate.getFirstKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n }\n case 'ArrowUp': {\n if (delegate.getKeyAbove) {\n let nextKey = manager.focusedKey != null\n ? delegate.getKeyAbove?.(manager.focusedKey)\n : delegate.getLastKey?.();\n if (nextKey == null && shouldFocusWrap) {\n nextKey = delegate.getLastKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n }\n case 'ArrowLeft': {\n if (delegate.getKeyLeftOf) {\n let nextKey: Key | undefined | null = manager.focusedKey != null ? delegate.getKeyLeftOf?.(manager.focusedKey) : null;\n if (nextKey == null && shouldFocusWrap) {\n nextKey = direction === 'rtl' ? delegate.getFirstKey?.(manager.focusedKey) : delegate.getLastKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey, direction === 'rtl' ? 'first' : 'last');\n }\n }\n break;\n }\n case 'ArrowRight': {\n if (delegate.getKeyRightOf) {\n let nextKey: Key | undefined | null = manager.focusedKey != null ? delegate.getKeyRightOf?.(manager.focusedKey) : null;\n if (nextKey == null && shouldFocusWrap) {\n nextKey = direction === 'rtl' ? delegate.getLastKey?.(manager.focusedKey) : delegate.getFirstKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey, direction === 'rtl' ? 'last' : 'first');\n }\n }\n break;\n }\n case 'Home':\n if (delegate.getFirstKey) {\n if (manager.focusedKey === null && e.shiftKey) {\n return;\n }\n e.preventDefault();\n let firstKey: Key | null = delegate.getFirstKey(manager.focusedKey, isCtrlKeyPressed(e));\n manager.setFocusedKey(firstKey);\n if (firstKey != null) {\n if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(firstKey);\n } else if (selectOnFocus) {\n manager.replaceSelection(firstKey);\n }\n }\n }\n break;\n case 'End':\n if (delegate.getLastKey) {\n if (manager.focusedKey === null && e.shiftKey) {\n return;\n }\n e.preventDefault();\n let lastKey = delegate.getLastKey(manager.focusedKey, isCtrlKeyPressed(e));\n manager.setFocusedKey(lastKey);\n if (lastKey != null) {\n if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(lastKey);\n } else if (selectOnFocus) {\n manager.replaceSelection(lastKey);\n }\n }\n }\n break;\n case 'PageDown':\n if (delegate.getKeyPageBelow && manager.focusedKey != null) {\n let nextKey = delegate.getKeyPageBelow(manager.focusedKey);\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n case 'PageUp':\n if (delegate.getKeyPageAbove && manager.focusedKey != null) {\n let nextKey = delegate.getKeyPageAbove(manager.focusedKey);\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n case 'a':\n if (isCtrlKeyPressed(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {\n e.preventDefault();\n manager.selectAll();\n }\n break;\n case 'Escape':\n if (!disallowEmptySelection && manager.selectedKeys.size !== 0) {\n e.stopPropagation();\n e.preventDefault();\n manager.clearSelection();\n }\n break;\n case 'Tab': {\n if (!allowsTabNavigation) {\n // There may be elements that are \"tabbable\" inside a collection (e.g. in a grid cell).\n // However, collections should be treated as a single tab stop, with arrow key navigation internally.\n // We don't control the rendering of these, so we can't override the tabIndex to prevent tabbing.\n // Instead, we handle the Tab key, and move focus manually to the first/last tabbable element\n // in the collection, so that the browser default behavior will apply starting from that element\n // rather than the currently focused one.\n if (e.shiftKey) {\n ref.current.focus();\n } else {\n let walker = getFocusableTreeWalker(ref.current, {tabbable: true});\n let next: FocusableElement | undefined = undefined;\n let last: FocusableElement;\n do {\n last = walker.lastChild() as FocusableElement;\n if (last) {\n next = last;\n }\n } while (last);\n\n if (next && !next.contains(document.activeElement)) {\n focusWithoutScrolling(next);\n }\n }\n break;\n }\n }\n }\n };\n\n // Store the scroll position so we can restore it later.\n /// TODO: should this happen all the time??\n let scrollPos = useRef({top: 0, left: 0});\n useEvent(scrollRef, 'scroll', isVirtualized ? undefined : () => {\n scrollPos.current = {\n top: scrollRef.current?.scrollTop ?? 0,\n left: scrollRef.current?.scrollLeft ?? 0\n };\n });\n\n let onFocus = (e: FocusEvent) => {\n if (manager.isFocused) {\n // If a focus event bubbled through a portal, reset focus state.\n if (!e.currentTarget.contains(e.target)) {\n manager.setFocused(false);\n }\n\n return;\n }\n\n // Focus events can bubble through portals. Ignore these events.\n if (!e.currentTarget.contains(e.target)) {\n return;\n }\n\n manager.setFocused(true);\n\n if (manager.focusedKey == null) {\n let navigateToFirstKey = (key: Key | undefined | null) => {\n if (key != null) {\n manager.setFocusedKey(key);\n if (selectOnFocus) {\n manager.replaceSelection(key);\n }\n }\n };\n // If the user hasn't yet interacted with the collection, there will be no focusedKey set.\n // Attempt to detect whether the user is tabbing forward or backward into the collection\n // and either focus the first or last item accordingly.\n let relatedTarget = e.relatedTarget as Element;\n if (relatedTarget && (e.currentTarget.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING)) {\n navigateToFirstKey(manager.lastSelectedKey ?? delegate.getLastKey?.());\n } else {\n navigateToFirstKey(manager.firstSelectedKey ?? delegate.getFirstKey?.());\n }\n } else if (!isVirtualized && scrollRef.current) {\n // Restore the scroll position to what it was before.\n scrollRef.current.scrollTop = scrollPos.current.top;\n scrollRef.current.scrollLeft = scrollPos.current.left;\n }\n\n if (manager.focusedKey != null && scrollRef.current) {\n // Refocus and scroll the focused item into view if it exists within the scrollable region.\n let element = scrollRef.current.querySelector(`[data-key=\"${CSS.escape(manager.focusedKey.toString())}\"]`) as HTMLElement;\n if (element) {\n // This prevents a flash of focus on the first/last element in the collection, or the collection itself.\n if (!element.contains(document.activeElement)) {\n focusWithoutScrolling(element);\n }\n\n let modality = getInteractionModality();\n if (modality === 'keyboard') {\n scrollIntoViewport(element, {containingElement: ref.current});\n }\n }\n }\n };\n\n let onBlur = (e) => {\n // Don't set blurred and then focused again if moving focus within the collection.\n if (!e.currentTarget.contains(e.relatedTarget as HTMLElement)) {\n manager.setFocused(false);\n }\n };\n\n // Add event listeners for custom virtual events. These handle updating the focused key in response to various keyboard events\n // at the autocomplete level\n // TODO: fix type later\n useEvent(ref, FOCUS_EVENT, !shouldUseVirtualFocus ? undefined : (e: any) => {\n let {detail} = e;\n e.stopPropagation();\n manager.setFocused(true);\n\n // If the user is typing forwards, autofocus the first option in the list.\n if (detail?.focusStrategy === 'first') {\n let keyToFocus = delegate.getFirstKey?.() ?? null;\n // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist\n if (keyToFocus == null) {\n ref.current?.dispatchEvent(\n new CustomEvent(UPDATE_ACTIVEDESCENDANT, {\n cancelable: true,\n bubbles: true\n })\n );\n }\n\n manager.setFocusedKey(keyToFocus);\n }\n });\n\n useEvent(ref, CLEAR_FOCUS_EVENT, !shouldUseVirtualFocus ? undefined : (e) => {\n e.stopPropagation();\n manager.setFocused(false);\n manager.setFocusedKey(null);\n });\n\n const autoFocusRef = useRef(autoFocus);\n useEffect(() => {\n if (autoFocusRef.current) {\n let focusedKey: Key | null = null;\n\n // Check focus strategy to determine which item to focus\n if (autoFocus === 'first') {\n focusedKey = delegate.getFirstKey?.() ?? null;\n } if (autoFocus === 'last') {\n focusedKey = delegate.getLastKey?.() ?? null;\n }\n\n // If there are any selected keys, make the first one the new focus target\n let selectedKeys = manager.selectedKeys;\n if (selectedKeys.size) {\n for (let key of selectedKeys) {\n if (manager.canSelectItem(key)) {\n focusedKey = key;\n break;\n }\n }\n }\n\n manager.setFocused(true);\n manager.setFocusedKey(focusedKey);\n\n // If no default focus key is selected, focus the collection itself.\n if (focusedKey == null && !shouldUseVirtualFocus && ref.current) {\n focusSafely(ref.current);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Scroll the focused element into view when the focusedKey changes.\n let lastFocusedKey = useRef(manager.focusedKey);\n useEffect(() => {\n if (manager.isFocused && manager.focusedKey != null && (manager.focusedKey !== lastFocusedKey.current || autoFocusRef.current) && scrollRef.current && ref.current) {\n let modality = getInteractionModality();\n let element = ref.current.querySelector(`[data-key=\"${CSS.escape(manager.focusedKey.toString())}\"]`) as HTMLElement;\n if (!element) {\n // If item element wasn't found, return early (don't update autoFocusRef and lastFocusedKey).\n // The collection may initially be empty (e.g. virtualizer), so wait until the element exists.\n return;\n }\n\n if (modality === 'keyboard' || autoFocusRef.current) {\n scrollIntoView(scrollRef.current, element);\n\n // Avoid scroll in iOS VO, since it may cause overlay to close (i.e. RAC submenu)\n if (modality !== 'virtual') {\n scrollIntoViewport(element, {containingElement: ref.current});\n }\n }\n }\n\n // If the focused key becomes null (e.g. the last item is deleted), focus the whole collection.\n if (!shouldUseVirtualFocus && manager.isFocused && manager.focusedKey == null && lastFocusedKey.current != null && ref.current) {\n focusSafely(ref.current);\n }\n\n lastFocusedKey.current = manager.focusedKey;\n autoFocusRef.current = false;\n });\n\n // Intercept FocusScope restoration since virtualized collections can reuse DOM nodes.\n useEvent(ref, 'react-aria-focus-scope-restore', e => {\n e.preventDefault();\n manager.setFocused(true);\n });\n\n let handlers = {\n onKeyDown,\n onFocus,\n onBlur,\n onMouseDown(e) {\n // Ignore events that bubbled through portals.\n if (scrollRef.current === e.target) {\n // Prevent focus going to the collection when clicking on the scrollbar.\n e.preventDefault();\n }\n }\n };\n\n let {typeSelectProps} = useTypeSelect({\n keyboardDelegate: delegate,\n selectionManager: manager\n });\n\n if (!disallowTypeAhead) {\n handlers = mergeProps(typeSelectProps, handlers);\n }\n\n // If nothing is focused within the collection, make the collection itself tabbable.\n // This will be marshalled to either the first or last item depending on where focus came from.\n let tabIndex: number | undefined = undefined;\n if (!shouldUseVirtualFocus) {\n tabIndex = manager.focusedKey == null ? 0 : -1;\n } else {\n tabIndex = -1;\n }\n\n return {\n collectionProps: {\n ...handlers,\n tabIndex\n }\n };\n}\n"],"names":[],"version":3,"file":"useSelectableCollection.module.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-aria/selection/src/useSelectableCollection.ts"],"sourcesContent":["/*\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\nimport {CLEAR_FOCUS_EVENT, FOCUS_EVENT, focusWithoutScrolling, isCtrlKeyPressed, mergeProps, scrollIntoView, scrollIntoViewport, UPDATE_ACTIVEDESCENDANT, useEffectEvent, useEvent, useRouter, useUpdateLayoutEffect} from '@react-aria/utils';\nimport {DOMAttributes, FocusableElement, FocusStrategy, Key, KeyboardDelegate, RefObject} from '@react-types/shared';\nimport {flushSync} from 'react-dom';\nimport {FocusEvent, KeyboardEvent, useEffect, useRef} from 'react';\nimport {focusSafely, getFocusableTreeWalker} from '@react-aria/focus';\nimport {getInteractionModality} from '@react-aria/interactions';\nimport {isNonContiguousSelectionModifier} from './utils';\nimport {MultipleSelectionManager} from '@react-stately/selection';\nimport {useLocale} from '@react-aria/i18n';\nimport {useTypeSelect} from './useTypeSelect';\n\nexport interface AriaSelectableCollectionOptions {\n /**\n * An interface for reading and updating multiple selection state.\n */\n selectionManager: MultipleSelectionManager,\n /**\n * A delegate object that implements behavior for keyboard focus movement.\n */\n keyboardDelegate: KeyboardDelegate,\n /**\n * The ref attached to the element representing the collection.\n */\n ref: RefObject<HTMLElement | null>,\n /**\n * Whether the collection or one of its items should be automatically focused upon render.\n * @default false\n */\n autoFocus?: boolean | FocusStrategy,\n /**\n * Whether focus should wrap around when the end/start is reached.\n * @default false\n */\n shouldFocusWrap?: boolean,\n /**\n * Whether the collection allows empty selection.\n * @default false\n */\n disallowEmptySelection?: boolean,\n /**\n * Whether the collection allows the user to select all items via keyboard shortcut.\n * @default false\n */\n disallowSelectAll?: boolean,\n /**\n * Whether selection should occur automatically on focus.\n * @default false\n */\n selectOnFocus?: boolean,\n /**\n * Whether typeahead is disabled.\n * @default false\n */\n disallowTypeAhead?: boolean,\n /**\n * Whether the collection items should use virtual focus instead of being focused directly.\n */\n shouldUseVirtualFocus?: boolean,\n /**\n * Whether navigation through tab key is enabled.\n */\n allowsTabNavigation?: boolean,\n /**\n * Whether the collection items are contained in a virtual scroller.\n */\n isVirtualized?: boolean,\n /**\n * The ref attached to the scrollable body. Used to provide automatic scrolling on item focus for non-virtualized collections.\n * If not provided, defaults to the collection ref.\n */\n scrollRef?: RefObject<HTMLElement | null>,\n /**\n * The behavior of links in the collection.\n * - 'action': link behaves like onAction.\n * - 'selection': link follows selection interactions (e.g. if URL drives selection).\n * - 'override': links override all other interactions (link items are not selectable).\n * @default 'action'\n */\n linkBehavior?: 'action' | 'selection' | 'override'\n}\n\nexport interface SelectableCollectionAria {\n /** Props for the collection element. */\n collectionProps: DOMAttributes\n}\n\n/**\n * Handles interactions with selectable collections.\n */\nexport function useSelectableCollection(options: AriaSelectableCollectionOptions): SelectableCollectionAria {\n let {\n selectionManager: manager,\n keyboardDelegate: delegate,\n ref,\n autoFocus = false,\n shouldFocusWrap = false,\n disallowEmptySelection = false,\n disallowSelectAll = false,\n selectOnFocus = manager.selectionBehavior === 'replace',\n disallowTypeAhead = false,\n shouldUseVirtualFocus,\n allowsTabNavigation = false,\n isVirtualized,\n // If no scrollRef is provided, assume the collection ref is the scrollable region\n scrollRef = ref,\n linkBehavior = 'action'\n } = options;\n let {direction} = useLocale();\n let router = useRouter();\n\n let onKeyDown = (e: KeyboardEvent) => {\n // Prevent option + tab from doing anything since it doesn't move focus to the cells, only buttons/checkboxes\n if (e.altKey && e.key === 'Tab') {\n e.preventDefault();\n }\n\n // Keyboard events bubble through portals. Don't handle keyboard events\n // for elements outside the collection (e.g. menus).\n if (!ref.current?.contains(e.target as Element)) {\n return;\n }\n\n const navigateToKey = (key: Key | undefined, childFocus?: FocusStrategy) => {\n if (key != null) {\n if (manager.isLink(key) && linkBehavior === 'selection' && selectOnFocus && !isNonContiguousSelectionModifier(e)) {\n // Set focused key and re-render synchronously to bring item into view if needed.\n flushSync(() => {\n manager.setFocusedKey(key, childFocus);\n });\n\n let item = scrollRef.current?.querySelector(`[data-key=\"${CSS.escape(key.toString())}\"]`);\n let itemProps = manager.getItemProps(key);\n if (item) {\n router.open(item, e, itemProps.href, itemProps.routerOptions);\n }\n\n return;\n }\n\n manager.setFocusedKey(key, childFocus);\n\n if (manager.isLink(key) && linkBehavior === 'override') {\n return;\n }\n\n if (e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(key);\n } else if (selectOnFocus && !isNonContiguousSelectionModifier(e)) {\n manager.replaceSelection(key);\n }\n }\n };\n\n switch (e.key) {\n case 'ArrowDown': {\n if (delegate.getKeyBelow) {\n let nextKey = manager.focusedKey != null\n ? delegate.getKeyBelow?.(manager.focusedKey)\n : delegate.getFirstKey?.();\n if (nextKey == null && shouldFocusWrap) {\n nextKey = delegate.getFirstKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n }\n case 'ArrowUp': {\n if (delegate.getKeyAbove) {\n let nextKey = manager.focusedKey != null\n ? delegate.getKeyAbove?.(manager.focusedKey)\n : delegate.getLastKey?.();\n if (nextKey == null && shouldFocusWrap) {\n nextKey = delegate.getLastKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n }\n case 'ArrowLeft': {\n if (delegate.getKeyLeftOf) {\n let nextKey: Key | undefined | null = manager.focusedKey != null ? delegate.getKeyLeftOf?.(manager.focusedKey) : null;\n if (nextKey == null && shouldFocusWrap) {\n nextKey = direction === 'rtl' ? delegate.getFirstKey?.(manager.focusedKey) : delegate.getLastKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey, direction === 'rtl' ? 'first' : 'last');\n }\n }\n break;\n }\n case 'ArrowRight': {\n if (delegate.getKeyRightOf) {\n let nextKey: Key | undefined | null = manager.focusedKey != null ? delegate.getKeyRightOf?.(manager.focusedKey) : null;\n if (nextKey == null && shouldFocusWrap) {\n nextKey = direction === 'rtl' ? delegate.getLastKey?.(manager.focusedKey) : delegate.getFirstKey?.(manager.focusedKey);\n }\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey, direction === 'rtl' ? 'last' : 'first');\n }\n }\n break;\n }\n case 'Home':\n if (delegate.getFirstKey) {\n if (manager.focusedKey === null && e.shiftKey) {\n return;\n }\n e.preventDefault();\n let firstKey: Key | null = delegate.getFirstKey(manager.focusedKey, isCtrlKeyPressed(e));\n manager.setFocusedKey(firstKey);\n if (firstKey != null) {\n if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(firstKey);\n } else if (selectOnFocus) {\n manager.replaceSelection(firstKey);\n }\n }\n }\n break;\n case 'End':\n if (delegate.getLastKey) {\n if (manager.focusedKey === null && e.shiftKey) {\n return;\n }\n e.preventDefault();\n let lastKey = delegate.getLastKey(manager.focusedKey, isCtrlKeyPressed(e));\n manager.setFocusedKey(lastKey);\n if (lastKey != null) {\n if (isCtrlKeyPressed(e) && e.shiftKey && manager.selectionMode === 'multiple') {\n manager.extendSelection(lastKey);\n } else if (selectOnFocus) {\n manager.replaceSelection(lastKey);\n }\n }\n }\n break;\n case 'PageDown':\n if (delegate.getKeyPageBelow && manager.focusedKey != null) {\n let nextKey = delegate.getKeyPageBelow(manager.focusedKey);\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n case 'PageUp':\n if (delegate.getKeyPageAbove && manager.focusedKey != null) {\n let nextKey = delegate.getKeyPageAbove(manager.focusedKey);\n if (nextKey != null) {\n e.preventDefault();\n navigateToKey(nextKey);\n }\n }\n break;\n case 'a':\n if (isCtrlKeyPressed(e) && manager.selectionMode === 'multiple' && disallowSelectAll !== true) {\n e.preventDefault();\n manager.selectAll();\n }\n break;\n case 'Escape':\n if (!disallowEmptySelection && manager.selectedKeys.size !== 0) {\n e.stopPropagation();\n e.preventDefault();\n manager.clearSelection();\n }\n break;\n case 'Tab': {\n if (!allowsTabNavigation) {\n // There may be elements that are \"tabbable\" inside a collection (e.g. in a grid cell).\n // However, collections should be treated as a single tab stop, with arrow key navigation internally.\n // We don't control the rendering of these, so we can't override the tabIndex to prevent tabbing.\n // Instead, we handle the Tab key, and move focus manually to the first/last tabbable element\n // in the collection, so that the browser default behavior will apply starting from that element\n // rather than the currently focused one.\n if (e.shiftKey) {\n ref.current.focus();\n } else {\n let walker = getFocusableTreeWalker(ref.current, {tabbable: true});\n let next: FocusableElement | undefined = undefined;\n let last: FocusableElement;\n do {\n last = walker.lastChild() as FocusableElement;\n if (last) {\n next = last;\n }\n } while (last);\n\n if (next && !next.contains(document.activeElement)) {\n focusWithoutScrolling(next);\n }\n }\n break;\n }\n }\n }\n };\n\n // Store the scroll position so we can restore it later.\n /// TODO: should this happen all the time??\n let scrollPos = useRef({top: 0, left: 0});\n useEvent(scrollRef, 'scroll', isVirtualized ? undefined : () => {\n scrollPos.current = {\n top: scrollRef.current?.scrollTop ?? 0,\n left: scrollRef.current?.scrollLeft ?? 0\n };\n });\n\n let onFocus = (e: FocusEvent) => {\n if (manager.isFocused) {\n // If a focus event bubbled through a portal, reset focus state.\n if (!e.currentTarget.contains(e.target)) {\n manager.setFocused(false);\n }\n\n return;\n }\n\n // Focus events can bubble through portals. Ignore these events.\n if (!e.currentTarget.contains(e.target)) {\n return;\n }\n\n manager.setFocused(true);\n\n if (manager.focusedKey == null) {\n let navigateToFirstKey = (key: Key | undefined | null) => {\n if (key != null) {\n manager.setFocusedKey(key);\n if (selectOnFocus) {\n manager.replaceSelection(key);\n }\n }\n };\n // If the user hasn't yet interacted with the collection, there will be no focusedKey set.\n // Attempt to detect whether the user is tabbing forward or backward into the collection\n // and either focus the first or last item accordingly.\n let relatedTarget = e.relatedTarget as Element;\n if (relatedTarget && (e.currentTarget.compareDocumentPosition(relatedTarget) & Node.DOCUMENT_POSITION_FOLLOWING)) {\n navigateToFirstKey(manager.lastSelectedKey ?? delegate.getLastKey?.());\n } else {\n navigateToFirstKey(manager.firstSelectedKey ?? delegate.getFirstKey?.());\n }\n } else if (!isVirtualized && scrollRef.current) {\n // Restore the scroll position to what it was before.\n scrollRef.current.scrollTop = scrollPos.current.top;\n scrollRef.current.scrollLeft = scrollPos.current.left;\n }\n\n if (manager.focusedKey != null && scrollRef.current) {\n // Refocus and scroll the focused item into view if it exists within the scrollable region.\n let element = scrollRef.current.querySelector(`[data-key=\"${CSS.escape(manager.focusedKey.toString())}\"]`) as HTMLElement;\n if (element) {\n // This prevents a flash of focus on the first/last element in the collection, or the collection itself.\n if (!element.contains(document.activeElement)) {\n focusWithoutScrolling(element);\n }\n\n let modality = getInteractionModality();\n if (modality === 'keyboard') {\n scrollIntoViewport(element, {containingElement: ref.current});\n }\n }\n }\n };\n\n let onBlur = (e) => {\n // Don't set blurred and then focused again if moving focus within the collection.\n if (!e.currentTarget.contains(e.relatedTarget as HTMLElement)) {\n manager.setFocused(false);\n }\n };\n\n // Ref to track whether the first item in the collection should be automatically focused. Specifically used for autocomplete when user types\n // to focus the first key AFTER the collection updates.\n // TODO: potentially expand the usage of this\n let shouldVirtualFocusFirst = useRef(false);\n // Add event listeners for custom virtual events. These handle updating the focused key in response to various keyboard events\n // at the autocomplete level\n // TODO: fix type later\n useEvent(ref, FOCUS_EVENT, !shouldUseVirtualFocus ? undefined : (e: any) => {\n let {detail} = e;\n e.stopPropagation();\n manager.setFocused(true);\n\n // If the user is typing forwards, autofocus the first option in the list.\n if (detail?.focusStrategy === 'first') {\n shouldVirtualFocusFirst.current = true;\n }\n });\n\n let updateActiveDescendant = useEffectEvent(() => {\n let keyToFocus = delegate.getFirstKey?.() ?? null;\n\n // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist\n if (keyToFocus == null) {\n ref.current?.dispatchEvent(\n new CustomEvent(UPDATE_ACTIVEDESCENDANT, {\n cancelable: true,\n bubbles: true\n })\n );\n } else {\n manager.setFocusedKey(keyToFocus);\n // Only set shouldVirtualFocusFirst to false if we've successfully set the first key as the focused key\n // If there wasn't a key to focus, we might be in a temporary loading state so we'll want to still focus the first key\n // after the collection updates after load\n shouldVirtualFocusFirst.current = false;\n }\n });\n\n useUpdateLayoutEffect(() => {\n if (shouldVirtualFocusFirst.current) {\n updateActiveDescendant();\n }\n\n }, [manager.collection, updateActiveDescendant]);\n\n let resetFocusFirstFlag = useEffectEvent(() => {\n // If user causes the focused key to change in any other way, clear shouldVirtualFocusFirst so we don't\n // accidentally move focus from under them. Skip this if the collection was empty because we might be in a load\n // state and will still want to focus the first item after load\n if (manager.collection.size > 0) {\n shouldVirtualFocusFirst.current = false;\n }\n });\n\n useUpdateLayoutEffect(() => {\n resetFocusFirstFlag();\n }, [manager.focusedKey, resetFocusFirstFlag]);\n\n useEvent(ref, CLEAR_FOCUS_EVENT, !shouldUseVirtualFocus ? undefined : (e) => {\n e.stopPropagation();\n manager.setFocused(false);\n manager.setFocusedKey(null);\n });\n\n const autoFocusRef = useRef(autoFocus);\n useEffect(() => {\n if (autoFocusRef.current) {\n let focusedKey: Key | null = null;\n\n // Check focus strategy to determine which item to focus\n if (autoFocus === 'first') {\n focusedKey = delegate.getFirstKey?.() ?? null;\n } if (autoFocus === 'last') {\n focusedKey = delegate.getLastKey?.() ?? null;\n }\n\n // If there are any selected keys, make the first one the new focus target\n let selectedKeys = manager.selectedKeys;\n if (selectedKeys.size) {\n for (let key of selectedKeys) {\n if (manager.canSelectItem(key)) {\n focusedKey = key;\n break;\n }\n }\n }\n\n manager.setFocused(true);\n manager.setFocusedKey(focusedKey);\n\n // If no default focus key is selected, focus the collection itself.\n if (focusedKey == null && !shouldUseVirtualFocus && ref.current) {\n focusSafely(ref.current);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Scroll the focused element into view when the focusedKey changes.\n let lastFocusedKey = useRef(manager.focusedKey);\n useEffect(() => {\n if (manager.isFocused && manager.focusedKey != null && (manager.focusedKey !== lastFocusedKey.current || autoFocusRef.current) && scrollRef.current && ref.current) {\n let modality = getInteractionModality();\n let element = ref.current.querySelector(`[data-key=\"${CSS.escape(manager.focusedKey.toString())}\"]`) as HTMLElement;\n if (!element) {\n // If item element wasn't found, return early (don't update autoFocusRef and lastFocusedKey).\n // The collection may initially be empty (e.g. virtualizer), so wait until the element exists.\n return;\n }\n\n if (modality === 'keyboard' || autoFocusRef.current) {\n scrollIntoView(scrollRef.current, element);\n\n // Avoid scroll in iOS VO, since it may cause overlay to close (i.e. RAC submenu)\n if (modality !== 'virtual') {\n scrollIntoViewport(element, {containingElement: ref.current});\n }\n }\n }\n\n // If the focused key becomes null (e.g. the last item is deleted), focus the whole collection.\n if (!shouldUseVirtualFocus && manager.isFocused && manager.focusedKey == null && lastFocusedKey.current != null && ref.current) {\n focusSafely(ref.current);\n }\n\n lastFocusedKey.current = manager.focusedKey;\n autoFocusRef.current = false;\n });\n\n // Intercept FocusScope restoration since virtualized collections can reuse DOM nodes.\n useEvent(ref, 'react-aria-focus-scope-restore', e => {\n e.preventDefault();\n manager.setFocused(true);\n });\n\n let handlers = {\n onKeyDown,\n onFocus,\n onBlur,\n onMouseDown(e) {\n // Ignore events that bubbled through portals.\n if (scrollRef.current === e.target) {\n // Prevent focus going to the collection when clicking on the scrollbar.\n e.preventDefault();\n }\n }\n };\n\n let {typeSelectProps} = useTypeSelect({\n keyboardDelegate: delegate,\n selectionManager: manager\n });\n\n if (!disallowTypeAhead) {\n handlers = mergeProps(typeSelectProps, handlers);\n }\n\n // If nothing is focused within the collection, make the collection itself tabbable.\n // This will be marshalled to either the first or last item depending on where focus came from.\n let tabIndex: number | undefined = undefined;\n if (!shouldUseVirtualFocus) {\n tabIndex = manager.focusedKey == null ? 0 : -1;\n } else {\n tabIndex = -1;\n }\n\n return {\n collectionProps: {\n ...handlers,\n tabIndex\n }\n };\n}\n"],"names":[],"version":3,"file":"useSelectableCollection.module.js.map"}
@@ -46,12 +46,15 @@ function $433b1145b0781e10$export$ecf600387e221c37(options) {
46
46
  if (manager.isSelected(key) && !manager.disallowEmptySelection) manager.toggleSelection(key);
47
47
  else manager.replaceSelection(key);
48
48
  } else if (e && e.shiftKey) manager.extendSelection(key);
49
- else if (manager.selectionBehavior === 'toggle' || e && ((0, $ee0bdf4faa47f2a8$exports.isCtrlKeyPressed)(e) || e.pointerType === 'touch' || e.pointerType === 'virtual')) // 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
49
+ else if (manager.selectionBehavior === 'toggle' || e && ((0, $i4XHw$reactariautils.isCtrlKeyPressed)(e) || e.pointerType === 'touch' || e.pointerType === 'virtual')) // 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
50
50
  manager.toggleSelection(key);
51
51
  else manager.replaceSelection(key);
52
52
  }
53
53
  };
54
54
  // Focus the associated DOM node when this item becomes the focusedKey
55
+ // TODO: can't make this useLayoutEffect bacause it breaks menus inside dialogs
56
+ // However, if this is a useEffect, it runs twice and dispatches two UPDATE_ACTIVEDESCENDANT and immediately sets
57
+ // aria-activeDescendant in useAutocomplete... I've worked around this for now
55
58
  (0, $i4XHw$react.useEffect)(()=>{
56
59
  let isFocused = key === manager.focusedKey;
57
60
  if (isFocused && manager.isFocused) {
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-aria/selection/src/useSelectableItem.ts"],"sourcesContent":["/*\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\nimport {DOMAttributes, DOMProps, FocusableElement, Key, LongPressEvent, PointerType, PressEvent, RefObject} from '@react-types/shared';\nimport {focusSafely} from '@react-aria/focus';\nimport {isCtrlKeyPressed, isNonContiguousSelectionModifier} from './utils';\nimport {mergeProps, openLink, UPDATE_ACTIVEDESCENDANT, useId, useRouter} from '@react-aria/utils';\nimport {MultipleSelectionManager} from '@react-stately/selection';\nimport {PressProps, useLongPress, usePress} from '@react-aria/interactions';\nimport {useEffect, useRef} from 'react';\n\nexport interface SelectableItemOptions extends DOMProps {\n /**\n * An interface for reading and updating multiple selection state.\n */\n selectionManager: MultipleSelectionManager,\n /**\n * A unique key for the item.\n */\n key: Key,\n /**\n * Ref to the item.\n */\n ref: RefObject<FocusableElement | null>,\n /**\n * By default, selection occurs on pointer down. This can be strange if selecting an\n * item causes the UI to disappear immediately (e.g. menus).\n */\n shouldSelectOnPressUp?: boolean,\n /**\n * Whether selection requires the pointer/mouse down and up events to occur on the same target or triggers selection on\n * the target of the pointer/mouse up event.\n */\n allowsDifferentPressOrigin?: boolean,\n /**\n * Whether the option is contained in a virtual scroller.\n */\n isVirtualized?: boolean,\n /**\n * Function to focus the item.\n */\n focus?: () => void,\n /**\n * Whether the option should use virtual focus instead of being focused directly.\n */\n shouldUseVirtualFocus?: boolean,\n /** Whether the item is disabled. */\n isDisabled?: boolean,\n /**\n * Handler that is called when a user performs an action on the item. The exact user event depends on\n * the collection's `selectionBehavior` prop and the interaction modality.\n */\n onAction?: () => void,\n /**\n * The behavior of links in the collection.\n * - 'action': link behaves like onAction.\n * - 'selection': link follows selection interactions (e.g. if URL drives selection).\n * - 'override': links override all other interactions (link items are not selectable).\n * - 'none': links are disabled for both selection and actions (e.g. handled elsewhere).\n * @default 'action'\n */\n linkBehavior?: 'action' | 'selection' | 'override' | 'none'\n}\n\nexport interface SelectableItemStates {\n /** Whether the item is currently in a pressed state. */\n isPressed: boolean,\n /** Whether the item is currently selected. */\n isSelected: boolean,\n /** Whether the item is currently focused. */\n isFocused: boolean,\n /**\n * Whether the item is non-interactive, i.e. both selection and actions are disabled and the item may\n * not be focused. Dependent on `disabledKeys` and `disabledBehavior`.\n */\n isDisabled: boolean,\n /**\n * Whether the item may be selected, dependent on `selectionMode`, `disabledKeys`, and `disabledBehavior`.\n */\n allowsSelection: boolean,\n /**\n * Whether the item has an action, dependent on `onAction`, `disabledKeys`,\n * and `disabledBehavior`. It may also change depending on the current selection state\n * of the list (e.g. when selection is primary). This can be used to enable or disable hover\n * styles or other visual indications of interactivity.\n */\n hasAction: boolean\n}\n\nexport interface SelectableItemAria extends SelectableItemStates {\n /**\n * Props to be spread on the item root node.\n */\n itemProps: DOMAttributes\n}\n\n/**\n * Handles interactions with an item in a selectable collection.\n */\nexport function useSelectableItem(options: SelectableItemOptions): SelectableItemAria {\n let {\n id,\n selectionManager: manager,\n key,\n ref,\n shouldSelectOnPressUp,\n shouldUseVirtualFocus,\n focus,\n isDisabled,\n onAction,\n allowsDifferentPressOrigin,\n linkBehavior = 'action'\n } = options;\n let router = useRouter();\n id = useId(id);\n let onSelect = (e: PressEvent | LongPressEvent | PointerEvent) => {\n if (e.pointerType === 'keyboard' && isNonContiguousSelectionModifier(e)) {\n manager.toggleSelection(key);\n } else {\n if (manager.selectionMode === 'none') {\n return;\n }\n\n if (manager.isLink(key)) {\n if (linkBehavior === 'selection' && ref.current) {\n let itemProps = manager.getItemProps(key);\n router.open(ref.current, e, itemProps.href, itemProps.routerOptions);\n // Always set selected keys back to what they were so that select and combobox close.\n manager.setSelectedKeys(manager.selectedKeys);\n return;\n } else if (linkBehavior === 'override' || linkBehavior === 'none') {\n return;\n }\n }\n\n if (manager.selectionMode === 'single') {\n if (manager.isSelected(key) && !manager.disallowEmptySelection) {\n manager.toggleSelection(key);\n } else {\n manager.replaceSelection(key);\n }\n } else if (e && e.shiftKey) {\n manager.extendSelection(key);\n } else if (manager.selectionBehavior === 'toggle' || (e && (isCtrlKeyPressed(e) || e.pointerType === 'touch' || e.pointerType === 'virtual'))) {\n // 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\n manager.toggleSelection(key);\n } else {\n manager.replaceSelection(key);\n }\n }\n };\n\n // Focus the associated DOM node when this item becomes the focusedKey\n useEffect(() => {\n let isFocused = key === manager.focusedKey;\n if (isFocused && manager.isFocused) {\n if (!shouldUseVirtualFocus) {\n if (focus) {\n focus();\n } else if (document.activeElement !== ref.current && ref.current) {\n focusSafely(ref.current);\n }\n } else {\n let updateActiveDescendant = new CustomEvent(UPDATE_ACTIVEDESCENDANT, {\n cancelable: true,\n bubbles: true\n });\n\n ref.current?.dispatchEvent(updateActiveDescendant);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ref, key, manager.focusedKey, manager.childFocusStrategy, manager.isFocused, shouldUseVirtualFocus]);\n\n isDisabled = isDisabled || manager.isDisabled(key);\n // Set tabIndex to 0 if the element is focused, or -1 otherwise so that only the last focused\n // item is tabbable. If using virtual focus, don't set a tabIndex at all so that VoiceOver\n // on iOS 14 doesn't try to move real DOM focus to the item anyway.\n let itemProps: SelectableItemAria['itemProps'] = {};\n if (!shouldUseVirtualFocus && !isDisabled) {\n itemProps = {\n tabIndex: key === manager.focusedKey ? 0 : -1,\n onFocus(e) {\n if (e.target === ref.current) {\n manager.setFocusedKey(key);\n }\n }\n };\n } else if (isDisabled) {\n itemProps.onMouseDown = (e) => {\n // Prevent focus going to the body when clicking on a disabled item.\n e.preventDefault();\n };\n }\n\n // With checkbox selection, onAction (i.e. navigation) becomes primary, and occurs on a single click of the row.\n // Clicking the checkbox enters selection mode, after which clicking anywhere on any row toggles selection for that row.\n // With highlight selection, onAction is secondary, and occurs on double click. Single click selects the row.\n // With touch, onAction occurs on single tap, and long press enters selection mode.\n let isLinkOverride = manager.isLink(key) && linkBehavior === 'override';\n let hasLinkAction = manager.isLink(key) && linkBehavior !== 'selection' && linkBehavior !== 'none';\n let allowsSelection = !isDisabled && manager.canSelectItem(key) && !isLinkOverride;\n let allowsActions = (onAction || hasLinkAction) && !isDisabled;\n let hasPrimaryAction = allowsActions && (\n manager.selectionBehavior === 'replace'\n ? !allowsSelection\n : !allowsSelection || manager.isEmpty\n );\n let hasSecondaryAction = allowsActions && allowsSelection && manager.selectionBehavior === 'replace';\n let hasAction = hasPrimaryAction || hasSecondaryAction;\n let modality = useRef<PointerType | null>(null);\n\n let longPressEnabled = hasAction && allowsSelection;\n let longPressEnabledOnPressStart = useRef(false);\n let hadPrimaryActionOnPressStart = useRef(false);\n\n let performAction = (e) => {\n if (onAction) {\n onAction();\n }\n\n if (hasLinkAction && ref.current) {\n let itemProps = manager.getItemProps(key);\n router.open(ref.current, e, itemProps.href, itemProps.routerOptions);\n }\n };\n\n // By default, selection occurs on pointer down. This can be strange if selecting an\n // item causes the UI to disappear immediately (e.g. menus).\n // If shouldSelectOnPressUp is true, we use onPressUp instead of onPressStart.\n // onPress requires a pointer down event on the same element as pointer up. For menus,\n // we want to be able to have the pointer down on the trigger that opens the menu and\n // the pointer up on the menu item rather than requiring a separate press.\n // For keyboard events, selection still occurs on key down.\n let itemPressProps: PressProps = {};\n if (shouldSelectOnPressUp) {\n itemPressProps.onPressStart = (e) => {\n modality.current = e.pointerType;\n longPressEnabledOnPressStart.current = longPressEnabled;\n if (e.pointerType === 'keyboard' && (!hasAction || isSelectionKey())) {\n onSelect(e);\n }\n };\n\n // If allowsDifferentPressOrigin and interacting with mouse, make selection happen on pressUp (e.g. open menu on press down, selection on menu item happens on press up.)\n // Otherwise, have selection happen onPress (prevents listview row selection when clicking on interactable elements in the row)\n if (!allowsDifferentPressOrigin) {\n itemPressProps.onPress = (e) => {\n if (hasPrimaryAction || (hasSecondaryAction && e.pointerType !== 'mouse')) {\n if (e.pointerType === 'keyboard' && !isActionKey()) {\n return;\n }\n\n performAction(e);\n } else if (e.pointerType !== 'keyboard' && allowsSelection) {\n onSelect(e);\n }\n };\n } else {\n itemPressProps.onPressUp = hasPrimaryAction ? undefined : (e) => {\n if (e.pointerType === 'mouse' && allowsSelection) {\n onSelect(e);\n }\n };\n\n itemPressProps.onPress = hasPrimaryAction ? performAction : (e) => {\n if (e.pointerType !== 'keyboard' && e.pointerType !== 'mouse' && allowsSelection) {\n onSelect(e);\n }\n };\n }\n } else {\n itemPressProps.onPressStart = (e) => {\n modality.current = e.pointerType;\n longPressEnabledOnPressStart.current = longPressEnabled;\n hadPrimaryActionOnPressStart.current = hasPrimaryAction;\n\n // Select on mouse down unless there is a primary action which will occur on mouse up.\n // For keyboard, select on key down. If there is an action, the Space key selects on key down,\n // and the Enter key performs onAction on key up.\n if (\n allowsSelection && (\n (e.pointerType === 'mouse' && !hasPrimaryAction) ||\n (e.pointerType === 'keyboard' && (!allowsActions || isSelectionKey()))\n )\n ) {\n onSelect(e);\n }\n };\n\n itemPressProps.onPress = (e) => {\n // Selection occurs on touch up. Primary actions always occur on pointer up.\n // Both primary and secondary actions occur on Enter key up. The only exception\n // is secondary actions, which occur on double click with a mouse.\n if (\n e.pointerType === 'touch' ||\n e.pointerType === 'pen' ||\n e.pointerType === 'virtual' ||\n (e.pointerType === 'keyboard' && hasAction && isActionKey()) ||\n (e.pointerType === 'mouse' && hadPrimaryActionOnPressStart.current)\n ) {\n if (hasAction) {\n performAction(e);\n } else if (allowsSelection) {\n onSelect(e);\n }\n }\n };\n }\n\n itemProps['data-key'] = key;\n itemPressProps.preventFocusOnPress = shouldUseVirtualFocus;\n let {pressProps, isPressed} = usePress(itemPressProps);\n\n // Double clicking with a mouse with selectionBehavior = 'replace' performs an action.\n let onDoubleClick = hasSecondaryAction ? (e) => {\n if (modality.current === 'mouse') {\n e.stopPropagation();\n e.preventDefault();\n performAction(e);\n }\n } : undefined;\n\n // Long pressing an item with touch when selectionBehavior = 'replace' switches the selection behavior\n // to 'toggle'. This changes the single tap behavior from performing an action (i.e. navigating) to\n // selecting, and may toggle the appearance of a UI affordance like checkboxes on each item.\n let {longPressProps} = useLongPress({\n isDisabled: !longPressEnabled,\n onLongPress(e) {\n if (e.pointerType === 'touch') {\n onSelect(e);\n manager.setSelectionBehavior('toggle');\n }\n }\n });\n\n // Prevent native drag and drop on long press if we also select on long press.\n // Once the user is in selection mode, they can long press again to drag.\n // Use a capturing listener to ensure this runs before useDrag, regardless of\n // the order the props get merged.\n let onDragStartCapture = e => {\n if (modality.current === 'touch' && longPressEnabledOnPressStart.current) {\n e.preventDefault();\n }\n };\n\n // Prevent default on link clicks so that we control exactly\n // when they open (to match selection behavior).\n let onClick = manager.isLink(key) ? e => {\n if (!(openLink as any).isOpening) {\n e.preventDefault();\n }\n } : undefined;\n\n return {\n itemProps: mergeProps(\n itemProps,\n allowsSelection || hasPrimaryAction ? pressProps : {},\n longPressEnabled ? longPressProps : {},\n {onDoubleClick, onDragStartCapture, onClick, id}\n ),\n isPressed,\n isSelected: manager.isSelected(key),\n isFocused: manager.isFocused && manager.focusedKey === key,\n isDisabled,\n allowsSelection,\n hasAction\n };\n}\n\nfunction isActionKey() {\n let event = window.event as KeyboardEvent;\n return event?.key === 'Enter';\n}\n\nfunction isSelectionKey() {\n let event = window.event as KeyboardEvent;\n return event?.key === ' ' || event?.code === 'Space';\n}\n"],"names":[],"version":3,"file":"useSelectableItem.main.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-aria/selection/src/useSelectableItem.ts"],"sourcesContent":["/*\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\nimport {DOMAttributes, DOMProps, FocusableElement, Key, LongPressEvent, PointerType, PressEvent, RefObject} from '@react-types/shared';\nimport {focusSafely} from '@react-aria/focus';\nimport {isCtrlKeyPressed, mergeProps, openLink, UPDATE_ACTIVEDESCENDANT, useId, useRouter} from '@react-aria/utils';\nimport {isNonContiguousSelectionModifier} from './utils';\nimport {MultipleSelectionManager} from '@react-stately/selection';\nimport {PressProps, useLongPress, usePress} from '@react-aria/interactions';\nimport {useEffect, useRef} from 'react';\n\nexport interface SelectableItemOptions extends DOMProps {\n /**\n * An interface for reading and updating multiple selection state.\n */\n selectionManager: MultipleSelectionManager,\n /**\n * A unique key for the item.\n */\n key: Key,\n /**\n * Ref to the item.\n */\n ref: RefObject<FocusableElement | null>,\n /**\n * By default, selection occurs on pointer down. This can be strange if selecting an\n * item causes the UI to disappear immediately (e.g. menus).\n */\n shouldSelectOnPressUp?: boolean,\n /**\n * Whether selection requires the pointer/mouse down and up events to occur on the same target or triggers selection on\n * the target of the pointer/mouse up event.\n */\n allowsDifferentPressOrigin?: boolean,\n /**\n * Whether the option is contained in a virtual scroller.\n */\n isVirtualized?: boolean,\n /**\n * Function to focus the item.\n */\n focus?: () => void,\n /**\n * Whether the option should use virtual focus instead of being focused directly.\n */\n shouldUseVirtualFocus?: boolean,\n /** Whether the item is disabled. */\n isDisabled?: boolean,\n /**\n * Handler that is called when a user performs an action on the item. The exact user event depends on\n * the collection's `selectionBehavior` prop and the interaction modality.\n */\n onAction?: () => void,\n /**\n * The behavior of links in the collection.\n * - 'action': link behaves like onAction.\n * - 'selection': link follows selection interactions (e.g. if URL drives selection).\n * - 'override': links override all other interactions (link items are not selectable).\n * - 'none': links are disabled for both selection and actions (e.g. handled elsewhere).\n * @default 'action'\n */\n linkBehavior?: 'action' | 'selection' | 'override' | 'none'\n}\n\nexport interface SelectableItemStates {\n /** Whether the item is currently in a pressed state. */\n isPressed: boolean,\n /** Whether the item is currently selected. */\n isSelected: boolean,\n /** Whether the item is currently focused. */\n isFocused: boolean,\n /**\n * Whether the item is non-interactive, i.e. both selection and actions are disabled and the item may\n * not be focused. Dependent on `disabledKeys` and `disabledBehavior`.\n */\n isDisabled: boolean,\n /**\n * Whether the item may be selected, dependent on `selectionMode`, `disabledKeys`, and `disabledBehavior`.\n */\n allowsSelection: boolean,\n /**\n * Whether the item has an action, dependent on `onAction`, `disabledKeys`,\n * and `disabledBehavior`. It may also change depending on the current selection state\n * of the list (e.g. when selection is primary). This can be used to enable or disable hover\n * styles or other visual indications of interactivity.\n */\n hasAction: boolean\n}\n\nexport interface SelectableItemAria extends SelectableItemStates {\n /**\n * Props to be spread on the item root node.\n */\n itemProps: DOMAttributes\n}\n\n/**\n * Handles interactions with an item in a selectable collection.\n */\nexport function useSelectableItem(options: SelectableItemOptions): SelectableItemAria {\n let {\n id,\n selectionManager: manager,\n key,\n ref,\n shouldSelectOnPressUp,\n shouldUseVirtualFocus,\n focus,\n isDisabled,\n onAction,\n allowsDifferentPressOrigin,\n linkBehavior = 'action'\n } = options;\n let router = useRouter();\n id = useId(id);\n let onSelect = (e: PressEvent | LongPressEvent | PointerEvent) => {\n if (e.pointerType === 'keyboard' && isNonContiguousSelectionModifier(e)) {\n manager.toggleSelection(key);\n } else {\n if (manager.selectionMode === 'none') {\n return;\n }\n\n if (manager.isLink(key)) {\n if (linkBehavior === 'selection' && ref.current) {\n let itemProps = manager.getItemProps(key);\n router.open(ref.current, e, itemProps.href, itemProps.routerOptions);\n // Always set selected keys back to what they were so that select and combobox close.\n manager.setSelectedKeys(manager.selectedKeys);\n return;\n } else if (linkBehavior === 'override' || linkBehavior === 'none') {\n return;\n }\n }\n\n if (manager.selectionMode === 'single') {\n if (manager.isSelected(key) && !manager.disallowEmptySelection) {\n manager.toggleSelection(key);\n } else {\n manager.replaceSelection(key);\n }\n } else if (e && e.shiftKey) {\n manager.extendSelection(key);\n } else if (manager.selectionBehavior === 'toggle' || (e && (isCtrlKeyPressed(e) || e.pointerType === 'touch' || e.pointerType === 'virtual'))) {\n // 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\n manager.toggleSelection(key);\n } else {\n manager.replaceSelection(key);\n }\n }\n };\n\n // Focus the associated DOM node when this item becomes the focusedKey\n // TODO: can't make this useLayoutEffect bacause it breaks menus inside dialogs\n // However, if this is a useEffect, it runs twice and dispatches two UPDATE_ACTIVEDESCENDANT and immediately sets\n // aria-activeDescendant in useAutocomplete... I've worked around this for now\n useEffect(() => {\n let isFocused = key === manager.focusedKey;\n if (isFocused && manager.isFocused) {\n if (!shouldUseVirtualFocus) {\n if (focus) {\n focus();\n } else if (document.activeElement !== ref.current && ref.current) {\n focusSafely(ref.current);\n }\n } else {\n let updateActiveDescendant = new CustomEvent(UPDATE_ACTIVEDESCENDANT, {\n cancelable: true,\n bubbles: true\n });\n\n ref.current?.dispatchEvent(updateActiveDescendant);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ref, key, manager.focusedKey, manager.childFocusStrategy, manager.isFocused, shouldUseVirtualFocus]);\n\n isDisabled = isDisabled || manager.isDisabled(key);\n // Set tabIndex to 0 if the element is focused, or -1 otherwise so that only the last focused\n // item is tabbable. If using virtual focus, don't set a tabIndex at all so that VoiceOver\n // on iOS 14 doesn't try to move real DOM focus to the item anyway.\n let itemProps: SelectableItemAria['itemProps'] = {};\n if (!shouldUseVirtualFocus && !isDisabled) {\n itemProps = {\n tabIndex: key === manager.focusedKey ? 0 : -1,\n onFocus(e) {\n if (e.target === ref.current) {\n manager.setFocusedKey(key);\n }\n }\n };\n } else if (isDisabled) {\n itemProps.onMouseDown = (e) => {\n // Prevent focus going to the body when clicking on a disabled item.\n e.preventDefault();\n };\n }\n\n // With checkbox selection, onAction (i.e. navigation) becomes primary, and occurs on a single click of the row.\n // Clicking the checkbox enters selection mode, after which clicking anywhere on any row toggles selection for that row.\n // With highlight selection, onAction is secondary, and occurs on double click. Single click selects the row.\n // With touch, onAction occurs on single tap, and long press enters selection mode.\n let isLinkOverride = manager.isLink(key) && linkBehavior === 'override';\n let hasLinkAction = manager.isLink(key) && linkBehavior !== 'selection' && linkBehavior !== 'none';\n let allowsSelection = !isDisabled && manager.canSelectItem(key) && !isLinkOverride;\n let allowsActions = (onAction || hasLinkAction) && !isDisabled;\n let hasPrimaryAction = allowsActions && (\n manager.selectionBehavior === 'replace'\n ? !allowsSelection\n : !allowsSelection || manager.isEmpty\n );\n let hasSecondaryAction = allowsActions && allowsSelection && manager.selectionBehavior === 'replace';\n let hasAction = hasPrimaryAction || hasSecondaryAction;\n let modality = useRef<PointerType | null>(null);\n\n let longPressEnabled = hasAction && allowsSelection;\n let longPressEnabledOnPressStart = useRef(false);\n let hadPrimaryActionOnPressStart = useRef(false);\n\n let performAction = (e) => {\n if (onAction) {\n onAction();\n }\n\n if (hasLinkAction && ref.current) {\n let itemProps = manager.getItemProps(key);\n router.open(ref.current, e, itemProps.href, itemProps.routerOptions);\n }\n };\n\n // By default, selection occurs on pointer down. This can be strange if selecting an\n // item causes the UI to disappear immediately (e.g. menus).\n // If shouldSelectOnPressUp is true, we use onPressUp instead of onPressStart.\n // onPress requires a pointer down event on the same element as pointer up. For menus,\n // we want to be able to have the pointer down on the trigger that opens the menu and\n // the pointer up on the menu item rather than requiring a separate press.\n // For keyboard events, selection still occurs on key down.\n let itemPressProps: PressProps = {};\n if (shouldSelectOnPressUp) {\n itemPressProps.onPressStart = (e) => {\n modality.current = e.pointerType;\n longPressEnabledOnPressStart.current = longPressEnabled;\n if (e.pointerType === 'keyboard' && (!hasAction || isSelectionKey())) {\n onSelect(e);\n }\n };\n\n // If allowsDifferentPressOrigin and interacting with mouse, make selection happen on pressUp (e.g. open menu on press down, selection on menu item happens on press up.)\n // Otherwise, have selection happen onPress (prevents listview row selection when clicking on interactable elements in the row)\n if (!allowsDifferentPressOrigin) {\n itemPressProps.onPress = (e) => {\n if (hasPrimaryAction || (hasSecondaryAction && e.pointerType !== 'mouse')) {\n if (e.pointerType === 'keyboard' && !isActionKey()) {\n return;\n }\n\n performAction(e);\n } else if (e.pointerType !== 'keyboard' && allowsSelection) {\n onSelect(e);\n }\n };\n } else {\n itemPressProps.onPressUp = hasPrimaryAction ? undefined : (e) => {\n if (e.pointerType === 'mouse' && allowsSelection) {\n onSelect(e);\n }\n };\n\n itemPressProps.onPress = hasPrimaryAction ? performAction : (e) => {\n if (e.pointerType !== 'keyboard' && e.pointerType !== 'mouse' && allowsSelection) {\n onSelect(e);\n }\n };\n }\n } else {\n itemPressProps.onPressStart = (e) => {\n modality.current = e.pointerType;\n longPressEnabledOnPressStart.current = longPressEnabled;\n hadPrimaryActionOnPressStart.current = hasPrimaryAction;\n\n // Select on mouse down unless there is a primary action which will occur on mouse up.\n // For keyboard, select on key down. If there is an action, the Space key selects on key down,\n // and the Enter key performs onAction on key up.\n if (\n allowsSelection && (\n (e.pointerType === 'mouse' && !hasPrimaryAction) ||\n (e.pointerType === 'keyboard' && (!allowsActions || isSelectionKey()))\n )\n ) {\n onSelect(e);\n }\n };\n\n itemPressProps.onPress = (e) => {\n // Selection occurs on touch up. Primary actions always occur on pointer up.\n // Both primary and secondary actions occur on Enter key up. The only exception\n // is secondary actions, which occur on double click with a mouse.\n if (\n e.pointerType === 'touch' ||\n e.pointerType === 'pen' ||\n e.pointerType === 'virtual' ||\n (e.pointerType === 'keyboard' && hasAction && isActionKey()) ||\n (e.pointerType === 'mouse' && hadPrimaryActionOnPressStart.current)\n ) {\n if (hasAction) {\n performAction(e);\n } else if (allowsSelection) {\n onSelect(e);\n }\n }\n };\n }\n\n itemProps['data-key'] = key;\n itemPressProps.preventFocusOnPress = shouldUseVirtualFocus;\n let {pressProps, isPressed} = usePress(itemPressProps);\n\n // Double clicking with a mouse with selectionBehavior = 'replace' performs an action.\n let onDoubleClick = hasSecondaryAction ? (e) => {\n if (modality.current === 'mouse') {\n e.stopPropagation();\n e.preventDefault();\n performAction(e);\n }\n } : undefined;\n\n // Long pressing an item with touch when selectionBehavior = 'replace' switches the selection behavior\n // to 'toggle'. This changes the single tap behavior from performing an action (i.e. navigating) to\n // selecting, and may toggle the appearance of a UI affordance like checkboxes on each item.\n let {longPressProps} = useLongPress({\n isDisabled: !longPressEnabled,\n onLongPress(e) {\n if (e.pointerType === 'touch') {\n onSelect(e);\n manager.setSelectionBehavior('toggle');\n }\n }\n });\n\n // Prevent native drag and drop on long press if we also select on long press.\n // Once the user is in selection mode, they can long press again to drag.\n // Use a capturing listener to ensure this runs before useDrag, regardless of\n // the order the props get merged.\n let onDragStartCapture = e => {\n if (modality.current === 'touch' && longPressEnabledOnPressStart.current) {\n e.preventDefault();\n }\n };\n\n // Prevent default on link clicks so that we control exactly\n // when they open (to match selection behavior).\n let onClick = manager.isLink(key) ? e => {\n if (!(openLink as any).isOpening) {\n e.preventDefault();\n }\n } : undefined;\n\n return {\n itemProps: mergeProps(\n itemProps,\n allowsSelection || hasPrimaryAction ? pressProps : {},\n longPressEnabled ? longPressProps : {},\n {onDoubleClick, onDragStartCapture, onClick, id}\n ),\n isPressed,\n isSelected: manager.isSelected(key),\n isFocused: manager.isFocused && manager.focusedKey === key,\n isDisabled,\n allowsSelection,\n hasAction\n };\n}\n\nfunction isActionKey() {\n let event = window.event as KeyboardEvent;\n return event?.key === 'Enter';\n}\n\nfunction isSelectionKey() {\n let event = window.event as KeyboardEvent;\n return event?.key === ' ' || event?.code === 'Space';\n}\n"],"names":[],"version":3,"file":"useSelectableItem.main.js.map"}
@@ -1,6 +1,6 @@
1
- import {isCtrlKeyPressed as $feb5ffebff200149$export$16792effe837dba3, isNonContiguousSelectionModifier as $feb5ffebff200149$export$d3e3bd3e26688c04} from "./utils.mjs";
1
+ import {isNonContiguousSelectionModifier as $feb5ffebff200149$export$d3e3bd3e26688c04} from "./utils.mjs";
2
2
  import {focusSafely as $581M0$focusSafely} from "@react-aria/focus";
3
- import {useRouter as $581M0$useRouter, useId as $581M0$useId, UPDATE_ACTIVEDESCENDANT as $581M0$UPDATE_ACTIVEDESCENDANT, openLink as $581M0$openLink, mergeProps as $581M0$mergeProps} from "@react-aria/utils";
3
+ import {useRouter as $581M0$useRouter, useId as $581M0$useId, isCtrlKeyPressed as $581M0$isCtrlKeyPressed, UPDATE_ACTIVEDESCENDANT as $581M0$UPDATE_ACTIVEDESCENDANT, openLink as $581M0$openLink, mergeProps as $581M0$mergeProps} from "@react-aria/utils";
4
4
  import {usePress as $581M0$usePress, useLongPress as $581M0$useLongPress} from "@react-aria/interactions";
5
5
  import {useEffect as $581M0$useEffect, useRef as $581M0$useRef} from "react";
6
6
 
@@ -40,12 +40,15 @@ function $880e95eb8b93ba9a$export$ecf600387e221c37(options) {
40
40
  if (manager.isSelected(key) && !manager.disallowEmptySelection) manager.toggleSelection(key);
41
41
  else manager.replaceSelection(key);
42
42
  } else if (e && e.shiftKey) manager.extendSelection(key);
43
- else if (manager.selectionBehavior === 'toggle' || e && ((0, $feb5ffebff200149$export$16792effe837dba3)(e) || e.pointerType === 'touch' || e.pointerType === 'virtual')) // 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
43
+ else if (manager.selectionBehavior === 'toggle' || e && ((0, $581M0$isCtrlKeyPressed)(e) || e.pointerType === 'touch' || e.pointerType === 'virtual')) // 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
44
44
  manager.toggleSelection(key);
45
45
  else manager.replaceSelection(key);
46
46
  }
47
47
  };
48
48
  // Focus the associated DOM node when this item becomes the focusedKey
49
+ // TODO: can't make this useLayoutEffect bacause it breaks menus inside dialogs
50
+ // However, if this is a useEffect, it runs twice and dispatches two UPDATE_ACTIVEDESCENDANT and immediately sets
51
+ // aria-activeDescendant in useAutocomplete... I've worked around this for now
49
52
  (0, $581M0$useEffect)(()=>{
50
53
  let isFocused = key === manager.focusedKey;
51
54
  if (isFocused && manager.isFocused) {
@@ -1,6 +1,6 @@
1
- import {isCtrlKeyPressed as $feb5ffebff200149$export$16792effe837dba3, isNonContiguousSelectionModifier as $feb5ffebff200149$export$d3e3bd3e26688c04} from "./utils.module.js";
1
+ import {isNonContiguousSelectionModifier as $feb5ffebff200149$export$d3e3bd3e26688c04} from "./utils.module.js";
2
2
  import {focusSafely as $581M0$focusSafely} from "@react-aria/focus";
3
- import {useRouter as $581M0$useRouter, useId as $581M0$useId, UPDATE_ACTIVEDESCENDANT as $581M0$UPDATE_ACTIVEDESCENDANT, openLink as $581M0$openLink, mergeProps as $581M0$mergeProps} from "@react-aria/utils";
3
+ import {useRouter as $581M0$useRouter, useId as $581M0$useId, isCtrlKeyPressed as $581M0$isCtrlKeyPressed, UPDATE_ACTIVEDESCENDANT as $581M0$UPDATE_ACTIVEDESCENDANT, openLink as $581M0$openLink, mergeProps as $581M0$mergeProps} from "@react-aria/utils";
4
4
  import {usePress as $581M0$usePress, useLongPress as $581M0$useLongPress} from "@react-aria/interactions";
5
5
  import {useEffect as $581M0$useEffect, useRef as $581M0$useRef} from "react";
6
6
 
@@ -40,12 +40,15 @@ function $880e95eb8b93ba9a$export$ecf600387e221c37(options) {
40
40
  if (manager.isSelected(key) && !manager.disallowEmptySelection) manager.toggleSelection(key);
41
41
  else manager.replaceSelection(key);
42
42
  } else if (e && e.shiftKey) manager.extendSelection(key);
43
- else if (manager.selectionBehavior === 'toggle' || e && ((0, $feb5ffebff200149$export$16792effe837dba3)(e) || e.pointerType === 'touch' || e.pointerType === 'virtual')) // 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
43
+ else if (manager.selectionBehavior === 'toggle' || e && ((0, $581M0$isCtrlKeyPressed)(e) || e.pointerType === 'touch' || e.pointerType === 'virtual')) // 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
44
44
  manager.toggleSelection(key);
45
45
  else manager.replaceSelection(key);
46
46
  }
47
47
  };
48
48
  // Focus the associated DOM node when this item becomes the focusedKey
49
+ // TODO: can't make this useLayoutEffect bacause it breaks menus inside dialogs
50
+ // However, if this is a useEffect, it runs twice and dispatches two UPDATE_ACTIVEDESCENDANT and immediately sets
51
+ // aria-activeDescendant in useAutocomplete... I've worked around this for now
49
52
  (0, $581M0$useEffect)(()=>{
50
53
  let isFocused = key === manager.focusedKey;
51
54
  if (isFocused && manager.isFocused) {
@@ -1 +1 @@
1
- {"mappings":";;;;;;AAAA;;;;;;;;;;CAUC;;;;;AAkGM,SAAS,0CAAkB,OAA8B;IAC9D,IAAI,MACF,EAAE,EACF,kBAAkB,OAAO,OACzB,GAAG,OACH,GAAG,yBACH,qBAAqB,yBACrB,qBAAqB,SACrB,KAAK,cACL,UAAU,YACV,QAAQ,8BACR,0BAA0B,gBAC1B,eAAe,UAChB,GAAG;IACJ,IAAI,SAAS,CAAA,GAAA,gBAAQ;IACrB,KAAK,CAAA,GAAA,YAAI,EAAE;IACX,IAAI,WAAW,CAAC;QACd,IAAI,EAAE,WAAW,KAAK,cAAc,CAAA,GAAA,yCAA+B,EAAE,IACnE,QAAQ,eAAe,CAAC;aACnB;YACL,IAAI,QAAQ,aAAa,KAAK,QAC5B;YAGF,IAAI,QAAQ,MAAM,CAAC,MAAM;gBACvB,IAAI,iBAAiB,eAAe,IAAI,OAAO,EAAE;oBAC/C,IAAI,YAAY,QAAQ,YAAY,CAAC;oBACrC,OAAO,IAAI,CAAC,IAAI,OAAO,EAAE,GAAG,UAAU,IAAI,EAAE,UAAU,aAAa;oBACnE,qFAAqF;oBACrF,QAAQ,eAAe,CAAC,QAAQ,YAAY;oBAC5C;gBACF,OAAO,IAAI,iBAAiB,cAAc,iBAAiB,QACzD;YAEJ;YAEA,IAAI,QAAQ,aAAa,KAAK;gBAC5B,IAAI,QAAQ,UAAU,CAAC,QAAQ,CAAC,QAAQ,sBAAsB,EAC5D,QAAQ,eAAe,CAAC;qBAExB,QAAQ,gBAAgB,CAAC;mBAEtB,IAAI,KAAK,EAAE,QAAQ,EACxB,QAAQ,eAAe,CAAC;iBACnB,IAAI,QAAQ,iBAAiB,KAAK,YAAa,KAAM,CAAA,CAAA,GAAA,yCAAe,EAAE,MAAM,EAAE,WAAW,KAAK,WAAW,EAAE,WAAW,KAAK,SAAQ,GACxI,wIAAwI;YACxI,QAAQ,eAAe,CAAC;iBAExB,QAAQ,gBAAgB,CAAC;QAE7B;IACF;IAEA,sEAAsE;IACtE,CAAA,GAAA,gBAAQ,EAAE;QACR,IAAI,YAAY,QAAQ,QAAQ,UAAU;QAC1C,IAAI,aAAa,QAAQ,SAAS;YAChC,IAAI,CAAC,uBAAuB;gBAC1B,IAAI,OACF;qBACK,IAAI,SAAS,aAAa,KAAK,IAAI,OAAO,IAAI,IAAI,OAAO,EAC9D,CAAA,GAAA,kBAAU,EAAE,IAAI,OAAO;YAE3B,OAAO;oBAML;gBALA,IAAI,yBAAyB,IAAI,YAAY,CAAA,GAAA,8BAAsB,GAAG;oBACpE,YAAY;oBACZ,SAAS;gBACX;iBAEA,eAAA,IAAI,OAAO,cAAX,mCAAA,aAAa,aAAa,CAAC;YAC7B;;IAEJ,uDAAuD;IACvD,GAAG;QAAC;QAAK;QAAK,QAAQ,UAAU;QAAE,QAAQ,kBAAkB;QAAE,QAAQ,SAAS;QAAE;KAAsB;IAEvG,aAAa,cAAc,QAAQ,UAAU,CAAC;IAC9C,6FAA6F;IAC7F,2FAA2F;IAC3F,mEAAmE;IACnE,IAAI,YAA6C,CAAC;IAClD,IAAI,CAAC,yBAAyB,CAAC,YAC7B,YAAY;QACV,UAAU,QAAQ,QAAQ,UAAU,GAAG,IAAI;QAC3C,SAAQ,CAAC;YACP,IAAI,EAAE,MAAM,KAAK,IAAI,OAAO,EAC1B,QAAQ,aAAa,CAAC;QAE1B;IACF;SACK,IAAI,YACT,UAAU,WAAW,GAAG,CAAC;QACvB,oEAAoE;QACpE,EAAE,cAAc;IAClB;IAGF,gHAAgH;IAChH,wHAAwH;IACxH,6GAA6G;IAC7G,mFAAmF;IACnF,IAAI,iBAAiB,QAAQ,MAAM,CAAC,QAAQ,iBAAiB;IAC7D,IAAI,gBAAgB,QAAQ,MAAM,CAAC,QAAQ,iBAAiB,eAAe,iBAAiB;IAC5F,IAAI,kBAAkB,CAAC,cAAc,QAAQ,aAAa,CAAC,QAAQ,CAAC;IACpE,IAAI,gBAAgB,AAAC,CAAA,YAAY,aAAY,KAAM,CAAC;IACpD,IAAI,mBAAmB,iBACrB,CAAA,QAAQ,iBAAiB,KAAK,YAC1B,CAAC,kBACD,CAAC,mBAAmB,QAAQ,OAAO,AAAD;IAExC,IAAI,qBAAqB,iBAAiB,mBAAmB,QAAQ,iBAAiB,KAAK;IAC3F,IAAI,YAAY,oBAAoB;IACpC,IAAI,WAAW,CAAA,GAAA,aAAK,EAAsB;IAE1C,IAAI,mBAAmB,aAAa;IACpC,IAAI,+BAA+B,CAAA,GAAA,aAAK,EAAE;IAC1C,IAAI,+BAA+B,CAAA,GAAA,aAAK,EAAE;IAE1C,IAAI,gBAAgB,CAAC;QACnB,IAAI,UACF;QAGF,IAAI,iBAAiB,IAAI,OAAO,EAAE;YAChC,IAAI,YAAY,QAAQ,YAAY,CAAC;YACrC,OAAO,IAAI,CAAC,IAAI,OAAO,EAAE,GAAG,UAAU,IAAI,EAAE,UAAU,aAAa;QACrE;IACF;IAEA,oFAAoF;IACpF,4DAA4D;IAC5D,8EAA8E;IAC9E,sFAAsF;IACtF,qFAAqF;IACrF,0EAA0E;IAC1E,2DAA2D;IAC3D,IAAI,iBAA6B,CAAC;IAClC,IAAI,uBAAuB;QACzB,eAAe,YAAY,GAAG,CAAC;YAC7B,SAAS,OAAO,GAAG,EAAE,WAAW;YAChC,6BAA6B,OAAO,GAAG;YACvC,IAAI,EAAE,WAAW,KAAK,cAAe,CAAA,CAAC,aAAa,sCAAe,GAChE,SAAS;QAEb;QAEA,yKAAyK;QACzK,+HAA+H;QAC/H,IAAI,CAAC,4BACH,eAAe,OAAO,GAAG,CAAC;YACxB,IAAI,oBAAqB,sBAAsB,EAAE,WAAW,KAAK,SAAU;gBACzE,IAAI,EAAE,WAAW,KAAK,cAAc,CAAC,qCACnC;gBAGF,cAAc;YAChB,OAAO,IAAI,EAAE,WAAW,KAAK,cAAc,iBACzC,SAAS;QAEb;aACK;YACL,eAAe,SAAS,GAAG,mBAAmB,YAAY,CAAC;gBACzD,IAAI,EAAE,WAAW,KAAK,WAAW,iBAC/B,SAAS;YAEb;YAEA,eAAe,OAAO,GAAG,mBAAmB,gBAAgB,CAAC;gBAC3D,IAAI,EAAE,WAAW,KAAK,cAAc,EAAE,WAAW,KAAK,WAAW,iBAC/D,SAAS;YAEb;QACF;IACF,OAAO;QACL,eAAe,YAAY,GAAG,CAAC;YAC7B,SAAS,OAAO,GAAG,EAAE,WAAW;YAChC,6BAA6B,OAAO,GAAG;YACvC,6BAA6B,OAAO,GAAG;YAEvC,sFAAsF;YACtF,8FAA8F;YAC9F,iDAAiD;YACjD,IACE,mBACE,CAAA,AAAC,EAAE,WAAW,KAAK,WAAW,CAAC,oBAC9B,EAAE,WAAW,KAAK,cAAe,CAAA,CAAC,iBAAiB,sCAAe,CAAE,GAGvE,SAAS;QAEb;QAEA,eAAe,OAAO,GAAG,CAAC;YACxB,4EAA4E;YAC5E,+EAA+E;YAC/E,kEAAkE;YAClE,IACE,EAAE,WAAW,KAAK,WAClB,EAAE,WAAW,KAAK,SAClB,EAAE,WAAW,KAAK,aACjB,EAAE,WAAW,KAAK,cAAc,aAAa,uCAC7C,EAAE,WAAW,KAAK,WAAW,6BAA6B,OAAO,EAClE;gBACA,IAAI,WACF,cAAc;qBACT,IAAI,iBACT,SAAS;YAEb;QACF;IACF;IAEA,SAAS,CAAC,WAAW,GAAG;IACxB,eAAe,mBAAmB,GAAG;IACrC,IAAI,cAAC,UAAU,aAAE,SAAS,EAAC,GAAG,CAAA,GAAA,eAAO,EAAE;IAEvC,sFAAsF;IACtF,IAAI,gBAAgB,qBAAqB,CAAC;QACxC,IAAI,SAAS,OAAO,KAAK,SAAS;YAChC,EAAE,eAAe;YACjB,EAAE,cAAc;YAChB,cAAc;QAChB;IACF,IAAI;IAEJ,sGAAsG;IACtG,mGAAmG;IACnG,4FAA4F;IAC5F,IAAI,kBAAC,cAAc,EAAC,GAAG,CAAA,GAAA,mBAAW,EAAE;QAClC,YAAY,CAAC;QACb,aAAY,CAAC;YACX,IAAI,EAAE,WAAW,KAAK,SAAS;gBAC7B,SAAS;gBACT,QAAQ,oBAAoB,CAAC;YAC/B;QACF;IACF;IAEA,8EAA8E;IAC9E,yEAAyE;IACzE,6EAA6E;IAC7E,kCAAkC;IAClC,IAAI,qBAAqB,CAAA;QACvB,IAAI,SAAS,OAAO,KAAK,WAAW,6BAA6B,OAAO,EACtE,EAAE,cAAc;IAEpB;IAEA,4DAA4D;IAC5D,gDAAgD;IAChD,IAAI,UAAU,QAAQ,MAAM,CAAC,OAAO,CAAA;QAClC,IAAI,CAAC,AAAC,CAAA,GAAA,eAAO,EAAU,SAAS,EAC9B,EAAE,cAAc;IAEpB,IAAI;IAEJ,OAAO;QACL,WAAW,CAAA,GAAA,iBAAS,EAClB,WACA,mBAAmB,mBAAmB,aAAa,CAAC,GACpD,mBAAmB,iBAAiB,CAAC,GACrC;2BAAC;gCAAe;qBAAoB;gBAAS;QAAE;mBAEjD;QACA,YAAY,QAAQ,UAAU,CAAC;QAC/B,WAAW,QAAQ,SAAS,IAAI,QAAQ,UAAU,KAAK;oBACvD;yBACA;mBACA;IACF;AACF;AAEA,SAAS;IACP,IAAI,QAAQ,OAAO,KAAK;IACxB,OAAO,CAAA,kBAAA,4BAAA,MAAO,GAAG,MAAK;AACxB;AAEA,SAAS;IACP,IAAI,QAAQ,OAAO,KAAK;IACxB,OAAO,CAAA,kBAAA,4BAAA,MAAO,GAAG,MAAK,OAAO,CAAA,kBAAA,4BAAA,MAAO,IAAI,MAAK;AAC/C","sources":["packages/@react-aria/selection/src/useSelectableItem.ts"],"sourcesContent":["/*\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\nimport {DOMAttributes, DOMProps, FocusableElement, Key, LongPressEvent, PointerType, PressEvent, RefObject} from '@react-types/shared';\nimport {focusSafely} from '@react-aria/focus';\nimport {isCtrlKeyPressed, isNonContiguousSelectionModifier} from './utils';\nimport {mergeProps, openLink, UPDATE_ACTIVEDESCENDANT, useId, useRouter} from '@react-aria/utils';\nimport {MultipleSelectionManager} from '@react-stately/selection';\nimport {PressProps, useLongPress, usePress} from '@react-aria/interactions';\nimport {useEffect, useRef} from 'react';\n\nexport interface SelectableItemOptions extends DOMProps {\n /**\n * An interface for reading and updating multiple selection state.\n */\n selectionManager: MultipleSelectionManager,\n /**\n * A unique key for the item.\n */\n key: Key,\n /**\n * Ref to the item.\n */\n ref: RefObject<FocusableElement | null>,\n /**\n * By default, selection occurs on pointer down. This can be strange if selecting an\n * item causes the UI to disappear immediately (e.g. menus).\n */\n shouldSelectOnPressUp?: boolean,\n /**\n * Whether selection requires the pointer/mouse down and up events to occur on the same target or triggers selection on\n * the target of the pointer/mouse up event.\n */\n allowsDifferentPressOrigin?: boolean,\n /**\n * Whether the option is contained in a virtual scroller.\n */\n isVirtualized?: boolean,\n /**\n * Function to focus the item.\n */\n focus?: () => void,\n /**\n * Whether the option should use virtual focus instead of being focused directly.\n */\n shouldUseVirtualFocus?: boolean,\n /** Whether the item is disabled. */\n isDisabled?: boolean,\n /**\n * Handler that is called when a user performs an action on the item. The exact user event depends on\n * the collection's `selectionBehavior` prop and the interaction modality.\n */\n onAction?: () => void,\n /**\n * The behavior of links in the collection.\n * - 'action': link behaves like onAction.\n * - 'selection': link follows selection interactions (e.g. if URL drives selection).\n * - 'override': links override all other interactions (link items are not selectable).\n * - 'none': links are disabled for both selection and actions (e.g. handled elsewhere).\n * @default 'action'\n */\n linkBehavior?: 'action' | 'selection' | 'override' | 'none'\n}\n\nexport interface SelectableItemStates {\n /** Whether the item is currently in a pressed state. */\n isPressed: boolean,\n /** Whether the item is currently selected. */\n isSelected: boolean,\n /** Whether the item is currently focused. */\n isFocused: boolean,\n /**\n * Whether the item is non-interactive, i.e. both selection and actions are disabled and the item may\n * not be focused. Dependent on `disabledKeys` and `disabledBehavior`.\n */\n isDisabled: boolean,\n /**\n * Whether the item may be selected, dependent on `selectionMode`, `disabledKeys`, and `disabledBehavior`.\n */\n allowsSelection: boolean,\n /**\n * Whether the item has an action, dependent on `onAction`, `disabledKeys`,\n * and `disabledBehavior`. It may also change depending on the current selection state\n * of the list (e.g. when selection is primary). This can be used to enable or disable hover\n * styles or other visual indications of interactivity.\n */\n hasAction: boolean\n}\n\nexport interface SelectableItemAria extends SelectableItemStates {\n /**\n * Props to be spread on the item root node.\n */\n itemProps: DOMAttributes\n}\n\n/**\n * Handles interactions with an item in a selectable collection.\n */\nexport function useSelectableItem(options: SelectableItemOptions): SelectableItemAria {\n let {\n id,\n selectionManager: manager,\n key,\n ref,\n shouldSelectOnPressUp,\n shouldUseVirtualFocus,\n focus,\n isDisabled,\n onAction,\n allowsDifferentPressOrigin,\n linkBehavior = 'action'\n } = options;\n let router = useRouter();\n id = useId(id);\n let onSelect = (e: PressEvent | LongPressEvent | PointerEvent) => {\n if (e.pointerType === 'keyboard' && isNonContiguousSelectionModifier(e)) {\n manager.toggleSelection(key);\n } else {\n if (manager.selectionMode === 'none') {\n return;\n }\n\n if (manager.isLink(key)) {\n if (linkBehavior === 'selection' && ref.current) {\n let itemProps = manager.getItemProps(key);\n router.open(ref.current, e, itemProps.href, itemProps.routerOptions);\n // Always set selected keys back to what they were so that select and combobox close.\n manager.setSelectedKeys(manager.selectedKeys);\n return;\n } else if (linkBehavior === 'override' || linkBehavior === 'none') {\n return;\n }\n }\n\n if (manager.selectionMode === 'single') {\n if (manager.isSelected(key) && !manager.disallowEmptySelection) {\n manager.toggleSelection(key);\n } else {\n manager.replaceSelection(key);\n }\n } else if (e && e.shiftKey) {\n manager.extendSelection(key);\n } else if (manager.selectionBehavior === 'toggle' || (e && (isCtrlKeyPressed(e) || e.pointerType === 'touch' || e.pointerType === 'virtual'))) {\n // 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\n manager.toggleSelection(key);\n } else {\n manager.replaceSelection(key);\n }\n }\n };\n\n // Focus the associated DOM node when this item becomes the focusedKey\n useEffect(() => {\n let isFocused = key === manager.focusedKey;\n if (isFocused && manager.isFocused) {\n if (!shouldUseVirtualFocus) {\n if (focus) {\n focus();\n } else if (document.activeElement !== ref.current && ref.current) {\n focusSafely(ref.current);\n }\n } else {\n let updateActiveDescendant = new CustomEvent(UPDATE_ACTIVEDESCENDANT, {\n cancelable: true,\n bubbles: true\n });\n\n ref.current?.dispatchEvent(updateActiveDescendant);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ref, key, manager.focusedKey, manager.childFocusStrategy, manager.isFocused, shouldUseVirtualFocus]);\n\n isDisabled = isDisabled || manager.isDisabled(key);\n // Set tabIndex to 0 if the element is focused, or -1 otherwise so that only the last focused\n // item is tabbable. If using virtual focus, don't set a tabIndex at all so that VoiceOver\n // on iOS 14 doesn't try to move real DOM focus to the item anyway.\n let itemProps: SelectableItemAria['itemProps'] = {};\n if (!shouldUseVirtualFocus && !isDisabled) {\n itemProps = {\n tabIndex: key === manager.focusedKey ? 0 : -1,\n onFocus(e) {\n if (e.target === ref.current) {\n manager.setFocusedKey(key);\n }\n }\n };\n } else if (isDisabled) {\n itemProps.onMouseDown = (e) => {\n // Prevent focus going to the body when clicking on a disabled item.\n e.preventDefault();\n };\n }\n\n // With checkbox selection, onAction (i.e. navigation) becomes primary, and occurs on a single click of the row.\n // Clicking the checkbox enters selection mode, after which clicking anywhere on any row toggles selection for that row.\n // With highlight selection, onAction is secondary, and occurs on double click. Single click selects the row.\n // With touch, onAction occurs on single tap, and long press enters selection mode.\n let isLinkOverride = manager.isLink(key) && linkBehavior === 'override';\n let hasLinkAction = manager.isLink(key) && linkBehavior !== 'selection' && linkBehavior !== 'none';\n let allowsSelection = !isDisabled && manager.canSelectItem(key) && !isLinkOverride;\n let allowsActions = (onAction || hasLinkAction) && !isDisabled;\n let hasPrimaryAction = allowsActions && (\n manager.selectionBehavior === 'replace'\n ? !allowsSelection\n : !allowsSelection || manager.isEmpty\n );\n let hasSecondaryAction = allowsActions && allowsSelection && manager.selectionBehavior === 'replace';\n let hasAction = hasPrimaryAction || hasSecondaryAction;\n let modality = useRef<PointerType | null>(null);\n\n let longPressEnabled = hasAction && allowsSelection;\n let longPressEnabledOnPressStart = useRef(false);\n let hadPrimaryActionOnPressStart = useRef(false);\n\n let performAction = (e) => {\n if (onAction) {\n onAction();\n }\n\n if (hasLinkAction && ref.current) {\n let itemProps = manager.getItemProps(key);\n router.open(ref.current, e, itemProps.href, itemProps.routerOptions);\n }\n };\n\n // By default, selection occurs on pointer down. This can be strange if selecting an\n // item causes the UI to disappear immediately (e.g. menus).\n // If shouldSelectOnPressUp is true, we use onPressUp instead of onPressStart.\n // onPress requires a pointer down event on the same element as pointer up. For menus,\n // we want to be able to have the pointer down on the trigger that opens the menu and\n // the pointer up on the menu item rather than requiring a separate press.\n // For keyboard events, selection still occurs on key down.\n let itemPressProps: PressProps = {};\n if (shouldSelectOnPressUp) {\n itemPressProps.onPressStart = (e) => {\n modality.current = e.pointerType;\n longPressEnabledOnPressStart.current = longPressEnabled;\n if (e.pointerType === 'keyboard' && (!hasAction || isSelectionKey())) {\n onSelect(e);\n }\n };\n\n // If allowsDifferentPressOrigin and interacting with mouse, make selection happen on pressUp (e.g. open menu on press down, selection on menu item happens on press up.)\n // Otherwise, have selection happen onPress (prevents listview row selection when clicking on interactable elements in the row)\n if (!allowsDifferentPressOrigin) {\n itemPressProps.onPress = (e) => {\n if (hasPrimaryAction || (hasSecondaryAction && e.pointerType !== 'mouse')) {\n if (e.pointerType === 'keyboard' && !isActionKey()) {\n return;\n }\n\n performAction(e);\n } else if (e.pointerType !== 'keyboard' && allowsSelection) {\n onSelect(e);\n }\n };\n } else {\n itemPressProps.onPressUp = hasPrimaryAction ? undefined : (e) => {\n if (e.pointerType === 'mouse' && allowsSelection) {\n onSelect(e);\n }\n };\n\n itemPressProps.onPress = hasPrimaryAction ? performAction : (e) => {\n if (e.pointerType !== 'keyboard' && e.pointerType !== 'mouse' && allowsSelection) {\n onSelect(e);\n }\n };\n }\n } else {\n itemPressProps.onPressStart = (e) => {\n modality.current = e.pointerType;\n longPressEnabledOnPressStart.current = longPressEnabled;\n hadPrimaryActionOnPressStart.current = hasPrimaryAction;\n\n // Select on mouse down unless there is a primary action which will occur on mouse up.\n // For keyboard, select on key down. If there is an action, the Space key selects on key down,\n // and the Enter key performs onAction on key up.\n if (\n allowsSelection && (\n (e.pointerType === 'mouse' && !hasPrimaryAction) ||\n (e.pointerType === 'keyboard' && (!allowsActions || isSelectionKey()))\n )\n ) {\n onSelect(e);\n }\n };\n\n itemPressProps.onPress = (e) => {\n // Selection occurs on touch up. Primary actions always occur on pointer up.\n // Both primary and secondary actions occur on Enter key up. The only exception\n // is secondary actions, which occur on double click with a mouse.\n if (\n e.pointerType === 'touch' ||\n e.pointerType === 'pen' ||\n e.pointerType === 'virtual' ||\n (e.pointerType === 'keyboard' && hasAction && isActionKey()) ||\n (e.pointerType === 'mouse' && hadPrimaryActionOnPressStart.current)\n ) {\n if (hasAction) {\n performAction(e);\n } else if (allowsSelection) {\n onSelect(e);\n }\n }\n };\n }\n\n itemProps['data-key'] = key;\n itemPressProps.preventFocusOnPress = shouldUseVirtualFocus;\n let {pressProps, isPressed} = usePress(itemPressProps);\n\n // Double clicking with a mouse with selectionBehavior = 'replace' performs an action.\n let onDoubleClick = hasSecondaryAction ? (e) => {\n if (modality.current === 'mouse') {\n e.stopPropagation();\n e.preventDefault();\n performAction(e);\n }\n } : undefined;\n\n // Long pressing an item with touch when selectionBehavior = 'replace' switches the selection behavior\n // to 'toggle'. This changes the single tap behavior from performing an action (i.e. navigating) to\n // selecting, and may toggle the appearance of a UI affordance like checkboxes on each item.\n let {longPressProps} = useLongPress({\n isDisabled: !longPressEnabled,\n onLongPress(e) {\n if (e.pointerType === 'touch') {\n onSelect(e);\n manager.setSelectionBehavior('toggle');\n }\n }\n });\n\n // Prevent native drag and drop on long press if we also select on long press.\n // Once the user is in selection mode, they can long press again to drag.\n // Use a capturing listener to ensure this runs before useDrag, regardless of\n // the order the props get merged.\n let onDragStartCapture = e => {\n if (modality.current === 'touch' && longPressEnabledOnPressStart.current) {\n e.preventDefault();\n }\n };\n\n // Prevent default on link clicks so that we control exactly\n // when they open (to match selection behavior).\n let onClick = manager.isLink(key) ? e => {\n if (!(openLink as any).isOpening) {\n e.preventDefault();\n }\n } : undefined;\n\n return {\n itemProps: mergeProps(\n itemProps,\n allowsSelection || hasPrimaryAction ? pressProps : {},\n longPressEnabled ? longPressProps : {},\n {onDoubleClick, onDragStartCapture, onClick, id}\n ),\n isPressed,\n isSelected: manager.isSelected(key),\n isFocused: manager.isFocused && manager.focusedKey === key,\n isDisabled,\n allowsSelection,\n hasAction\n };\n}\n\nfunction isActionKey() {\n let event = window.event as KeyboardEvent;\n return event?.key === 'Enter';\n}\n\nfunction isSelectionKey() {\n let event = window.event as KeyboardEvent;\n return event?.key === ' ' || event?.code === 'Space';\n}\n"],"names":[],"version":3,"file":"useSelectableItem.module.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-aria/selection/src/useSelectableItem.ts"],"sourcesContent":["/*\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\nimport {DOMAttributes, DOMProps, FocusableElement, Key, LongPressEvent, PointerType, PressEvent, RefObject} from '@react-types/shared';\nimport {focusSafely} from '@react-aria/focus';\nimport {isCtrlKeyPressed, mergeProps, openLink, UPDATE_ACTIVEDESCENDANT, useId, useRouter} from '@react-aria/utils';\nimport {isNonContiguousSelectionModifier} from './utils';\nimport {MultipleSelectionManager} from '@react-stately/selection';\nimport {PressProps, useLongPress, usePress} from '@react-aria/interactions';\nimport {useEffect, useRef} from 'react';\n\nexport interface SelectableItemOptions extends DOMProps {\n /**\n * An interface for reading and updating multiple selection state.\n */\n selectionManager: MultipleSelectionManager,\n /**\n * A unique key for the item.\n */\n key: Key,\n /**\n * Ref to the item.\n */\n ref: RefObject<FocusableElement | null>,\n /**\n * By default, selection occurs on pointer down. This can be strange if selecting an\n * item causes the UI to disappear immediately (e.g. menus).\n */\n shouldSelectOnPressUp?: boolean,\n /**\n * Whether selection requires the pointer/mouse down and up events to occur on the same target or triggers selection on\n * the target of the pointer/mouse up event.\n */\n allowsDifferentPressOrigin?: boolean,\n /**\n * Whether the option is contained in a virtual scroller.\n */\n isVirtualized?: boolean,\n /**\n * Function to focus the item.\n */\n focus?: () => void,\n /**\n * Whether the option should use virtual focus instead of being focused directly.\n */\n shouldUseVirtualFocus?: boolean,\n /** Whether the item is disabled. */\n isDisabled?: boolean,\n /**\n * Handler that is called when a user performs an action on the item. The exact user event depends on\n * the collection's `selectionBehavior` prop and the interaction modality.\n */\n onAction?: () => void,\n /**\n * The behavior of links in the collection.\n * - 'action': link behaves like onAction.\n * - 'selection': link follows selection interactions (e.g. if URL drives selection).\n * - 'override': links override all other interactions (link items are not selectable).\n * - 'none': links are disabled for both selection and actions (e.g. handled elsewhere).\n * @default 'action'\n */\n linkBehavior?: 'action' | 'selection' | 'override' | 'none'\n}\n\nexport interface SelectableItemStates {\n /** Whether the item is currently in a pressed state. */\n isPressed: boolean,\n /** Whether the item is currently selected. */\n isSelected: boolean,\n /** Whether the item is currently focused. */\n isFocused: boolean,\n /**\n * Whether the item is non-interactive, i.e. both selection and actions are disabled and the item may\n * not be focused. Dependent on `disabledKeys` and `disabledBehavior`.\n */\n isDisabled: boolean,\n /**\n * Whether the item may be selected, dependent on `selectionMode`, `disabledKeys`, and `disabledBehavior`.\n */\n allowsSelection: boolean,\n /**\n * Whether the item has an action, dependent on `onAction`, `disabledKeys`,\n * and `disabledBehavior`. It may also change depending on the current selection state\n * of the list (e.g. when selection is primary). This can be used to enable or disable hover\n * styles or other visual indications of interactivity.\n */\n hasAction: boolean\n}\n\nexport interface SelectableItemAria extends SelectableItemStates {\n /**\n * Props to be spread on the item root node.\n */\n itemProps: DOMAttributes\n}\n\n/**\n * Handles interactions with an item in a selectable collection.\n */\nexport function useSelectableItem(options: SelectableItemOptions): SelectableItemAria {\n let {\n id,\n selectionManager: manager,\n key,\n ref,\n shouldSelectOnPressUp,\n shouldUseVirtualFocus,\n focus,\n isDisabled,\n onAction,\n allowsDifferentPressOrigin,\n linkBehavior = 'action'\n } = options;\n let router = useRouter();\n id = useId(id);\n let onSelect = (e: PressEvent | LongPressEvent | PointerEvent) => {\n if (e.pointerType === 'keyboard' && isNonContiguousSelectionModifier(e)) {\n manager.toggleSelection(key);\n } else {\n if (manager.selectionMode === 'none') {\n return;\n }\n\n if (manager.isLink(key)) {\n if (linkBehavior === 'selection' && ref.current) {\n let itemProps = manager.getItemProps(key);\n router.open(ref.current, e, itemProps.href, itemProps.routerOptions);\n // Always set selected keys back to what they were so that select and combobox close.\n manager.setSelectedKeys(manager.selectedKeys);\n return;\n } else if (linkBehavior === 'override' || linkBehavior === 'none') {\n return;\n }\n }\n\n if (manager.selectionMode === 'single') {\n if (manager.isSelected(key) && !manager.disallowEmptySelection) {\n manager.toggleSelection(key);\n } else {\n manager.replaceSelection(key);\n }\n } else if (e && e.shiftKey) {\n manager.extendSelection(key);\n } else if (manager.selectionBehavior === 'toggle' || (e && (isCtrlKeyPressed(e) || e.pointerType === 'touch' || e.pointerType === 'virtual'))) {\n // 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\n manager.toggleSelection(key);\n } else {\n manager.replaceSelection(key);\n }\n }\n };\n\n // Focus the associated DOM node when this item becomes the focusedKey\n // TODO: can't make this useLayoutEffect bacause it breaks menus inside dialogs\n // However, if this is a useEffect, it runs twice and dispatches two UPDATE_ACTIVEDESCENDANT and immediately sets\n // aria-activeDescendant in useAutocomplete... I've worked around this for now\n useEffect(() => {\n let isFocused = key === manager.focusedKey;\n if (isFocused && manager.isFocused) {\n if (!shouldUseVirtualFocus) {\n if (focus) {\n focus();\n } else if (document.activeElement !== ref.current && ref.current) {\n focusSafely(ref.current);\n }\n } else {\n let updateActiveDescendant = new CustomEvent(UPDATE_ACTIVEDESCENDANT, {\n cancelable: true,\n bubbles: true\n });\n\n ref.current?.dispatchEvent(updateActiveDescendant);\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ref, key, manager.focusedKey, manager.childFocusStrategy, manager.isFocused, shouldUseVirtualFocus]);\n\n isDisabled = isDisabled || manager.isDisabled(key);\n // Set tabIndex to 0 if the element is focused, or -1 otherwise so that only the last focused\n // item is tabbable. If using virtual focus, don't set a tabIndex at all so that VoiceOver\n // on iOS 14 doesn't try to move real DOM focus to the item anyway.\n let itemProps: SelectableItemAria['itemProps'] = {};\n if (!shouldUseVirtualFocus && !isDisabled) {\n itemProps = {\n tabIndex: key === manager.focusedKey ? 0 : -1,\n onFocus(e) {\n if (e.target === ref.current) {\n manager.setFocusedKey(key);\n }\n }\n };\n } else if (isDisabled) {\n itemProps.onMouseDown = (e) => {\n // Prevent focus going to the body when clicking on a disabled item.\n e.preventDefault();\n };\n }\n\n // With checkbox selection, onAction (i.e. navigation) becomes primary, and occurs on a single click of the row.\n // Clicking the checkbox enters selection mode, after which clicking anywhere on any row toggles selection for that row.\n // With highlight selection, onAction is secondary, and occurs on double click. Single click selects the row.\n // With touch, onAction occurs on single tap, and long press enters selection mode.\n let isLinkOverride = manager.isLink(key) && linkBehavior === 'override';\n let hasLinkAction = manager.isLink(key) && linkBehavior !== 'selection' && linkBehavior !== 'none';\n let allowsSelection = !isDisabled && manager.canSelectItem(key) && !isLinkOverride;\n let allowsActions = (onAction || hasLinkAction) && !isDisabled;\n let hasPrimaryAction = allowsActions && (\n manager.selectionBehavior === 'replace'\n ? !allowsSelection\n : !allowsSelection || manager.isEmpty\n );\n let hasSecondaryAction = allowsActions && allowsSelection && manager.selectionBehavior === 'replace';\n let hasAction = hasPrimaryAction || hasSecondaryAction;\n let modality = useRef<PointerType | null>(null);\n\n let longPressEnabled = hasAction && allowsSelection;\n let longPressEnabledOnPressStart = useRef(false);\n let hadPrimaryActionOnPressStart = useRef(false);\n\n let performAction = (e) => {\n if (onAction) {\n onAction();\n }\n\n if (hasLinkAction && ref.current) {\n let itemProps = manager.getItemProps(key);\n router.open(ref.current, e, itemProps.href, itemProps.routerOptions);\n }\n };\n\n // By default, selection occurs on pointer down. This can be strange if selecting an\n // item causes the UI to disappear immediately (e.g. menus).\n // If shouldSelectOnPressUp is true, we use onPressUp instead of onPressStart.\n // onPress requires a pointer down event on the same element as pointer up. For menus,\n // we want to be able to have the pointer down on the trigger that opens the menu and\n // the pointer up on the menu item rather than requiring a separate press.\n // For keyboard events, selection still occurs on key down.\n let itemPressProps: PressProps = {};\n if (shouldSelectOnPressUp) {\n itemPressProps.onPressStart = (e) => {\n modality.current = e.pointerType;\n longPressEnabledOnPressStart.current = longPressEnabled;\n if (e.pointerType === 'keyboard' && (!hasAction || isSelectionKey())) {\n onSelect(e);\n }\n };\n\n // If allowsDifferentPressOrigin and interacting with mouse, make selection happen on pressUp (e.g. open menu on press down, selection on menu item happens on press up.)\n // Otherwise, have selection happen onPress (prevents listview row selection when clicking on interactable elements in the row)\n if (!allowsDifferentPressOrigin) {\n itemPressProps.onPress = (e) => {\n if (hasPrimaryAction || (hasSecondaryAction && e.pointerType !== 'mouse')) {\n if (e.pointerType === 'keyboard' && !isActionKey()) {\n return;\n }\n\n performAction(e);\n } else if (e.pointerType !== 'keyboard' && allowsSelection) {\n onSelect(e);\n }\n };\n } else {\n itemPressProps.onPressUp = hasPrimaryAction ? undefined : (e) => {\n if (e.pointerType === 'mouse' && allowsSelection) {\n onSelect(e);\n }\n };\n\n itemPressProps.onPress = hasPrimaryAction ? performAction : (e) => {\n if (e.pointerType !== 'keyboard' && e.pointerType !== 'mouse' && allowsSelection) {\n onSelect(e);\n }\n };\n }\n } else {\n itemPressProps.onPressStart = (e) => {\n modality.current = e.pointerType;\n longPressEnabledOnPressStart.current = longPressEnabled;\n hadPrimaryActionOnPressStart.current = hasPrimaryAction;\n\n // Select on mouse down unless there is a primary action which will occur on mouse up.\n // For keyboard, select on key down. If there is an action, the Space key selects on key down,\n // and the Enter key performs onAction on key up.\n if (\n allowsSelection && (\n (e.pointerType === 'mouse' && !hasPrimaryAction) ||\n (e.pointerType === 'keyboard' && (!allowsActions || isSelectionKey()))\n )\n ) {\n onSelect(e);\n }\n };\n\n itemPressProps.onPress = (e) => {\n // Selection occurs on touch up. Primary actions always occur on pointer up.\n // Both primary and secondary actions occur on Enter key up. The only exception\n // is secondary actions, which occur on double click with a mouse.\n if (\n e.pointerType === 'touch' ||\n e.pointerType === 'pen' ||\n e.pointerType === 'virtual' ||\n (e.pointerType === 'keyboard' && hasAction && isActionKey()) ||\n (e.pointerType === 'mouse' && hadPrimaryActionOnPressStart.current)\n ) {\n if (hasAction) {\n performAction(e);\n } else if (allowsSelection) {\n onSelect(e);\n }\n }\n };\n }\n\n itemProps['data-key'] = key;\n itemPressProps.preventFocusOnPress = shouldUseVirtualFocus;\n let {pressProps, isPressed} = usePress(itemPressProps);\n\n // Double clicking with a mouse with selectionBehavior = 'replace' performs an action.\n let onDoubleClick = hasSecondaryAction ? (e) => {\n if (modality.current === 'mouse') {\n e.stopPropagation();\n e.preventDefault();\n performAction(e);\n }\n } : undefined;\n\n // Long pressing an item with touch when selectionBehavior = 'replace' switches the selection behavior\n // to 'toggle'. This changes the single tap behavior from performing an action (i.e. navigating) to\n // selecting, and may toggle the appearance of a UI affordance like checkboxes on each item.\n let {longPressProps} = useLongPress({\n isDisabled: !longPressEnabled,\n onLongPress(e) {\n if (e.pointerType === 'touch') {\n onSelect(e);\n manager.setSelectionBehavior('toggle');\n }\n }\n });\n\n // Prevent native drag and drop on long press if we also select on long press.\n // Once the user is in selection mode, they can long press again to drag.\n // Use a capturing listener to ensure this runs before useDrag, regardless of\n // the order the props get merged.\n let onDragStartCapture = e => {\n if (modality.current === 'touch' && longPressEnabledOnPressStart.current) {\n e.preventDefault();\n }\n };\n\n // Prevent default on link clicks so that we control exactly\n // when they open (to match selection behavior).\n let onClick = manager.isLink(key) ? e => {\n if (!(openLink as any).isOpening) {\n e.preventDefault();\n }\n } : undefined;\n\n return {\n itemProps: mergeProps(\n itemProps,\n allowsSelection || hasPrimaryAction ? pressProps : {},\n longPressEnabled ? longPressProps : {},\n {onDoubleClick, onDragStartCapture, onClick, id}\n ),\n isPressed,\n isSelected: manager.isSelected(key),\n isFocused: manager.isFocused && manager.focusedKey === key,\n isDisabled,\n allowsSelection,\n hasAction\n };\n}\n\nfunction isActionKey() {\n let event = window.event as KeyboardEvent;\n return event?.key === 'Enter';\n}\n\nfunction isSelectionKey() {\n let event = window.event as KeyboardEvent;\n return event?.key === ' ' || event?.code === 'Space';\n}\n"],"names":[],"version":3,"file":"useSelectableItem.module.js.map"}
@@ -6,7 +6,6 @@ function $parcel$export(e, n, v, s) {
6
6
  }
7
7
 
8
8
  $parcel$export(module.exports, "isNonContiguousSelectionModifier", () => $ee0bdf4faa47f2a8$export$d3e3bd3e26688c04);
9
- $parcel$export(module.exports, "isCtrlKeyPressed", () => $ee0bdf4faa47f2a8$export$16792effe837dba3);
10
9
  /*
11
10
  * Copyright 2020 Adobe. All rights reserved.
12
11
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
@@ -23,10 +22,6 @@ function $ee0bdf4faa47f2a8$export$d3e3bd3e26688c04(e) {
23
22
  // On Windows and Ubuntu, Alt + Space has a system wide meaning.
24
23
  return (0, $gP8Dl$reactariautils.isAppleDevice)() ? e.altKey : e.ctrlKey;
25
24
  }
26
- function $ee0bdf4faa47f2a8$export$16792effe837dba3(e) {
27
- if ((0, $gP8Dl$reactariautils.isMac)()) return e.metaKey;
28
- return e.ctrlKey;
29
- }
30
25
 
31
26
 
32
27
  //# sourceMappingURL=utils.main.js.map
@@ -1 +1 @@
1
- {"mappings":";;;;;;;;;AAAA;;;;;;;;;;CAUC;AAUM,SAAS,0CAAiC,CAAQ;IACvD,qFAAqF;IACrF,gEAAgE;IAChE,OAAO,CAAA,GAAA,mCAAY,MAAM,EAAE,MAAM,GAAG,EAAE,OAAO;AAC/C;AAEO,SAAS,0CAAiB,CAAQ;IACvC,IAAI,CAAA,GAAA,2BAAI,KACN,OAAO,EAAE,OAAO;IAGlB,OAAO,EAAE,OAAO;AAClB","sources":["packages/@react-aria/selection/src/utils.ts"],"sourcesContent":["/*\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\nimport {isAppleDevice, isMac} from '@react-aria/utils';\n\ninterface Event {\n altKey: boolean,\n ctrlKey: boolean,\n metaKey: boolean\n}\n\nexport function isNonContiguousSelectionModifier(e: Event) {\n // Ctrl + Arrow Up/Arrow Down has a system wide meaning on macOS, so use Alt instead.\n // On Windows and Ubuntu, Alt + Space has a system wide meaning.\n return isAppleDevice() ? e.altKey : e.ctrlKey;\n}\n\nexport function isCtrlKeyPressed(e: Event) {\n if (isMac()) {\n return e.metaKey;\n }\n\n return e.ctrlKey;\n}\n"],"names":[],"version":3,"file":"utils.main.js.map"}
1
+ {"mappings":";;;;;;;;AAAA;;;;;;;;;;CAUC;AAUM,SAAS,0CAAiC,CAAQ;IACvD,qFAAqF;IACrF,gEAAgE;IAChE,OAAO,CAAA,GAAA,mCAAY,MAAM,EAAE,MAAM,GAAG,EAAE,OAAO;AAC/C","sources":["packages/@react-aria/selection/src/utils.ts"],"sourcesContent":["/*\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\nimport {isAppleDevice} from '@react-aria/utils';\n\ninterface Event {\n altKey: boolean,\n ctrlKey: boolean,\n metaKey: boolean\n}\n\nexport function isNonContiguousSelectionModifier(e: Event) {\n // Ctrl + Arrow Up/Arrow Down has a system wide meaning on macOS, so use Alt instead.\n // On Windows and Ubuntu, Alt + Space has a system wide meaning.\n return isAppleDevice() ? e.altKey : e.ctrlKey;\n}\n"],"names":[],"version":3,"file":"utils.main.js.map"}
package/dist/utils.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import {isAppleDevice as $jUnAJ$isAppleDevice, isMac as $jUnAJ$isMac} from "@react-aria/utils";
1
+ import {isAppleDevice as $jUnAJ$isAppleDevice} from "@react-aria/utils";
2
2
 
3
3
  /*
4
4
  * Copyright 2020 Adobe. All rights reserved.
@@ -16,11 +16,7 @@ function $feb5ffebff200149$export$d3e3bd3e26688c04(e) {
16
16
  // On Windows and Ubuntu, Alt + Space has a system wide meaning.
17
17
  return (0, $jUnAJ$isAppleDevice)() ? e.altKey : e.ctrlKey;
18
18
  }
19
- function $feb5ffebff200149$export$16792effe837dba3(e) {
20
- if ((0, $jUnAJ$isMac)()) return e.metaKey;
21
- return e.ctrlKey;
22
- }
23
19
 
24
20
 
25
- export {$feb5ffebff200149$export$d3e3bd3e26688c04 as isNonContiguousSelectionModifier, $feb5ffebff200149$export$16792effe837dba3 as isCtrlKeyPressed};
21
+ export {$feb5ffebff200149$export$d3e3bd3e26688c04 as isNonContiguousSelectionModifier};
26
22
  //# sourceMappingURL=utils.module.js.map
@@ -1,4 +1,4 @@
1
- import {isAppleDevice as $jUnAJ$isAppleDevice, isMac as $jUnAJ$isMac} from "@react-aria/utils";
1
+ import {isAppleDevice as $jUnAJ$isAppleDevice} from "@react-aria/utils";
2
2
 
3
3
  /*
4
4
  * Copyright 2020 Adobe. All rights reserved.
@@ -16,11 +16,7 @@ function $feb5ffebff200149$export$d3e3bd3e26688c04(e) {
16
16
  // On Windows and Ubuntu, Alt + Space has a system wide meaning.
17
17
  return (0, $jUnAJ$isAppleDevice)() ? e.altKey : e.ctrlKey;
18
18
  }
19
- function $feb5ffebff200149$export$16792effe837dba3(e) {
20
- if ((0, $jUnAJ$isMac)()) return e.metaKey;
21
- return e.ctrlKey;
22
- }
23
19
 
24
20
 
25
- export {$feb5ffebff200149$export$d3e3bd3e26688c04 as isNonContiguousSelectionModifier, $feb5ffebff200149$export$16792effe837dba3 as isCtrlKeyPressed};
21
+ export {$feb5ffebff200149$export$d3e3bd3e26688c04 as isNonContiguousSelectionModifier};
26
22
  //# sourceMappingURL=utils.module.js.map
@@ -1 +1 @@
1
- {"mappings":";;AAAA;;;;;;;;;;CAUC;AAUM,SAAS,0CAAiC,CAAQ;IACvD,qFAAqF;IACrF,gEAAgE;IAChE,OAAO,CAAA,GAAA,oBAAY,MAAM,EAAE,MAAM,GAAG,EAAE,OAAO;AAC/C;AAEO,SAAS,0CAAiB,CAAQ;IACvC,IAAI,CAAA,GAAA,YAAI,KACN,OAAO,EAAE,OAAO;IAGlB,OAAO,EAAE,OAAO;AAClB","sources":["packages/@react-aria/selection/src/utils.ts"],"sourcesContent":["/*\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\nimport {isAppleDevice, isMac} from '@react-aria/utils';\n\ninterface Event {\n altKey: boolean,\n ctrlKey: boolean,\n metaKey: boolean\n}\n\nexport function isNonContiguousSelectionModifier(e: Event) {\n // Ctrl + Arrow Up/Arrow Down has a system wide meaning on macOS, so use Alt instead.\n // On Windows and Ubuntu, Alt + Space has a system wide meaning.\n return isAppleDevice() ? e.altKey : e.ctrlKey;\n}\n\nexport function isCtrlKeyPressed(e: Event) {\n if (isMac()) {\n return e.metaKey;\n }\n\n return e.ctrlKey;\n}\n"],"names":[],"version":3,"file":"utils.module.js.map"}
1
+ {"mappings":";;AAAA;;;;;;;;;;CAUC;AAUM,SAAS,0CAAiC,CAAQ;IACvD,qFAAqF;IACrF,gEAAgE;IAChE,OAAO,CAAA,GAAA,oBAAY,MAAM,EAAE,MAAM,GAAG,EAAE,OAAO;AAC/C","sources":["packages/@react-aria/selection/src/utils.ts"],"sourcesContent":["/*\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\nimport {isAppleDevice} from '@react-aria/utils';\n\ninterface Event {\n altKey: boolean,\n ctrlKey: boolean,\n metaKey: boolean\n}\n\nexport function isNonContiguousSelectionModifier(e: Event) {\n // Ctrl + Arrow Up/Arrow Down has a system wide meaning on macOS, so use Alt instead.\n // On Windows and Ubuntu, Alt + Space has a system wide meaning.\n return isAppleDevice() ? e.altKey : e.ctrlKey;\n}\n"],"names":[],"version":3,"file":"utils.module.js.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-aria/selection",
3
- "version": "3.0.0-nightly-4dd0993da-250106",
3
+ "version": "3.0.0-nightly-e7053dd8f-250108",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -22,12 +22,12 @@
22
22
  "url": "https://github.com/adobe/react-spectrum"
23
23
  },
24
24
  "dependencies": {
25
- "@react-aria/focus": "3.0.0-nightly-4dd0993da-250106",
26
- "@react-aria/i18n": "3.0.0-nightly-4dd0993da-250106",
27
- "@react-aria/interactions": "3.0.0-nightly-4dd0993da-250106",
28
- "@react-aria/utils": "3.0.0-nightly-4dd0993da-250106",
29
- "@react-stately/selection": "3.0.0-nightly-4dd0993da-250106",
30
- "@react-types/shared": "3.0.0-nightly-4dd0993da-250106",
25
+ "@react-aria/focus": "3.0.0-nightly-e7053dd8f-250108",
26
+ "@react-aria/i18n": "3.0.0-nightly-e7053dd8f-250108",
27
+ "@react-aria/interactions": "3.0.0-nightly-e7053dd8f-250108",
28
+ "@react-aria/utils": "3.0.0-nightly-e7053dd8f-250108",
29
+ "@react-stately/selection": "3.0.0-nightly-e7053dd8f-250108",
30
+ "@react-types/shared": "3.0.0-nightly-e7053dd8f-250108",
31
31
  "@swc/helpers": "^0.5.0"
32
32
  },
33
33
  "peerDependencies": {
@@ -10,13 +10,13 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import {CLEAR_FOCUS_EVENT, FOCUS_EVENT, focusWithoutScrolling, mergeProps, scrollIntoView, scrollIntoViewport, UPDATE_ACTIVEDESCENDANT, useEvent, useRouter} from '@react-aria/utils';
13
+ import {CLEAR_FOCUS_EVENT, FOCUS_EVENT, focusWithoutScrolling, isCtrlKeyPressed, mergeProps, scrollIntoView, scrollIntoViewport, UPDATE_ACTIVEDESCENDANT, useEffectEvent, useEvent, useRouter, useUpdateLayoutEffect} from '@react-aria/utils';
14
14
  import {DOMAttributes, FocusableElement, FocusStrategy, Key, KeyboardDelegate, RefObject} from '@react-types/shared';
15
15
  import {flushSync} from 'react-dom';
16
16
  import {FocusEvent, KeyboardEvent, useEffect, useRef} from 'react';
17
17
  import {focusSafely, getFocusableTreeWalker} from '@react-aria/focus';
18
18
  import {getInteractionModality} from '@react-aria/interactions';
19
- import {isCtrlKeyPressed, isNonContiguousSelectionModifier} from './utils';
19
+ import {isNonContiguousSelectionModifier} from './utils';
20
20
  import {MultipleSelectionManager} from '@react-stately/selection';
21
21
  import {useLocale} from '@react-aria/i18n';
22
22
  import {useTypeSelect} from './useTypeSelect';
@@ -391,6 +391,10 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
391
391
  }
392
392
  };
393
393
 
394
+ // Ref to track whether the first item in the collection should be automatically focused. Specifically used for autocomplete when user types
395
+ // to focus the first key AFTER the collection updates.
396
+ // TODO: potentially expand the usage of this
397
+ let shouldVirtualFocusFirst = useRef(false);
394
398
  // Add event listeners for custom virtual events. These handle updating the focused key in response to various keyboard events
395
399
  // at the autocomplete level
396
400
  // TODO: fix type later
@@ -401,21 +405,50 @@ export function useSelectableCollection(options: AriaSelectableCollectionOptions
401
405
 
402
406
  // If the user is typing forwards, autofocus the first option in the list.
403
407
  if (detail?.focusStrategy === 'first') {
404
- let keyToFocus = delegate.getFirstKey?.() ?? null;
405
- // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist
406
- if (keyToFocus == null) {
407
- ref.current?.dispatchEvent(
408
- new CustomEvent(UPDATE_ACTIVEDESCENDANT, {
409
- cancelable: true,
410
- bubbles: true
411
- })
412
- );
413
- }
408
+ shouldVirtualFocusFirst.current = true;
409
+ }
410
+ });
414
411
 
412
+ let updateActiveDescendant = useEffectEvent(() => {
413
+ let keyToFocus = delegate.getFirstKey?.() ?? null;
414
+
415
+ // If no focusable items exist in the list, make sure to clear any activedescendant that may still exist
416
+ if (keyToFocus == null) {
417
+ ref.current?.dispatchEvent(
418
+ new CustomEvent(UPDATE_ACTIVEDESCENDANT, {
419
+ cancelable: true,
420
+ bubbles: true
421
+ })
422
+ );
423
+ } else {
415
424
  manager.setFocusedKey(keyToFocus);
425
+ // Only set shouldVirtualFocusFirst to false if we've successfully set the first key as the focused key
426
+ // If there wasn't a key to focus, we might be in a temporary loading state so we'll want to still focus the first key
427
+ // after the collection updates after load
428
+ shouldVirtualFocusFirst.current = false;
429
+ }
430
+ });
431
+
432
+ useUpdateLayoutEffect(() => {
433
+ if (shouldVirtualFocusFirst.current) {
434
+ updateActiveDescendant();
435
+ }
436
+
437
+ }, [manager.collection, updateActiveDescendant]);
438
+
439
+ let resetFocusFirstFlag = useEffectEvent(() => {
440
+ // If user causes the focused key to change in any other way, clear shouldVirtualFocusFirst so we don't
441
+ // accidentally move focus from under them. Skip this if the collection was empty because we might be in a load
442
+ // state and will still want to focus the first item after load
443
+ if (manager.collection.size > 0) {
444
+ shouldVirtualFocusFirst.current = false;
416
445
  }
417
446
  });
418
447
 
448
+ useUpdateLayoutEffect(() => {
449
+ resetFocusFirstFlag();
450
+ }, [manager.focusedKey, resetFocusFirstFlag]);
451
+
419
452
  useEvent(ref, CLEAR_FOCUS_EVENT, !shouldUseVirtualFocus ? undefined : (e) => {
420
453
  e.stopPropagation();
421
454
  manager.setFocused(false);
@@ -12,8 +12,8 @@
12
12
 
13
13
  import {DOMAttributes, DOMProps, FocusableElement, Key, LongPressEvent, PointerType, PressEvent, RefObject} from '@react-types/shared';
14
14
  import {focusSafely} from '@react-aria/focus';
15
- import {isCtrlKeyPressed, isNonContiguousSelectionModifier} from './utils';
16
- import {mergeProps, openLink, UPDATE_ACTIVEDESCENDANT, useId, useRouter} from '@react-aria/utils';
15
+ import {isCtrlKeyPressed, mergeProps, openLink, UPDATE_ACTIVEDESCENDANT, useId, useRouter} from '@react-aria/utils';
16
+ import {isNonContiguousSelectionModifier} from './utils';
17
17
  import {MultipleSelectionManager} from '@react-stately/selection';
18
18
  import {PressProps, useLongPress, usePress} from '@react-aria/interactions';
19
19
  import {useEffect, useRef} from 'react';
@@ -160,6 +160,9 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte
160
160
  };
161
161
 
162
162
  // Focus the associated DOM node when this item becomes the focusedKey
163
+ // TODO: can't make this useLayoutEffect bacause it breaks menus inside dialogs
164
+ // However, if this is a useEffect, it runs twice and dispatches two UPDATE_ACTIVEDESCENDANT and immediately sets
165
+ // aria-activeDescendant in useAutocomplete... I've worked around this for now
163
166
  useEffect(() => {
164
167
  let isFocused = key === manager.focusedKey;
165
168
  if (isFocused && manager.isFocused) {
package/src/utils.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import {isAppleDevice, isMac} from '@react-aria/utils';
13
+ import {isAppleDevice} from '@react-aria/utils';
14
14
 
15
15
  interface Event {
16
16
  altKey: boolean,
@@ -23,11 +23,3 @@ export function isNonContiguousSelectionModifier(e: Event) {
23
23
  // On Windows and Ubuntu, Alt + Space has a system wide meaning.
24
24
  return isAppleDevice() ? e.altKey : e.ctrlKey;
25
25
  }
26
-
27
- export function isCtrlKeyPressed(e: Event) {
28
- if (isMac()) {
29
- return e.metaKey;
30
- }
31
-
32
- return e.ctrlKey;
33
- }