keyborg 2.14.0-canary.0 → 2.14.0
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/dist/index.cjs +394 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +71 -0
- package/dist/index.d.ts +40 -99
- package/dist/index.js +366 -486
- package/dist/index.js.map +1 -1
- package/dist/ts3.9/index.d.ts +14 -66
- package/package.json +34 -21
- package/dist/esm/index.js +0 -474
- package/dist/esm/index.js.map +0 -1
- package/dist/index.d.mts +0 -130
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
//#region src/dom.mts
|
|
4
|
+
/*!
|
|
5
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6
|
+
* Licensed under the MIT License.
|
|
7
|
+
*/
|
|
8
|
+
const addEventListener = (target, type, handler) => {
|
|
9
|
+
target.addEventListener(type, handler, true);
|
|
10
|
+
};
|
|
11
|
+
const removeEventListener = (target, type, handler) => {
|
|
12
|
+
target.removeEventListener(type, handler, true);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/FocusEvent.mts
|
|
17
|
+
/*!
|
|
18
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
19
|
+
* Licensed under the MIT License.
|
|
20
|
+
*/
|
|
21
|
+
const KEYBORG_FOCUSIN = "keyborg:focusin";
|
|
22
|
+
const KEYBORG_FOCUSOUT = "keyborg:focusout";
|
|
23
|
+
const FOCUS_IN_HANDLER = 0;
|
|
24
|
+
const FOCUS_OUT_HANDLER = 1;
|
|
25
|
+
const SHADOW_TARGETS = 2;
|
|
26
|
+
const LAST_FOCUSED_PROGRAMMATICALLY = 3;
|
|
27
|
+
function canOverrideNativeFocus(win) {
|
|
28
|
+
const HTMLElement = win.HTMLElement;
|
|
29
|
+
const origFocus = HTMLElement.prototype.focus;
|
|
30
|
+
let isCustomFocusCalled = false;
|
|
31
|
+
HTMLElement.prototype.focus = function focus() {
|
|
32
|
+
isCustomFocusCalled = true;
|
|
33
|
+
};
|
|
34
|
+
win.document.createElement("button").focus();
|
|
35
|
+
HTMLElement.prototype.focus = origFocus;
|
|
36
|
+
return isCustomFocusCalled;
|
|
37
|
+
}
|
|
38
|
+
let _canOverrideNativeFocus = false;
|
|
39
|
+
/**
|
|
40
|
+
* Guarantees that the native `focus` will be used
|
|
41
|
+
*/
|
|
42
|
+
function nativeFocus(element) {
|
|
43
|
+
const focus = element.focus;
|
|
44
|
+
if (focus.__keyborgNativeFocus) focus.__keyborgNativeFocus.call(element);
|
|
45
|
+
else element.focus();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Overrides the native `focus` and setups the keyborg focus event
|
|
49
|
+
*/
|
|
50
|
+
function setupFocusEvent(win) {
|
|
51
|
+
const kwin = win;
|
|
52
|
+
const doc = kwin.document;
|
|
53
|
+
const proto = kwin.HTMLElement.prototype;
|
|
54
|
+
if (!_canOverrideNativeFocus) _canOverrideNativeFocus = canOverrideNativeFocus(kwin);
|
|
55
|
+
const origFocus = proto.focus;
|
|
56
|
+
if (origFocus.__keyborgNativeFocus) return;
|
|
57
|
+
proto.focus = focus;
|
|
58
|
+
const shadowTargets = /* @__PURE__ */ new Set();
|
|
59
|
+
const focusOutHandler = (e) => {
|
|
60
|
+
const target = e.target;
|
|
61
|
+
if (!target) return;
|
|
62
|
+
const event = new CustomEvent(KEYBORG_FOCUSOUT, {
|
|
63
|
+
cancelable: true,
|
|
64
|
+
bubbles: true,
|
|
65
|
+
composed: true,
|
|
66
|
+
detail: { originalEvent: e }
|
|
67
|
+
});
|
|
68
|
+
target.dispatchEvent(event);
|
|
69
|
+
};
|
|
70
|
+
const focusInHandler = (e) => {
|
|
71
|
+
const target = e.target;
|
|
72
|
+
if (!target) return;
|
|
73
|
+
let node = e.composedPath()[0];
|
|
74
|
+
const currentShadows = /* @__PURE__ */ new Set();
|
|
75
|
+
while (node) if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
|
76
|
+
currentShadows.add(node);
|
|
77
|
+
node = node.host;
|
|
78
|
+
} else node = node.parentNode;
|
|
79
|
+
for (const shadowRootWeakRef of shadowTargets) {
|
|
80
|
+
const shadowRoot = shadowRootWeakRef.deref();
|
|
81
|
+
if (!shadowRoot || !currentShadows.has(shadowRoot)) {
|
|
82
|
+
shadowTargets.delete(shadowRootWeakRef);
|
|
83
|
+
if (shadowRoot) {
|
|
84
|
+
removeEventListener(shadowRoot, "focusin", focusInHandler);
|
|
85
|
+
removeEventListener(shadowRoot, "focusout", focusOutHandler);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
onFocusIn(target, e.relatedTarget || void 0);
|
|
90
|
+
};
|
|
91
|
+
const onFocusIn = (target, relatedTarget, originalEvent) => {
|
|
92
|
+
const shadowRoot = target.shadowRoot;
|
|
93
|
+
if (shadowRoot) {
|
|
94
|
+
/**
|
|
95
|
+
* https://bugs.chromium.org/p/chromium/issues/detail?id=1512028
|
|
96
|
+
* focusin events don't bubble up through an open shadow root once focus is inside
|
|
97
|
+
* once focus moves into a shadow root - we drop the same focusin handler there
|
|
98
|
+
* keyborg's custom event will still bubble up since it is composed
|
|
99
|
+
* event handlers should be cleaned up once focus leaves the shadow root.
|
|
100
|
+
*
|
|
101
|
+
* When a focusin event is dispatched from a shadow root, its target is the shadow root parent.
|
|
102
|
+
* Each shadow root encounter requires a new capture listener.
|
|
103
|
+
* Why capture? - we want to follow the focus event in order or descending nested shadow roots
|
|
104
|
+
* When there are no more shadow root targets - dispatch the keyborg:focusin event
|
|
105
|
+
*
|
|
106
|
+
* 1. no focus event
|
|
107
|
+
* > document - capture listener ✅
|
|
108
|
+
* > shadow root 1
|
|
109
|
+
* > shadow root 2
|
|
110
|
+
* > shadow root 3
|
|
111
|
+
* > focused element
|
|
112
|
+
*
|
|
113
|
+
* 2. focus event received by document listener
|
|
114
|
+
* > document - capture listener ✅ (focus event here)
|
|
115
|
+
* > shadow root 1 - capture listener ✅
|
|
116
|
+
* > shadow root 2
|
|
117
|
+
* > shadow root 3
|
|
118
|
+
* > focused element
|
|
119
|
+
*
|
|
120
|
+
* 3. focus event received by root l1 listener
|
|
121
|
+
* > document - capture listener ✅
|
|
122
|
+
* > shadow root 1 - capture listener ✅ (focus event here)
|
|
123
|
+
* > shadow root 2 - capture listener ✅
|
|
124
|
+
* > shadow root 3
|
|
125
|
+
* > focused element
|
|
126
|
+
*
|
|
127
|
+
* 4. focus event received by root l2 listener
|
|
128
|
+
* > document - capture listener ✅
|
|
129
|
+
* > shadow root 1 - capture listener ✅
|
|
130
|
+
* > shadow root 2 - capture listener ✅ (focus event here)
|
|
131
|
+
* > shadow root 3 - capture listener ✅
|
|
132
|
+
* > focused element
|
|
133
|
+
*
|
|
134
|
+
* 5. focus event received by root l3 listener, no more shadow root targets
|
|
135
|
+
* > document - capture listener ✅
|
|
136
|
+
* > shadow root 1 - capture listener ✅
|
|
137
|
+
* > shadow root 2 - capture listener ✅
|
|
138
|
+
* > shadow root 3 - capture listener ✅ (focus event here)
|
|
139
|
+
* > focused element ✅ (no shadow root - dispatch keyborg event)
|
|
140
|
+
*/
|
|
141
|
+
for (const shadowRootWeakRef of shadowTargets) if (shadowRootWeakRef.deref() === shadowRoot) return;
|
|
142
|
+
addEventListener(shadowRoot, "focusin", focusInHandler);
|
|
143
|
+
addEventListener(shadowRoot, "focusout", focusOutHandler);
|
|
144
|
+
shadowTargets.add(new WeakRef(shadowRoot));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const details = {
|
|
148
|
+
relatedTarget,
|
|
149
|
+
originalEvent
|
|
150
|
+
};
|
|
151
|
+
const event = new CustomEvent(KEYBORG_FOCUSIN, {
|
|
152
|
+
cancelable: true,
|
|
153
|
+
bubbles: true,
|
|
154
|
+
composed: true,
|
|
155
|
+
detail: details
|
|
156
|
+
});
|
|
157
|
+
event.details = details;
|
|
158
|
+
if (_canOverrideNativeFocus || data[LAST_FOCUSED_PROGRAMMATICALLY]) {
|
|
159
|
+
details.isFocusedProgrammatically = target === data[LAST_FOCUSED_PROGRAMMATICALLY]?.deref();
|
|
160
|
+
data[LAST_FOCUSED_PROGRAMMATICALLY] = void 0;
|
|
161
|
+
}
|
|
162
|
+
target.dispatchEvent(event);
|
|
163
|
+
};
|
|
164
|
+
const data = [
|
|
165
|
+
focusInHandler,
|
|
166
|
+
focusOutHandler,
|
|
167
|
+
shadowTargets
|
|
168
|
+
];
|
|
169
|
+
kwin.__keyborgData = data;
|
|
170
|
+
addEventListener(doc, "focusin", focusInHandler);
|
|
171
|
+
addEventListener(doc, "focusout", focusOutHandler);
|
|
172
|
+
function focus() {
|
|
173
|
+
const d = kwin.__keyborgData;
|
|
174
|
+
if (d) d[LAST_FOCUSED_PROGRAMMATICALLY] = new WeakRef(this);
|
|
175
|
+
return origFocus.apply(this, arguments);
|
|
176
|
+
}
|
|
177
|
+
let activeElement = doc.activeElement;
|
|
178
|
+
while (activeElement && activeElement.shadowRoot) {
|
|
179
|
+
onFocusIn(activeElement);
|
|
180
|
+
activeElement = activeElement.shadowRoot.activeElement;
|
|
181
|
+
}
|
|
182
|
+
focus.__keyborgNativeFocus = origFocus;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Removes keyborg event listeners and custom focus override
|
|
186
|
+
* @param win The window that stores keyborg focus events
|
|
187
|
+
*/
|
|
188
|
+
function disposeFocusEvent(win) {
|
|
189
|
+
const kwin = win;
|
|
190
|
+
const proto = kwin.HTMLElement.prototype;
|
|
191
|
+
const origFocus = proto.focus.__keyborgNativeFocus;
|
|
192
|
+
const data = kwin.__keyborgData;
|
|
193
|
+
if (data) {
|
|
194
|
+
const doc = kwin.document;
|
|
195
|
+
removeEventListener(doc, "focusin", data[FOCUS_IN_HANDLER]);
|
|
196
|
+
removeEventListener(doc, "focusout", data[FOCUS_OUT_HANDLER]);
|
|
197
|
+
for (const shadowRootWeakRef of data[SHADOW_TARGETS]) {
|
|
198
|
+
const shadowRoot = shadowRootWeakRef.deref();
|
|
199
|
+
if (shadowRoot) {
|
|
200
|
+
removeEventListener(shadowRoot, "focusin", data[FOCUS_IN_HANDLER]);
|
|
201
|
+
removeEventListener(shadowRoot, "focusout", data[FOCUS_OUT_HANDLER]);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
data[SHADOW_TARGETS].clear();
|
|
205
|
+
delete kwin.__keyborgData;
|
|
206
|
+
}
|
|
207
|
+
if (origFocus) proto.focus = origFocus;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* @param win The window that stores keyborg focus events
|
|
211
|
+
* @returns The last element focused with element.focus()
|
|
212
|
+
*/
|
|
213
|
+
function getLastFocusedProgrammatically(win) {
|
|
214
|
+
const data = win.__keyborgData;
|
|
215
|
+
return data ? data[LAST_FOCUSED_PROGRAMMATICALLY]?.deref() || null : void 0;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/Keyborg.mts
|
|
220
|
+
/*!
|
|
221
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
222
|
+
* Licensed under the MIT License.
|
|
223
|
+
*/
|
|
224
|
+
const _dismissTimeout = 500;
|
|
225
|
+
let _lastId = 0;
|
|
226
|
+
function createKeyborgCore(targetWindow, props) {
|
|
227
|
+
let currentTargetWindow = targetWindow;
|
|
228
|
+
let isNavigating = false;
|
|
229
|
+
let isMouseOrTouchUsedTimer;
|
|
230
|
+
let dismissTimer;
|
|
231
|
+
let triggerKeys;
|
|
232
|
+
let dismissKeys;
|
|
233
|
+
if (props) {
|
|
234
|
+
if (props.triggerKeys?.length) triggerKeys = new Set(props.triggerKeys);
|
|
235
|
+
if (props.dismissKeys?.length) dismissKeys = new Set(props.dismissKeys);
|
|
236
|
+
}
|
|
237
|
+
const broadcast = () => {
|
|
238
|
+
const refs = currentTargetWindow?.__keyborg?.refs;
|
|
239
|
+
if (refs) for (const id of Object.keys(refs)) refs[id]._notify(isNavigating);
|
|
240
|
+
};
|
|
241
|
+
const setNavigating = (val) => {
|
|
242
|
+
if (isNavigating !== val) {
|
|
243
|
+
isNavigating = val;
|
|
244
|
+
broadcast();
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
const shouldTrigger = (e) => {
|
|
248
|
+
if (e.key === "Tab") return true;
|
|
249
|
+
const active = currentTargetWindow?.document.activeElement;
|
|
250
|
+
const isTriggerKey = !triggerKeys || triggerKeys.has(e.keyCode);
|
|
251
|
+
const isEditable = active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA" || active.isContentEditable);
|
|
252
|
+
return isTriggerKey && !isEditable;
|
|
253
|
+
};
|
|
254
|
+
const shouldDismiss = (e) => {
|
|
255
|
+
return !!dismissKeys?.has(e.keyCode);
|
|
256
|
+
};
|
|
257
|
+
const scheduleDismiss = () => {
|
|
258
|
+
const targetWindow = currentTargetWindow;
|
|
259
|
+
if (!targetWindow) return;
|
|
260
|
+
if (dismissTimer) {
|
|
261
|
+
targetWindow.clearTimeout(dismissTimer);
|
|
262
|
+
dismissTimer = void 0;
|
|
263
|
+
}
|
|
264
|
+
const previousActiveElement = targetWindow.document.activeElement;
|
|
265
|
+
dismissTimer = targetWindow.setTimeout(() => {
|
|
266
|
+
dismissTimer = void 0;
|
|
267
|
+
const currentActiveElement = targetWindow.document.activeElement;
|
|
268
|
+
if (previousActiveElement && currentActiveElement && previousActiveElement === currentActiveElement) setNavigating(false);
|
|
269
|
+
}, _dismissTimeout);
|
|
270
|
+
};
|
|
271
|
+
const onFocusIn = (e) => {
|
|
272
|
+
if (isMouseOrTouchUsedTimer) return;
|
|
273
|
+
if (isNavigating) return;
|
|
274
|
+
const details = e.detail;
|
|
275
|
+
if (!details.relatedTarget) return;
|
|
276
|
+
if (details.isFocusedProgrammatically || details.isFocusedProgrammatically === void 0) return;
|
|
277
|
+
setNavigating(true);
|
|
278
|
+
};
|
|
279
|
+
const onMouseOrTouch = () => {
|
|
280
|
+
if (currentTargetWindow) {
|
|
281
|
+
if (isMouseOrTouchUsedTimer) currentTargetWindow.clearTimeout(isMouseOrTouchUsedTimer);
|
|
282
|
+
isMouseOrTouchUsedTimer = currentTargetWindow.setTimeout(() => {
|
|
283
|
+
isMouseOrTouchUsedTimer = void 0;
|
|
284
|
+
}, 1e3);
|
|
285
|
+
}
|
|
286
|
+
setNavigating(false);
|
|
287
|
+
};
|
|
288
|
+
const onMouseDown = (e) => {
|
|
289
|
+
if (e.buttons === 0 || e.clientX === 0 && e.clientY === 0 && e.screenX === 0 && e.screenY === 0) return;
|
|
290
|
+
onMouseOrTouch();
|
|
291
|
+
};
|
|
292
|
+
const onKeyDown = (e) => {
|
|
293
|
+
if (isNavigating) {
|
|
294
|
+
if (shouldDismiss(e)) scheduleDismiss();
|
|
295
|
+
} else if (shouldTrigger(e)) setNavigating(true);
|
|
296
|
+
};
|
|
297
|
+
const targetDocument = targetWindow.document;
|
|
298
|
+
addEventListener(targetDocument, KEYBORG_FOCUSIN, onFocusIn);
|
|
299
|
+
addEventListener(targetDocument, "mousedown", onMouseDown);
|
|
300
|
+
addEventListener(targetWindow, "keydown", onKeyDown);
|
|
301
|
+
addEventListener(targetDocument, "touchstart", onMouseOrTouch);
|
|
302
|
+
addEventListener(targetDocument, "touchend", onMouseOrTouch);
|
|
303
|
+
addEventListener(targetDocument, "touchcancel", onMouseOrTouch);
|
|
304
|
+
setupFocusEvent(targetWindow);
|
|
305
|
+
const dispose = () => {
|
|
306
|
+
if (!currentTargetWindow) return;
|
|
307
|
+
if (isMouseOrTouchUsedTimer) {
|
|
308
|
+
currentTargetWindow.clearTimeout(isMouseOrTouchUsedTimer);
|
|
309
|
+
isMouseOrTouchUsedTimer = void 0;
|
|
310
|
+
}
|
|
311
|
+
if (dismissTimer) {
|
|
312
|
+
currentTargetWindow.clearTimeout(dismissTimer);
|
|
313
|
+
dismissTimer = void 0;
|
|
314
|
+
}
|
|
315
|
+
disposeFocusEvent(currentTargetWindow);
|
|
316
|
+
const targetDocument = currentTargetWindow.document;
|
|
317
|
+
removeEventListener(targetDocument, KEYBORG_FOCUSIN, onFocusIn);
|
|
318
|
+
removeEventListener(targetDocument, "mousedown", onMouseDown);
|
|
319
|
+
removeEventListener(currentTargetWindow, "keydown", onKeyDown);
|
|
320
|
+
removeEventListener(targetDocument, "touchstart", onMouseOrTouch);
|
|
321
|
+
removeEventListener(targetDocument, "touchend", onMouseOrTouch);
|
|
322
|
+
removeEventListener(targetDocument, "touchcancel", onMouseOrTouch);
|
|
323
|
+
currentTargetWindow = void 0;
|
|
324
|
+
};
|
|
325
|
+
return {
|
|
326
|
+
dispose,
|
|
327
|
+
getNavigating: () => isNavigating,
|
|
328
|
+
setNavigating
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function createKeyborg(win, props) {
|
|
332
|
+
const kwin = win;
|
|
333
|
+
const id = "k" + ++_lastId;
|
|
334
|
+
let localWin = kwin;
|
|
335
|
+
let core;
|
|
336
|
+
let callbacks = [];
|
|
337
|
+
const existing = kwin.__keyborg;
|
|
338
|
+
if (existing) core = existing.core;
|
|
339
|
+
else core = createKeyborgCore(kwin, props);
|
|
340
|
+
const instance = {
|
|
341
|
+
isNavigatingWithKeyboard() {
|
|
342
|
+
return !!core?.getNavigating();
|
|
343
|
+
},
|
|
344
|
+
subscribe(callback) {
|
|
345
|
+
callbacks.push(callback);
|
|
346
|
+
},
|
|
347
|
+
unsubscribe(callback) {
|
|
348
|
+
const index = callbacks.indexOf(callback);
|
|
349
|
+
if (index >= 0) callbacks.splice(index, 1);
|
|
350
|
+
},
|
|
351
|
+
setVal(val) {
|
|
352
|
+
core?.setNavigating(val);
|
|
353
|
+
},
|
|
354
|
+
_notify(val) {
|
|
355
|
+
callbacks.forEach((cb) => cb(val));
|
|
356
|
+
},
|
|
357
|
+
_dispose() {
|
|
358
|
+
const wkb = localWin?.__keyborg;
|
|
359
|
+
if (wkb?.refs[id]) {
|
|
360
|
+
delete wkb.refs[id];
|
|
361
|
+
if (Object.keys(wkb.refs).length === 0) {
|
|
362
|
+
wkb.core.dispose();
|
|
363
|
+
delete localWin.__keyborg;
|
|
364
|
+
}
|
|
365
|
+
} else if (process.env.NODE_ENV !== "production") console.error(`Keyborg instance ${id} is being disposed incorrectly.`);
|
|
366
|
+
callbacks = [];
|
|
367
|
+
core = void 0;
|
|
368
|
+
localWin = void 0;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
if (existing) existing.refs[id] = instance;
|
|
372
|
+
else kwin.__keyborg = {
|
|
373
|
+
core,
|
|
374
|
+
refs: { [id]: instance }
|
|
375
|
+
};
|
|
376
|
+
return instance;
|
|
377
|
+
}
|
|
378
|
+
function disposeKeyborg(instance) {
|
|
379
|
+
instance._dispose();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
//#endregion
|
|
383
|
+
//#region src/index.mts
|
|
384
|
+
const version = "2.14.0";
|
|
385
|
+
|
|
386
|
+
//#endregion
|
|
387
|
+
exports.KEYBORG_FOCUSIN = KEYBORG_FOCUSIN;
|
|
388
|
+
exports.KEYBORG_FOCUSOUT = KEYBORG_FOCUSOUT;
|
|
389
|
+
exports.createKeyborg = createKeyborg;
|
|
390
|
+
exports.disposeKeyborg = disposeKeyborg;
|
|
391
|
+
exports.getLastFocusedProgrammatically = getLastFocusedProgrammatically;
|
|
392
|
+
exports.nativeFocus = nativeFocus;
|
|
393
|
+
exports.version = version;
|
|
394
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/dom.mts","../src/FocusEvent.mts","../src/Keyborg.mts","../src/index.mts"],"sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// All keyborg listeners use the capture phase; centralizing the calls lets the\n// minifier collapse the repeated DOM method names into a single short-named\n// import binding.\nexport const addEventListener = (\n target: EventTarget,\n type: string,\n handler: EventListener,\n): void => {\n target.addEventListener(type, handler, true);\n};\n\nexport const removeEventListener = (\n target: EventTarget,\n type: string,\n handler: EventListener,\n): void => {\n target.removeEventListener(type, handler, true);\n};\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { addEventListener, removeEventListener } from \"./dom.mts\";\n\nexport const KEYBORG_FOCUSIN = \"keyborg:focusin\";\nexport const KEYBORG_FOCUSOUT = \"keyborg:focusout\";\n\ninterface KeyborgFocus {\n /**\n * This is the native `focus` function that is retained so that it can be restored when keyborg is disposed\n */\n __keyborgNativeFocus?: (options?: FocusOptions | undefined) => void;\n}\n\n// Internal data stored on `window.__keyborgData` as a tuple. Nothing outside\n// this module reads these slots, so a tuple drops the property-name strings\n// from the minified output — the indexes below inline as numeric literals.\nconst FOCUS_IN_HANDLER = 0;\nconst FOCUS_OUT_HANDLER = 1;\nconst SHADOW_TARGETS = 2;\nconst LAST_FOCUSED_PROGRAMMATICALLY = 3;\ntype KeyborgFocusEventData = [\n (e: FocusEvent) => void,\n (e: FocusEvent) => void,\n Set<WeakRef<ShadowRoot>>,\n WeakRef<HTMLElement>?,\n];\n\n/**\n * Extends the global window with keyborg focus event data\n */\ninterface WindowWithKeyborgFocusEvent extends Window {\n HTMLElement: typeof HTMLElement;\n __keyborgData?: KeyborgFocusEventData;\n}\n\nfunction canOverrideNativeFocus(win: Window): boolean {\n const HTMLElement = (win as WindowWithKeyborgFocusEvent).HTMLElement;\n const origFocus = HTMLElement.prototype.focus;\n\n let isCustomFocusCalled = false;\n\n HTMLElement.prototype.focus = function focus(): void {\n isCustomFocusCalled = true;\n };\n\n const btn = win.document.createElement(\"button\");\n\n btn.focus();\n\n HTMLElement.prototype.focus = origFocus;\n\n return isCustomFocusCalled;\n}\n\nlet _canOverrideNativeFocus = false;\n\nexport interface KeyborgFocusInEventDetails {\n relatedTarget?: HTMLElement;\n isFocusedProgrammatically?: boolean;\n originalEvent?: FocusEvent;\n}\n\nexport interface KeyborgFocusInEvent extends CustomEvent<KeyborgFocusInEventDetails> {\n /**\n * @deprecated - used `event.detail`\n */\n details?: KeyborgFocusInEventDetails;\n}\n\nexport interface KeyborgFocusOutEventDetails {\n originalEvent: FocusEvent;\n}\n\nexport type KeyborgFocusOutEvent = CustomEvent<KeyborgFocusOutEventDetails>;\n\n/**\n * Guarantees that the native `focus` will be used\n */\nexport function nativeFocus(element: HTMLElement): void {\n const focus = element.focus as KeyborgFocus;\n\n if (focus.__keyborgNativeFocus) {\n focus.__keyborgNativeFocus.call(element);\n } else {\n element.focus();\n }\n}\n\n/**\n * Overrides the native `focus` and setups the keyborg focus event\n */\nexport function setupFocusEvent(win: Window): void {\n const kwin = win as WindowWithKeyborgFocusEvent;\n const doc = kwin.document;\n const proto = kwin.HTMLElement.prototype;\n\n if (!_canOverrideNativeFocus) {\n _canOverrideNativeFocus = canOverrideNativeFocus(kwin);\n }\n\n const origFocus = proto.focus;\n\n if ((origFocus as KeyborgFocus).__keyborgNativeFocus) {\n // Already set up.\n return;\n }\n\n proto.focus = focus;\n\n const shadowTargets: Set<WeakRef<ShadowRoot>> = new Set();\n\n const focusOutHandler = (e: FocusEvent) => {\n const target = e.target as HTMLElement;\n\n if (!target) {\n return;\n }\n\n const event: KeyborgFocusOutEvent = new CustomEvent(KEYBORG_FOCUSOUT, {\n cancelable: true,\n bubbles: true,\n // Allows the event to bubble past an open shadow root\n composed: true,\n detail: {\n originalEvent: e,\n },\n });\n\n target.dispatchEvent(event);\n };\n\n const focusInHandler = (e: FocusEvent) => {\n const target = e.target as HTMLElement;\n\n if (!target) {\n return;\n }\n\n let node: Node | null | undefined = e.composedPath()[0] as\n | Node\n | null\n | undefined;\n\n const currentShadows: Set<ShadowRoot> = new Set();\n\n while (node) {\n if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n currentShadows.add(node as ShadowRoot);\n node = (node as ShadowRoot).host;\n } else {\n node = node.parentNode;\n }\n }\n\n for (const shadowRootWeakRef of shadowTargets) {\n const shadowRoot = shadowRootWeakRef.deref();\n\n if (!shadowRoot || !currentShadows.has(shadowRoot)) {\n shadowTargets.delete(shadowRootWeakRef);\n\n if (shadowRoot) {\n removeEventListener(shadowRoot, \"focusin\", focusInHandler);\n removeEventListener(shadowRoot, \"focusout\", focusOutHandler);\n }\n }\n }\n\n onFocusIn(target, (e.relatedTarget as HTMLElement | null) || undefined);\n };\n\n const onFocusIn = (\n target: Element,\n relatedTarget?: HTMLElement,\n originalEvent?: FocusEvent,\n ) => {\n const shadowRoot = target.shadowRoot;\n\n if (shadowRoot) {\n /**\n * https://bugs.chromium.org/p/chromium/issues/detail?id=1512028\n * focusin events don't bubble up through an open shadow root once focus is inside\n * once focus moves into a shadow root - we drop the same focusin handler there\n * keyborg's custom event will still bubble up since it is composed\n * event handlers should be cleaned up once focus leaves the shadow root.\n *\n * When a focusin event is dispatched from a shadow root, its target is the shadow root parent.\n * Each shadow root encounter requires a new capture listener.\n * Why capture? - we want to follow the focus event in order or descending nested shadow roots\n * When there are no more shadow root targets - dispatch the keyborg:focusin event\n *\n * 1. no focus event\n * > document - capture listener ✅\n * > shadow root 1\n * > shadow root 2\n * > shadow root 3\n * > focused element\n *\n * 2. focus event received by document listener\n * > document - capture listener ✅ (focus event here)\n * > shadow root 1 - capture listener ✅\n * > shadow root 2\n * > shadow root 3\n * > focused element\n *\n * 3. focus event received by root l1 listener\n * > document - capture listener ✅\n * > shadow root 1 - capture listener ✅ (focus event here)\n * > shadow root 2 - capture listener ✅\n * > shadow root 3\n * > focused element\n *\n * 4. focus event received by root l2 listener\n * > document - capture listener ✅\n * > shadow root 1 - capture listener ✅\n * > shadow root 2 - capture listener ✅ (focus event here)\n * > shadow root 3 - capture listener ✅\n * > focused element\n *\n * 5. focus event received by root l3 listener, no more shadow root targets\n * > document - capture listener ✅\n * > shadow root 1 - capture listener ✅\n * > shadow root 2 - capture listener ✅\n * > shadow root 3 - capture listener ✅ (focus event here)\n * > focused element ✅ (no shadow root - dispatch keyborg event)\n */\n\n for (const shadowRootWeakRef of shadowTargets) {\n if (shadowRootWeakRef.deref() === shadowRoot) {\n return;\n }\n }\n\n addEventListener(shadowRoot, \"focusin\", focusInHandler);\n addEventListener(shadowRoot, \"focusout\", focusOutHandler);\n\n shadowTargets.add(new WeakRef(shadowRoot));\n\n return;\n }\n\n const details: KeyborgFocusInEventDetails = {\n relatedTarget,\n originalEvent,\n };\n\n const event: KeyborgFocusInEvent = new CustomEvent(KEYBORG_FOCUSIN, {\n cancelable: true,\n bubbles: true,\n // Allows the event to bubble past an open shadow root\n composed: true,\n detail: details,\n });\n\n // Tabster (and other users) can still use the legacy details field - keeping for backwards compat\n event.details = details;\n\n if (_canOverrideNativeFocus || data[LAST_FOCUSED_PROGRAMMATICALLY]) {\n details.isFocusedProgrammatically =\n target === data[LAST_FOCUSED_PROGRAMMATICALLY]?.deref();\n\n data[LAST_FOCUSED_PROGRAMMATICALLY] = undefined;\n }\n\n target.dispatchEvent(event);\n };\n\n const data: KeyborgFocusEventData = [\n focusInHandler,\n focusOutHandler,\n shadowTargets,\n ];\n kwin.__keyborgData = data;\n\n addEventListener(doc, \"focusin\", focusInHandler);\n addEventListener(doc, \"focusout\", focusOutHandler);\n\n function focus(this: HTMLElement) {\n const d = (kwin as WindowWithKeyborgFocusEvent).__keyborgData;\n\n if (d) {\n d[LAST_FOCUSED_PROGRAMMATICALLY] = new WeakRef(this);\n }\n\n // eslint-disable-next-line prefer-rest-params\n return origFocus.apply(this, arguments);\n }\n\n let activeElement = doc.activeElement as Element | null;\n\n // If keyborg is created with the focus inside shadow root, we need\n // to go through the shadows up to make sure all relevant shadows\n // have focus handlers attached.\n while (activeElement && activeElement.shadowRoot) {\n onFocusIn(activeElement);\n activeElement = activeElement.shadowRoot.activeElement;\n }\n\n (focus as KeyborgFocus).__keyborgNativeFocus = origFocus;\n}\n\n/**\n * Removes keyborg event listeners and custom focus override\n * @param win The window that stores keyborg focus events\n */\nexport function disposeFocusEvent(win: Window): void {\n const kwin = win as WindowWithKeyborgFocusEvent;\n const proto = kwin.HTMLElement.prototype;\n const origFocus = (proto.focus as KeyborgFocus).__keyborgNativeFocus;\n const data = kwin.__keyborgData;\n\n if (data) {\n const doc = kwin.document;\n removeEventListener(doc, \"focusin\", data[FOCUS_IN_HANDLER]);\n removeEventListener(doc, \"focusout\", data[FOCUS_OUT_HANDLER]);\n\n for (const shadowRootWeakRef of data[SHADOW_TARGETS]) {\n const shadowRoot = shadowRootWeakRef.deref();\n\n if (shadowRoot) {\n removeEventListener(shadowRoot, \"focusin\", data[FOCUS_IN_HANDLER]);\n removeEventListener(shadowRoot, \"focusout\", data[FOCUS_OUT_HANDLER]);\n }\n }\n\n data[SHADOW_TARGETS].clear();\n\n delete kwin.__keyborgData;\n }\n\n if (origFocus) {\n proto.focus = origFocus;\n }\n}\n\n/**\n * @param win The window that stores keyborg focus events\n * @returns The last element focused with element.focus()\n */\nexport function getLastFocusedProgrammatically(\n win: Window,\n): HTMLElement | null | undefined {\n const data = (win as WindowWithKeyborgFocusEvent).__keyborgData;\n\n return data\n ? data[LAST_FOCUSED_PROGRAMMATICALLY]?.deref() || null\n : undefined;\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { addEventListener, removeEventListener } from \"./dom.mts\";\nimport {\n disposeFocusEvent,\n KeyborgFocusInEvent,\n KEYBORG_FOCUSIN,\n setupFocusEvent,\n} from \"./FocusEvent.mts\";\n\ninterface WindowWithKeyborg extends Window {\n __keyborg?: {\n core: KeyborgCoreHandle;\n refs: { [id: string]: Keyborg };\n };\n}\n\n// When a key from dismissKeys is pressed and the focus is not moved during\n// _dismissTimeout ms, keyboard navigation mode is dismissed.\nconst _dismissTimeout = 500;\n\nlet _lastId = 0;\n\nexport interface KeyborgProps {\n // Keys to be used to trigger keyboard navigation mode. By default, any key\n // will trigger it. Could be limited to, for example, just Tab (or Tab and\n // arrow keys).\n triggerKeys?: number[];\n // Keys to be used to dismiss keyboard navigation mode using keyboard (in\n // addition to mouse clicks which dismiss it). For example, Esc could be used\n // to dismiss.\n dismissKeys?: number[];\n}\n\nexport type KeyborgCallback = (isNavigatingWithKeyboard: boolean) => void;\n\n/**\n * Internal handle for the per-window core state. Not part of the public API.\n */\ninterface KeyborgCoreHandle {\n dispose(): void;\n getNavigating(): boolean;\n setNavigating(val: boolean): void;\n}\n\n/**\n * Used to determine the keyboard navigation state.\n */\nexport interface Keyborg {\n /**\n * @returns Whether the user is navigating with keyboard\n */\n isNavigatingWithKeyboard(): boolean;\n /**\n * @param callback - Called when the keyboard navigation state changes\n */\n subscribe(callback: KeyborgCallback): void;\n /**\n * @param callback - Registered with subscribe\n */\n unsubscribe(callback: KeyborgCallback): void;\n /**\n * Manually set the keyboard navigation state\n */\n setVal(isNavigatingWithKeyboard: boolean): void;\n}\n\n// Augments the public Keyborg with internal methods invoked by the core's\n// broadcast loop and by disposeKeyborg. Not exported.\ninterface KeyborgInternal extends Keyborg {\n _notify(isNavigatingWithKeyboard: boolean): void;\n _dispose(): void;\n}\n\nfunction createKeyborgCore(\n targetWindow: WindowWithKeyborg,\n props?: KeyborgProps,\n): KeyborgCoreHandle {\n let currentTargetWindow: WindowWithKeyborg | undefined = targetWindow;\n let isNavigating = false;\n let isMouseOrTouchUsedTimer: number | undefined;\n let dismissTimer: number | undefined;\n let triggerKeys: Set<number> | undefined;\n let dismissKeys: Set<number> | undefined;\n\n if (props) {\n if (props.triggerKeys?.length) {\n triggerKeys = new Set(props.triggerKeys);\n }\n if (props.dismissKeys?.length) {\n dismissKeys = new Set(props.dismissKeys);\n }\n }\n\n const broadcast = (): void => {\n const refs = currentTargetWindow?.__keyborg?.refs;\n if (refs) {\n for (const id of Object.keys(refs)) {\n (refs[id] as KeyborgInternal)._notify(isNavigating);\n }\n }\n };\n\n const setNavigating = (val: boolean): void => {\n if (isNavigating !== val) {\n isNavigating = val;\n broadcast();\n }\n };\n\n const shouldTrigger = (e: KeyboardEvent): boolean => {\n // TODO Some rich text fields can allow Tab key for indentation so it\n // doesn't need to be a navigation key. If there is a bug regarding that\n // we should revisit.\n if (e.key === \"Tab\") {\n return true;\n }\n const active = currentTargetWindow?.document\n .activeElement as HTMLElement | null;\n const isTriggerKey = !triggerKeys || triggerKeys.has(e.keyCode);\n const isEditable =\n active &&\n (active.tagName === \"INPUT\" ||\n active.tagName === \"TEXTAREA\" ||\n active.isContentEditable);\n return isTriggerKey && !isEditable;\n };\n\n const shouldDismiss = (e: KeyboardEvent): boolean => {\n return !!dismissKeys?.has(e.keyCode);\n };\n\n const scheduleDismiss = (): void => {\n const targetWindow = currentTargetWindow;\n if (!targetWindow) {\n return;\n }\n if (dismissTimer) {\n targetWindow.clearTimeout(dismissTimer);\n dismissTimer = undefined;\n }\n const previousActiveElement = targetWindow.document.activeElement;\n dismissTimer = targetWindow.setTimeout(() => {\n dismissTimer = undefined;\n const currentActiveElement = targetWindow.document.activeElement;\n if (\n previousActiveElement &&\n currentActiveElement &&\n previousActiveElement === currentActiveElement\n ) {\n // Esc was pressed, currently focused element hasn't changed.\n // Just dismiss the keyboard navigation mode.\n setNavigating(false);\n }\n }, _dismissTimeout);\n };\n\n const onFocusIn = (e: KeyborgFocusInEvent): void => {\n // When the focus is moved not programmatically and without keydown events,\n // it is likely that the focus is moved by screen reader (as it might\n // swallow the events when the screen reader shortcuts are used). The\n // screen reader usage is keyboard navigation.\n if (isMouseOrTouchUsedTimer) {\n return;\n }\n if (isNavigating) {\n return;\n }\n const details = e.detail;\n if (!details.relatedTarget) {\n return;\n }\n if (\n details.isFocusedProgrammatically ||\n details.isFocusedProgrammatically === undefined\n ) {\n return;\n }\n setNavigating(true);\n };\n\n const onMouseOrTouch = (): void => {\n if (currentTargetWindow) {\n if (isMouseOrTouchUsedTimer) {\n currentTargetWindow.clearTimeout(isMouseOrTouchUsedTimer);\n }\n isMouseOrTouchUsedTimer = currentTargetWindow.setTimeout(() => {\n isMouseOrTouchUsedTimer = undefined;\n }, 1000);\n }\n setNavigating(false);\n };\n\n const onMouseDown = (e: MouseEvent): void => {\n if (\n e.buttons === 0 ||\n (e.clientX === 0 && e.clientY === 0 && e.screenX === 0 && e.screenY === 0)\n ) {\n // This is most likely an event triggered by the screen reader to\n // perform an action on an element, do not dismiss the keyboard\n // navigation mode.\n return;\n }\n onMouseOrTouch();\n };\n\n const onKeyDown = (e: KeyboardEvent): void => {\n if (isNavigating) {\n if (shouldDismiss(e)) {\n scheduleDismiss();\n }\n } else if (shouldTrigger(e)) {\n setNavigating(true);\n }\n };\n\n const targetDocument = targetWindow.document;\n addEventListener(targetDocument, KEYBORG_FOCUSIN, onFocusIn as EventListener);\n addEventListener(targetDocument, \"mousedown\", onMouseDown as EventListener);\n addEventListener(targetWindow, \"keydown\", onKeyDown as EventListener);\n addEventListener(targetDocument, \"touchstart\", onMouseOrTouch);\n addEventListener(targetDocument, \"touchend\", onMouseOrTouch);\n addEventListener(targetDocument, \"touchcancel\", onMouseOrTouch);\n\n setupFocusEvent(targetWindow);\n\n const dispose = (): void => {\n if (!currentTargetWindow) {\n return;\n }\n if (isMouseOrTouchUsedTimer) {\n currentTargetWindow.clearTimeout(isMouseOrTouchUsedTimer);\n isMouseOrTouchUsedTimer = undefined;\n }\n if (dismissTimer) {\n currentTargetWindow.clearTimeout(dismissTimer);\n dismissTimer = undefined;\n }\n disposeFocusEvent(currentTargetWindow);\n const targetDocument = currentTargetWindow.document;\n removeEventListener(\n targetDocument,\n KEYBORG_FOCUSIN,\n onFocusIn as EventListener,\n );\n removeEventListener(\n targetDocument,\n \"mousedown\",\n onMouseDown as EventListener,\n );\n removeEventListener(\n currentTargetWindow,\n \"keydown\",\n onKeyDown as EventListener,\n );\n removeEventListener(targetDocument, \"touchstart\", onMouseOrTouch);\n removeEventListener(targetDocument, \"touchend\", onMouseOrTouch);\n removeEventListener(targetDocument, \"touchcancel\", onMouseOrTouch);\n currentTargetWindow = undefined;\n };\n\n return {\n dispose,\n getNavigating: () => isNavigating,\n setNavigating,\n };\n}\n\nexport function createKeyborg(win: Window, props?: KeyborgProps): Keyborg {\n const kwin = win as WindowWithKeyborg;\n const id = \"k\" + ++_lastId;\n let localWin: WindowWithKeyborg | undefined = kwin;\n let core: KeyborgCoreHandle | undefined;\n let callbacks: KeyborgCallback[] = [];\n\n const existing = kwin.__keyborg;\n if (existing) {\n core = existing.core;\n } else {\n core = createKeyborgCore(kwin, props);\n }\n\n const instance: KeyborgInternal = {\n isNavigatingWithKeyboard() {\n return !!core?.getNavigating();\n },\n subscribe(callback) {\n callbacks.push(callback);\n },\n unsubscribe(callback) {\n const index = callbacks.indexOf(callback);\n if (index >= 0) {\n callbacks.splice(index, 1);\n }\n },\n setVal(val) {\n core?.setNavigating(val);\n },\n _notify(val) {\n callbacks.forEach((cb) => cb(val));\n },\n _dispose() {\n const wkb = localWin?.__keyborg;\n if (wkb?.refs[id]) {\n delete wkb.refs[id];\n if (Object.keys(wkb.refs).length === 0) {\n wkb.core.dispose();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n delete localWin!.__keyborg;\n }\n } else if (process.env.NODE_ENV !== \"production\") {\n console.error(`Keyborg instance ${id} is being disposed incorrectly.`);\n }\n callbacks = [];\n core = undefined;\n localWin = undefined;\n },\n };\n\n if (existing) {\n existing.refs[id] = instance;\n } else {\n kwin.__keyborg = {\n core,\n refs: { [id]: instance },\n };\n }\n\n return instance;\n}\n\nexport function disposeKeyborg(instance: Keyborg): void {\n (instance as KeyborgInternal)._dispose();\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport type { Keyborg, KeyborgCallback } from \"./Keyborg.mts\";\nexport { createKeyborg, disposeKeyborg } from \"./Keyborg.mts\";\n\nexport type {\n KeyborgFocusInEvent,\n KeyborgFocusInEventDetails,\n KeyborgFocusOutEvent,\n KeyborgFocusOutEventDetails,\n} from \"./FocusEvent.mts\";\nexport {\n getLastFocusedProgrammatically,\n nativeFocus,\n KEYBORG_FOCUSIN,\n KEYBORG_FOCUSOUT,\n} from \"./FocusEvent.mts\";\n\nexport const version = process.env.PKG_VERSION;\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//#region src/Keyborg.d.mts
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
interface KeyborgProps {
|
|
7
|
+
triggerKeys?: number[];
|
|
8
|
+
dismissKeys?: number[];
|
|
9
|
+
}
|
|
10
|
+
type KeyborgCallback = (isNavigatingWithKeyboard: boolean) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Used to determine the keyboard navigation state.
|
|
13
|
+
*/
|
|
14
|
+
interface Keyborg {
|
|
15
|
+
/**
|
|
16
|
+
* @returns Whether the user is navigating with keyboard
|
|
17
|
+
*/
|
|
18
|
+
isNavigatingWithKeyboard(): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* @param callback - Called when the keyboard navigation state changes
|
|
21
|
+
*/
|
|
22
|
+
subscribe(callback: KeyborgCallback): void;
|
|
23
|
+
/**
|
|
24
|
+
* @param callback - Registered with subscribe
|
|
25
|
+
*/
|
|
26
|
+
unsubscribe(callback: KeyborgCallback): void;
|
|
27
|
+
/**
|
|
28
|
+
* Manually set the keyboard navigation state
|
|
29
|
+
*/
|
|
30
|
+
setVal(isNavigatingWithKeyboard: boolean): void;
|
|
31
|
+
}
|
|
32
|
+
declare function createKeyborg(win: Window, props?: KeyborgProps): Keyborg;
|
|
33
|
+
declare function disposeKeyborg(instance: Keyborg): void;
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/FocusEvent.d.mts
|
|
36
|
+
/*!
|
|
37
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
38
|
+
* Licensed under the MIT License.
|
|
39
|
+
*/
|
|
40
|
+
declare const KEYBORG_FOCUSIN = "keyborg:focusin";
|
|
41
|
+
declare const KEYBORG_FOCUSOUT = "keyborg:focusout";
|
|
42
|
+
interface KeyborgFocusInEventDetails {
|
|
43
|
+
relatedTarget?: HTMLElement;
|
|
44
|
+
isFocusedProgrammatically?: boolean;
|
|
45
|
+
originalEvent?: FocusEvent;
|
|
46
|
+
}
|
|
47
|
+
interface KeyborgFocusInEvent extends CustomEvent<KeyborgFocusInEventDetails> {
|
|
48
|
+
/**
|
|
49
|
+
* @deprecated - used `event.detail`
|
|
50
|
+
*/
|
|
51
|
+
details?: KeyborgFocusInEventDetails;
|
|
52
|
+
}
|
|
53
|
+
interface KeyborgFocusOutEventDetails {
|
|
54
|
+
originalEvent: FocusEvent;
|
|
55
|
+
}
|
|
56
|
+
type KeyborgFocusOutEvent = CustomEvent<KeyborgFocusOutEventDetails>;
|
|
57
|
+
/**
|
|
58
|
+
* Guarantees that the native `focus` will be used
|
|
59
|
+
*/
|
|
60
|
+
declare function nativeFocus(element: HTMLElement): void;
|
|
61
|
+
/**
|
|
62
|
+
* @param win The window that stores keyborg focus events
|
|
63
|
+
* @returns The last element focused with element.focus()
|
|
64
|
+
*/
|
|
65
|
+
declare function getLastFocusedProgrammatically(win: Window): HTMLElement | null | undefined;
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/index.d.mts
|
|
68
|
+
declare const version: string | undefined;
|
|
69
|
+
//#endregion
|
|
70
|
+
export { KEYBORG_FOCUSIN, KEYBORG_FOCUSOUT, type Keyborg, type KeyborgCallback, type KeyborgFocusInEvent, type KeyborgFocusInEventDetails, type KeyborgFocusOutEvent, type KeyborgFocusOutEventDetails, createKeyborg, disposeKeyborg, getLastFocusedProgrammatically, nativeFocus, version };
|
|
71
|
+
//# sourceMappingURL=index.d.cts.map
|