keyborg 2.325.0-canary.0 → 3.0.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 ADDED
@@ -0,0 +1,347 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/dom.mts
3
+ /*!
4
+ * Copyright (c) Microsoft Corporation. All rights reserved.
5
+ * Licensed under the MIT License.
6
+ */
7
+ const addEventListener = (target, type, handler) => {
8
+ target.addEventListener(type, handler, true);
9
+ };
10
+ const removeEventListener = (target, type, handler) => {
11
+ target.removeEventListener(type, handler, true);
12
+ };
13
+ //#endregion
14
+ //#region src/FocusEvent.mts
15
+ /*!
16
+ * Copyright (c) Microsoft Corporation. All rights reserved.
17
+ * Licensed under the MIT License.
18
+ */
19
+ const KEYBORG_FOCUSIN = "keyborg:focusin";
20
+ const KEYBORG_FOCUSOUT = "keyborg:focusout";
21
+ const FOCUS_IN_HANDLER = 0;
22
+ const FOCUS_OUT_HANDLER = 1;
23
+ const SHADOW_TARGETS = 2;
24
+ const LAST_FOCUSED_PROGRAMMATICALLY = 3;
25
+ /**
26
+ * Guarantees that the native `focus` will be used
27
+ */
28
+ function nativeFocus(element) {
29
+ const focus = element.focus;
30
+ if (focus.__keyborgNativeFocus) focus.__keyborgNativeFocus.call(element);
31
+ else element.focus();
32
+ }
33
+ /**
34
+ * Overrides the native `focus` and setups the keyborg focus event
35
+ */
36
+ function setupFocusEvent(win) {
37
+ const kwin = win;
38
+ const doc = kwin.document;
39
+ const proto = kwin.HTMLElement.prototype;
40
+ const origFocus = proto.focus;
41
+ if (origFocus.__keyborgNativeFocus) return;
42
+ proto.focus = focus;
43
+ const shadowTargets = /* @__PURE__ */ new Set();
44
+ const focusOutHandler = (e) => {
45
+ const target = e.target;
46
+ if (!target) return;
47
+ const event = new CustomEvent(KEYBORG_FOCUSOUT, {
48
+ cancelable: true,
49
+ bubbles: true,
50
+ composed: true,
51
+ detail: { originalEvent: e }
52
+ });
53
+ target.dispatchEvent(event);
54
+ };
55
+ const focusInHandler = (e) => {
56
+ const target = e.target;
57
+ if (!target) return;
58
+ let node = e.composedPath()[0];
59
+ const currentShadows = /* @__PURE__ */ new Set();
60
+ while (node) if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
61
+ currentShadows.add(node);
62
+ node = node.host;
63
+ } else node = node.parentNode;
64
+ for (const shadowRootWeakRef of shadowTargets) {
65
+ const shadowRoot = shadowRootWeakRef.deref();
66
+ if (!shadowRoot || !currentShadows.has(shadowRoot)) {
67
+ shadowTargets.delete(shadowRootWeakRef);
68
+ if (shadowRoot) {
69
+ removeEventListener(shadowRoot, "focusin", focusInHandler);
70
+ removeEventListener(shadowRoot, "focusout", focusOutHandler);
71
+ }
72
+ }
73
+ }
74
+ onFocusIn(target, e.relatedTarget || void 0);
75
+ };
76
+ const onFocusIn = (target, relatedTarget, originalEvent) => {
77
+ const shadowRoot = target.shadowRoot;
78
+ if (shadowRoot) {
79
+ /**
80
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=1512028
81
+ * focusin events don't bubble up through an open shadow root once focus is inside
82
+ * once focus moves into a shadow root - we drop the same focusin handler there
83
+ * keyborg's custom event will still bubble up since it is composed
84
+ * event handlers should be cleaned up once focus leaves the shadow root.
85
+ *
86
+ * When a focusin event is dispatched from a shadow root, its target is the shadow root parent.
87
+ * Each shadow root encounter requires a new capture listener.
88
+ * Why capture? - we want to follow the focus event in order or descending nested shadow roots
89
+ * When there are no more shadow root targets - dispatch the keyborg:focusin event
90
+ *
91
+ * 1. no focus event
92
+ * > document - capture listener ✅
93
+ * > shadow root 1
94
+ * > shadow root 2
95
+ * > shadow root 3
96
+ * > focused element
97
+ *
98
+ * 2. focus event received by document listener
99
+ * > document - capture listener ✅ (focus event here)
100
+ * > shadow root 1 - capture listener ✅
101
+ * > shadow root 2
102
+ * > shadow root 3
103
+ * > focused element
104
+ *
105
+ * 3. focus event received by root l1 listener
106
+ * > document - capture listener ✅
107
+ * > shadow root 1 - capture listener ✅ (focus event here)
108
+ * > shadow root 2 - capture listener ✅
109
+ * > shadow root 3
110
+ * > focused element
111
+ *
112
+ * 4. focus event received by root l2 listener
113
+ * > document - capture listener ✅
114
+ * > shadow root 1 - capture listener ✅
115
+ * > shadow root 2 - capture listener ✅ (focus event here)
116
+ * > shadow root 3 - capture listener ✅
117
+ * > focused element
118
+ *
119
+ * 5. focus event received by root l3 listener, no more shadow root targets
120
+ * > document - capture listener ✅
121
+ * > shadow root 1 - capture listener ✅
122
+ * > shadow root 2 - capture listener ✅
123
+ * > shadow root 3 - capture listener ✅ (focus event here)
124
+ * > focused element ✅ (no shadow root - dispatch keyborg event)
125
+ */
126
+ for (const shadowRootWeakRef of shadowTargets) if (shadowRootWeakRef.deref() === shadowRoot) return;
127
+ addEventListener(shadowRoot, "focusin", focusInHandler);
128
+ addEventListener(shadowRoot, "focusout", focusOutHandler);
129
+ shadowTargets.add(new WeakRef(shadowRoot));
130
+ return;
131
+ }
132
+ const details = {
133
+ relatedTarget,
134
+ originalEvent
135
+ };
136
+ const event = new CustomEvent(KEYBORG_FOCUSIN, {
137
+ cancelable: true,
138
+ bubbles: true,
139
+ composed: true,
140
+ detail: details
141
+ });
142
+ details.isFocusedProgrammatically = target === data[LAST_FOCUSED_PROGRAMMATICALLY]?.deref();
143
+ data[LAST_FOCUSED_PROGRAMMATICALLY] = void 0;
144
+ target.dispatchEvent(event);
145
+ };
146
+ const data = [
147
+ focusInHandler,
148
+ focusOutHandler,
149
+ shadowTargets
150
+ ];
151
+ kwin.__keyborgData = data;
152
+ addEventListener(doc, "focusin", focusInHandler);
153
+ addEventListener(doc, "focusout", focusOutHandler);
154
+ function focus() {
155
+ const d = kwin.__keyborgData;
156
+ if (d) d[LAST_FOCUSED_PROGRAMMATICALLY] = new WeakRef(this);
157
+ return origFocus.apply(this, arguments);
158
+ }
159
+ let activeElement = doc.activeElement;
160
+ while (activeElement && activeElement.shadowRoot) {
161
+ onFocusIn(activeElement);
162
+ activeElement = activeElement.shadowRoot.activeElement;
163
+ }
164
+ focus.__keyborgNativeFocus = origFocus;
165
+ }
166
+ /**
167
+ * Removes keyborg event listeners and custom focus override
168
+ * @param win The window that stores keyborg focus events
169
+ */
170
+ function disposeFocusEvent(win) {
171
+ const kwin = win;
172
+ const proto = kwin.HTMLElement.prototype;
173
+ const origFocus = proto.focus.__keyborgNativeFocus;
174
+ const data = kwin.__keyborgData;
175
+ if (data) {
176
+ const doc = kwin.document;
177
+ removeEventListener(doc, "focusin", data[FOCUS_IN_HANDLER]);
178
+ removeEventListener(doc, "focusout", data[FOCUS_OUT_HANDLER]);
179
+ for (const shadowRootWeakRef of data[SHADOW_TARGETS]) {
180
+ const shadowRoot = shadowRootWeakRef.deref();
181
+ if (shadowRoot) {
182
+ removeEventListener(shadowRoot, "focusin", data[FOCUS_IN_HANDLER]);
183
+ removeEventListener(shadowRoot, "focusout", data[FOCUS_OUT_HANDLER]);
184
+ }
185
+ }
186
+ data[SHADOW_TARGETS].clear();
187
+ delete kwin.__keyborgData;
188
+ }
189
+ if (origFocus) proto.focus = origFocus;
190
+ }
191
+ /**
192
+ * @param win The window that stores keyborg focus events
193
+ * @returns The last element focused with element.focus()
194
+ */
195
+ function getLastFocusedProgrammatically(win) {
196
+ const data = win.__keyborgData;
197
+ return data ? data[LAST_FOCUSED_PROGRAMMATICALLY]?.deref() || null : void 0;
198
+ }
199
+ //#endregion
200
+ //#region src/Keyborg.mts
201
+ /*!
202
+ * Copyright (c) Microsoft Corporation. All rights reserved.
203
+ * Licensed under the MIT License.
204
+ */
205
+ let _lastId = 0;
206
+ function createKeyborgCore(targetWindow) {
207
+ let currentTargetWindow = targetWindow;
208
+ let isNavigating = false;
209
+ let isMouseOrTouchUsedTimer;
210
+ const broadcast = () => {
211
+ const refs = currentTargetWindow?.__keyborg?.refs;
212
+ if (refs) for (const id of Object.keys(refs)) refs[id]._cb.forEach((cb) => cb(isNavigating));
213
+ };
214
+ const setNavigating = (val) => {
215
+ if (isNavigating !== val) {
216
+ isNavigating = val;
217
+ broadcast();
218
+ }
219
+ };
220
+ const shouldTrigger = (e) => {
221
+ if (e.key === "Tab") return true;
222
+ const active = currentTargetWindow?.document.activeElement;
223
+ return !(active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA" || active.isContentEditable));
224
+ };
225
+ const onFocusIn = (e) => {
226
+ if (isMouseOrTouchUsedTimer) return;
227
+ if (isNavigating) return;
228
+ const details = e.detail;
229
+ if (!details.relatedTarget) return;
230
+ if (details.isFocusedProgrammatically || details.isFocusedProgrammatically === void 0) return;
231
+ setNavigating(true);
232
+ };
233
+ const onMouseOrTouch = () => {
234
+ if (currentTargetWindow) {
235
+ if (isMouseOrTouchUsedTimer) currentTargetWindow.clearTimeout(isMouseOrTouchUsedTimer);
236
+ isMouseOrTouchUsedTimer = currentTargetWindow.setTimeout(() => {
237
+ isMouseOrTouchUsedTimer = void 0;
238
+ }, 1e3);
239
+ }
240
+ setNavigating(false);
241
+ };
242
+ const onMouseDown = (e) => {
243
+ if (e.buttons === 0 || e.clientX === 0 && e.clientY === 0 && e.screenX === 0 && e.screenY === 0) return;
244
+ onMouseOrTouch();
245
+ };
246
+ const onKeyDown = (e) => {
247
+ if (!isNavigating && shouldTrigger(e)) setNavigating(true);
248
+ };
249
+ const targetDocument = targetWindow.document;
250
+ addEventListener(targetDocument, KEYBORG_FOCUSIN, onFocusIn);
251
+ addEventListener(targetDocument, "mousedown", onMouseDown);
252
+ addEventListener(targetWindow, "keydown", onKeyDown);
253
+ addEventListener(targetDocument, "touchstart", onMouseOrTouch);
254
+ addEventListener(targetDocument, "touchend", onMouseOrTouch);
255
+ addEventListener(targetDocument, "touchcancel", onMouseOrTouch);
256
+ setupFocusEvent(targetWindow);
257
+ const dispose = () => {
258
+ if (!currentTargetWindow) return;
259
+ if (isMouseOrTouchUsedTimer) {
260
+ currentTargetWindow.clearTimeout(isMouseOrTouchUsedTimer);
261
+ isMouseOrTouchUsedTimer = void 0;
262
+ }
263
+ disposeFocusEvent(currentTargetWindow);
264
+ const targetDocument = currentTargetWindow.document;
265
+ removeEventListener(targetDocument, KEYBORG_FOCUSIN, onFocusIn);
266
+ removeEventListener(targetDocument, "mousedown", onMouseDown);
267
+ removeEventListener(currentTargetWindow, "keydown", onKeyDown);
268
+ removeEventListener(targetDocument, "touchstart", onMouseOrTouch);
269
+ removeEventListener(targetDocument, "touchend", onMouseOrTouch);
270
+ removeEventListener(targetDocument, "touchcancel", onMouseOrTouch);
271
+ currentTargetWindow = void 0;
272
+ };
273
+ return {
274
+ dispose,
275
+ get isNavigatingWithKeyboard() {
276
+ return isNavigating;
277
+ },
278
+ set isNavigatingWithKeyboard(val) {
279
+ setNavigating(val);
280
+ }
281
+ };
282
+ }
283
+ function createKeyborg(win) {
284
+ const kwin = win;
285
+ const id = "k" + ++_lastId;
286
+ let localWin = kwin;
287
+ let core;
288
+ const callbacks = [];
289
+ const existing = kwin.__keyborg;
290
+ if (existing) core = existing.core;
291
+ else core = createKeyborgCore(kwin);
292
+ const instance = {
293
+ isNavigatingWithKeyboard() {
294
+ return !!core?.isNavigatingWithKeyboard;
295
+ },
296
+ subscribe(callback) {
297
+ callbacks.push(callback);
298
+ },
299
+ unsubscribe(callback) {
300
+ const index = callbacks.indexOf(callback);
301
+ if (index >= 0) callbacks.splice(index, 1);
302
+ },
303
+ setVal(val) {
304
+ if (core) core.isNavigatingWithKeyboard = val;
305
+ },
306
+ _cb: callbacks,
307
+ dispose() {
308
+ const wkb = localWin?.__keyborg;
309
+ if (wkb?.refs[id]) {
310
+ delete wkb.refs[id];
311
+ if (Object.keys(wkb.refs).length === 0) {
312
+ wkb.core.dispose();
313
+ delete localWin.__keyborg;
314
+ }
315
+ } else if (process.env.NODE_ENV !== "production") console.error(`Keyborg instance ${id} is being disposed incorrectly.`);
316
+ callbacks.length = 0;
317
+ core = void 0;
318
+ localWin = void 0;
319
+ }
320
+ };
321
+ if (existing) existing.refs[id] = instance;
322
+ else kwin.__keyborg = {
323
+ core,
324
+ refs: { [id]: instance }
325
+ };
326
+ return instance;
327
+ }
328
+ function disposeKeyborg(instance) {
329
+ instance.dispose();
330
+ }
331
+ //#endregion
332
+ //#region src/index.mts
333
+ /*!
334
+ * Copyright (c) Microsoft Corporation. All rights reserved.
335
+ * Licensed under the MIT License.
336
+ */
337
+ const version = "3.0.0";
338
+ //#endregion
339
+ exports.KEYBORG_FOCUSIN = KEYBORG_FOCUSIN;
340
+ exports.KEYBORG_FOCUSOUT = KEYBORG_FOCUSOUT;
341
+ exports.createKeyborg = createKeyborg;
342
+ exports.disposeKeyborg = disposeKeyborg;
343
+ exports.getLastFocusedProgrammatically = getLastFocusedProgrammatically;
344
+ exports.nativeFocus = nativeFocus;
345
+ exports.version = version;
346
+
347
+ //# 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\nexport interface KeyborgFocusInEventDetails {\n relatedTarget?: HTMLElement;\n isFocusedProgrammatically?: boolean;\n originalEvent?: FocusEvent;\n}\n\nexport type KeyborgFocusInEvent = CustomEvent<KeyborgFocusInEventDetails>;\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 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 details.isFocusedProgrammatically =\n target === data[LAST_FOCUSED_PROGRAMMATICALLY]?.deref();\n\n data[LAST_FOCUSED_PROGRAMMATICALLY] = undefined;\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\nlet _lastId = 0;\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 *\n * Shape is part of the `__keyborg.core` slot contract: when multiple keyborg\n * majors share the same window, the second loader reads `core` set by the\n * first. Keep `isNavigatingWithKeyboard` as a writable property accessor and\n * `dispose()` as a method so older majors can still read/write state without\n * TypeError. Changes here are breaking for that interop.\n */\ninterface KeyborgCoreHandle {\n isNavigatingWithKeyboard: boolean;\n dispose(): 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 members that also form the\n// `__keyborg.refs` slot wire protocol. The shape — `_cb` callback array and\n// `dispose()` method — matches keyborg <= 2.6.0's `Keyborg` class so that\n// mixed-version environments can broadcast and tear down each other's\n// instances without TypeError. Changes here are breaking for that interop.\ninterface KeyborgInternal extends Keyborg {\n _cb: KeyborgCallback[];\n dispose(): void;\n}\n\nfunction createKeyborgCore(targetWindow: WindowWithKeyborg): KeyborgCoreHandle {\n let currentTargetWindow: WindowWithKeyborg | undefined = targetWindow;\n let isNavigating = false;\n let isMouseOrTouchUsedTimer: number | undefined;\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)._cb.forEach((cb) => cb(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 isEditable =\n active &&\n (active.tagName === \"INPUT\" ||\n active.tagName === \"TEXTAREA\" ||\n active.isContentEditable);\n return !isEditable;\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 && 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 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 get isNavigatingWithKeyboard() {\n return isNavigating;\n },\n set isNavigatingWithKeyboard(val: boolean) {\n setNavigating(val);\n },\n };\n}\n\nexport function createKeyborg(win: Window): Keyborg {\n const kwin = win as WindowWithKeyborg;\n const id = \"k\" + ++_lastId;\n let localWin: WindowWithKeyborg | undefined = kwin;\n let core: KeyborgCoreHandle | undefined;\n // `callbacks` is exposed as `instance._cb` to satisfy the slot wire\n // protocol. We mutate the array in place (push/splice/length=0) so the\n // reference stays stable for foreign-version broadcasts.\n const callbacks: KeyborgCallback[] = [];\n\n const existing = kwin.__keyborg;\n if (existing) {\n core = existing.core;\n } else {\n core = createKeyborgCore(kwin);\n }\n\n const instance: KeyborgInternal = {\n isNavigatingWithKeyboard() {\n return !!core?.isNavigatingWithKeyboard;\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 if (core) {\n core.isNavigatingWithKeyboard = val;\n }\n },\n _cb: callbacks,\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.length = 0;\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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"}
@@ -0,0 +1,62 @@
1
+ //#region src/Keyborg.d.mts
2
+ /*!
3
+ * Copyright (c) Microsoft Corporation. All rights reserved.
4
+ * Licensed under the MIT License.
5
+ */
6
+ type KeyborgCallback = (isNavigatingWithKeyboard: boolean) => void;
7
+ /**
8
+ * Used to determine the keyboard navigation state.
9
+ */
10
+ interface Keyborg {
11
+ /**
12
+ * @returns Whether the user is navigating with keyboard
13
+ */
14
+ isNavigatingWithKeyboard(): boolean;
15
+ /**
16
+ * @param callback - Called when the keyboard navigation state changes
17
+ */
18
+ subscribe(callback: KeyborgCallback): void;
19
+ /**
20
+ * @param callback - Registered with subscribe
21
+ */
22
+ unsubscribe(callback: KeyborgCallback): void;
23
+ /**
24
+ * Manually set the keyboard navigation state
25
+ */
26
+ setVal(isNavigatingWithKeyboard: boolean): void;
27
+ }
28
+ declare function createKeyborg(win: Window): Keyborg;
29
+ declare function disposeKeyborg(instance: Keyborg): void;
30
+ //#endregion
31
+ //#region src/FocusEvent.d.mts
32
+ /*!
33
+ * Copyright (c) Microsoft Corporation. All rights reserved.
34
+ * Licensed under the MIT License.
35
+ */
36
+ declare const KEYBORG_FOCUSIN = "keyborg:focusin";
37
+ declare const KEYBORG_FOCUSOUT = "keyborg:focusout";
38
+ interface KeyborgFocusInEventDetails {
39
+ relatedTarget?: HTMLElement;
40
+ isFocusedProgrammatically?: boolean;
41
+ originalEvent?: FocusEvent;
42
+ }
43
+ type KeyborgFocusInEvent = CustomEvent<KeyborgFocusInEventDetails>;
44
+ interface KeyborgFocusOutEventDetails {
45
+ originalEvent: FocusEvent;
46
+ }
47
+ type KeyborgFocusOutEvent = CustomEvent<KeyborgFocusOutEventDetails>;
48
+ /**
49
+ * Guarantees that the native `focus` will be used
50
+ */
51
+ declare function nativeFocus(element: HTMLElement): void;
52
+ /**
53
+ * @param win The window that stores keyborg focus events
54
+ * @returns The last element focused with element.focus()
55
+ */
56
+ declare function getLastFocusedProgrammatically(win: Window): HTMLElement | null | undefined;
57
+ //#endregion
58
+ //#region src/index.d.mts
59
+ declare const version: any;
60
+ //#endregion
61
+ export { KEYBORG_FOCUSIN, KEYBORG_FOCUSOUT, type Keyborg, type KeyborgCallback, type KeyborgFocusInEvent, type KeyborgFocusInEventDetails, type KeyborgFocusOutEvent, type KeyborgFocusOutEventDetails, createKeyborg, disposeKeyborg, getLastFocusedProgrammatically, nativeFocus, version };
62
+ //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1,113 +1,48 @@
1
- /**
2
- * Allows disposable instances to be used
3
- */
4
- interface Disposable {
5
- isDisposed?(): boolean;
6
- }
7
-
1
+ //#region src/Keyborg.d.mts
8
2
  /*!
9
3
  * Copyright (c) Microsoft Corporation. All rights reserved.
10
4
  * Licensed under the MIT License.
11
5
  */
12
-
13
- interface WindowWithKeyborg extends Window {
14
- __keyborg?: {
15
- core: KeyborgCore;
16
- refs: {
17
- [id: string]: Keyborg;
18
- };
19
- };
20
- }
21
- interface KeyborgProps {
22
- triggerKeys?: number[];
23
- dismissKeys?: number[];
24
- }
25
6
  type KeyborgCallback = (isNavigatingWithKeyboard: boolean) => void;
26
7
  /**
27
- * Manages a collection of Keyborg instances in a window/document and updates keyborg state
8
+ * Used to determine the keyboard navigation state.
28
9
  */
29
- declare class KeyborgCore implements Disposable {
30
- readonly id: string;
31
- private _win?;
32
- private _isMouseOrTouchUsedTimer;
33
- private _dismissTimer;
34
- private _triggerKeys?;
35
- private _dismissKeys?;
36
- private _isNavigatingWithKeyboard_DO_NOT_USE;
37
- constructor(win: WindowWithKeyborg, props?: KeyborgProps);
38
- get isNavigatingWithKeyboard(): boolean;
39
- set isNavigatingWithKeyboard(val: boolean);
40
- dispose(): void;
41
- isDisposed(): boolean;
42
- /**
43
- * Updates all keyborg instances with the keyboard navigation state
44
- */
45
- update(): void;
46
- private _onFocusIn;
47
- private _onMouseDown;
48
- private _onMouseOrTouch;
49
- private _onKeyDown;
50
- /**
51
- * @returns whether the keyboard event should trigger keyboard navigation mode
52
- */
53
- private _shouldTriggerKeyboardNavigation;
54
- /**
55
- * @returns whether the keyboard event should dismiss keyboard navigation mode
56
- */
57
- private _shouldDismissKeyboardNavigation;
58
- private _scheduleDismiss;
59
- }
60
- /**
61
- * Used to determine the keyboard navigation state
62
- */
63
- declare class Keyborg {
64
- private _id;
65
- private _win?;
66
- private _core?;
67
- private _cb;
68
- static create(win: WindowWithKeyborg, props?: KeyborgProps): Keyborg;
69
- static dispose(instance: Keyborg): void;
70
- /**
71
- * Updates all subscribed callbacks with the keyboard navigation state
72
- */
73
- static update(instance: Keyborg, isNavigatingWithKeyboard: boolean): void;
74
- private constructor();
75
- private dispose;
76
- /**
77
- * @returns Whether the user is navigating with keyboard
78
- */
79
- isNavigatingWithKeyboard(): boolean;
80
- /**
81
- * @param callback - Called when the keyboard navigation state changes
82
- */
83
- subscribe(callback: KeyborgCallback): void;
84
- /**
85
- * @param callback - Registered with subscribe
86
- */
87
- unsubscribe(callback: KeyborgCallback): void;
88
- /**
89
- * Manually set the keyboard navigtion state
90
- */
91
- setVal(isNavigatingWithKeyboard: boolean): void;
92
- }
93
- declare function createKeyborg(win: Window, props?: KeyborgProps): Keyborg;
10
+ interface Keyborg {
11
+ /**
12
+ * @returns Whether the user is navigating with keyboard
13
+ */
14
+ isNavigatingWithKeyboard(): boolean;
15
+ /**
16
+ * @param callback - Called when the keyboard navigation state changes
17
+ */
18
+ subscribe(callback: KeyborgCallback): void;
19
+ /**
20
+ * @param callback - Registered with subscribe
21
+ */
22
+ unsubscribe(callback: KeyborgCallback): void;
23
+ /**
24
+ * Manually set the keyboard navigation state
25
+ */
26
+ setVal(isNavigatingWithKeyboard: boolean): void;
27
+ }
28
+ declare function createKeyborg(win: Window): Keyborg;
94
29
  declare function disposeKeyborg(instance: Keyborg): void;
95
-
30
+ //#endregion
31
+ //#region src/FocusEvent.d.mts
32
+ /*!
33
+ * Copyright (c) Microsoft Corporation. All rights reserved.
34
+ * Licensed under the MIT License.
35
+ */
96
36
  declare const KEYBORG_FOCUSIN = "keyborg:focusin";
97
37
  declare const KEYBORG_FOCUSOUT = "keyborg:focusout";
98
38
  interface KeyborgFocusInEventDetails {
99
- relatedTarget?: HTMLElement;
100
- isFocusedProgrammatically?: boolean;
101
- originalEvent?: FocusEvent;
102
- }
103
- interface KeyborgFocusInEvent extends CustomEvent<KeyborgFocusInEventDetails> {
104
- /**
105
- * @deprecated - used `event.detail`
106
- */
107
- details?: KeyborgFocusInEventDetails;
39
+ relatedTarget?: HTMLElement;
40
+ isFocusedProgrammatically?: boolean;
41
+ originalEvent?: FocusEvent;
108
42
  }
43
+ type KeyborgFocusInEvent = CustomEvent<KeyborgFocusInEventDetails>;
109
44
  interface KeyborgFocusOutEventDetails {
110
- originalEvent: FocusEvent;
45
+ originalEvent: FocusEvent;
111
46
  }
112
47
  type KeyborgFocusOutEvent = CustomEvent<KeyborgFocusOutEventDetails>;
113
48
  /**
@@ -119,12 +54,9 @@ declare function nativeFocus(element: HTMLElement): void;
119
54
  * @returns The last element focused with element.focus()
120
55
  */
121
56
  declare function getLastFocusedProgrammatically(win: Window): HTMLElement | null | undefined;
122
-
123
- /*!
124
- * Copyright (c) Microsoft Corporation. All rights reserved.
125
- * Licensed under the MIT License.
126
- */
127
-
128
- declare const version: string | undefined;
129
-
130
- export { KEYBORG_FOCUSIN, KEYBORG_FOCUSOUT, Keyborg, type KeyborgCallback, type KeyborgFocusInEvent, type KeyborgFocusInEventDetails, type KeyborgFocusOutEvent, type KeyborgFocusOutEventDetails, createKeyborg, disposeKeyborg, getLastFocusedProgrammatically, nativeFocus, version };
57
+ //#endregion
58
+ //#region src/index.d.mts
59
+ declare const version: any;
60
+ //#endregion
61
+ export { KEYBORG_FOCUSIN, KEYBORG_FOCUSOUT, type Keyborg, type KeyborgCallback, type KeyborgFocusInEvent, type KeyborgFocusInEventDetails, type KeyborgFocusOutEvent, type KeyborgFocusOutEventDetails, createKeyborg, disposeKeyborg, getLastFocusedProgrammatically, nativeFocus, version };
62
+ //# sourceMappingURL=index.d.ts.map