UNPKG

3.78 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.captureFocusRestore = exports.recordElementLocation = void 0;
4var DOMutils_1 = require("./utils/DOMutils");
5function weakRef(value) {
6 if (!value)
7 return null;
8 var w = value ? new WeakRef(value) : null;
9 return function () { return (w === null || w === void 0 ? void 0 : w.deref()) || null; };
10}
11var recordElementLocation = function (element) {
12 if (!element) {
13 return null;
14 }
15 var stack = [];
16 var currentElement = element;
17 while (currentElement && currentElement !== document.body) {
18 stack.push({
19 current: weakRef(currentElement),
20 parent: weakRef(currentElement.parentElement),
21 left: weakRef(currentElement.previousElementSibling),
22 right: weakRef(currentElement.nextElementSibling),
23 });
24 currentElement = currentElement.parentElement;
25 }
26 return {
27 element: weakRef(element),
28 stack: stack,
29 ownerDocument: element.ownerDocument,
30 };
31};
32exports.recordElementLocation = recordElementLocation;
33var restoreFocusTo = function (location) {
34 var _a, _b, _c, _d, _e;
35 if (!location) {
36 return undefined;
37 }
38 var stack = location.stack, ownerDocument = location.ownerDocument;
39 var visibilityCache = new Map();
40 for (var _i = 0, stack_1 = stack; _i < stack_1.length; _i++) {
41 var line = stack_1[_i];
42 var parent_1 = (_a = line.parent) === null || _a === void 0 ? void 0 : _a.call(line);
43 // is it still here?
44 if (parent_1 && ownerDocument.contains(parent_1)) {
45 var left = (_b = line.left) === null || _b === void 0 ? void 0 : _b.call(line);
46 var savedCurrent = line.current();
47 var current = parent_1.contains(savedCurrent) ? savedCurrent : undefined;
48 var right = (_c = line.right) === null || _c === void 0 ? void 0 : _c.call(line);
49 var focusables = (0, DOMutils_1.getTabbableNodes)([parent_1], visibilityCache);
50 var aim =
51 // that is element itself
52 (_e = (_d = current !== null && current !== void 0 ? current :
53 // or something in it's place
54 left === null || left === void 0 ? void 0 : left.nextElementSibling) !== null && _d !== void 0 ? _d :
55 // or somebody to the right, still close enough
56 right) !== null && _e !== void 0 ? _e :
57 // or somebody to the left, something?
58 left;
59 while (aim) {
60 for (var _f = 0, focusables_1 = focusables; _f < focusables_1.length; _f++) {
61 var focusable = focusables_1[_f];
62 if (aim === null || aim === void 0 ? void 0 : aim.contains(focusable.node)) {
63 return focusable.node;
64 }
65 }
66 aim = aim.nextElementSibling;
67 }
68 if (focusables.length) {
69 // if parent contains a focusable - move there
70 return focusables[0].node;
71 }
72 }
73 }
74 // nothing matched
75 return undefined;
76};
77/**
78 * Captures the current focused element to restore focus as close as possible in the future
79 * Handles situations where the focused element is removed from the DOM or no longer focusable
80 * moving focus to the closest focusable element
81 * @param targetElement - element where focus should be restored
82 * @returns a function returning a new element to focus
83 */
84var captureFocusRestore = function (targetElement) {
85 var location = (0, exports.recordElementLocation)(targetElement);
86 return function () {
87 return restoreFocusTo(location);
88 };
89};
90exports.captureFocusRestore = captureFocusRestore;