focus-lock
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -17,6 +17,8 @@ interface FocusableNode { | ||
/** | ||
* @returns list of focusable elements inside a given top node | ||
* @see {@link getFocusableNodes} for lower level access | ||
* traverses all related nodes (including groups) returning a list of all nodes(outer and internal) with meta information | ||
* This is low-level API! | ||
* @returns list of focusable elements inside a given top(!) node. | ||
* @see {@link getFocusableNodes} providing a simpler API | ||
*/ | ||
export declare const expandFocusableNodes: (topNode: HTMLElement) => FocusableNode[]; | ||
export declare const expandFocusableNodes: (topNode: HTMLElement | HTMLElement[]) => FocusableNode[]; | ||
export {}; |
@@ -1,8 +0,11 @@ | ||
import { getTabbableNodes } from './utils/DOMutils'; | ||
import { getAllAffectedNodes } from './utils/all-affected'; | ||
import { isGuard, isNotAGuard } from './utils/is'; | ||
import { getTopCommonParent } from './utils/parenting'; | ||
import { orderByTabIndex } from './utils/tabOrder'; | ||
import { getFocusables } from './utils/tabUtils'; | ||
/** | ||
* @returns list of focusable elements inside a given top node | ||
* @see {@link getFocusableNodes} for lower level access | ||
* traverses all related nodes (including groups) returning a list of all nodes(outer and internal) with meta information | ||
* This is low-level API! | ||
* @returns list of focusable elements inside a given top(!) node. | ||
* @see {@link getFocusableNodes} providing a simpler API | ||
*/ | ||
@@ -12,13 +15,4 @@ export var expandFocusableNodes = function (topNode) { | ||
var commonParent = getTopCommonParent(topNode, topNode, entries); | ||
var visibilityCache = new Map(); | ||
var outerNodes = getTabbableNodes([commonParent], visibilityCache, true); | ||
var innerElements = getTabbableNodes(entries, visibilityCache) | ||
.filter(function (_a) { | ||
var node = _a.node; | ||
return isNotAGuard(node); | ||
}) | ||
.map(function (_a) { | ||
var node = _a.node; | ||
return node; | ||
}); | ||
var outerNodes = orderByTabIndex(getFocusables([commonParent], true), true, true); | ||
var innerElements = getFocusables(entries, false); | ||
return outerNodes.map(function (_a) { | ||
@@ -25,0 +19,0 @@ var node = _a.node, index = _a.index; |
@@ -7,2 +7,3 @@ import * as allConstants from './constants'; | ||
import { moveFocusInside } from './moveFocusInside'; | ||
import { captureFocusRestore } from './return-focus'; | ||
import { focusNextElement, focusPrevElement, getRelativeFocusable } from './sibling'; | ||
@@ -15,3 +16,3 @@ import { getFocusableNodes, getTabbableNodes } from './utils/DOMutils'; | ||
declare const constants: typeof allConstants; | ||
export { constants, focusInside, focusIsHidden, moveFocusInside, focusSolver, expandFocusableNodes, getFocusableNodes, getTabbableNodes, focusNextElement, focusPrevElement, getRelativeFocusable, }; | ||
export { constants, focusInside, focusIsHidden, moveFocusInside, focusSolver, expandFocusableNodes, getFocusableNodes, getTabbableNodes, focusNextElement, focusPrevElement, getRelativeFocusable, captureFocusRestore, }; | ||
/** | ||
@@ -18,0 +19,0 @@ * @deprecated - please use {@link moveFocusInside} named export |
@@ -7,2 +7,3 @@ import * as allConstants from './constants'; | ||
import { moveFocusInside } from './moveFocusInside'; | ||
import { captureFocusRestore } from './return-focus'; | ||
import { focusNextElement, focusPrevElement, getRelativeFocusable } from './sibling'; | ||
@@ -23,3 +24,5 @@ import { getFocusableNodes, getTabbableNodes } from './utils/DOMutils'; | ||
// | ||
focusNextElement, focusPrevElement, getRelativeFocusable, }; | ||
focusNextElement, focusPrevElement, getRelativeFocusable, | ||
// | ||
captureFocusRestore, }; | ||
/** | ||
@@ -26,0 +29,0 @@ * @deprecated - please use {@link moveFocusInside} named export |
@@ -26,2 +26,5 @@ import { FOCUS_NO_AUTOFOCUS } from '../constants'; | ||
var isInert = function (node) { return node.hasAttribute('inert'); }; | ||
/** | ||
* @see https://github.com/testing-library/jest-dom/blob/main/src/to-be-visible.js | ||
*/ | ||
var isVisibleUncached = function (node, checkParent) { | ||
@@ -28,0 +31,0 @@ return !node || isTopNode(node) || (!isElementHidden(node) && !isInert(node) && checkParent(getParentNode(node))); |
@@ -17,6 +17,8 @@ interface FocusableNode { | ||
/** | ||
* @returns list of focusable elements inside a given top node | ||
* @see {@link getFocusableNodes} for lower level access | ||
* traverses all related nodes (including groups) returning a list of all nodes(outer and internal) with meta information | ||
* This is low-level API! | ||
* @returns list of focusable elements inside a given top(!) node. | ||
* @see {@link getFocusableNodes} providing a simpler API | ||
*/ | ||
export declare const expandFocusableNodes: (topNode: HTMLElement) => FocusableNode[]; | ||
export declare const expandFocusableNodes: (topNode: HTMLElement | HTMLElement[]) => FocusableNode[]; | ||
export {}; |
@@ -1,8 +0,11 @@ | ||
import { getTabbableNodes } from './utils/DOMutils'; | ||
import { getAllAffectedNodes } from './utils/all-affected'; | ||
import { isGuard, isNotAGuard } from './utils/is'; | ||
import { getTopCommonParent } from './utils/parenting'; | ||
import { orderByTabIndex } from './utils/tabOrder'; | ||
import { getFocusables } from './utils/tabUtils'; | ||
/** | ||
* @returns list of focusable elements inside a given top node | ||
* @see {@link getFocusableNodes} for lower level access | ||
* traverses all related nodes (including groups) returning a list of all nodes(outer and internal) with meta information | ||
* This is low-level API! | ||
* @returns list of focusable elements inside a given top(!) node. | ||
* @see {@link getFocusableNodes} providing a simpler API | ||
*/ | ||
@@ -12,7 +15,4 @@ export const expandFocusableNodes = (topNode) => { | ||
const commonParent = getTopCommonParent(topNode, topNode, entries); | ||
const visibilityCache = new Map(); | ||
const outerNodes = getTabbableNodes([commonParent], visibilityCache, true); | ||
const innerElements = getTabbableNodes(entries, visibilityCache) | ||
.filter(({ node }) => isNotAGuard(node)) | ||
.map(({ node }) => node); | ||
const outerNodes = orderByTabIndex(getFocusables([commonParent], true), true, true); | ||
const innerElements = getFocusables(entries, false); | ||
return outerNodes.map(({ node, index }) => ({ | ||
@@ -19,0 +19,0 @@ node, |
@@ -7,2 +7,3 @@ import * as allConstants from './constants'; | ||
import { moveFocusInside } from './moveFocusInside'; | ||
import { captureFocusRestore } from './return-focus'; | ||
import { focusNextElement, focusPrevElement, getRelativeFocusable } from './sibling'; | ||
@@ -15,3 +16,3 @@ import { getFocusableNodes, getTabbableNodes } from './utils/DOMutils'; | ||
declare const constants: typeof allConstants; | ||
export { constants, focusInside, focusIsHidden, moveFocusInside, focusSolver, expandFocusableNodes, getFocusableNodes, getTabbableNodes, focusNextElement, focusPrevElement, getRelativeFocusable, }; | ||
export { constants, focusInside, focusIsHidden, moveFocusInside, focusSolver, expandFocusableNodes, getFocusableNodes, getTabbableNodes, focusNextElement, focusPrevElement, getRelativeFocusable, captureFocusRestore, }; | ||
/** | ||
@@ -18,0 +19,0 @@ * @deprecated - please use {@link moveFocusInside} named export |
@@ -7,2 +7,3 @@ import * as allConstants from './constants'; | ||
import { moveFocusInside } from './moveFocusInside'; | ||
import { captureFocusRestore } from './return-focus'; | ||
import { focusNextElement, focusPrevElement, getRelativeFocusable } from './sibling'; | ||
@@ -23,3 +24,5 @@ import { getFocusableNodes, getTabbableNodes } from './utils/DOMutils'; | ||
// | ||
focusNextElement, focusPrevElement, getRelativeFocusable, }; | ||
focusNextElement, focusPrevElement, getRelativeFocusable, | ||
// | ||
captureFocusRestore, }; | ||
/** | ||
@@ -26,0 +29,0 @@ * @deprecated - please use {@link moveFocusInside} named export |
@@ -24,2 +24,5 @@ import { FOCUS_NO_AUTOFOCUS } from '../constants'; | ||
const isInert = (node) => node.hasAttribute('inert'); | ||
/** | ||
* @see https://github.com/testing-library/jest-dom/blob/main/src/to-be-visible.js | ||
*/ | ||
const isVisibleUncached = (node, checkParent) => !node || isTopNode(node) || (!isElementHidden(node) && !isInert(node) && checkParent(getParentNode(node))); | ||
@@ -26,0 +29,0 @@ export const isVisibleCached = (visibilityCache, node) => { |
@@ -17,6 +17,8 @@ interface FocusableNode { | ||
/** | ||
* @returns list of focusable elements inside a given top node | ||
* @see {@link getFocusableNodes} for lower level access | ||
* traverses all related nodes (including groups) returning a list of all nodes(outer and internal) with meta information | ||
* This is low-level API! | ||
* @returns list of focusable elements inside a given top(!) node. | ||
* @see {@link getFocusableNodes} providing a simpler API | ||
*/ | ||
export declare const expandFocusableNodes: (topNode: HTMLElement) => FocusableNode[]; | ||
export declare const expandFocusableNodes: (topNode: HTMLElement | HTMLElement[]) => FocusableNode[]; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.expandFocusableNodes = void 0; | ||
var DOMutils_1 = require("./utils/DOMutils"); | ||
var all_affected_1 = require("./utils/all-affected"); | ||
var is_1 = require("./utils/is"); | ||
var parenting_1 = require("./utils/parenting"); | ||
var tabOrder_1 = require("./utils/tabOrder"); | ||
var tabUtils_1 = require("./utils/tabUtils"); | ||
/** | ||
* @returns list of focusable elements inside a given top node | ||
* @see {@link getFocusableNodes} for lower level access | ||
* traverses all related nodes (including groups) returning a list of all nodes(outer and internal) with meta information | ||
* This is low-level API! | ||
* @returns list of focusable elements inside a given top(!) node. | ||
* @see {@link getFocusableNodes} providing a simpler API | ||
*/ | ||
@@ -15,13 +18,4 @@ var expandFocusableNodes = function (topNode) { | ||
var commonParent = (0, parenting_1.getTopCommonParent)(topNode, topNode, entries); | ||
var visibilityCache = new Map(); | ||
var outerNodes = (0, DOMutils_1.getTabbableNodes)([commonParent], visibilityCache, true); | ||
var innerElements = (0, DOMutils_1.getTabbableNodes)(entries, visibilityCache) | ||
.filter(function (_a) { | ||
var node = _a.node; | ||
return (0, is_1.isNotAGuard)(node); | ||
}) | ||
.map(function (_a) { | ||
var node = _a.node; | ||
return node; | ||
}); | ||
var outerNodes = (0, tabOrder_1.orderByTabIndex)((0, tabUtils_1.getFocusables)([commonParent], true), true, true); | ||
var innerElements = (0, tabUtils_1.getFocusables)(entries, false); | ||
return outerNodes.map(function (_a) { | ||
@@ -28,0 +22,0 @@ var node = _a.node, index = _a.index; |
@@ -7,2 +7,3 @@ import * as allConstants from './constants'; | ||
import { moveFocusInside } from './moveFocusInside'; | ||
import { captureFocusRestore } from './return-focus'; | ||
import { focusNextElement, focusPrevElement, getRelativeFocusable } from './sibling'; | ||
@@ -15,3 +16,3 @@ import { getFocusableNodes, getTabbableNodes } from './utils/DOMutils'; | ||
declare const constants: typeof allConstants; | ||
export { constants, focusInside, focusIsHidden, moveFocusInside, focusSolver, expandFocusableNodes, getFocusableNodes, getTabbableNodes, focusNextElement, focusPrevElement, getRelativeFocusable, }; | ||
export { constants, focusInside, focusIsHidden, moveFocusInside, focusSolver, expandFocusableNodes, getFocusableNodes, getTabbableNodes, focusNextElement, focusPrevElement, getRelativeFocusable, captureFocusRestore, }; | ||
/** | ||
@@ -18,0 +19,0 @@ * @deprecated - please use {@link moveFocusInside} named export |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getRelativeFocusable = exports.focusPrevElement = exports.focusNextElement = exports.getTabbableNodes = exports.getFocusableNodes = exports.expandFocusableNodes = exports.focusSolver = exports.moveFocusInside = exports.focusIsHidden = exports.focusInside = exports.constants = void 0; | ||
exports.captureFocusRestore = exports.getRelativeFocusable = exports.focusPrevElement = exports.focusNextElement = exports.getTabbableNodes = exports.getFocusableNodes = exports.expandFocusableNodes = exports.focusSolver = exports.moveFocusInside = exports.focusIsHidden = exports.focusInside = exports.constants = void 0; | ||
var tslib_1 = require("tslib"); | ||
@@ -16,2 +16,4 @@ var allConstants = (0, tslib_1.__importStar)(require("./constants")); | ||
Object.defineProperty(exports, "moveFocusInside", { enumerable: true, get: function () { return moveFocusInside_1.moveFocusInside; } }); | ||
var return_focus_1 = require("./return-focus"); | ||
Object.defineProperty(exports, "captureFocusRestore", { enumerable: true, get: function () { return return_focus_1.captureFocusRestore; } }); | ||
var sibling_1 = require("./sibling"); | ||
@@ -18,0 +20,0 @@ Object.defineProperty(exports, "focusNextElement", { enumerable: true, get: function () { return sibling_1.focusNextElement; } }); |
@@ -29,2 +29,5 @@ "use strict"; | ||
var isInert = function (node) { return node.hasAttribute('inert'); }; | ||
/** | ||
* @see https://github.com/testing-library/jest-dom/blob/main/src/to-be-visible.js | ||
*/ | ||
var isVisibleUncached = function (node, checkParent) { | ||
@@ -31,0 +34,0 @@ return !node || isTopNode(node) || (!isElementHidden(node) && !isInert(node) && checkParent(getParentNode(node))); |
{ | ||
"name": "focus-lock", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "DOM trap for a focus", | ||
@@ -5,0 +5,0 @@ "main": "dist/es5/index.js", |
@@ -31,2 +31,22 @@ # focus-lock | ||
> note that tracking `lastActiveFocus` is on the end user. | ||
## Declarative control | ||
`focus-lock` provides not only API to be called by some other scripts, but also a way one can leave instructions inside HTML markup | ||
to amend focus behavior in a desired way. | ||
These are `data-attributes` one can add on the elements: | ||
- control | ||
- `data-focus-lock=[group-name]` to create a focus group (scattered focus) | ||
- `data-focus-lock-disabled="disabled"` marks such group as disabled and removes from the list. Equal to removing elements from the DOM. | ||
- `data-no-focus-lock` focus-lock will ignore/allow focus inside marked area. Focus on this elements will not be managed by focus-lock. | ||
- autofocus (via `moveFocusInside(someNode, null)`) | ||
- `data-autofocus` will autofocus marked element on activation. | ||
- `data-autofocus-inside` focus-lock will try to autofocus elements within selected area on activation. | ||
- `data-no-autofocus` focus-lock will not autofocus any node within marked area on activation. | ||
These markers are available as `import * as markers from 'focus-lock/constants'` | ||
## Additional API | ||
@@ -41,5 +61,2 @@ | ||
// returns an "extended information" but focusable nodes inside. To be used for advances cases (react-focus-lock) | ||
expandFocusableNodes(singleNodes); | ||
// returns all focusable nodes inside given locations | ||
@@ -50,2 +67,5 @@ getFocusableNodes([many, nodes])[0].node.focus(); | ||
getTabbleNodes([many, nodes])[0].node.focus(); | ||
// returns an "extended information" about focusable nodes inside. To be used for advances cases (react-focus-lock) | ||
expandFocusableNodes(singleNodes); | ||
``` | ||
@@ -55,5 +75,7 @@ | ||
Allows moving back and forth between focusable/tabbable elements | ||
```ts | ||
import { focusNextElement, focusPrevElement } from 'focus-lock'; | ||
focusNextElement(sourceElement, { | ||
focusNextElement(document.activeElement, { | ||
scope: theBoundingDOMNode, | ||
@@ -63,2 +85,13 @@ }); // -> next tabbable element | ||
### Return focus | ||
Advanced API to return focus (from the Modal) to the last or the next best location | ||
```ts | ||
import { captureFocusRestore } from 'focus-lock'; | ||
const restore = captureFocusRestore(element); | ||
// .... | ||
restore()?.focus(); // restores focus the the element, or it's siblings in case it no longer exists | ||
``` | ||
# WHY? | ||
@@ -75,20 +108,2 @@ | ||
# Declarative control | ||
`Focus-lock` provides not only API to be called by some other scripts, but also a way one can leave instructions inside HTML markup | ||
to amend focus behavior in a desired way. | ||
These are data-attributes one can add on the elements: | ||
- control | ||
- `data-focus-lock` to create a focus group (scattered focus) | ||
- `data-focus-lock-disabled` marks such group as disabled and removes from the list | ||
- `data-no-focus-lock` focus-lock will ignore focus inside marked area | ||
- autofocus | ||
- `data-autofocus` will autofocus marked element on activation. Require _control delegation_ to focus-lock | ||
- `data-autofocus-inside` focus-lock will try to autofocus elements within selected area | ||
- `data-no-autofocus` focus-lock will not autofocus any node within marked area | ||
These markers are available as `import * as markers from 'focus-lock/constants'` | ||
# Focus fighting | ||
@@ -95,0 +110,0 @@ |
177438
166
4228
126