@react-aria/focus
Advanced tools
Comparing version 3.0.0-nightly.1062 to 3.0.0-nightly.1071
145
dist/main.js
@@ -20,4 +20,5 @@ var _babelRuntimeHelpersObjectWithoutPropertiesLoose = $parcel$interopDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose")); | ||
getInteractionModality, | ||
isFocusVisible: _isFocusVisible, | ||
useFocus, | ||
useFocusVisible, | ||
useFocusVisibleListener, | ||
useFocusWithin, | ||
@@ -160,3 +161,3 @@ useKeyboard | ||
$bdceb2956edbee43435a9382ef97283f$var$useAutoFocus(scopeRef, autoFocus); | ||
let focusManager = $bdceb2956edbee43435a9382ef97283f$var$createFocusManager(scopeRef); | ||
let focusManager = $bdceb2956edbee43435a9382ef97283f$var$createFocusManagerForScope(scopeRef); | ||
return /*#__PURE__*/_react.createElement($bdceb2956edbee43435a9382ef97283f$var$FocusContext.Provider, { | ||
@@ -187,3 +188,3 @@ value: focusManager | ||
function $bdceb2956edbee43435a9382ef97283f$var$createFocusManager(scopeRef) { | ||
function $bdceb2956edbee43435a9382ef97283f$var$createFocusManagerForScope(scopeRef) { | ||
return { | ||
@@ -256,3 +257,3 @@ focusNext(opts) { | ||
const $bdceb2956edbee43435a9382ef97283f$var$focusableElements = ['input:not([disabled]):not([type=hidden])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'a[href]', 'area[href]', 'summary', 'iframe', 'object', 'embed', 'audio[controls]', 'video[controls]', '[contenteditable]']; | ||
const $bdceb2956edbee43435a9382ef97283f$var$FOCUSABLE_ELEMENT_SELECTOR = $bdceb2956edbee43435a9382ef97283f$var$focusableElements.join(':not([hidden]),') + ',[tabindex]:not([hidden])'; | ||
const $bdceb2956edbee43435a9382ef97283f$var$FOCUSABLE_ELEMENT_SELECTOR = $bdceb2956edbee43435a9382ef97283f$var$focusableElements.join(':not([hidden]),') + ',[tabindex]:not([disabled]):not([hidden])'; | ||
$bdceb2956edbee43435a9382ef97283f$var$focusableElements.push('[tabindex]:not([tabindex="-1"]):not([disabled])'); | ||
@@ -510,5 +511,107 @@ const $bdceb2956edbee43435a9382ef97283f$var$TABBABLE_ELEMENT_SELECTOR = $bdceb2956edbee43435a9382ef97283f$var$focusableElements.join(':not([hidden]):not([tabindex="-1"]),'); | ||
} | ||
/** | ||
* Creates a FocusManager object that can be used to move focus within an element. | ||
*/ | ||
exports.getFocusableTreeWalker = getFocusableTreeWalker; | ||
function createFocusManager(ref) { | ||
return { | ||
focusNext(opts) { | ||
if (opts === void 0) { | ||
opts = {}; | ||
} | ||
let root = ref.current; | ||
let { | ||
from, | ||
tabbable, | ||
wrap | ||
} = opts; | ||
let node = from || document.activeElement; | ||
let walker = getFocusableTreeWalker(root, { | ||
tabbable | ||
}); | ||
if (root.contains(node)) { | ||
walker.currentNode = node; | ||
} | ||
let nextNode = walker.nextNode(); | ||
if (!nextNode && wrap) { | ||
walker.currentNode = root; | ||
nextNode = walker.nextNode(); | ||
} | ||
if (nextNode) { | ||
$bdceb2956edbee43435a9382ef97283f$var$focusElement(nextNode, true); | ||
} | ||
return nextNode; | ||
}, | ||
focusPrevious(opts) { | ||
if (opts === void 0) { | ||
opts = {}; | ||
} | ||
let root = ref.current; | ||
let { | ||
from, | ||
tabbable, | ||
wrap | ||
} = opts; | ||
let node = from || document.activeElement; | ||
let walker = getFocusableTreeWalker(root, { | ||
tabbable | ||
}); | ||
if (root.contains(node)) { | ||
walker.currentNode = node; | ||
} else { | ||
let next = $bdceb2956edbee43435a9382ef97283f$var$last(walker); | ||
if (next) { | ||
$bdceb2956edbee43435a9382ef97283f$var$focusElement(next, true); | ||
} | ||
return next; | ||
} | ||
let previousNode = walker.previousNode(); | ||
if (!previousNode && wrap) { | ||
walker.currentNode = root; | ||
previousNode = $bdceb2956edbee43435a9382ef97283f$var$last(walker); | ||
} | ||
if (previousNode) { | ||
$bdceb2956edbee43435a9382ef97283f$var$focusElement(previousNode, true); | ||
} | ||
return previousNode; | ||
} | ||
}; | ||
} | ||
exports.createFocusManager = createFocusManager; | ||
function $bdceb2956edbee43435a9382ef97283f$var$last(walker) { | ||
let next; | ||
let last; | ||
do { | ||
last = walker.lastChild(); | ||
if (last) { | ||
next = last; | ||
} | ||
} while (last); | ||
return next; | ||
} | ||
/** | ||
@@ -525,14 +628,30 @@ * Determines whether a focus ring should be shown to indicate keyboard focus. | ||
let { | ||
autoFocus = false, | ||
isTextInput, | ||
within | ||
} = props; | ||
let [isFocused, setFocused] = useState(false); | ||
let [isFocusWithin, setFocusWithin] = useState(false); | ||
let state = useRef({ | ||
isFocused: autoFocus, | ||
isFocusVisible: _isFocusVisible() | ||
}).current; | ||
let [isFocusVisibleState, setFocusVisible] = useState(() => state.isFocused && state.isFocusVisible); | ||
let updateState = () => setFocusVisible(state.isFocused && state.isFocusVisible); | ||
let onFocusChange = isFocused => { | ||
state.isFocused = isFocused; | ||
updateState(); | ||
}; | ||
useFocusVisibleListener(isFocusVisible => { | ||
state.isFocusVisible = isFocusVisible; | ||
updateState(); | ||
}, [], { | ||
isTextInput | ||
}); | ||
let { | ||
isFocusVisible | ||
} = useFocusVisible(props); | ||
let { | ||
focusProps | ||
} = useFocus({ | ||
isDisabled: within, | ||
onFocusChange: setFocused | ||
onFocusChange | ||
}); | ||
@@ -543,7 +662,7 @@ let { | ||
isDisabled: !within, | ||
onFocusWithinChange: setFocusWithin | ||
onFocusWithinChange: onFocusChange | ||
}); | ||
return { | ||
isFocused: within ? isFocusWithin : isFocused, | ||
isFocusVisible: (within ? isFocusWithin : isFocused) && isFocusVisible, | ||
isFocused: state.isFocused, | ||
isFocusVisible: state.isFocused && isFocusVisibleState, | ||
focusProps: within ? focusWithinProps : focusProps | ||
@@ -550,0 +669,0 @@ }; |
@@ -5,3 +5,3 @@ import _babelRuntimeHelpersEsmObjectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; | ||
import _react, { useContext, useEffect, useRef, useState } from "react"; | ||
import { getInteractionModality, useFocus, useFocusVisible, useFocusWithin, useKeyboard } from "@react-aria/interactions"; | ||
import { getInteractionModality, isFocusVisible as _isFocusVisible, useFocus, useFocusVisibleListener, useFocusWithin, useKeyboard } from "@react-aria/interactions"; | ||
import { focusWithoutScrolling, runAfterTransition, useLayoutEffect, mergeProps, useSyncRef } from "@react-aria/utils"; | ||
@@ -128,3 +128,3 @@ | ||
$c9e8f80f5bb1841844f54e4ad30b$var$useAutoFocus(scopeRef, autoFocus); | ||
let focusManager = $c9e8f80f5bb1841844f54e4ad30b$var$createFocusManager(scopeRef); | ||
let focusManager = $c9e8f80f5bb1841844f54e4ad30b$var$createFocusManagerForScope(scopeRef); | ||
return /*#__PURE__*/_react.createElement($c9e8f80f5bb1841844f54e4ad30b$var$FocusContext.Provider, { | ||
@@ -150,3 +150,3 @@ value: focusManager | ||
function $c9e8f80f5bb1841844f54e4ad30b$var$createFocusManager(scopeRef) { | ||
function $c9e8f80f5bb1841844f54e4ad30b$var$createFocusManagerForScope(scopeRef) { | ||
return { | ||
@@ -219,3 +219,3 @@ focusNext(opts) { | ||
const $c9e8f80f5bb1841844f54e4ad30b$var$focusableElements = ['input:not([disabled]):not([type=hidden])', 'select:not([disabled])', 'textarea:not([disabled])', 'button:not([disabled])', 'a[href]', 'area[href]', 'summary', 'iframe', 'object', 'embed', 'audio[controls]', 'video[controls]', '[contenteditable]']; | ||
const $c9e8f80f5bb1841844f54e4ad30b$var$FOCUSABLE_ELEMENT_SELECTOR = $c9e8f80f5bb1841844f54e4ad30b$var$focusableElements.join(':not([hidden]),') + ',[tabindex]:not([hidden])'; | ||
const $c9e8f80f5bb1841844f54e4ad30b$var$FOCUSABLE_ELEMENT_SELECTOR = $c9e8f80f5bb1841844f54e4ad30b$var$focusableElements.join(':not([hidden]),') + ',[tabindex]:not([disabled]):not([hidden])'; | ||
$c9e8f80f5bb1841844f54e4ad30b$var$focusableElements.push('[tabindex]:not([tabindex="-1"]):not([disabled])'); | ||
@@ -473,3 +473,102 @@ const $c9e8f80f5bb1841844f54e4ad30b$var$TABBABLE_ELEMENT_SELECTOR = $c9e8f80f5bb1841844f54e4ad30b$var$focusableElements.join(':not([hidden]):not([tabindex="-1"]),'); | ||
} | ||
/** | ||
* Creates a FocusManager object that can be used to move focus within an element. | ||
*/ | ||
export function createFocusManager(ref) { | ||
return { | ||
focusNext(opts) { | ||
if (opts === void 0) { | ||
opts = {}; | ||
} | ||
let root = ref.current; | ||
let { | ||
from, | ||
tabbable, | ||
wrap | ||
} = opts; | ||
let node = from || document.activeElement; | ||
let walker = getFocusableTreeWalker(root, { | ||
tabbable | ||
}); | ||
if (root.contains(node)) { | ||
walker.currentNode = node; | ||
} | ||
let nextNode = walker.nextNode(); | ||
if (!nextNode && wrap) { | ||
walker.currentNode = root; | ||
nextNode = walker.nextNode(); | ||
} | ||
if (nextNode) { | ||
$c9e8f80f5bb1841844f54e4ad30b$var$focusElement(nextNode, true); | ||
} | ||
return nextNode; | ||
}, | ||
focusPrevious(opts) { | ||
if (opts === void 0) { | ||
opts = {}; | ||
} | ||
let root = ref.current; | ||
let { | ||
from, | ||
tabbable, | ||
wrap | ||
} = opts; | ||
let node = from || document.activeElement; | ||
let walker = getFocusableTreeWalker(root, { | ||
tabbable | ||
}); | ||
if (root.contains(node)) { | ||
walker.currentNode = node; | ||
} else { | ||
let next = $c9e8f80f5bb1841844f54e4ad30b$var$last(walker); | ||
if (next) { | ||
$c9e8f80f5bb1841844f54e4ad30b$var$focusElement(next, true); | ||
} | ||
return next; | ||
} | ||
let previousNode = walker.previousNode(); | ||
if (!previousNode && wrap) { | ||
walker.currentNode = root; | ||
previousNode = $c9e8f80f5bb1841844f54e4ad30b$var$last(walker); | ||
} | ||
if (previousNode) { | ||
$c9e8f80f5bb1841844f54e4ad30b$var$focusElement(previousNode, true); | ||
} | ||
return previousNode; | ||
} | ||
}; | ||
} | ||
function $c9e8f80f5bb1841844f54e4ad30b$var$last(walker) { | ||
let next; | ||
let last; | ||
do { | ||
last = walker.lastChild(); | ||
if (last) { | ||
next = last; | ||
} | ||
} while (last); | ||
return next; | ||
} | ||
/** | ||
@@ -486,14 +585,30 @@ * Determines whether a focus ring should be shown to indicate keyboard focus. | ||
let { | ||
autoFocus = false, | ||
isTextInput, | ||
within | ||
} = props; | ||
let [isFocused, setFocused] = useState(false); | ||
let [isFocusWithin, setFocusWithin] = useState(false); | ||
let state = useRef({ | ||
isFocused: autoFocus, | ||
isFocusVisible: _isFocusVisible() | ||
}).current; | ||
let [isFocusVisibleState, setFocusVisible] = useState(() => state.isFocused && state.isFocusVisible); | ||
let updateState = () => setFocusVisible(state.isFocused && state.isFocusVisible); | ||
let onFocusChange = isFocused => { | ||
state.isFocused = isFocused; | ||
updateState(); | ||
}; | ||
useFocusVisibleListener(isFocusVisible => { | ||
state.isFocusVisible = isFocusVisible; | ||
updateState(); | ||
}, [], { | ||
isTextInput | ||
}); | ||
let { | ||
isFocusVisible | ||
} = useFocusVisible(props); | ||
let { | ||
focusProps | ||
} = useFocus({ | ||
isDisabled: within, | ||
onFocusChange: setFocused | ||
onFocusChange | ||
}); | ||
@@ -504,7 +619,7 @@ let { | ||
isDisabled: !within, | ||
onFocusWithinChange: setFocusWithin | ||
onFocusWithinChange: onFocusChange | ||
}); | ||
return { | ||
isFocused: within ? isFocusWithin : isFocused, | ||
isFocusVisible: (within ? isFocusWithin : isFocused) && isFocusVisible, | ||
isFocused: state.isFocused, | ||
isFocusVisible: state.isFocused && isFocusVisibleState, | ||
focusProps: within ? focusWithinProps : focusProps | ||
@@ -511,0 +626,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
import React, { ReactNode, HTMLAttributes, ReactElement, MutableRefObject, RefObject } from "react"; | ||
import React, { ReactNode, RefObject, HTMLAttributes, ReactElement, MutableRefObject } from "react"; | ||
import { FocusableDOMProps, FocusableProps } from "@react-types/shared"; | ||
@@ -57,2 +57,6 @@ /** | ||
export function getFocusableTreeWalker(root: HTMLElement, opts?: FocusManagerOptions, scope?: HTMLElement[]): TreeWalker; | ||
/** | ||
* Creates a FocusManager object that can be used to move focus within an element. | ||
*/ | ||
export function createFocusManager(ref: RefObject<HTMLElement>): FocusManager; | ||
interface FocusRingProps { | ||
@@ -59,0 +63,0 @@ /** |
{ | ||
"name": "@react-aria/focus", | ||
"version": "3.0.0-nightly.1062+f6cea8a92", | ||
"version": "3.0.0-nightly.1071+50906638d", | ||
"description": "Spectrum UI components in React", | ||
@@ -21,5 +21,5 @@ "license": "Apache-2.0", | ||
"@babel/runtime": "^7.6.2", | ||
"@react-aria/interactions": "3.0.0-nightly.1062+f6cea8a92", | ||
"@react-aria/utils": "3.0.0-nightly.1062+f6cea8a92", | ||
"@react-types/shared": "3.0.0-nightly.1062+f6cea8a92", | ||
"@react-aria/interactions": "3.0.0-nightly.1071+50906638d", | ||
"@react-aria/utils": "3.0.0-nightly.1071+50906638d", | ||
"@react-types/shared": "3.0.0-nightly.1071+50906638d", | ||
"clsx": "^1.1.1" | ||
@@ -33,3 +33,3 @@ }, | ||
}, | ||
"gitHead": "f6cea8a92994384f56d96ec979579f3e3092eb26" | ||
"gitHead": "50906638d417a6ae1a32aa7235591b35d91ad7eb" | ||
} |
import {HTMLAttributes, useState} from 'react'; | ||
import {useFocus, useFocusVisible, useFocusWithin} from '@react-aria/interactions'; | ||
import {isFocusVisible, useFocus, useFocusVisibleListener, useFocusWithin} from '@react-aria/interactions'; | ||
import {useRef} from 'react'; | ||
@@ -37,20 +38,39 @@ interface FocusRingProps { | ||
export function useFocusRing(props: FocusRingProps = {}): FocusRingAria { | ||
let {within} = props; | ||
let [isFocused, setFocused] = useState(false); | ||
let [isFocusWithin, setFocusWithin] = useState(false); | ||
let {isFocusVisible} = useFocusVisible(props); | ||
let { | ||
autoFocus = false, | ||
isTextInput, | ||
within | ||
} = props; | ||
let state = useRef({ | ||
isFocused: autoFocus, | ||
isFocusVisible: isFocusVisible() | ||
}).current; | ||
let [isFocusVisibleState, setFocusVisible] = useState(() => state.isFocused && state.isFocusVisible); | ||
let updateState = () => setFocusVisible(state.isFocused && state.isFocusVisible); | ||
let onFocusChange = isFocused => { | ||
state.isFocused = isFocused; | ||
updateState(); | ||
}; | ||
useFocusVisibleListener((isFocusVisible) => { | ||
state.isFocusVisible = isFocusVisible; | ||
updateState(); | ||
}, [], {isTextInput}); | ||
let {focusProps} = useFocus({ | ||
isDisabled: within, | ||
onFocusChange: setFocused | ||
onFocusChange | ||
}); | ||
let {focusWithinProps} = useFocusWithin({ | ||
isDisabled: !within, | ||
onFocusWithinChange: setFocusWithin | ||
onFocusWithinChange: onFocusChange | ||
}); | ||
return { | ||
isFocused: within ? isFocusWithin : isFocused, | ||
isFocusVisible: (within ? isFocusWithin : isFocused) && isFocusVisible, | ||
isFocused: state.isFocused, | ||
isFocusVisible: state.isFocused && isFocusVisibleState, | ||
focusProps: within ? focusWithinProps : focusProps | ||
}; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
209266
2318