Socket
Socket
Sign inDemoInstall

focus-lock

Package Overview
Dependencies
1
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.7.0 to 0.8.0

dist/es2015/constants.d.ts

2

dist/es2015/constants.js
export var FOCUS_GROUP = 'data-focus-lock';
export var FOCUS_DISABLED = 'data-focus-lock-disabled';
export var FOCUS_ALLOW = 'data-no-focus-lock';
export var FOCUS_AUTO = 'data-autofocus-inside';
export var FOCUS_AUTO = 'data-autofocus-inside';

@@ -1,23 +0,13 @@

import getAllAffectedNodes from './utils/all-affected';
import { arrayFind, toArray } from './utils/array';
var focusInFrame = function focusInFrame(frame) {
return frame === document.activeElement;
import { getAllAffectedNodes } from './utils/all-affected';
import { toArray } from './utils/array';
var focusInFrame = function (frame) { return frame === document.activeElement; };
var focusInsideIframe = function (topNode) {
return Boolean(toArray(topNode.querySelectorAll('iframe')).some(function (node) { return focusInFrame(node); }));
};
var focusInsideIframe = function focusInsideIframe(topNode) {
return !!arrayFind(toArray(topNode.querySelectorAll('iframe')), focusInFrame);
export var focusInside = function (topNode) {
var activeElement = document && document.activeElement;
if (!activeElement || (activeElement.dataset && activeElement.dataset.focusGuard)) {
return false;
}
return getAllAffectedNodes(topNode).reduce(function (result, node) { return result || node.contains(activeElement) || focusInsideIframe(node); }, false);
};
var focusInside = function focusInside(topNode) {
var activeElement = document && document.activeElement;
if (!activeElement || activeElement.dataset && activeElement.dataset.focusGuard) {
return false;
}
return getAllAffectedNodes(topNode).reduce(function (result, node) {
return result || node.contains(activeElement) || focusInsideIframe(node);
}, false);
};
export default focusInside;

@@ -0,10 +1,6 @@

import { FOCUS_ALLOW } from './constants';
import { toArray } from './utils/array';
import { FOCUS_ALLOW } from './constants';
var focusIsHidden = function focusIsHidden() {
return document && toArray(document.querySelectorAll('[' + FOCUS_ALLOW + ']')).some(function (node) {
return node.contains(document.activeElement);
});
export var focusIsHidden = function () {
return document &&
toArray(document.querySelectorAll("[" + FOCUS_ALLOW + "]")).some(function (node) { return node.contains(document.activeElement); });
};
export default focusIsHidden;

@@ -1,196 +0,55 @@

import { getCommonParent, getTabbableNodes, getAllTabbableNodes, parentAutofocusables } from './utils/DOMutils';
import pickFirstFocus, { pickFocusable } from './utils/firstFocus';
import getAllAffectedNodes from './utils/all-affected';
import { asArray } from './utils/array';
import { correctNodes } from './utils/correctFocus';
var findAutoFocused = function findAutoFocused(autoFocusables) {
return function (node) {
return !!node.autofocus || node.dataset && !!node.dataset.autofocus || autoFocusables.indexOf(node) >= 0;
};
import { NEW_FOCUS, newFocus } from './solver';
import { getAllAffectedNodes } from './utils/all-affected';
import { getAllTabbableNodes, getTabbableNodes } from './utils/DOMutils';
import { pickFirstFocus } from './utils/firstFocus';
import { isDefined, isNotAGuard } from './utils/is';
import { allParentAutofocusables, getTopCommonParent } from './utils/parenting';
var findAutoFocused = function (autoFocusables) { return function (node) {
return node.autofocus || (node.dataset && !!node.dataset.autofocus) || autoFocusables.indexOf(node) >= 0;
}; };
var reorderNodes = function (srcNodes, dstNodes) {
var remap = new Map();
dstNodes.forEach(function (entity) { return remap.set(entity.node, entity); });
return srcNodes.map(function (node) { return remap.get(node); }).filter(isDefined);
};
var isGuard = function isGuard(node) {
return node && node.dataset && node.dataset.focusGuard;
};
var notAGuard = function notAGuard(node) {
return !isGuard(node);
};
export var NEW_FOCUS = 'NEW_FOCUS';
export var newFocus = function newFocus(innerNodes, outerNodes, activeElement, lastNode) {
var cnt = innerNodes.length;
var firstFocus = innerNodes[0];
var lastFocus = innerNodes[cnt - 1];
var isOnGuard = isGuard(activeElement);
// focus is inside
if (innerNodes.indexOf(activeElement) >= 0) {
return undefined;
}
var activeIndex = outerNodes.indexOf(activeElement);
var lastIndex = outerNodes.indexOf(lastNode || activeIndex);
var lastNodeInside = innerNodes.indexOf(lastNode);
var indexDiff = activeIndex - lastIndex;
var firstNodeIndex = outerNodes.indexOf(firstFocus);
var lastNodeIndex = outerNodes.indexOf(lastFocus);
var correctedNodes = correctNodes(outerNodes);
var correctedIndexDiff = correctedNodes.indexOf(activeElement) - correctedNodes.indexOf(lastNode || activeIndex);
var returnFirstNode = pickFocusable(innerNodes, 0);
var returnLastNode = pickFocusable(innerNodes, cnt - 1);
// new focus
if (activeIndex === -1 || lastNodeInside === -1) {
return NEW_FOCUS;
}
// old focus
if (!indexDiff && lastNodeInside >= 0) {
return lastNodeInside;
}
// first element
if (activeIndex <= firstNodeIndex && isOnGuard && Math.abs(indexDiff) > 1) {
return returnLastNode;
}
// last element
if (activeIndex >= lastNodeIndex && isOnGuard && Math.abs(indexDiff) > 1) {
return returnFirstNode;
}
// jump out, but not on the guard
if (indexDiff && Math.abs(correctedIndexDiff) > 1) {
return lastNodeInside;
}
// focus above lock
if (activeIndex <= firstNodeIndex) {
return returnLastNode;
}
// focus below lock
if (activeIndex > lastNodeIndex) {
return returnFirstNode;
}
// index is inside tab order, but outside Lock
if (indexDiff) {
if (Math.abs(indexDiff) > 1) {
return lastNodeInside;
}
return (cnt + lastNodeInside + indexDiff) % cnt;
}
// do nothing
return undefined;
};
var getTopCommonParent = function getTopCommonParent(baseActiveElement, leftEntry, rightEntries) {
var activeElements = asArray(baseActiveElement);
var leftEntries = asArray(leftEntry);
var activeElement = activeElements[0];
var topCommon = null;
leftEntries.filter(Boolean).forEach(function (entry) {
topCommon = getCommonParent(topCommon || entry, entry) || topCommon;
rightEntries.filter(Boolean).forEach(function (subEntry) {
var common = getCommonParent(activeElement, subEntry);
if (common) {
if (!topCommon || common.contains(topCommon)) {
topCommon = common;
} else {
topCommon = getCommonParent(common, topCommon);
}
}
export var getFocusMerge = function (topNode, lastNode) {
var activeElement = (document && document.activeElement);
var entries = getAllAffectedNodes(topNode).filter(isNotAGuard);
var commonParent = getTopCommonParent(activeElement || topNode, topNode, entries);
var anyFocusable = getAllTabbableNodes(entries);
var innerElements = getTabbableNodes(entries).filter(function (_a) {
var node = _a.node;
return isNotAGuard(node);
});
});
return topCommon;
};
var allParentAutofocusables = function allParentAutofocusables(entries) {
return entries.reduce(function (acc, node) {
return acc.concat(parentAutofocusables(node));
}, []);
};
var reorderNodes = function reorderNodes(srcNodes, dstNodes) {
var remap = new Map();
// no Set(dstNodes) for IE11 :(
dstNodes.forEach(function (entity) {
return remap.set(entity.node, entity);
});
// remap to dstNodes
return srcNodes.map(function (node) {
return remap.get(node);
}).filter(Boolean);
};
export var getFocusabledIn = function getFocusabledIn(topNode) {
var entries = getAllAffectedNodes(topNode).filter(notAGuard);
var commonParent = getTopCommonParent(topNode, topNode, entries);
var outerNodes = getTabbableNodes([commonParent], true);
var innerElements = getTabbableNodes(entries).filter(function (_ref) {
var node = _ref.node;
return notAGuard(node);
}).map(function (_ref2) {
var node = _ref2.node;
return node;
});
return outerNodes.map(function (_ref3) {
var node = _ref3.node,
index = _ref3.index;
return {
node: node,
index: index,
lockItem: innerElements.indexOf(node) >= 0,
guard: isGuard(node)
};
});
};
var getFocusMerge = function getFocusMerge(topNode, lastNode) {
var activeElement = document && document.activeElement;
var entries = getAllAffectedNodes(topNode).filter(notAGuard);
var commonParent = getTopCommonParent(activeElement || topNode, topNode, entries);
var anyFocusable = getAllTabbableNodes(entries);
var innerElements = getTabbableNodes(entries).filter(function (_ref4) {
var node = _ref4.node;
return notAGuard(node);
});
if (!innerElements[0]) {
innerElements = anyFocusable;
if (!innerElements[0]) {
return undefined;
innerElements = anyFocusable;
if (!innerElements[0]) {
return undefined;
}
}
}
var outerNodes = getAllTabbableNodes([commonParent]).map(function (_ref5) {
var node = _ref5.node;
return node;
});
var orderedInnerElements = reorderNodes(outerNodes, innerElements);
var innerNodes = orderedInnerElements.map(function (_ref6) {
var node = _ref6.node;
return node;
});
var newId = newFocus(innerNodes, outerNodes, activeElement, lastNode);
if (newId === "NEW_FOCUS") {
var autoFocusable = anyFocusable.map(function (_ref7) {
var node = _ref7.node;
return node;
}).filter(findAutoFocused(allParentAutofocusables(entries)));
return {
node: autoFocusable && autoFocusable.length ? pickFirstFocus(autoFocusable) : pickFirstFocus(innerNodes)
};
}
if (newId === undefined) {
return newId;
}
return orderedInnerElements[newId];
var outerNodes = getAllTabbableNodes([commonParent]).map(function (_a) {
var node = _a.node;
return node;
});
var orderedInnerElements = reorderNodes(outerNodes, innerElements);
var innerNodes = orderedInnerElements.map(function (_a) {
var node = _a.node;
return node;
});
var newId = newFocus(innerNodes, outerNodes, activeElement, lastNode);
if (newId === NEW_FOCUS) {
var autoFocusable = anyFocusable
.map(function (_a) {
var node = _a.node;
return node;
})
.filter(findAutoFocused(allParentAutofocusables(entries)));
return {
node: autoFocusable && autoFocusable.length ? pickFirstFocus(autoFocusable) : pickFirstFocus(innerNodes),
};
}
if (newId === undefined) {
return newId;
}
return orderedInnerElements[newId];
};
export default getFocusMerge;

@@ -0,11 +1,11 @@

import * as constants from './constants';
import { getFocusabledIn } from './focusables';
import { focusInside } from './focusInside';
import { focusIsHidden } from './focusIsHidden';
import { getFocusMerge as focusMerge } from './focusMerge';
import { setFocus } from './setFocus';
import { focusNextElement, focusPrevElement } from './sibling';
import tabHook from './tabHook';
import focusMerge, { getFocusabledIn } from './focusMerge';
import focusInside from './focusInside';
import focusIsHidden from './focusIsHidden';
import setFocus from './setFocus';
import * as constants from './constants';
import getAllAffectedNodes from './utils/all-affected';
export { tabHook, focusInside, focusIsHidden, focusMerge, getFocusabledIn, constants, getAllAffectedNodes };
export default setFocus;
import { getAllAffectedNodes } from './utils/all-affected';
export { tabHook, focusInside, focusIsHidden, focusMerge, getFocusabledIn, constants, getAllAffectedNodes, focusNextElement, focusPrevElement, };
export default setFocus;

@@ -1,34 +0,29 @@

import getFocusMerge from './focusMerge';
export var focusOn = function focusOn(target) {
target.focus();
if (target.contentWindow) {
target.contentWindow.focus();
}
import { getFocusMerge } from './focusMerge';
export var focusOn = function (target) {
target.focus();
if ('contentWindow' in target && target.contentWindow) {
target.contentWindow.focus();
}
};
var guardCount = 0;
var lockDisabled = false;
export default (function (topNode, lastNode) {
var focusable = getFocusMerge(topNode, lastNode);
if (lockDisabled) {
return;
}
if (focusable) {
if (guardCount > 2) {
// eslint-disable-next-line no-console
console.error('FocusLock: focus-fighting detected. Only one focus management system could be active. ' + 'See https://github.com/theKashey/focus-lock/#focus-fighting');
lockDisabled = true;
setTimeout(function () {
lockDisabled = false;
}, 1);
return;
export var setFocus = function (topNode, lastNode) {
var focusable = getFocusMerge(topNode, lastNode);
if (lockDisabled) {
return;
}
guardCount++;
focusOn(focusable.node);
guardCount--;
}
});
if (focusable) {
if (guardCount > 2) {
console.error('FocusLock: focus-fighting detected. Only one focus management system could be active. ' +
'See https://github.com/theKashey/focus-lock/#focus-fighting');
lockDisabled = true;
setTimeout(function () {
lockDisabled = false;
}, 1);
return;
}
guardCount++;
focusOn(focusable.node);
guardCount--;
}
};
export default {
attach: function attach() {},
detach: function detach() {}
};
attach: function () { },
detach: function () { },
};

@@ -1,43 +0,31 @@

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
import { FOCUS_DISABLED, FOCUS_GROUP } from '../constants';
import { asArray, toArray } from './array';
var filterNested = function filterNested(nodes) {
var l = nodes.length;
for (var i = 0; i < l; i += 1) {
var _loop = function _loop(j) {
if (i !== j) {
if (nodes[i].contains(nodes[j])) {
return {
v: filterNested(nodes.filter(function (x) {
return x !== nodes[j];
}))
};
var filterNested = function (nodes) {
var contained = new Set();
var l = nodes.length;
for (var i = 0; i < l; i += 1) {
for (var j = i + 1; j < l; j += 1) {
var position = nodes[i].compareDocumentPosition(nodes[j]);
if ((position & Node.DOCUMENT_POSITION_CONTAINED_BY) > 0) {
contained.add(j);
}
if ((position & Node.DOCUMENT_POSITION_CONTAINS) > 0) {
contained.add(i);
}
}
}
};
for (var j = 0; j < l; j += 1) {
var _ret = _loop(j);
if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
}
}
return nodes;
return nodes.filter(function (_, index) { return !contained.has(index); });
};
var getTopParent = function getTopParent(node) {
return node.parentNode ? getTopParent(node.parentNode) : node;
var getTopParent = function (node) {
return node.parentNode ? getTopParent(node.parentNode) : node;
};
var getAllAffectedNodes = function getAllAffectedNodes(node) {
var nodes = asArray(node);
return nodes.filter(Boolean).reduce(function (acc, currentNode) {
var group = currentNode.getAttribute(FOCUS_GROUP);
acc.push.apply(acc, group ? filterNested(toArray(getTopParent(currentNode).querySelectorAll('[' + FOCUS_GROUP + '="' + group + '"]:not([' + FOCUS_DISABLED + '="disabled"])'))) : [currentNode]);
return acc;
}, []);
export var getAllAffectedNodes = function (node) {
var nodes = asArray(node);
return nodes.filter(Boolean).reduce(function (acc, currentNode) {
var group = currentNode.getAttribute(FOCUS_GROUP);
acc.push.apply(acc, (group
? filterNested(toArray(getTopParent(currentNode).querySelectorAll("[" + FOCUS_GROUP + "=\"" + group + "\"]:not([" + FOCUS_DISABLED + "=\"disabled\"])")))
: [currentNode]));
return acc;
}, []);
};
export default getAllAffectedNodes;

@@ -1,17 +0,8 @@

export var toArray = function toArray(a) {
var ret = Array(a.length);
for (var i = 0; i < a.length; ++i) {
ret[i] = a[i];
}
return ret;
export var toArray = function (a) {
var ret = Array(a.length);
for (var i = 0; i < a.length; ++i) {
ret[i] = a[i];
}
return ret;
};
export var arrayFind = function arrayFind(array, search) {
return array.filter(function (a) {
return a === search;
})[0];
};
export var asArray = function asArray(a) {
return Array.isArray(a) ? a : [a];
};
export var asArray = function (a) { return (Array.isArray(a) ? a : [a]); };

@@ -1,30 +0,18 @@

var isRadio = function isRadio(node) {
return node.tagName === 'INPUT' && node.type === 'radio';
var isRadio = function (node) { return node.tagName === 'INPUT' && node.type === 'radio'; };
var findSelectedRadio = function (node, nodes) {
return nodes
.filter(isRadio)
.filter(function (el) { return el.name === node.name; })
.filter(function (el) { return el.checked; })[0] || node;
};
var findSelectedRadio = function findSelectedRadio(node, nodes) {
return nodes.filter(isRadio).filter(function (el) {
return el.name === node.name;
}).filter(function (el) {
return el.checked;
})[0] || node;
export var correctNode = function (node, nodes) {
if (isRadio(node) && node.name) {
return findSelectedRadio(node, nodes);
}
return node;
};
export var correctNode = function correctNode(node, nodes) {
if (isRadio(node) && node.name) {
return findSelectedRadio(node, nodes);
}
return node;
export var correctNodes = function (nodes) {
var resultSet = new Set();
nodes.forEach(function (node) { return resultSet.add(correctNode(node, nodes)); });
return nodes.filter(function (node) { return resultSet.has(node); });
};
export var correctNodes = function correctNodes(nodes) {
// IE11 has no Set constructor
var resultSet = new Set();
nodes.forEach(function (node) {
return resultSet.add(correctNode(node, nodes));
});
// using filter to support IE11
return nodes.filter(function (node) {
return resultSet.has(node);
});
};

@@ -0,64 +1,18 @@

import { toArray } from './array';
import { isVisible, notHiddenInput } from './is';
import { orderByTabIndex } from './tabOrder';
import { getFocusables, getParentAutofocusables } from './tabUtils';
import { toArray } from './array';
var isElementHidden = function isElementHidden(computedStyle) {
if (!computedStyle || !computedStyle.getPropertyValue) {
return false;
}
return computedStyle.getPropertyValue('display') === 'none' || computedStyle.getPropertyValue('visibility') === 'hidden';
export var filterFocusable = function (nodes) {
return toArray(nodes)
.filter(function (node) { return isVisible(node); })
.filter(function (node) { return notHiddenInput(node); });
};
export var isVisible = function isVisible(node) {
return !node || node === document || node.nodeType === Node.DOCUMENT_NODE || !isElementHidden(window.getComputedStyle(node, null)) && isVisible(node.parentNode && node.parentNode.nodeType === node.DOCUMENT_FRAGMENT_NODE ? node.parentNode.host : node.parentNode);
export var getTabbableNodes = function (topNodes, withGuards) {
return orderByTabIndex(filterFocusable(getFocusables(topNodes, withGuards)), true, withGuards);
};
export var notHiddenInput = function notHiddenInput(node) {
return !((node.tagName === 'INPUT' || node.tagName === 'BUTTON') && (node.type === 'hidden' || node.disabled));
export var getAllTabbableNodes = function (topNodes) {
return orderByTabIndex(filterFocusable(getFocusables(topNodes)), false);
};
var getParents = function getParents(node) {
var parents = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
parents.push(node);
if (node.parentNode) {
getParents(node.parentNode, parents);
}
return parents;
export var parentAutofocusables = function (topNode) {
return filterFocusable(getParentAutofocusables(topNode));
};
export var getCommonParent = function getCommonParent(nodea, nodeb) {
var parentsA = getParents(nodea);
var parentsB = getParents(nodeb);
for (var i = 0; i < parentsA.length; i += 1) {
var currentParent = parentsA[i];
if (parentsB.indexOf(currentParent) >= 0) {
return currentParent;
}
}
return false;
};
export var filterFocusable = function filterFocusable(nodes) {
return toArray(nodes).filter(function (node) {
return isVisible(node);
}).filter(function (node) {
return notHiddenInput(node);
});
};
export var getTabbableNodes = function getTabbableNodes(topNodes, withGuards) {
return orderByTabIndex(filterFocusable(getFocusables(topNodes, withGuards)), true, withGuards);
};
/**
* actually anything focusable
*/
export var getAllTabbableNodes = function getAllTabbableNodes(topNodes) {
return orderByTabIndex(filterFocusable(getFocusables(topNodes)), false);
};
export var parentAutofocusables = function parentAutofocusables(topNode) {
return filterFocusable(getParentAutofocusables(topNode));
};
import { correctNode } from './correctFocus';
var pickFirstFocus = function pickFirstFocus(nodes) {
if (nodes[0] && nodes.length > 1) {
return correctNode(nodes[0], nodes);
}
return nodes[0];
export var pickFirstFocus = function (nodes) {
if (nodes[0] && nodes.length > 1) {
return correctNode(nodes[0], nodes);
}
return nodes[0];
};
export var pickFocusable = function pickFocusable(nodes, index) {
if (nodes.length > 1) {
return nodes.indexOf(correctNode(nodes[index], nodes));
}
return index;
export var pickFocusable = function (nodes, index) {
if (nodes.length > 1) {
return nodes.indexOf(correctNode(nodes[index], nodes));
}
return index;
};
export default pickFirstFocus;

@@ -1,1 +0,17 @@

export default ['button:enabled:not([readonly])', 'select:enabled:not([readonly])', 'textarea:enabled:not([readonly])', 'input:enabled:not([readonly])', 'a[href]', 'area[href]', 'iframe', 'object', 'embed', '[tabindex]', '[contenteditable]', '[autofocus]'];
export var tabbables = [
'button:enabled',
'select:enabled',
'textarea:enabled',
'input:enabled',
'a[href]',
'area[href]',
'summary',
'iframe',
'object',
'embed',
'audio[controls]',
'video[controls]',
'[tabindex]',
'[contenteditable]',
'[autofocus]',
];
import { toArray } from './array';
export var tabSort = function tabSort(a, b) {
var tabDiff = a.tabIndex - b.tabIndex;
var indexDiff = a.index - b.index;
if (tabDiff) {
if (!a.tabIndex) return 1;
if (!b.tabIndex) return -1;
}
return tabDiff || indexDiff;
export var tabSort = function (a, b) {
var tabDiff = a.tabIndex - b.tabIndex;
var indexDiff = a.index - b.index;
if (tabDiff) {
if (!a.tabIndex) {
return 1;
}
if (!b.tabIndex) {
return -1;
}
}
return tabDiff || indexDiff;
};
export var orderByTabIndex = function orderByTabIndex(nodes, filterNegative, keepGuards) {
return toArray(nodes).map(function (node, index) {
return {
node: node,
index: index,
tabIndex: keepGuards && node.tabIndex === -1 ? (node.dataset || {}).focusGuard ? 0 : -1 : node.tabIndex
};
}).filter(function (data) {
return !filterNegative || data.tabIndex >= 0;
}).sort(tabSort);
};
export var orderByTabIndex = function (nodes, filterNegative, keepGuards) {
return toArray(nodes)
.map(function (node, index) { return ({
node: node,
index: index,
tabIndex: keepGuards && node.tabIndex === -1 ? ((node.dataset || {}).focusGuard ? 0 : -1) : node.tabIndex,
}); })
.filter(function (data) { return !filterNegative || data.tabIndex >= 0; })
.sort(tabSort);
};

@@ -1,27 +0,18 @@

import tabbables from './tabbables';
import { FOCUS_AUTO } from '../constants';
import { toArray } from './array';
import { FOCUS_AUTO } from '../constants';
import { tabbables } from './tabbables';
var queryTabbables = tabbables.join(',');
var queryGuardTabbables = queryTabbables + ', [data-focus-guard]';
export var getFocusables = function getFocusables(parents, withGuards) {
return parents.reduce(function (acc, parent) {
return acc.concat(
// add all tabbables inside
toArray(parent.querySelectorAll(withGuards ? queryGuardTabbables : queryTabbables)),
// add if node is tabble itself
parent.parentNode ? toArray(parent.parentNode.querySelectorAll(tabbables.join(','))).filter(function (node) {
return node === parent;
}) : []);
}, []);
var queryGuardTabbables = queryTabbables + ", [data-focus-guard]";
export var getFocusables = function (parents, withGuards) {
return parents.reduce(function (acc, parent) {
return acc.concat(toArray(parent.querySelectorAll(withGuards ? queryGuardTabbables : queryTabbables)), parent.parentNode
? toArray(parent.parentNode.querySelectorAll(queryTabbables)).filter(function (node) { return node === parent; })
: []);
}, []);
};
export var getParentAutofocusables = function getParentAutofocusables(parent) {
var parentFocus = parent.querySelectorAll('[' + FOCUS_AUTO + ']');
return toArray(parentFocus).map(function (node) {
return getFocusables([node]);
}).reduce(function (acc, nodes) {
return acc.concat(nodes);
}, []);
};
export var getParentAutofocusables = function (parent) {
var parentFocus = parent.querySelectorAll("[" + FOCUS_AUTO + "]");
return toArray(parentFocus)
.map(function (node) { return getFocusables([node]); })
.reduce(function (acc, nodes) { return acc.concat(nodes); }, []);
};
{
"name": "focus-lock",
"version": "0.7.0",
"version": "0.8.0",
"description": "DOM trap for a focus",
"main": "dist/cjs/index.js",
"main": "dist/es5/index.js",
"jsnext:main": "dist/es2015/index.js",

@@ -10,12 +10,17 @@ "module": "dist/es2015/index.js",

"scripts": {
"build:cjs": "NODE_ENV=cjs babel src -d dist/cjs",
"build:es5": "NODE_ENV=es2015 babel src -d dist/es2015",
"build": "rm -Rf ./dist && yarn build:es5 && yarn build:cjs",
"test": "NODE_ENV=cjs npm run test:pick -- '_tests/**/*spec.js'",
"test:pick": "NODE_ENV=cjs mocha --compilers js:babel-core/register -r jsdom-global/register",
"prepublish": "npm run build && npm run changelog",
"lint": "eslint src tests",
"lint:fix": "eslint src tests --fix",
"size": "yarn size-limit",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
"dev": "lib-builder dev",
"test": "jest",
"test:ci": "jest --runInBand --coverage",
"build": "lib-builder build && yarn size:report",
"release": "yarn build && yarn test",
"size": "npx size-limit",
"size:report": "npx size-limit --json > .size.json",
"lint": "lib-builder lint",
"format": "lib-builder format",
"update": "lib-builder update",
"docz:dev": "docz dev",
"docz:build": "docz build",
"prepublish": "yarn build && yarn changelog",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"changelog:rewrite": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
},

@@ -32,4 +37,3 @@ "repository": {

"files": [
"dist",
"constants"
"dist"
],

@@ -43,22 +47,35 @@ "author": "theKashey <thekashey@gmail.com>",

"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.25.0",
"babel-eslint": "^7.2.3",
"babel-preset-env": "1.6.0",
"chai": "^4.1.0",
"chai-enzyme": "^0.8.0",
"conventional-changelog-cli": "^2.0.12",
"enzyme": "^2.9.1",
"eslint": "^4.2.0",
"eslint-config-airbnb": "15.1.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-jsx-a11y": "6.0.2",
"eslint-plugin-mocha": "^4.11.0",
"eslint-plugin-react": "^7.3.0",
"jsdom": "11.1.0",
"jsdom-global": "3.0.2",
"mocha": "^3.4.2",
"sinon": "3.2.1",
"size-limit": "^0.21.1"
"@theuiteam/lib-builder": "^0.0.11",
"@size-limit/preset-small-lib": "^2.1.6"
},
"types": "dist/es5/index.d.ts",
"engines": {
"node": ">=10"
},
"dependencies": {
"tslib": "^1.9.3"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{ts,tsx}": [
"prettier --write",
"tslint --fix",
"git add"
],
"*.{js,css,json,md}": [
"prettier --write",
"git add"
]
},
"prettier": {
"printWidth": 120,
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": true
}
}
# focus-lock
It is a trap! We got your focus and will not let him out!

@@ -9,11 +10,13 @@

This is a base package for:
- [react-focus-lock](https://github.com/theKashey/react-focus-lock)
- [react-focus-lock](https://github.com/theKashey/react-focus-lock)
[![downloads](https://badgen.net/npm/dm/react-focus-lock)](https://www.npmtrends.com/react-focus-lock)
- [vue-focus-lock](https://github.com/theKashey/vue-focus-lock)
- [vue-focus-lock](https://github.com/theKashey/vue-focus-lock)
[![downloads](https://badgen.net/npm/dm/vue-focus-lock)](https://www.npmtrends.com/vue-focus-lock)
- [dom-focus-lock](https://github.com/theKashey/dom-focus-lock)
- [dom-focus-lock](https://github.com/theKashey/dom-focus-lock)
[![downloads](https://badgen.net/npm/dm/dom-focus-lock)](https://www.npmtrends.com/dom-focus-lock)
Provides a low level API, to be used by final realization. Usually everything
can be solved in 3 lines
Provides a low level API, to be used by final realization.
Usually everything can be solved in 3 lines
```js

@@ -27,14 +30,28 @@ import moveFocusInside, { focusInside } from 'focus-lock';

## Additional API
### Programmatic focus management
```ts
import { focusNextElement, focusPrevElement } from 'focus-lock';
focusNextElement(sourceElement, {
scope: theBoundingDOMNode,
}); // -> next tabbable element
```
# WHY?
From [MDN Article about accessible dialogs](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_dialog_role):
- The dialog must be properly labeled
- Keyboard __focus must be managed__ correctly
- The dialog must be properly labeled
- Keyboard **focus must be managed** correctly
This one is about managing the focus.
I'v got a good [article about focus management, dialogs and WAI-ARIA](https://medium.com/@antonkorzunov/its-a-focus-trap-699a04d66fb5).
I'v got a good [article about focus management, dialogs and WAI-ARIA](https://medium.com/@antonkorzunov/its-a-focus-trap-699a04d66fb5).
# Focus fighting
It is possible, that more that one "focus management system" is present on the site.
For example you are using FocusLock for your content, and also using some
For example, you are using FocusLock for your content, and also using some
Modal dialog, with FocusTrap inside.

@@ -49,4 +66,4 @@

You may also land a peace by special data attribute - `data-no-focus-lock`(constants.FOCUS_ALLOW). It will
remove focus management from all nested elements, letting you open modals, forms, or
use any third party component safely. Focus lock will just do nothing, while focus is on the marked elements.
remove focus management from all nested elements, letting you open modals, forms, or
use any third party component safely. Focus lock will just do nothing, while focus is on the marked elements.

@@ -56,6 +73,5 @@ # API

`default(topNode, lastNode)` (aka setFocus), moves focus inside topNode, keeping in mind that last focus inside was - lastNode
# Licence
MIT
MIT
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc