@charlietango/use-focus-trap
Advanced tools
Comparing version 1.2.9 to 1.2.10
@@ -6,2 +6,8 @@ # Change Log | ||
## [1.2.10](https://github.com/charlie-tango/hooks/compare/@charlietango/use-focus-trap@1.2.9...@charlietango/use-focus-trap@1.2.10) (2020-01-29) | ||
### Bug Fixes | ||
- **useFocusTrap:** delay setting focus a single frame ([6e2f583](https://github.com/charlie-tango/hooks/commit/6e2f58307b30e235591baa70dcb98d1898476c46)) | ||
## [1.2.9](https://github.com/charlie-tango/hooks/compare/@charlietango/use-focus-trap@1.2.8...@charlietango/use-focus-trap@1.2.9) (2020-01-28) | ||
@@ -8,0 +14,0 @@ |
@@ -0,1 +1,2 @@ | ||
export declare const focusSelector = "a, input, select, textarea, button, object, [tabindex]"; | ||
export declare function focusable(element: HTMLElement): boolean | ""; | ||
@@ -7,5 +8,1 @@ export declare function tabbable(element: HTMLElement): boolean | ""; | ||
export declare function findTabbableDescendants(element: HTMLElement): Array<HTMLElement>; | ||
/** | ||
* Focusable elements are elements that can receive focus in one way or the other | ||
* */ | ||
export declare function findFocusableDescendants(element: HTMLElement): Array<HTMLElement>; |
@@ -19,3 +19,3 @@ 'use strict'; | ||
var tabbableNode = /input|select|textarea|button|object/; | ||
var selector = 'a, input, select, textarea, button, object, [tabindex]'; | ||
var focusSelector = 'a, input, select, textarea, button, object, [tabindex]'; | ||
@@ -62,12 +62,5 @@ function hidden(el) { | ||
function findTabbableDescendants(element) { | ||
return Array.from(element.querySelectorAll(selector)).filter(tabbable); | ||
return Array.from(element.querySelectorAll(focusSelector)).filter(tabbable); | ||
} | ||
/** | ||
* Focusable elements are elements that can receive focus in one way or the other | ||
* */ | ||
function findFocusableDescendants(element) { | ||
return Array.from(element.querySelectorAll(selector)).filter(focusable); | ||
} | ||
var focusLaterElements = []; | ||
@@ -198,3 +191,8 @@ var focusElement = null; | ||
var ref = react.useRef(); | ||
var restoreAria = react.useRef(null); | ||
var setRef = react.useCallback(function (node) { | ||
if (restoreAria.current) { | ||
restoreAria.current(); | ||
} | ||
if (ref.current) { | ||
@@ -208,26 +206,43 @@ returnFocus(); | ||
markForFocusLater(); | ||
var focusElement = null; | ||
if (options.focusSelector) { | ||
focusElement = typeof options.focusSelector === 'string' ? node.querySelector(options.focusSelector) : options.focusSelector; | ||
} | ||
var processNode = function processNode(node) { | ||
// See if we should disable aria | ||
restoreAria.current = !options.disableAriaHider ? createAriaHider(node) : null; // Find the initial focus element | ||
if (!focusElement) { | ||
var children = findTabbableDescendants(node); // If no tabbable children are found, see if we can find an element that can receive focus instead | ||
var focusElement = null; | ||
if (!children.length) children = findFocusableDescendants(node); | ||
if (options.focusSelector) { | ||
focusElement = typeof options.focusSelector === 'string' ? node.querySelector(options.focusSelector) : options.focusSelector; | ||
} | ||
if (children.length) { | ||
focusElement = children[0]; | ||
if (!focusElement) { | ||
var children = Array.from(node.querySelectorAll(focusSelector)); | ||
focusElement = // Prefer tabbable elements, But fallback to any focusable element | ||
children.find(tabbable) || // But fallback to any focusable element | ||
children.find(focusable) || // Nothing found | ||
null; // If everything else fails, see if the node itself can handle focus | ||
if (!focusElement && focusable(node)) focusElement = node; | ||
} | ||
} | ||
if (!focusElement && focusable(node)) { | ||
focusElement = node; | ||
} | ||
if (focusElement) { | ||
// Set the initial focus inside the traps | ||
focusElement.focus(); | ||
} else { | ||
if (process.env.NODE_ENV === 'development') { | ||
// eslint-disable-next-line no-console | ||
console.warn('[useFocusTrap]: Failed to find a focusable element after activating the focus trap. Make sure to include at an element that can recieve focus. As a fallback, you can also set "tabIndex={-1}" on the focus trap node.', node); | ||
} | ||
} | ||
}; // Delay processing the HTML node by a frame. This ensures focus is assigned correctly. | ||
if (focusElement) { | ||
focusElement.focus(); | ||
} | ||
setTimeout(function () { | ||
if (node.ownerDocument) { | ||
processNode(node); | ||
} else if (process.env.NODE_ENV === 'development') { | ||
// eslint-disable-next-line no-console | ||
console.warn('[useFocusTrap]: The focus trap is not part of the DOM yet, so it is unable to correctly set focus. Make sure to render the ref node.', node); | ||
} | ||
}); | ||
ref.current = node; | ||
@@ -237,3 +252,3 @@ } else { | ||
} | ||
}, [active, options.focusSelector]); | ||
}, [active, options.focusSelector, options.disableAriaHider]); | ||
react.useEffect(function () { | ||
@@ -248,9 +263,7 @@ if (!active) return undefined; | ||
var restoreAria = ref.current && !options.disableAriaHider ? createAriaHider(ref.current) : undefined; | ||
document.addEventListener('keydown', handleKeyDown); | ||
return function () { | ||
document.removeEventListener('keydown', handleKeyDown); | ||
if (restoreAria) restoreAria(); | ||
}; | ||
}, [active, options.disableAriaHider]); | ||
}, [active]); | ||
return setRef; | ||
@@ -257,0 +270,0 @@ } |
@@ -15,3 +15,3 @@ import { useRef, useCallback, useEffect } from 'react'; | ||
var tabbableNode = /input|select|textarea|button|object/; | ||
var selector = 'a, input, select, textarea, button, object, [tabindex]'; | ||
var focusSelector = 'a, input, select, textarea, button, object, [tabindex]'; | ||
@@ -58,12 +58,5 @@ function hidden(el) { | ||
function findTabbableDescendants(element) { | ||
return Array.from(element.querySelectorAll(selector)).filter(tabbable); | ||
return Array.from(element.querySelectorAll(focusSelector)).filter(tabbable); | ||
} | ||
/** | ||
* Focusable elements are elements that can receive focus in one way or the other | ||
* */ | ||
function findFocusableDescendants(element) { | ||
return Array.from(element.querySelectorAll(selector)).filter(focusable); | ||
} | ||
var focusLaterElements = []; | ||
@@ -194,3 +187,8 @@ var focusElement = null; | ||
var ref = useRef(); | ||
var restoreAria = useRef(null); | ||
var setRef = useCallback(function (node) { | ||
if (restoreAria.current) { | ||
restoreAria.current(); | ||
} | ||
if (ref.current) { | ||
@@ -204,26 +202,43 @@ returnFocus(); | ||
markForFocusLater(); | ||
var focusElement = null; | ||
if (options.focusSelector) { | ||
focusElement = typeof options.focusSelector === 'string' ? node.querySelector(options.focusSelector) : options.focusSelector; | ||
} | ||
var processNode = function processNode(node) { | ||
// See if we should disable aria | ||
restoreAria.current = !options.disableAriaHider ? createAriaHider(node) : null; // Find the initial focus element | ||
if (!focusElement) { | ||
var children = findTabbableDescendants(node); // If no tabbable children are found, see if we can find an element that can receive focus instead | ||
var focusElement = null; | ||
if (!children.length) children = findFocusableDescendants(node); | ||
if (options.focusSelector) { | ||
focusElement = typeof options.focusSelector === 'string' ? node.querySelector(options.focusSelector) : options.focusSelector; | ||
} | ||
if (children.length) { | ||
focusElement = children[0]; | ||
if (!focusElement) { | ||
var children = Array.from(node.querySelectorAll(focusSelector)); | ||
focusElement = // Prefer tabbable elements, But fallback to any focusable element | ||
children.find(tabbable) || // But fallback to any focusable element | ||
children.find(focusable) || // Nothing found | ||
null; // If everything else fails, see if the node itself can handle focus | ||
if (!focusElement && focusable(node)) focusElement = node; | ||
} | ||
} | ||
if (!focusElement && focusable(node)) { | ||
focusElement = node; | ||
} | ||
if (focusElement) { | ||
// Set the initial focus inside the traps | ||
focusElement.focus(); | ||
} else { | ||
if (process.env.NODE_ENV === 'development') { | ||
// eslint-disable-next-line no-console | ||
console.warn('[useFocusTrap]: Failed to find a focusable element after activating the focus trap. Make sure to include at an element that can recieve focus. As a fallback, you can also set "tabIndex={-1}" on the focus trap node.', node); | ||
} | ||
} | ||
}; // Delay processing the HTML node by a frame. This ensures focus is assigned correctly. | ||
if (focusElement) { | ||
focusElement.focus(); | ||
} | ||
setTimeout(function () { | ||
if (node.ownerDocument) { | ||
processNode(node); | ||
} else if (process.env.NODE_ENV === 'development') { | ||
// eslint-disable-next-line no-console | ||
console.warn('[useFocusTrap]: The focus trap is not part of the DOM yet, so it is unable to correctly set focus. Make sure to render the ref node.', node); | ||
} | ||
}); | ||
ref.current = node; | ||
@@ -233,3 +248,3 @@ } else { | ||
} | ||
}, [active, options.focusSelector]); | ||
}, [active, options.focusSelector, options.disableAriaHider]); | ||
useEffect(function () { | ||
@@ -244,9 +259,7 @@ if (!active) return undefined; | ||
var restoreAria = ref.current && !options.disableAriaHider ? createAriaHider(ref.current) : undefined; | ||
document.addEventListener('keydown', handleKeyDown); | ||
return function () { | ||
document.removeEventListener('keydown', handleKeyDown); | ||
if (restoreAria) restoreAria(); | ||
}; | ||
}, [active, options.disableAriaHider]); | ||
}, [active]); | ||
return setRef; | ||
@@ -253,0 +266,0 @@ } |
{ | ||
"name": "@charlietango/use-focus-trap", | ||
"description": "Trap keyboard focus inside a DOM element, to prevent the user navigating outside a modal", | ||
"version": "1.2.9", | ||
"version": "1.2.10", | ||
"private": false, | ||
@@ -41,3 +41,3 @@ "sideEffects": false, | ||
}, | ||
"gitHead": "55c2d9eaed9ea775bc9b8f0627b55780d251d5ca" | ||
"gitHead": "8bf83428b83f8104c0ccc60509b9097162f37603" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25782
470
6