@react-aria/focus 3.19.0 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"mappings":";;;AAEO,SAAS,0CAAiB,EAAkB;IACjD,IAAI,OAAO,0CAA2B,CAAA,GAAA,uBAAe,EAAE;IACvD,IAAI,SAAS,IAAI;QACf,IAAI,MACF,0CAAoB,MAAM;QAE5B,IAAI,IACF,0CAAqB,IAAI;IAE7B;AACF;AAEO,SAAS,0CAAoB,IAAa,EAAE,EAAkB;IACnE,KAAK,aAAa,CAAC,IAAI,WAAW,QAAQ;QAAC,eAAe;IAAE;IAC5D,KAAK,aAAa,CAAC,IAAI,WAAW,YAAY;QAAC,SAAS;QAAM,eAAe;IAAE;AACjF;AAEO,SAAS,0CAAqB,EAAW,EAAE,IAAoB;IACpE,GAAG,aAAa,CAAC,IAAI,WAAW,SAAS;QAAC,eAAe;IAAI;IAC7D,GAAG,aAAa,CAAC,IAAI,WAAW,WAAW;QAAC,SAAS;QAAM,eAAe;IAAI;AAChF;AAEO,SAAS,0CAA2B,QAAkB;IAC3D,IAAI,gBAAgB,CAAA,GAAA,uBAAe,EAAE;IACrC,IAAI,mBAAmB,0BAAA,oCAAA,cAAe,YAAY,CAAC;IACnD,IAAI,kBACF,OAAO,SAAS,cAAc,CAAC,qBAAqB;IAGtD,OAAO;AACT","sources":["packages/@react-aria/focus/src/virtualFocus.ts"],"sourcesContent":["import {getActiveElement, getOwnerDocument} from '@react-aria/utils';\n\nexport function moveVirtualFocus(to: Element | null) {\n let from = getVirtuallyFocusedElement(getOwnerDocument(to));\n if (from !== to) {\n if (from) {\n dispatchVirtualBlur(from, to);\n }\n if (to) {\n dispatchVirtualFocus(to, from);\n }\n }\n}\n\nexport function dispatchVirtualBlur(from: Element, to: Element | null) {\n from.dispatchEvent(new FocusEvent('blur', {relatedTarget: to}));\n from.dispatchEvent(new FocusEvent('focusout', {bubbles: true, relatedTarget: to}));\n}\n\nexport function dispatchVirtualFocus(to: Element, from: Element | null) {\n to.dispatchEvent(new FocusEvent('focus', {relatedTarget: from}));\n to.dispatchEvent(new FocusEvent('focusin', {bubbles: true, relatedTarget: from}));\n}\n\nexport function getVirtuallyFocusedElement(document: Document) {\n let activeElement = getActiveElement(document);\n let activeDescendant = activeElement?.getAttribute('aria-activedescendant');\n if (activeDescendant) {\n return document.getElementById(activeDescendant) || activeElement;\n }\n\n return activeElement;\n}\n"],"names":[],"version":3,"file":"virtualFocus.module.js.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-aria/focus",
3
- "version": "3.19.0",
3
+ "version": "3.20.0",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -22,17 +22,18 @@
22
22
  "url": "https://github.com/adobe/react-spectrum"
23
23
  },
24
24
  "dependencies": {
25
- "@react-aria/interactions": "^3.22.5",
26
- "@react-aria/utils": "^3.26.0",
27
- "@react-types/shared": "^3.26.0",
25
+ "@react-aria/interactions": "^3.24.0",
26
+ "@react-aria/utils": "^3.28.0",
27
+ "@react-types/shared": "^3.28.0",
28
28
  "@swc/helpers": "^0.5.0",
29
29
  "clsx": "^2.0.0"
30
30
  },
31
31
  "peerDependencies": {
32
- "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
32
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
33
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
33
34
  },
34
35
  "publishConfig": {
35
36
  "access": "public"
36
37
  },
37
- "gitHead": "71f0ef23053f9e03ee7e97df736e8b083e006849"
38
+ "gitHead": "4d3c72c94eea2d72eb3a0e7d56000c6ef7e39726"
38
39
  }
@@ -10,9 +10,20 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
+ import {
14
+ createShadowTreeWalker,
15
+ getActiveElement,
16
+ getEventTarget,
17
+ getOwnerDocument,
18
+ isAndroid,
19
+ isChrome,
20
+ isFocusable,
21
+ isTabbable,
22
+ ShadowTreeWalker,
23
+ useLayoutEffect
24
+ } from '@react-aria/utils';
13
25
  import {FocusableElement, RefObject} from '@react-types/shared';
14
- import {focusSafely} from './focusSafely';
15
- import {getOwnerDocument, useLayoutEffect} from '@react-aria/utils';
26
+ import {focusSafely, getInteractionModality} from '@react-aria/interactions';
16
27
  import {isElementVisible} from './isElementVisible';
17
28
  import React, {ReactNode, useContext, useEffect, useMemo, useRef} from 'react';
18
29
 
@@ -54,7 +65,7 @@ export interface FocusManager {
54
65
  focusPrevious(opts?: FocusManagerOptions): FocusableElement | null,
55
66
  /** Moves focus to the first focusable or tabbable element in the focus scope. */
56
67
  focusFirst(opts?: FocusManagerOptions): FocusableElement | null,
57
- /** Moves focus to the last focusable or tabbable element in the focus scope. */
68
+ /** Moves focus to the last focusable or tabbable element in the focus scope. */
58
69
  focusLast(opts?: FocusManagerOptions): FocusableElement | null
59
70
  }
60
71
 
@@ -143,7 +154,7 @@ export function FocusScope(props: FocusScopeProps) {
143
154
  // This needs to be an effect so that activeScope is updated after the FocusScope tree is complete.
144
155
  // It cannot be a useLayoutEffect because the parent of this node hasn't been attached in the tree yet.
145
156
  useEffect(() => {
146
- const activeElement = getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined).activeElement;
157
+ const activeElement = getActiveElement(getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined));
147
158
  let scope: TreeNode | null = null;
148
159
 
149
160
  if (isElementInScope(activeElement, scopeRef.current)) {
@@ -207,7 +218,7 @@ function createFocusManagerForScope(scopeRef: React.RefObject<Element[] | null>)
207
218
  focusNext(opts: FocusManagerOptions = {}) {
208
219
  let scope = scopeRef.current!;
209
220
  let {from, tabbable, wrap, accept} = opts;
210
- let node = from || getOwnerDocument(scope[0]).activeElement!;
221
+ let node = from || getActiveElement(getOwnerDocument(scope[0] ?? undefined))!;
211
222
  let sentinel = scope[0].previousElementSibling!;
212
223
  let scopeRoot = getScopeRoot(scope);
213
224
  let walker = getFocusableTreeWalker(scopeRoot, {tabbable, accept}, scope);
@@ -225,11 +236,11 @@ function createFocusManagerForScope(scopeRef: React.RefObject<Element[] | null>)
225
236
  focusPrevious(opts: FocusManagerOptions = {}) {
226
237
  let scope = scopeRef.current!;
227
238
  let {from, tabbable, wrap, accept} = opts;
228
- let node = from || getOwnerDocument(scope[0]).activeElement!;
239
+ let node = from || getActiveElement(getOwnerDocument(scope[0] ?? undefined))!;
229
240
  let sentinel = scope[scope.length - 1].nextElementSibling!;
230
241
  let scopeRoot = getScopeRoot(scope);
231
242
  let walker = getFocusableTreeWalker(scopeRoot, {tabbable, accept}, scope);
232
- walker.currentNode = isElementInScope(node, scope) ? node : sentinel;
243
+ walker.currentNode = isElementInScope(node, scope) ? node : sentinel;
233
244
  let previousNode = walker.previousNode() as FocusableElement;
234
245
  if (!previousNode && wrap) {
235
246
  walker.currentNode = sentinel;
@@ -267,31 +278,6 @@ function createFocusManagerForScope(scopeRef: React.RefObject<Element[] | null>)
267
278
  };
268
279
  }
269
280
 
270
- const focusableElements = [
271
- 'input:not([disabled]):not([type=hidden])',
272
- 'select:not([disabled])',
273
- 'textarea:not([disabled])',
274
- 'button:not([disabled])',
275
- 'a[href]',
276
- 'area[href]',
277
- 'summary',
278
- 'iframe',
279
- 'object',
280
- 'embed',
281
- 'audio[controls]',
282
- 'video[controls]',
283
- '[contenteditable]'
284
- ];
285
-
286
- const FOCUSABLE_ELEMENT_SELECTOR = focusableElements.join(':not([hidden]),') + ',[tabindex]:not([disabled]):not([hidden])';
287
-
288
- focusableElements.push('[tabindex]:not([tabindex="-1"]):not([disabled])');
289
- const TABBABLE_ELEMENT_SELECTOR = focusableElements.join(':not([hidden]):not([tabindex="-1"]),');
290
-
291
- export function isFocusable(element: HTMLElement) {
292
- return element.matches(FOCUSABLE_ELEMENT_SELECTOR);
293
- }
294
-
295
281
  function getScopeRoot(scope: Element[]) {
296
282
  return scope[0].parentElement!;
297
283
  }
@@ -332,7 +318,7 @@ function useFocusContainment(scopeRef: RefObject<Element[] | null>, contain?: bo
332
318
  return;
333
319
  }
334
320
 
335
- let focusedElement = ownerDocument.activeElement;
321
+ let focusedElement = getActiveElement(ownerDocument);
336
322
  let scope = scopeRef.current;
337
323
  if (!scope || !isElementInScope(focusedElement, scope)) {
338
324
  return;
@@ -356,13 +342,13 @@ function useFocusContainment(scopeRef: RefObject<Element[] | null>, contain?: bo
356
342
  }
357
343
  };
358
344
 
359
- let onFocus = (e) => {
345
+ let onFocus: EventListener = (e) => {
360
346
  // If focusing an element in a child scope of the currently active scope, the child becomes active.
361
347
  // Moving out of the active scope to an ancestor is not allowed.
362
- if ((!activeScope || isAncestorScope(activeScope, scopeRef)) && isElementInScope(e.target, scopeRef.current)) {
348
+ if ((!activeScope || isAncestorScope(activeScope, scopeRef)) && isElementInScope(getEventTarget(e) as Element, scopeRef.current)) {
363
349
  activeScope = scopeRef;
364
- focusedNode.current = e.target;
365
- } else if (shouldContainFocus(scopeRef) && !isElementInChildScope(e.target, scopeRef)) {
350
+ focusedNode.current = getEventTarget(e) as FocusableElement;
351
+ } else if (shouldContainFocus(scopeRef) && !isElementInChildScope(getEventTarget(e) as Element, scopeRef)) {
366
352
  // If a focus event occurs outside the active scope (e.g. user tabs from browser location bar),
367
353
  // restore focus to the previously focused node or the first tabbable element in the active scope.
368
354
  if (focusedNode.current) {
@@ -371,21 +357,29 @@ function useFocusContainment(scopeRef: RefObject<Element[] | null>, contain?: bo
371
357
  focusFirstInScope(activeScope.current);
372
358
  }
373
359
  } else if (shouldContainFocus(scopeRef)) {
374
- focusedNode.current = e.target;
360
+ focusedNode.current = getEventTarget(e) as FocusableElement;
375
361
  }
376
362
  };
377
363
 
378
- let onBlur = (e) => {
364
+ let onBlur: EventListener = (e) => {
379
365
  // Firefox doesn't shift focus back to the Dialog properly without this
380
366
  if (raf.current) {
381
367
  cancelAnimationFrame(raf.current);
382
368
  }
383
369
  raf.current = requestAnimationFrame(() => {
370
+ // Patches infinite focus coersion loop for Android Talkback where the user isn't able to move the virtual cursor
371
+ // if within a containing focus scope. Bug filed against Chrome: https://issuetracker.google.com/issues/384844019.
372
+ // Note that this means focus can leave focus containing modals due to this, but it is isolated to Chrome Talkback.
373
+ let modality = getInteractionModality();
374
+ let shouldSkipFocusRestore = (modality === 'virtual' || modality === null) && isAndroid() && isChrome();
375
+
384
376
  // Use document.activeElement instead of e.relatedTarget so we can tell if user clicked into iframe
385
- if (ownerDocument.activeElement && shouldContainFocus(scopeRef) && !isElementInChildScope(ownerDocument.activeElement, scopeRef)) {
377
+ let activeElement = getActiveElement(ownerDocument);
378
+ if (!shouldSkipFocusRestore && activeElement && shouldContainFocus(scopeRef) && !isElementInChildScope(activeElement, scopeRef)) {
386
379
  activeScope = scopeRef;
387
- if (ownerDocument.body.contains(e.target)) {
388
- focusedNode.current = e.target;
380
+ let target = getEventTarget(e) as FocusableElement;
381
+ if (target && target.isConnected) {
382
+ focusedNode.current = target;
389
383
  focusedNode.current?.focus();
390
384
  } else if (activeScope.current) {
391
385
  focusFirstInScope(activeScope.current);
@@ -508,7 +502,7 @@ function useAutoFocus(scopeRef: RefObject<Element[] | null>, autoFocus?: boolean
508
502
  if (autoFocusRef.current) {
509
503
  activeScope = scopeRef;
510
504
  const ownerDocument = getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined);
511
- if (!isElementInScope(ownerDocument.activeElement, activeScope.current) && scopeRef.current) {
505
+ if (!isElementInScope(getActiveElement(ownerDocument), activeScope.current) && scopeRef.current) {
512
506
  focusFirstInScope(scopeRef.current);
513
507
  }
514
508
  }
@@ -528,7 +522,7 @@ function useActiveScopeTracker(scopeRef: RefObject<Element[] | null>, restore?:
528
522
  const ownerDocument = getOwnerDocument(scope ? scope[0] : undefined);
529
523
 
530
524
  let onFocus = (e) => {
531
- let target = e.target as Element;
525
+ let target = getEventTarget(e) as Element;
532
526
  if (isElementInScope(target, scopeRef.current)) {
533
527
  activeScope = scopeRef;
534
528
  } else if (!isElementInAnyScope(target)) {
@@ -561,7 +555,7 @@ function shouldRestoreFocus(scopeRef: ScopeRef) {
561
555
  function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: boolean, contain?: boolean) {
562
556
  // create a ref during render instead of useLayoutEffect so the active element is saved before a child with autoFocus=true mounts.
563
557
  // eslint-disable-next-line no-restricted-globals
564
- const nodeToRestoreRef = useRef(typeof document !== 'undefined' ? getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined).activeElement as FocusableElement : null);
558
+ const nodeToRestoreRef = useRef(typeof document !== 'undefined' ? getActiveElement(getOwnerDocument(scopeRef.current ? scopeRef.current[0] : undefined)) as FocusableElement : null);
565
559
 
566
560
  // restoring scopes should all track if they are active regardless of contain, but contain already tracks it plus logic to contain the focus
567
561
  // restoring-non-containing scopes should only care if they become active so they can perform the restore
@@ -576,7 +570,7 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
576
570
  // If focusing an element in a child scope of the currently active scope, the child becomes active.
577
571
  // Moving out of the active scope to an ancestor is not allowed.
578
572
  if ((!activeScope || isAncestorScope(activeScope, scopeRef)) &&
579
- isElementInScope(ownerDocument.activeElement, scopeRef.current)
573
+ isElementInScope(getActiveElement(ownerDocument), scopeRef.current)
580
574
  ) {
581
575
  activeScope = scopeRef;
582
576
  }
@@ -588,7 +582,7 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
588
582
  ownerDocument.removeEventListener('focusin', onFocus, false);
589
583
  scope?.forEach(element => element.removeEventListener('focusin', onFocus, false));
590
584
  };
591
- // eslint-disable-next-line react-hooks/exhaustive-deps
585
+ // eslint-disable-next-line react-hooks/exhaustive-deps
592
586
  }, [scopeRef, contain]);
593
587
 
594
588
  useLayoutEffect(() => {
@@ -624,7 +618,7 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
624
618
  walker.currentNode = focusedElement;
625
619
  let nextElement = (e.shiftKey ? walker.previousNode() : walker.nextNode()) as FocusableElement;
626
620
 
627
- if (!nodeToRestore || !ownerDocument.body.contains(nodeToRestore) || nodeToRestore === ownerDocument.body) {
621
+ if (!nodeToRestore || !nodeToRestore.isConnected || nodeToRestore === ownerDocument.body) {
628
622
  nodeToRestore = undefined;
629
623
  treeNode.nodeToRestore = undefined;
630
624
  }
@@ -644,9 +638,9 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
644
638
  if (nextElement) {
645
639
  focusElement(nextElement, true);
646
640
  } else {
647
- // If there is no next element and the nodeToRestore isn't within a FocusScope (i.e. we are leaving the top level focus scope)
648
- // then move focus to the body.
649
- // Otherwise restore focus to the nodeToRestore (e.g menu within a popover -> tabbing to close the menu should move focus to menu trigger)
641
+ // If there is no next element and the nodeToRestore isn't within a FocusScope (i.e. we are leaving the top level focus scope)
642
+ // then move focus to the body.
643
+ // Otherwise restore focus to the nodeToRestore (e.g menu within a popover -> tabbing to close the menu should move focus to menu trigger)
650
644
  if (!isElementInAnyScope(nodeToRestore)) {
651
645
  focusedElement.blur();
652
646
  } else {
@@ -657,12 +651,12 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
657
651
  };
658
652
 
659
653
  if (!contain) {
660
- ownerDocument.addEventListener('keydown', onKeyDown, true);
654
+ ownerDocument.addEventListener('keydown', onKeyDown as EventListener, true);
661
655
  }
662
656
 
663
657
  return () => {
664
658
  if (!contain) {
665
- ownerDocument.removeEventListener('keydown', onKeyDown, true);
659
+ ownerDocument.removeEventListener('keydown', onKeyDown as EventListener, true);
666
660
  }
667
661
  };
668
662
  }, [scopeRef, restoreFocus, contain]);
@@ -688,11 +682,12 @@ function useRestoreFocus(scopeRef: RefObject<Element[] | null>, restoreFocus?: b
688
682
  let nodeToRestore = treeNode.nodeToRestore;
689
683
 
690
684
  // if we already lost focus to the body and this was the active scope, then we should attempt to restore
685
+ let activeElement = getActiveElement(ownerDocument);
691
686
  if (
692
687
  restoreFocus
693
688
  && nodeToRestore
694
689
  && (
695
- ((ownerDocument.activeElement && isElementInChildScope(ownerDocument.activeElement, scopeRef)) || (ownerDocument.activeElement === ownerDocument.body && shouldRestoreFocus(scopeRef)))
690
+ ((activeElement && isElementInChildScope(activeElement, scopeRef)) || (activeElement === ownerDocument.body && shouldRestoreFocus(scopeRef)))
696
691
  )
697
692
  ) {
698
693
  // freeze the focusScopeTree so it persists after the raf, otherwise during unmount nodes are removed from it
@@ -741,10 +736,19 @@ function restoreFocusToElement(node: FocusableElement) {
741
736
  * Create a [TreeWalker]{@link https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker}
742
737
  * that matches all focusable/tabbable elements.
743
738
  */
744
- export function getFocusableTreeWalker(root: Element, opts?: FocusManagerOptions, scope?: Element[]) {
745
- let selector = opts?.tabbable ? TABBABLE_ELEMENT_SELECTOR : FOCUSABLE_ELEMENT_SELECTOR;
746
- let walker = getOwnerDocument(root).createTreeWalker(
747
- root,
739
+ export function getFocusableTreeWalker(root: Element, opts?: FocusManagerOptions, scope?: Element[]): ShadowTreeWalker | TreeWalker {
740
+ let filter = opts?.tabbable ? isTabbable : isFocusable;
741
+
742
+ // Ensure that root is an Element or fall back appropriately
743
+ let rootElement = root?.nodeType === Node.ELEMENT_NODE ? (root as Element) : null;
744
+
745
+ // Determine the document to use
746
+ let doc = getOwnerDocument(rootElement);
747
+
748
+ // Create a TreeWalker, ensuring the root is an Element or Document
749
+ let walker = createShadowTreeWalker(
750
+ doc,
751
+ root || doc,
748
752
  NodeFilter.SHOW_ELEMENT,
749
753
  {
750
754
  acceptNode(node) {
@@ -753,7 +757,7 @@ export function getFocusableTreeWalker(root: Element, opts?: FocusManagerOptions
753
757
  return NodeFilter.FILTER_REJECT;
754
758
  }
755
759
 
756
- if ((node as Element).matches(selector)
760
+ if (filter(node as Element)
757
761
  && isElementVisible(node as Element)
758
762
  && (!scope || isElementInScope(node as Element, scope))
759
763
  && (!opts?.accept || opts.accept(node as Element))
@@ -784,7 +788,7 @@ export function createFocusManager(ref: RefObject<Element | null>, defaultOption
784
788
  return null;
785
789
  }
786
790
  let {from, tabbable = defaultOptions.tabbable, wrap = defaultOptions.wrap, accept = defaultOptions.accept} = opts;
787
- let node = from || getOwnerDocument(root).activeElement;
791
+ let node = from || getActiveElement(getOwnerDocument(root));
788
792
  let walker = getFocusableTreeWalker(root, {tabbable, accept});
789
793
  if (root.contains(node)) {
790
794
  walker.currentNode = node!;
@@ -805,7 +809,7 @@ export function createFocusManager(ref: RefObject<Element | null>, defaultOption
805
809
  return null;
806
810
  }
807
811
  let {from, tabbable = defaultOptions.tabbable, wrap = defaultOptions.wrap, accept = defaultOptions.accept} = opts;
808
- let node = from || getOwnerDocument(root).activeElement;
812
+ let node = from || getActiveElement(getOwnerDocument(root));
809
813
  let walker = getFocusableTreeWalker(root, {tabbable, accept});
810
814
  if (root.contains(node)) {
811
815
  walker.currentNode = node!;
@@ -860,7 +864,7 @@ export function createFocusManager(ref: RefObject<Element | null>, defaultOption
860
864
  };
861
865
  }
862
866
 
863
- function last(walker: TreeWalker) {
867
+ function last(walker: ShadowTreeWalker | TreeWalker) {
864
868
  let next: FocusableElement | undefined = undefined;
865
869
  let last: FocusableElement;
866
870
  do {
package/src/index.ts CHANGED
@@ -10,14 +10,16 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- export {FocusScope, useFocusManager, getFocusableTreeWalker, createFocusManager, isElementInChildOfActiveScope, isFocusable} from './FocusScope';
13
+ export {FocusScope, useFocusManager, getFocusableTreeWalker, createFocusManager, isElementInChildOfActiveScope} from './FocusScope';
14
14
  export {FocusRing} from './FocusRing';
15
- export {FocusableProvider, useFocusable} from './useFocusable';
16
15
  export {useFocusRing} from './useFocusRing';
17
- export {focusSafely} from './focusSafely';
18
16
  export {useHasTabbableChild} from './useHasTabbableChild';
17
+ export {moveVirtualFocus, dispatchVirtualBlur, dispatchVirtualFocus, getVirtuallyFocusedElement} from './virtualFocus';
18
+ // For backward compatibility.
19
+ export {isFocusable} from '@react-aria/utils';
20
+ export {FocusableProvider, Focusable, useFocusable, focusSafely} from '@react-aria/interactions';
19
21
 
20
22
  export type {FocusScopeProps, FocusManager, FocusManagerOptions} from './FocusScope';
21
23
  export type {FocusRingProps} from './FocusRing';
22
- export type {FocusableAria, FocusableOptions, FocusableProviderProps} from './useFocusable';
24
+ export type {FocusableAria, FocusableOptions, FocusableProviderProps} from '@react-aria/interactions';
23
25
  export type {AriaFocusRingProps, FocusRingAria} from './useFocusRing';
@@ -0,0 +1,33 @@
1
+ import {getActiveElement, getOwnerDocument} from '@react-aria/utils';
2
+
3
+ export function moveVirtualFocus(to: Element | null) {
4
+ let from = getVirtuallyFocusedElement(getOwnerDocument(to));
5
+ if (from !== to) {
6
+ if (from) {
7
+ dispatchVirtualBlur(from, to);
8
+ }
9
+ if (to) {
10
+ dispatchVirtualFocus(to, from);
11
+ }
12
+ }
13
+ }
14
+
15
+ export function dispatchVirtualBlur(from: Element, to: Element | null) {
16
+ from.dispatchEvent(new FocusEvent('blur', {relatedTarget: to}));
17
+ from.dispatchEvent(new FocusEvent('focusout', {bubbles: true, relatedTarget: to}));
18
+ }
19
+
20
+ export function dispatchVirtualFocus(to: Element, from: Element | null) {
21
+ to.dispatchEvent(new FocusEvent('focus', {relatedTarget: from}));
22
+ to.dispatchEvent(new FocusEvent('focusin', {bubbles: true, relatedTarget: from}));
23
+ }
24
+
25
+ export function getVirtuallyFocusedElement(document: Document) {
26
+ let activeElement = getActiveElement(document);
27
+ let activeDescendant = activeElement?.getAttribute('aria-activedescendant');
28
+ if (activeDescendant) {
29
+ return document.getElementById(activeDescendant) || activeElement;
30
+ }
31
+
32
+ return activeElement;
33
+ }
@@ -1,39 +0,0 @@
1
- var $cBYLt$reactariautils = require("@react-aria/utils");
2
- var $cBYLt$reactariainteractions = require("@react-aria/interactions");
3
-
4
-
5
- function $parcel$export(e, n, v, s) {
6
- Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
7
- }
8
-
9
- $parcel$export(module.exports, "focusSafely", () => $1c7f9157d722357d$export$80f3e147d781571c);
10
- /*
11
- * Copyright 2020 Adobe. All rights reserved.
12
- * This file is licensed to you under the Apache License, Version 2.0 (the 'License');
13
- * you may not use this file except in compliance with the License. You may obtain a copy
14
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
15
- *
16
- * Unless required by applicable law or agreed to in writing, software distributed under
17
- * the License is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
18
- * OF ANY KIND, either express or implied. See the License for the specific language
19
- * governing permissions and limitations under the License.
20
- */
21
-
22
- function $1c7f9157d722357d$export$80f3e147d781571c(element) {
23
- // If the user is interacting with a virtual cursor, e.g. screen reader, then
24
- // wait until after any animated transitions that are currently occurring on
25
- // the page before shifting focus. This avoids issues with VoiceOver on iOS
26
- // causing the page to scroll when moving focus if the element is transitioning
27
- // from off the screen.
28
- const ownerDocument = (0, $cBYLt$reactariautils.getOwnerDocument)(element);
29
- if ((0, $cBYLt$reactariainteractions.getInteractionModality)() === 'virtual') {
30
- let lastFocusedElement = ownerDocument.activeElement;
31
- (0, $cBYLt$reactariautils.runAfterTransition)(()=>{
32
- // If focus did not move and the element is still in the document, focus it.
33
- if (ownerDocument.activeElement === lastFocusedElement && element.isConnected) (0, $cBYLt$reactariautils.focusWithoutScrolling)(element);
34
- });
35
- } else (0, $cBYLt$reactariautils.focusWithoutScrolling)(element);
36
- }
37
-
38
-
39
- //# sourceMappingURL=focusSafely.main.js.map
@@ -1 +0,0 @@
1
- {"mappings":";;;;;;;;;AAAA;;;;;;;;;;CAUC;;AAUM,SAAS,0CAAY,OAAyB;IACnD,6EAA6E;IAC7E,4EAA4E;IAC5E,2EAA2E;IAC3E,+EAA+E;IAC/E,uBAAuB;IACvB,MAAM,gBAAgB,CAAA,GAAA,sCAAe,EAAE;IACvC,IAAI,CAAA,GAAA,mDAAqB,QAAQ,WAAW;QAC1C,IAAI,qBAAqB,cAAc,aAAa;QACpD,CAAA,GAAA,wCAAiB,EAAE;YACjB,4EAA4E;YAC5E,IAAI,cAAc,aAAa,KAAK,sBAAsB,QAAQ,WAAW,EAC3E,CAAA,GAAA,2CAAoB,EAAE;QAE1B;IACF,OACE,CAAA,GAAA,2CAAoB,EAAE;AAE1B","sources":["packages/@react-aria/focus/src/focusSafely.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 {FocusableElement} from '@react-types/shared';\nimport {focusWithoutScrolling, getOwnerDocument, runAfterTransition} from '@react-aria/utils';\nimport {getInteractionModality} from '@react-aria/interactions';\n\n/**\n * A utility function that focuses an element while avoiding undesired side effects such\n * as page scrolling and screen reader issues with CSS transitions.\n */\nexport function focusSafely(element: FocusableElement) {\n // If the user is interacting with a virtual cursor, e.g. screen reader, then\n // wait until after any animated transitions that are currently occurring on\n // the page before shifting focus. This avoids issues with VoiceOver on iOS\n // causing the page to scroll when moving focus if the element is transitioning\n // from off the screen.\n const ownerDocument = getOwnerDocument(element);\n if (getInteractionModality() === 'virtual') {\n let lastFocusedElement = ownerDocument.activeElement;\n runAfterTransition(() => {\n // If focus did not move and the element is still in the document, focus it.\n if (ownerDocument.activeElement === lastFocusedElement && element.isConnected) {\n focusWithoutScrolling(element);\n }\n });\n } else {\n focusWithoutScrolling(element);\n }\n}\n"],"names":[],"version":3,"file":"focusSafely.main.js.map"}
@@ -1,34 +0,0 @@
1
- import {getOwnerDocument as $jlOai$getOwnerDocument, runAfterTransition as $jlOai$runAfterTransition, focusWithoutScrolling as $jlOai$focusWithoutScrolling} from "@react-aria/utils";
2
- import {getInteractionModality as $jlOai$getInteractionModality} from "@react-aria/interactions";
3
-
4
- /*
5
- * Copyright 2020 Adobe. All rights reserved.
6
- * This file is licensed to you under the Apache License, Version 2.0 (the 'License');
7
- * you may not use this file except in compliance with the License. You may obtain a copy
8
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software distributed under
11
- * the License is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
12
- * OF ANY KIND, either express or implied. See the License for the specific language
13
- * governing permissions and limitations under the License.
14
- */
15
-
16
- function $6a99195332edec8b$export$80f3e147d781571c(element) {
17
- // If the user is interacting with a virtual cursor, e.g. screen reader, then
18
- // wait until after any animated transitions that are currently occurring on
19
- // the page before shifting focus. This avoids issues with VoiceOver on iOS
20
- // causing the page to scroll when moving focus if the element is transitioning
21
- // from off the screen.
22
- const ownerDocument = (0, $jlOai$getOwnerDocument)(element);
23
- if ((0, $jlOai$getInteractionModality)() === 'virtual') {
24
- let lastFocusedElement = ownerDocument.activeElement;
25
- (0, $jlOai$runAfterTransition)(()=>{
26
- // If focus did not move and the element is still in the document, focus it.
27
- if (ownerDocument.activeElement === lastFocusedElement && element.isConnected) (0, $jlOai$focusWithoutScrolling)(element);
28
- });
29
- } else (0, $jlOai$focusWithoutScrolling)(element);
30
- }
31
-
32
-
33
- export {$6a99195332edec8b$export$80f3e147d781571c as focusSafely};
34
- //# sourceMappingURL=focusSafely.module.js.map
@@ -1,34 +0,0 @@
1
- import {getOwnerDocument as $jlOai$getOwnerDocument, runAfterTransition as $jlOai$runAfterTransition, focusWithoutScrolling as $jlOai$focusWithoutScrolling} from "@react-aria/utils";
2
- import {getInteractionModality as $jlOai$getInteractionModality} from "@react-aria/interactions";
3
-
4
- /*
5
- * Copyright 2020 Adobe. All rights reserved.
6
- * This file is licensed to you under the Apache License, Version 2.0 (the 'License');
7
- * you may not use this file except in compliance with the License. You may obtain a copy
8
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software distributed under
11
- * the License is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
12
- * OF ANY KIND, either express or implied. See the License for the specific language
13
- * governing permissions and limitations under the License.
14
- */
15
-
16
- function $6a99195332edec8b$export$80f3e147d781571c(element) {
17
- // If the user is interacting with a virtual cursor, e.g. screen reader, then
18
- // wait until after any animated transitions that are currently occurring on
19
- // the page before shifting focus. This avoids issues with VoiceOver on iOS
20
- // causing the page to scroll when moving focus if the element is transitioning
21
- // from off the screen.
22
- const ownerDocument = (0, $jlOai$getOwnerDocument)(element);
23
- if ((0, $jlOai$getInteractionModality)() === 'virtual') {
24
- let lastFocusedElement = ownerDocument.activeElement;
25
- (0, $jlOai$runAfterTransition)(()=>{
26
- // If focus did not move and the element is still in the document, focus it.
27
- if (ownerDocument.activeElement === lastFocusedElement && element.isConnected) (0, $jlOai$focusWithoutScrolling)(element);
28
- });
29
- } else (0, $jlOai$focusWithoutScrolling)(element);
30
- }
31
-
32
-
33
- export {$6a99195332edec8b$export$80f3e147d781571c as focusSafely};
34
- //# sourceMappingURL=focusSafely.module.js.map
@@ -1 +0,0 @@
1
- {"mappings":";;;AAAA;;;;;;;;;;CAUC;;AAUM,SAAS,0CAAY,OAAyB;IACnD,6EAA6E;IAC7E,4EAA4E;IAC5E,2EAA2E;IAC3E,+EAA+E;IAC/E,uBAAuB;IACvB,MAAM,gBAAgB,CAAA,GAAA,uBAAe,EAAE;IACvC,IAAI,CAAA,GAAA,6BAAqB,QAAQ,WAAW;QAC1C,IAAI,qBAAqB,cAAc,aAAa;QACpD,CAAA,GAAA,yBAAiB,EAAE;YACjB,4EAA4E;YAC5E,IAAI,cAAc,aAAa,KAAK,sBAAsB,QAAQ,WAAW,EAC3E,CAAA,GAAA,4BAAoB,EAAE;QAE1B;IACF,OACE,CAAA,GAAA,4BAAoB,EAAE;AAE1B","sources":["packages/@react-aria/focus/src/focusSafely.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 {FocusableElement} from '@react-types/shared';\nimport {focusWithoutScrolling, getOwnerDocument, runAfterTransition} from '@react-aria/utils';\nimport {getInteractionModality} from '@react-aria/interactions';\n\n/**\n * A utility function that focuses an element while avoiding undesired side effects such\n * as page scrolling and screen reader issues with CSS transitions.\n */\nexport function focusSafely(element: FocusableElement) {\n // If the user is interacting with a virtual cursor, e.g. screen reader, then\n // wait until after any animated transitions that are currently occurring on\n // the page before shifting focus. This avoids issues with VoiceOver on iOS\n // causing the page to scroll when moving focus if the element is transitioning\n // from off the screen.\n const ownerDocument = getOwnerDocument(element);\n if (getInteractionModality() === 'virtual') {\n let lastFocusedElement = ownerDocument.activeElement;\n runAfterTransition(() => {\n // If focus did not move and the element is still in the document, focus it.\n if (ownerDocument.activeElement === lastFocusedElement && element.isConnected) {\n focusWithoutScrolling(element);\n }\n });\n } else {\n focusWithoutScrolling(element);\n }\n}\n"],"names":[],"version":3,"file":"focusSafely.module.js.map"}
@@ -1,75 +0,0 @@
1
- var $1c7f9157d722357d$exports = require("./focusSafely.main.js");
2
- var $ggOO2$reactariautils = require("@react-aria/utils");
3
- var $ggOO2$react = require("react");
4
- var $ggOO2$reactariainteractions = require("@react-aria/interactions");
5
-
6
-
7
- function $parcel$interopDefault(a) {
8
- return a && a.__esModule ? a.default : a;
9
- }
10
-
11
- function $parcel$export(e, n, v, s) {
12
- Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
13
- }
14
-
15
- $parcel$export(module.exports, "FocusableProvider", () => $fb504d83237fd6ac$export$13f3202a3e5ddd5);
16
- $parcel$export(module.exports, "useFocusable", () => $fb504d83237fd6ac$export$4c014de7c8940b4c);
17
- /*
18
- * Copyright 2020 Adobe. All rights reserved.
19
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
20
- * you may not use this file except in compliance with the License. You may obtain a copy
21
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
22
- *
23
- * Unless required by applicable law or agreed to in writing, software distributed under
24
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
25
- * OF ANY KIND, either express or implied. See the License for the specific language
26
- * governing permissions and limitations under the License.
27
- */
28
-
29
-
30
-
31
- let $fb504d83237fd6ac$var$FocusableContext = /*#__PURE__*/ (0, ($parcel$interopDefault($ggOO2$react))).createContext(null);
32
- function $fb504d83237fd6ac$var$useFocusableContext(ref) {
33
- let context = (0, $ggOO2$react.useContext)($fb504d83237fd6ac$var$FocusableContext) || {};
34
- (0, $ggOO2$reactariautils.useSyncRef)(context, ref);
35
- // eslint-disable-next-line
36
- let { ref: _, ...otherProps } = context;
37
- return otherProps;
38
- }
39
- /**
40
- * Provides DOM props to the nearest focusable child.
41
- */ function $fb504d83237fd6ac$var$FocusableProvider(props, ref) {
42
- let { children: children, ...otherProps } = props;
43
- let objRef = (0, $ggOO2$reactariautils.useObjectRef)(ref);
44
- let context = {
45
- ...otherProps,
46
- ref: objRef
47
- };
48
- return /*#__PURE__*/ (0, ($parcel$interopDefault($ggOO2$react))).createElement($fb504d83237fd6ac$var$FocusableContext.Provider, {
49
- value: context
50
- }, children);
51
- }
52
- let $fb504d83237fd6ac$export$13f3202a3e5ddd5 = /*#__PURE__*/ (0, ($parcel$interopDefault($ggOO2$react))).forwardRef($fb504d83237fd6ac$var$FocusableProvider);
53
- function $fb504d83237fd6ac$export$4c014de7c8940b4c(props, domRef) {
54
- let { focusProps: focusProps } = (0, $ggOO2$reactariainteractions.useFocus)(props);
55
- let { keyboardProps: keyboardProps } = (0, $ggOO2$reactariainteractions.useKeyboard)(props);
56
- let interactions = (0, $ggOO2$reactariautils.mergeProps)(focusProps, keyboardProps);
57
- let domProps = $fb504d83237fd6ac$var$useFocusableContext(domRef);
58
- let interactionProps = props.isDisabled ? {} : domProps;
59
- let autoFocusRef = (0, $ggOO2$react.useRef)(props.autoFocus);
60
- (0, $ggOO2$react.useEffect)(()=>{
61
- if (autoFocusRef.current && domRef.current) (0, $1c7f9157d722357d$exports.focusSafely)(domRef.current);
62
- autoFocusRef.current = false;
63
- }, [
64
- domRef
65
- ]);
66
- return {
67
- focusableProps: (0, $ggOO2$reactariautils.mergeProps)({
68
- ...interactions,
69
- tabIndex: props.excludeFromTabOrder && !props.isDisabled ? -1 : undefined
70
- }, interactionProps)
71
- };
72
- }
73
-
74
-
75
- //# sourceMappingURL=useFocusable.main.js.map
@@ -1 +0,0 @@
1
- {"mappings":";;;;;;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;AAsBD,IAAI,uDAAmB,CAAA,GAAA,sCAAI,EAAE,aAAa,CAA+B;AAEzE,SAAS,0CAAoB,GAAuC;IAClE,IAAI,UAAU,CAAA,GAAA,uBAAS,EAAE,2CAAqB,CAAC;IAC/C,CAAA,GAAA,gCAAS,EAAE,SAAS;IAEpB,2BAA2B;IAC3B,IAAI,EAAC,KAAK,CAAC,EAAE,GAAG,YAAW,GAAG;IAC9B,OAAO;AACT;AAEA;;CAEC,GACD,SAAS,wCAAkB,KAA6B,EAAE,GAAmC;IAC3F,IAAI,YAAC,QAAQ,EAAE,GAAG,YAAW,GAAG;IAChC,IAAI,SAAS,CAAA,GAAA,kCAAW,EAAE;IAC1B,IAAI,UAAU;QACZ,GAAG,UAAU;QACb,KAAK;IACP;IAEA,qBACE,0DAAC,uCAAiB,QAAQ;QAAC,OAAO;OAC/B;AAGP;AAEA,IAAI,yDAAqB,CAAA,GAAA,sCAAI,EAAE,UAAU,CAAC;AAWnC,SAAS,0CAA4D,KAA0B,EAAE,MAA0C;IAChJ,IAAI,cAAC,UAAU,EAAC,GAAG,CAAA,GAAA,qCAAO,EAAE;IAC5B,IAAI,iBAAC,aAAa,EAAC,GAAG,CAAA,GAAA,wCAAU,EAAE;IAClC,IAAI,eAAe,CAAA,GAAA,gCAAS,EAAE,YAAY;IAC1C,IAAI,WAAW,0CAAoB;IACnC,IAAI,mBAAmB,MAAM,UAAU,GAAG,CAAC,IAAI;IAC/C,IAAI,eAAe,CAAA,GAAA,mBAAK,EAAE,MAAM,SAAS;IAEzC,CAAA,GAAA,sBAAQ,EAAE;QACR,IAAI,aAAa,OAAO,IAAI,OAAO,OAAO,EACxC,CAAA,GAAA,qCAAU,EAAE,OAAO,OAAO;QAE5B,aAAa,OAAO,GAAG;IACzB,GAAG;QAAC;KAAO;IAEX,OAAO;QACL,gBAAgB,CAAA,GAAA,gCAAS,EACvB;YACE,GAAG,YAAY;YACf,UAAU,MAAM,mBAAmB,IAAI,CAAC,MAAM,UAAU,GAAG,KAAK;QAClE,GACA;IAEJ;AACF","sources":["packages/@react-aria/focus/src/useFocusable.tsx"],"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, FocusableDOMProps, FocusableElement, FocusableProps, RefObject} from '@react-types/shared';\nimport {focusSafely} from './';\nimport {mergeProps, useObjectRef, useSyncRef} from '@react-aria/utils';\nimport React, {ForwardedRef, MutableRefObject, ReactNode, useContext, useEffect, useRef} from 'react';\nimport {useFocus, useKeyboard} from '@react-aria/interactions';\n\nexport interface FocusableOptions<T = FocusableElement> extends FocusableProps<T>, FocusableDOMProps {\n /** Whether focus should be disabled. */\n isDisabled?: boolean\n}\n\nexport interface FocusableProviderProps extends DOMAttributes {\n /** The child element to provide DOM props to. */\n children?: ReactNode\n}\n\ninterface FocusableContextValue extends FocusableProviderProps {\n ref?: MutableRefObject<FocusableElement | null>\n}\n\nlet FocusableContext = React.createContext<FocusableContextValue | null>(null);\n\nfunction useFocusableContext(ref: RefObject<FocusableElement | null>): FocusableContextValue {\n let context = useContext(FocusableContext) || {};\n useSyncRef(context, ref);\n\n // eslint-disable-next-line\n let {ref: _, ...otherProps} = context;\n return otherProps;\n}\n\n/**\n * Provides DOM props to the nearest focusable child.\n */\nfunction FocusableProvider(props: FocusableProviderProps, ref: ForwardedRef<FocusableElement>) {\n let {children, ...otherProps} = props;\n let objRef = useObjectRef(ref);\n let context = {\n ...otherProps,\n ref: objRef\n };\n\n return (\n <FocusableContext.Provider value={context}>\n {children}\n </FocusableContext.Provider>\n );\n}\n\nlet _FocusableProvider = React.forwardRef(FocusableProvider);\nexport {_FocusableProvider as FocusableProvider};\n\nexport interface FocusableAria {\n /** Props for the focusable element. */\n focusableProps: DOMAttributes\n}\n\n/**\n * Used to make an element focusable and capable of auto focus.\n */\nexport function useFocusable<T extends FocusableElement = FocusableElement>(props: FocusableOptions<T>, domRef: RefObject<FocusableElement | null>): FocusableAria {\n let {focusProps} = useFocus(props);\n let {keyboardProps} = useKeyboard(props);\n let interactions = mergeProps(focusProps, keyboardProps);\n let domProps = useFocusableContext(domRef);\n let interactionProps = props.isDisabled ? {} : domProps;\n let autoFocusRef = useRef(props.autoFocus);\n\n useEffect(() => {\n if (autoFocusRef.current && domRef.current) {\n focusSafely(domRef.current);\n }\n autoFocusRef.current = false;\n }, [domRef]);\n\n return {\n focusableProps: mergeProps(\n {\n ...interactions,\n tabIndex: props.excludeFromTabOrder && !props.isDisabled ? -1 : undefined\n },\n interactionProps\n )\n };\n}\n"],"names":[],"version":3,"file":"useFocusable.main.js.map"}