focus-lock
Advanced tools
Comparing version 1.0.1 to 1.1.0
@@ -0,1 +1,9 @@ | ||
import { NodeIndex } from './utils/tabOrder'; | ||
declare type UnresolvedSolution = {}; | ||
declare type ResolvedSolution = { | ||
prev: NodeIndex; | ||
next: NodeIndex; | ||
first: NodeIndex; | ||
last: NodeIndex; | ||
}; | ||
/** | ||
@@ -8,13 +16,3 @@ * for a given `element` in a given `scope` returns focusable siblings | ||
*/ | ||
export declare const getRelativeFocusable: (element: Element, scope: HTMLElement | Document) => { | ||
prev?: undefined; | ||
next?: undefined; | ||
first?: undefined; | ||
last?: undefined; | ||
} | { | ||
prev: import("./utils/tabOrder").NodeIndex; | ||
next: import("./utils/tabOrder").NodeIndex; | ||
first: import("./utils/tabOrder").NodeIndex; | ||
last: import("./utils/tabOrder").NodeIndex; | ||
} | undefined; | ||
export declare const getRelativeFocusable: (element: Element, scope: HTMLElement | HTMLElement[] | Document, useTabbables: boolean) => UnresolvedSolution | ResolvedSolution | undefined; | ||
interface FocusNextOptions { | ||
@@ -25,3 +23,3 @@ /** | ||
*/ | ||
scope?: HTMLElement | HTMLDocument; | ||
scope?: HTMLElement | HTMLElement[] | HTMLDocument; | ||
/** | ||
@@ -36,2 +34,8 @@ * enables cycling inside the scope | ||
focusOptions?: FocusOptions; | ||
/** | ||
* scopes to only tabbable elements | ||
* set to false to include all focusable elements (tabindex -1) | ||
* @default true | ||
*/ | ||
onlyTabbable?: boolean; | ||
} | ||
@@ -38,0 +42,0 @@ /** |
import { focusOn } from './commands'; | ||
import { getTabbableNodes, contains } from './utils/DOMutils'; | ||
import { getTabbableNodes, contains, getFocusableNodes } from './utils/DOMutils'; | ||
import { asArray } from './utils/array'; | ||
/** | ||
@@ -10,7 +11,15 @@ * for a given `element` in a given `scope` returns focusable siblings | ||
*/ | ||
export var getRelativeFocusable = function (element, scope) { | ||
if (!element || !scope || !contains(scope, element)) { | ||
export var getRelativeFocusable = function (element, scope, useTabbables) { | ||
if (!element || !scope) { | ||
console.error('no element or scope given'); | ||
return {}; | ||
} | ||
var focusables = getTabbableNodes([scope], new Map()); | ||
var shards = asArray(scope); | ||
if (shards.every(function (shard) { return !contains(shard, element); })) { | ||
console.error('Active element is not contained in the scope'); | ||
return {}; | ||
} | ||
var focusables = useTabbables | ||
? getTabbableNodes(shards, new Map()) | ||
: getFocusableNodes(shards, new Map()); | ||
var current = focusables.findIndex(function (_a) { | ||
@@ -35,4 +44,17 @@ var node = _a.node; | ||
cycle: true, | ||
onlyTabbable: true, | ||
}, options); | ||
}; | ||
var moveFocus = function (fromElement, options, cb) { | ||
if (options === void 0) { options = {}; } | ||
var newOptions = defaultOptions(options); | ||
var solution = getRelativeFocusable(fromElement, newOptions.scope, newOptions.onlyTabbable); | ||
if (!solution) { | ||
return; | ||
} | ||
var target = cb(solution, newOptions.cycle); | ||
if (target) { | ||
focusOn(target.node, newOptions.focusOptions); | ||
} | ||
}; | ||
/** | ||
@@ -45,12 +67,6 @@ * focuses next element in the tab-order | ||
if (options === void 0) { options = {}; } | ||
var _a = defaultOptions(options), scope = _a.scope, cycle = _a.cycle; | ||
var solution = getRelativeFocusable(fromElement, scope); | ||
if (!solution) { | ||
return; | ||
} | ||
var next = solution.next, first = solution.first; | ||
var newTarget = next || (cycle && first); | ||
if (newTarget) { | ||
focusOn(newTarget.node, options.focusOptions); | ||
} | ||
moveFocus(fromElement, options, function (_a, cycle) { | ||
var next = _a.next, first = _a.first; | ||
return next || (cycle && first); | ||
}); | ||
}; | ||
@@ -64,12 +80,6 @@ /** | ||
if (options === void 0) { options = {}; } | ||
var _a = defaultOptions(options), scope = _a.scope, cycle = _a.cycle; | ||
var solution = getRelativeFocusable(fromElement, scope); | ||
if (!solution) { | ||
return; | ||
} | ||
var prev = solution.prev, last = solution.last; | ||
var newTarget = prev || (cycle && last); | ||
if (newTarget) { | ||
focusOn(newTarget.node, options.focusOptions); | ||
} | ||
moveFocus(fromElement, options, function (_a, cycle) { | ||
var prev = _a.prev, last = _a.last; | ||
return prev || (cycle && last); | ||
}); | ||
}; |
import { toArray } from './array'; | ||
export var tabSort = function (a, b) { | ||
var tabDiff = a.tabIndex - b.tabIndex; | ||
var aTab = Math.max(0, a.tabIndex); | ||
var bTab = Math.max(0, b.tabIndex); | ||
var tabDiff = aTab - bTab; | ||
var indexDiff = a.index - b.index; | ||
if (tabDiff) { | ||
if (!a.tabIndex) { | ||
if (!aTab) { | ||
return 1; | ||
} | ||
if (!b.tabIndex) { | ||
if (!bTab) { | ||
return -1; | ||
@@ -11,0 +13,0 @@ } |
@@ -0,1 +1,9 @@ | ||
import { NodeIndex } from './utils/tabOrder'; | ||
declare type UnresolvedSolution = {}; | ||
declare type ResolvedSolution = { | ||
prev: NodeIndex; | ||
next: NodeIndex; | ||
first: NodeIndex; | ||
last: NodeIndex; | ||
}; | ||
/** | ||
@@ -8,13 +16,3 @@ * for a given `element` in a given `scope` returns focusable siblings | ||
*/ | ||
export declare const getRelativeFocusable: (element: Element, scope: HTMLElement | Document) => { | ||
prev?: undefined; | ||
next?: undefined; | ||
first?: undefined; | ||
last?: undefined; | ||
} | { | ||
prev: import("./utils/tabOrder").NodeIndex; | ||
next: import("./utils/tabOrder").NodeIndex; | ||
first: import("./utils/tabOrder").NodeIndex; | ||
last: import("./utils/tabOrder").NodeIndex; | ||
} | undefined; | ||
export declare const getRelativeFocusable: (element: Element, scope: HTMLElement | HTMLElement[] | Document, useTabbables: boolean) => UnresolvedSolution | ResolvedSolution | undefined; | ||
interface FocusNextOptions { | ||
@@ -25,3 +23,3 @@ /** | ||
*/ | ||
scope?: HTMLElement | HTMLDocument; | ||
scope?: HTMLElement | HTMLElement[] | HTMLDocument; | ||
/** | ||
@@ -36,2 +34,8 @@ * enables cycling inside the scope | ||
focusOptions?: FocusOptions; | ||
/** | ||
* scopes to only tabbable elements | ||
* set to false to include all focusable elements (tabindex -1) | ||
* @default true | ||
*/ | ||
onlyTabbable?: boolean; | ||
} | ||
@@ -38,0 +42,0 @@ /** |
import { focusOn } from './commands'; | ||
import { getTabbableNodes, contains } from './utils/DOMutils'; | ||
import { getTabbableNodes, contains, getFocusableNodes } from './utils/DOMutils'; | ||
import { asArray } from './utils/array'; | ||
/** | ||
@@ -10,7 +11,15 @@ * for a given `element` in a given `scope` returns focusable siblings | ||
*/ | ||
export const getRelativeFocusable = (element, scope) => { | ||
if (!element || !scope || !contains(scope, element)) { | ||
export const getRelativeFocusable = (element, scope, useTabbables) => { | ||
if (!element || !scope) { | ||
console.error('no element or scope given'); | ||
return {}; | ||
} | ||
const focusables = getTabbableNodes([scope], new Map()); | ||
const shards = asArray(scope); | ||
if (shards.every((shard) => !contains(shard, element))) { | ||
console.error('Active element is not contained in the scope'); | ||
return {}; | ||
} | ||
const focusables = useTabbables | ||
? getTabbableNodes(shards, new Map()) | ||
: getFocusableNodes(shards, new Map()); | ||
const current = focusables.findIndex(({ node }) => node === element); | ||
@@ -31,3 +40,15 @@ if (current === -1) { | ||
cycle: true, | ||
onlyTabbable: true, | ||
}, options); | ||
const moveFocus = (fromElement, options = {}, cb) => { | ||
const newOptions = defaultOptions(options); | ||
const solution = getRelativeFocusable(fromElement, newOptions.scope, newOptions.onlyTabbable); | ||
if (!solution) { | ||
return; | ||
} | ||
const target = cb(solution, newOptions.cycle); | ||
if (target) { | ||
focusOn(target.node, newOptions.focusOptions); | ||
} | ||
}; | ||
/** | ||
@@ -39,12 +60,3 @@ * focuses next element in the tab-order | ||
export const focusNextElement = (fromElement, options = {}) => { | ||
const { scope, cycle } = defaultOptions(options); | ||
const solution = getRelativeFocusable(fromElement, scope); | ||
if (!solution) { | ||
return; | ||
} | ||
const { next, first } = solution; | ||
const newTarget = next || (cycle && first); | ||
if (newTarget) { | ||
focusOn(newTarget.node, options.focusOptions); | ||
} | ||
moveFocus(fromElement, options, ({ next, first }, cycle) => next || (cycle && first)); | ||
}; | ||
@@ -57,12 +69,3 @@ /** | ||
export const focusPrevElement = (fromElement, options = {}) => { | ||
const { scope, cycle } = defaultOptions(options); | ||
const solution = getRelativeFocusable(fromElement, scope); | ||
if (!solution) { | ||
return; | ||
} | ||
const { prev, last } = solution; | ||
const newTarget = prev || (cycle && last); | ||
if (newTarget) { | ||
focusOn(newTarget.node, options.focusOptions); | ||
} | ||
moveFocus(fromElement, options, ({ prev, last }, cycle) => prev || (cycle && last)); | ||
}; |
import { toArray } from './array'; | ||
export const tabSort = (a, b) => { | ||
const tabDiff = a.tabIndex - b.tabIndex; | ||
const aTab = Math.max(0, a.tabIndex); | ||
const bTab = Math.max(0, b.tabIndex); | ||
const tabDiff = aTab - bTab; | ||
const indexDiff = a.index - b.index; | ||
if (tabDiff) { | ||
if (!a.tabIndex) { | ||
if (!aTab) { | ||
return 1; | ||
} | ||
if (!b.tabIndex) { | ||
if (!bTab) { | ||
return -1; | ||
@@ -11,0 +13,0 @@ } |
@@ -0,1 +1,9 @@ | ||
import { NodeIndex } from './utils/tabOrder'; | ||
declare type UnresolvedSolution = {}; | ||
declare type ResolvedSolution = { | ||
prev: NodeIndex; | ||
next: NodeIndex; | ||
first: NodeIndex; | ||
last: NodeIndex; | ||
}; | ||
/** | ||
@@ -8,13 +16,3 @@ * for a given `element` in a given `scope` returns focusable siblings | ||
*/ | ||
export declare const getRelativeFocusable: (element: Element, scope: HTMLElement | Document) => { | ||
prev?: undefined; | ||
next?: undefined; | ||
first?: undefined; | ||
last?: undefined; | ||
} | { | ||
prev: import("./utils/tabOrder").NodeIndex; | ||
next: import("./utils/tabOrder").NodeIndex; | ||
first: import("./utils/tabOrder").NodeIndex; | ||
last: import("./utils/tabOrder").NodeIndex; | ||
} | undefined; | ||
export declare const getRelativeFocusable: (element: Element, scope: HTMLElement | HTMLElement[] | Document, useTabbables: boolean) => UnresolvedSolution | ResolvedSolution | undefined; | ||
interface FocusNextOptions { | ||
@@ -25,3 +23,3 @@ /** | ||
*/ | ||
scope?: HTMLElement | HTMLDocument; | ||
scope?: HTMLElement | HTMLElement[] | HTMLDocument; | ||
/** | ||
@@ -36,2 +34,8 @@ * enables cycling inside the scope | ||
focusOptions?: FocusOptions; | ||
/** | ||
* scopes to only tabbable elements | ||
* set to false to include all focusable elements (tabindex -1) | ||
* @default true | ||
*/ | ||
onlyTabbable?: boolean; | ||
} | ||
@@ -38,0 +42,0 @@ /** |
@@ -6,2 +6,3 @@ "use strict"; | ||
var DOMutils_1 = require("./utils/DOMutils"); | ||
var array_1 = require("./utils/array"); | ||
/** | ||
@@ -14,7 +15,15 @@ * for a given `element` in a given `scope` returns focusable siblings | ||
*/ | ||
var getRelativeFocusable = function (element, scope) { | ||
if (!element || !scope || !(0, DOMutils_1.contains)(scope, element)) { | ||
var getRelativeFocusable = function (element, scope, useTabbables) { | ||
if (!element || !scope) { | ||
console.error('no element or scope given'); | ||
return {}; | ||
} | ||
var focusables = (0, DOMutils_1.getTabbableNodes)([scope], new Map()); | ||
var shards = (0, array_1.asArray)(scope); | ||
if (shards.every(function (shard) { return !(0, DOMutils_1.contains)(shard, element); })) { | ||
console.error('Active element is not contained in the scope'); | ||
return {}; | ||
} | ||
var focusables = useTabbables | ||
? (0, DOMutils_1.getTabbableNodes)(shards, new Map()) | ||
: (0, DOMutils_1.getFocusableNodes)(shards, new Map()); | ||
var current = focusables.findIndex(function (_a) { | ||
@@ -40,4 +49,17 @@ var node = _a.node; | ||
cycle: true, | ||
onlyTabbable: true, | ||
}, options); | ||
}; | ||
var moveFocus = function (fromElement, options, cb) { | ||
if (options === void 0) { options = {}; } | ||
var newOptions = defaultOptions(options); | ||
var solution = (0, exports.getRelativeFocusable)(fromElement, newOptions.scope, newOptions.onlyTabbable); | ||
if (!solution) { | ||
return; | ||
} | ||
var target = cb(solution, newOptions.cycle); | ||
if (target) { | ||
(0, commands_1.focusOn)(target.node, newOptions.focusOptions); | ||
} | ||
}; | ||
/** | ||
@@ -50,12 +72,6 @@ * focuses next element in the tab-order | ||
if (options === void 0) { options = {}; } | ||
var _a = defaultOptions(options), scope = _a.scope, cycle = _a.cycle; | ||
var solution = (0, exports.getRelativeFocusable)(fromElement, scope); | ||
if (!solution) { | ||
return; | ||
} | ||
var next = solution.next, first = solution.first; | ||
var newTarget = next || (cycle && first); | ||
if (newTarget) { | ||
(0, commands_1.focusOn)(newTarget.node, options.focusOptions); | ||
} | ||
moveFocus(fromElement, options, function (_a, cycle) { | ||
var next = _a.next, first = _a.first; | ||
return next || (cycle && first); | ||
}); | ||
}; | ||
@@ -70,13 +86,7 @@ exports.focusNextElement = focusNextElement; | ||
if (options === void 0) { options = {}; } | ||
var _a = defaultOptions(options), scope = _a.scope, cycle = _a.cycle; | ||
var solution = (0, exports.getRelativeFocusable)(fromElement, scope); | ||
if (!solution) { | ||
return; | ||
} | ||
var prev = solution.prev, last = solution.last; | ||
var newTarget = prev || (cycle && last); | ||
if (newTarget) { | ||
(0, commands_1.focusOn)(newTarget.node, options.focusOptions); | ||
} | ||
moveFocus(fromElement, options, function (_a, cycle) { | ||
var prev = _a.prev, last = _a.last; | ||
return prev || (cycle && last); | ||
}); | ||
}; | ||
exports.focusPrevElement = focusPrevElement; |
@@ -6,9 +6,11 @@ "use strict"; | ||
var tabSort = function (a, b) { | ||
var tabDiff = a.tabIndex - b.tabIndex; | ||
var aTab = Math.max(0, a.tabIndex); | ||
var bTab = Math.max(0, b.tabIndex); | ||
var tabDiff = aTab - bTab; | ||
var indexDiff = a.index - b.index; | ||
if (tabDiff) { | ||
if (!a.tabIndex) { | ||
if (!aTab) { | ||
return 1; | ||
} | ||
if (!b.tabIndex) { | ||
if (!bTab) { | ||
return -1; | ||
@@ -15,0 +17,0 @@ } |
{ | ||
"name": "focus-lock", | ||
"version": "1.0.1", | ||
"version": "1.1.0", | ||
"description": "DOM trap for a focus", | ||
@@ -5,0 +5,0 @@ "main": "dist/es5/index.js", |
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
163414
3917