arrowtab 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -80,7 +80,10 @@ cleanup()
|
|
|
80
80
|
You can pass options to the `initArrowTab` function. For example:
|
|
81
81
|
|
|
82
82
|
```ts
|
|
83
|
-
initArrowTab({
|
|
83
|
+
initArrowTab({
|
|
84
|
+
debug: true,
|
|
85
|
+
autoDetectHistory: true,
|
|
86
|
+
})
|
|
84
87
|
```
|
|
85
88
|
|
|
86
89
|
### debug
|
|
@@ -103,6 +106,12 @@ If you click on a focusable element, debug information will be logged to the con
|
|
|
103
106
|
|
|
104
107
|
To deactivate the visual debug mode, press `Esc`.
|
|
105
108
|
|
|
109
|
+
### autoDetectHistory
|
|
110
|
+
|
|
111
|
+
default: `false`
|
|
112
|
+
|
|
113
|
+
If `true`, ArrowTab will automatically detect dialogs and refocuses the last focused element when the dialog closes.
|
|
114
|
+
|
|
106
115
|
## data-arrowtab
|
|
107
116
|
|
|
108
117
|
You can control the behavior of ArrowTab by adding a `data-arrowtab` attribute to any element. Separate the keywords with a space. For example: `<div data-arrowtab="disable-left disable-right">`
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const setHistoryCandidate: ({ element }: {
|
|
2
|
+
element: Element;
|
|
3
|
+
}) => void;
|
|
4
|
+
export declare const pushCandidateIntoHistory: () => void;
|
|
5
|
+
export declare const focusPrevious: () => void;
|
|
6
|
+
export declare const startAutoDetectHistory: ({ active }: {
|
|
7
|
+
active: boolean;
|
|
8
|
+
}) => {
|
|
9
|
+
cleanup: () => void;
|
|
10
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const focusHistory = [];
|
|
2
|
+
let historyCandidate;
|
|
3
|
+
export const setHistoryCandidate = ({ element }) => {
|
|
4
|
+
if (!(element instanceof HTMLElement)) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
historyCandidate = element;
|
|
8
|
+
};
|
|
9
|
+
export const pushCandidateIntoHistory = () => {
|
|
10
|
+
if (historyCandidate) {
|
|
11
|
+
focusHistory.push(historyCandidate);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export const focusPrevious = () => {
|
|
15
|
+
const lastHistoryElement = focusHistory.pop();
|
|
16
|
+
if (lastHistoryElement) {
|
|
17
|
+
lastHistoryElement.focus();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export const startAutoDetectHistory = ({ active }) => {
|
|
21
|
+
if (!active) {
|
|
22
|
+
return {
|
|
23
|
+
cleanup: () => { },
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
let dialogObserver = null;
|
|
27
|
+
// TODO: Support multiple dialogs
|
|
28
|
+
let lastDialogElement = null;
|
|
29
|
+
dialogObserver = new MutationObserver((mutationList) => {
|
|
30
|
+
for (const mutation of mutationList) {
|
|
31
|
+
if (mutation.type === 'childList') {
|
|
32
|
+
for (const node of mutation.addedNodes) {
|
|
33
|
+
if (node.nodeType === 1 &&
|
|
34
|
+
node instanceof HTMLElement &&
|
|
35
|
+
node.getAttribute('role') === 'dialog') {
|
|
36
|
+
lastDialogElement = node;
|
|
37
|
+
pushCandidateIntoHistory();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const node of mutation.removedNodes) {
|
|
41
|
+
if (node === lastDialogElement || node.contains(lastDialogElement)) {
|
|
42
|
+
lastDialogElement = null;
|
|
43
|
+
focusPrevious();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
dialogObserver.observe(document.body, {
|
|
51
|
+
childList: true,
|
|
52
|
+
subtree: true,
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
cleanup: () => {
|
|
56
|
+
dialogObserver?.disconnect();
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=focusHistory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focusHistory.js","sourceRoot":"","sources":["../../src/lib/focusHistory.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAkB,EAAE,CAAA;AACtC,IAAI,gBAAyC,CAAA;AAE7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAAE,OAAO,EAAwB,EAAE,EAAE;IACvE,IAAI,CAAC,CAAC,OAAO,YAAY,WAAW,CAAC,EAAE,CAAC;QACtC,OAAM;IACR,CAAC;IACD,gBAAgB,GAAG,OAAO,CAAA;AAC5B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAG,EAAE;IAC3C,IAAI,gBAAgB,EAAE,CAAC;QACrB,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IACrC,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,EAAE;IAChC,MAAM,kBAAkB,GAAG,YAAY,CAAC,GAAG,EAAE,CAAA;IAC7C,IAAI,kBAAkB,EAAE,CAAC;QACvB,kBAAkB,CAAC,KAAK,EAAE,CAAA;IAC5B,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,EAAE,MAAM,EAAuB,EAAE,EAAE;IACxE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;SAClB,CAAA;IACH,CAAC;IACD,IAAI,cAAc,GAA4B,IAAI,CAAA;IAClD,iCAAiC;IACjC,IAAI,iBAAiB,GAAuB,IAAI,CAAA;IAChD,cAAc,GAAG,IAAI,gBAAgB,CAAC,CAAC,YAAY,EAAE,EAAE;QACrD,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;YACpC,IAAI,QAAQ,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAClC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;oBACvC,IACE,IAAI,CAAC,QAAQ,KAAK,CAAC;wBACnB,IAAI,YAAY,WAAW;wBAC3B,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,QAAQ,EACtC,CAAC;wBACD,iBAAiB,GAAG,IAAI,CAAA;wBACxB,wBAAwB,EAAE,CAAA;oBAC5B,CAAC;gBACH,CAAC;gBAED,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;oBACzC,IAAI,IAAI,KAAK,iBAAiB,IAAI,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;wBACnE,iBAAiB,GAAG,IAAI,CAAA;wBACxB,aAAa,EAAE,CAAA;wBACf,OAAM;oBACR,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE;QACpC,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI;KACd,CAAC,CAAA;IAEF,OAAO;QACL,OAAO,EAAE,GAAG,EAAE;YACZ,cAAc,EAAE,UAAU,EAAE,CAAA;QAC9B,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
|
package/dist/lib/initArrowTab.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { activateDebugMode, deactivateDebugMode, isInDebugMode, } from './debugMode.js';
|
|
2
|
+
import { setHistoryCandidate, startAutoDetectHistory } from './focusHistory.js';
|
|
2
3
|
import { getFocusable } from './getFocusable.js';
|
|
3
4
|
import { hasDisabledKeys } from './hasDisabledKeys.js';
|
|
4
5
|
import { hasTextSelection } from './hasTextSelection.js';
|
|
@@ -16,7 +17,7 @@ import { getByGrid } from './strategies.js';
|
|
|
16
17
|
// TODO: Check if tab focuses the same elements as arrowTab
|
|
17
18
|
// TODO: select, details, summary, iframe
|
|
18
19
|
// TODO: Investigate links that don't show focus outline sometimes
|
|
19
|
-
export const initArrowTab = ({ debug = false } = {}) => {
|
|
20
|
+
export const initArrowTab = ({ debug = false, autoDetectHistory = false, } = {}) => {
|
|
20
21
|
const onKeyDown = (event) => {
|
|
21
22
|
if (event.key === 'Escape' && isInDebugMode()) {
|
|
22
23
|
deactivateDebugMode();
|
|
@@ -90,12 +91,17 @@ export const initArrowTab = ({ debug = false } = {}) => {
|
|
|
90
91
|
console.log('focusing element', nearest);
|
|
91
92
|
}
|
|
92
93
|
nearest.element.focus();
|
|
94
|
+
setHistoryCandidate({ element: nearest.element });
|
|
93
95
|
}
|
|
94
96
|
};
|
|
95
97
|
document.addEventListener('keydown', onKeyDown, { capture: true });
|
|
98
|
+
const { cleanup: cleanupAutoDetectHistory } = startAutoDetectHistory({
|
|
99
|
+
active: autoDetectHistory,
|
|
100
|
+
});
|
|
96
101
|
return {
|
|
97
102
|
cleanup: () => {
|
|
98
103
|
document.removeEventListener('keydown', onKeyDown, { capture: true });
|
|
104
|
+
cleanupAutoDetectHistory();
|
|
99
105
|
},
|
|
100
106
|
};
|
|
101
107
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initArrowTab.js","sourceRoot":"","sources":["../../src/lib/initArrowTab.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,GACd,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAA;AAChF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,gBAAgB;AAChB,0BAA0B;AAC1B,mDAAmD;AACnD,qCAAqC;AACrC,uBAAuB;AACvB,gCAAgC;AAChC,6DAA6D;AAC7D,yCAAyC;AACzC,wDAAwD;AAExD,2DAA2D;AAC3D,yCAAyC;AACzC,kEAAkE;AAElE,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"initArrowTab.js","sourceRoot":"","sources":["../../src/lib/initArrowTab.ts"],"names":[],"mappings":"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"}
|