keyborg 2.5.0-canary.0 → 2.5.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/esm/index.js CHANGED
@@ -85,7 +85,7 @@ function setupFocusEvent(win) {
85
85
  if (!target) {
86
86
  return;
87
87
  }
88
- let node = target;
88
+ let node = e.composedPath()[0];
89
89
  const currentShadows = /* @__PURE__ */ new Set();
90
90
  while (node) {
91
91
  if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
@@ -95,11 +95,14 @@ function setupFocusEvent(win) {
95
95
  node = node.parentNode;
96
96
  }
97
97
  }
98
- for (const shadow of shadowTargets) {
99
- if (!currentShadows.has(shadow)) {
100
- shadow.removeEventListener("focusin", focusInHandler, true);
101
- shadow.removeEventListener("focusout", focusOutHandler, true);
102
- shadowTargets.delete(shadow);
98
+ for (const shadowRootWeakRef of shadowTargets) {
99
+ const shadowRoot = shadowRootWeakRef.deref();
100
+ if (!shadowRoot || !currentShadows.has(shadowRoot)) {
101
+ shadowTargets.delete(shadowRootWeakRef);
102
+ if (shadowRoot) {
103
+ shadowRoot.removeEventListener("focusin", focusInHandler, true);
104
+ shadowRoot.removeEventListener("focusout", focusOutHandler, true);
105
+ }
103
106
  }
104
107
  }
105
108
  onFocusIn(target, e.relatedTarget || void 0);
@@ -108,12 +111,14 @@ function setupFocusEvent(win) {
108
111
  var _a;
109
112
  const shadowRoot = target.shadowRoot;
110
113
  if (shadowRoot) {
111
- if (shadowTargets.has(shadowRoot)) {
112
- return;
114
+ for (const shadowRootWeakRef of shadowTargets) {
115
+ if (shadowRootWeakRef.deref() === shadowRoot) {
116
+ return;
117
+ }
113
118
  }
114
119
  shadowRoot.addEventListener("focusin", focusInHandler, true);
115
120
  shadowRoot.addEventListener("focusout", focusOutHandler, true);
116
- shadowTargets.add(shadowRoot);
121
+ shadowTargets.add(new WeakRefInstance(shadowRoot));
117
122
  return;
118
123
  }
119
124
  const details = {
@@ -181,17 +186,20 @@ function disposeFocusEvent(win) {
181
186
  keyborgNativeFocusEvent.focusOutHandler,
182
187
  true
183
188
  );
184
- for (const shadow of keyborgNativeFocusEvent.shadowTargets) {
185
- shadow.removeEventListener(
186
- "focusin",
187
- keyborgNativeFocusEvent.focusInHandler,
188
- true
189
- );
190
- shadow.removeEventListener(
191
- "focusout",
192
- keyborgNativeFocusEvent.focusOutHandler,
193
- true
194
- );
189
+ for (const shadowRootWeakRef of keyborgNativeFocusEvent.shadowTargets) {
190
+ const shadowRoot = shadowRootWeakRef.deref();
191
+ if (shadowRoot) {
192
+ shadowRoot.removeEventListener(
193
+ "focusin",
194
+ keyborgNativeFocusEvent.focusInHandler,
195
+ true
196
+ );
197
+ shadowRoot.removeEventListener(
198
+ "focusout",
199
+ keyborgNativeFocusEvent.focusOutHandler,
200
+ true
201
+ );
202
+ }
195
203
  }
196
204
  keyborgNativeFocusEvent.shadowTargets.clear();
197
205
  delete kwin.__keyborgData;
@@ -209,50 +217,14 @@ function getLastFocusedProgrammatically(win) {
209
217
  // src/Keyborg.ts
210
218
  var _dismissTimeout = 500;
211
219
  var _lastId = 0;
212
- var KeyborgState = class {
213
- constructor() {
214
- this.__keyborgCoreRefs = {};
215
- this._isNavigatingWithKeyboard = false;
216
- }
217
- add(keyborg) {
218
- const id = keyborg.id;
219
- if (!(id in this.__keyborgCoreRefs)) {
220
- this.__keyborgCoreRefs[id] = new WeakRefInstance(keyborg);
221
- }
222
- }
223
- remove(id) {
224
- delete this.__keyborgCoreRefs[id];
225
- if (Object.keys(this.__keyborgCoreRefs).length === 0) {
226
- this._isNavigatingWithKeyboard = false;
227
- }
228
- }
229
- setVal(isNavigatingWithKeyboard) {
230
- if (this._isNavigatingWithKeyboard === isNavigatingWithKeyboard) {
231
- return;
232
- }
233
- this._isNavigatingWithKeyboard = isNavigatingWithKeyboard;
234
- for (const id of Object.keys(this.__keyborgCoreRefs)) {
235
- const ref = this.__keyborgCoreRefs[id];
236
- const keyborg = ref.deref();
237
- if (keyborg) {
238
- keyborg.update(isNavigatingWithKeyboard);
239
- } else {
240
- this.remove(id);
241
- }
242
- }
243
- }
244
- getVal() {
245
- return this._isNavigatingWithKeyboard;
246
- }
247
- };
248
- var _state = new KeyborgState();
249
220
  var KeyborgCore = class {
250
221
  constructor(win, props) {
222
+ this._isNavigatingWithKeyboard_DO_NOT_USE = false;
251
223
  this._onFocusIn = (e) => {
252
224
  if (this._isMouseUsedTimer) {
253
225
  return;
254
226
  }
255
- if (_state.getVal()) {
227
+ if (this.isNavigatingWithKeyboard) {
256
228
  return;
257
229
  }
258
230
  const details = e.detail;
@@ -262,7 +234,7 @@ var KeyborgCore = class {
262
234
  if (details.isFocusedProgrammatically || details.isFocusedProgrammatically === void 0) {
263
235
  return;
264
236
  }
265
- _state.setVal(true);
237
+ this.isNavigatingWithKeyboard = true;
266
238
  };
267
239
  this._onMouseDown = (e) => {
268
240
  if (e.buttons === 0 || e.clientX === 0 && e.clientY === 0 && e.screenX === 0 && e.screenY === 0) {
@@ -277,17 +249,17 @@ var KeyborgCore = class {
277
249
  delete this._isMouseUsedTimer;
278
250
  }, 1e3);
279
251
  }
280
- _state.setVal(false);
252
+ this.isNavigatingWithKeyboard = false;
281
253
  };
282
254
  this._onKeyDown = (e) => {
283
- const isNavigatingWithKeyboard = _state.getVal();
255
+ const isNavigatingWithKeyboard = this.isNavigatingWithKeyboard;
284
256
  if (isNavigatingWithKeyboard) {
285
257
  if (this._shouldDismissKeyboardNavigation(e)) {
286
258
  this._scheduleDismiss();
287
259
  }
288
260
  } else {
289
261
  if (this._shouldTriggerKeyboardNavigation(e)) {
290
- _state.setVal(true);
262
+ this.isNavigatingWithKeyboard = true;
291
263
  }
292
264
  }
293
265
  };
@@ -308,7 +280,15 @@ var KeyborgCore = class {
308
280
  doc.addEventListener("mousedown", this._onMouseDown, true);
309
281
  win.addEventListener("keydown", this._onKeyDown, true);
310
282
  setupFocusEvent(win);
311
- _state.add(this);
283
+ }
284
+ get isNavigatingWithKeyboard() {
285
+ return this._isNavigatingWithKeyboard_DO_NOT_USE;
286
+ }
287
+ set isNavigatingWithKeyboard(val) {
288
+ if (this._isNavigatingWithKeyboard_DO_NOT_USE !== val) {
289
+ this._isNavigatingWithKeyboard_DO_NOT_USE = val;
290
+ this.update();
291
+ }
312
292
  }
313
293
  dispose() {
314
294
  const win = this._win;
@@ -327,7 +307,6 @@ var KeyborgCore = class {
327
307
  doc.removeEventListener("mousedown", this._onMouseDown, true);
328
308
  win.removeEventListener("keydown", this._onKeyDown, true);
329
309
  delete this._win;
330
- _state.remove(this.id);
331
310
  }
332
311
  }
333
312
  isDisposed() {
@@ -336,12 +315,12 @@ var KeyborgCore = class {
336
315
  /**
337
316
  * Updates all keyborg instances with the keyboard navigation state
338
317
  */
339
- update(isNavigatingWithKeyboard) {
318
+ update() {
340
319
  var _a, _b;
341
320
  const keyborgs = (_b = (_a = this._win) == null ? void 0 : _a.__keyborg) == null ? void 0 : _b.refs;
342
321
  if (keyborgs) {
343
322
  for (const id of Object.keys(keyborgs)) {
344
- Keyborg.update(keyborgs[id], isNavigatingWithKeyboard);
323
+ Keyborg.update(keyborgs[id], this.isNavigatingWithKeyboard);
345
324
  }
346
325
  }
347
326
  }
@@ -377,7 +356,7 @@ var KeyborgCore = class {
377
356
  this._dismissTimer = void 0;
378
357
  const cur = win.document.activeElement;
379
358
  if (was && cur && was === cur) {
380
- _state.setVal(false);
359
+ this.isNavigatingWithKeyboard = false;
381
360
  }
382
361
  }, _dismissTimeout);
383
362
  }
@@ -434,7 +413,8 @@ var Keyborg = class _Keyborg {
434
413
  * @returns Whether the user is navigating with keyboard
435
414
  */
436
415
  isNavigatingWithKeyboard() {
437
- return _state.getVal();
416
+ var _a;
417
+ return !!((_a = this._core) == null ? void 0 : _a.isNavigatingWithKeyboard);
438
418
  }
439
419
  /**
440
420
  * @param callback - Called when the keyboard navigation state changes
@@ -455,7 +435,9 @@ var Keyborg = class _Keyborg {
455
435
  * Manually set the keyboard navigtion state
456
436
  */
457
437
  setVal(isNavigatingWithKeyboard) {
458
- _state.setVal(isNavigatingWithKeyboard);
438
+ if (this._core) {
439
+ this._core.isNavigatingWithKeyboard = isNavigatingWithKeyboard;
440
+ }
459
441
  }
460
442
  };
461
443
  function createKeyborg(win, props) {
@@ -466,7 +448,7 @@ function disposeKeyborg(instance) {
466
448
  }
467
449
 
468
450
  // src/index.ts
469
- var version = "2.5.0-canary.0";
451
+ var version = "2.5.0";
470
452
  export {
471
453
  KEYBORG_FOCUSIN,
472
454
  KEYBORG_FOCUSOUT,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/WeakRefInstance.ts","../../src/FocusEvent.ts","../../src/Keyborg.ts","../../src/index.ts"],"sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// IE11 compat, checks if WeakRef is supported\nexport const _canUseWeakRef = typeof WeakRef !== \"undefined\";\n\n/**\n * Allows disposable instances to be used\n */\nexport interface Disposable {\n isDisposed?(): boolean;\n}\n\n/**\n * WeakRef wrapper around a HTMLElement that also supports IE11\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef}\n * @internal\n */\nexport class WeakRefInstance<T extends Disposable | object> {\n private _weakRef?: WeakRef<T>;\n private _instance?: T;\n\n constructor(instance: T) {\n if (_canUseWeakRef && typeof instance === \"object\") {\n this._weakRef = new WeakRef(instance);\n } else {\n this._instance = instance;\n }\n }\n\n /**\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef/deref}\n */\n deref(): T | undefined {\n let instance: T | undefined;\n\n if (this._weakRef) {\n instance = this._weakRef?.deref();\n\n if (!instance) {\n delete this._weakRef;\n }\n } else {\n instance = this._instance;\n if ((instance as Disposable)?.isDisposed?.()) {\n delete this._instance;\n }\n }\n\n return instance;\n }\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { WeakRefInstance } from \"./WeakRefInstance\";\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\ninterface KeyborgFocusEventData {\n focusInHandler: (e: FocusEvent) => void;\n focusOutHandler: (e: FocusEvent) => void;\n lastFocusedProgrammatically?: WeakRefInstance<HTMLElement>;\n shadowTargets: Set<ShadowRoot>;\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\n 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\n if (!_canOverrideNativeFocus) {\n _canOverrideNativeFocus = canOverrideNativeFocus(kwin);\n }\n\n const origFocus = kwin.HTMLElement.prototype.focus;\n\n if ((origFocus as KeyborgFocus).__keyborgNativeFocus) {\n // Already set up.\n return;\n }\n\n kwin.HTMLElement.prototype.focus = focus;\n\n const shadowTargets: Set<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 = target;\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 shadow of shadowTargets) {\n if (!currentShadows.has(shadow)) {\n shadow.removeEventListener(\"focusin\", focusInHandler, true);\n shadow.removeEventListener(\"focusout\", focusOutHandler, true);\n shadowTargets.delete(shadow);\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 if (shadowTargets.has(shadowRoot)) {\n return;\n }\n\n shadowRoot.addEventListener(\"focusin\", focusInHandler, true);\n shadowRoot.addEventListener(\"focusout\", focusOutHandler, true);\n\n shadowTargets.add(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.lastFocusedProgrammatically) {\n details.isFocusedProgrammatically =\n target === data.lastFocusedProgrammatically?.deref();\n\n data.lastFocusedProgrammatically = undefined;\n }\n\n target.dispatchEvent(event);\n };\n\n const data: KeyborgFocusEventData = (kwin.__keyborgData = {\n focusInHandler,\n focusOutHandler,\n shadowTargets,\n });\n\n kwin.document.addEventListener(\n \"focusin\",\n kwin.__keyborgData.focusInHandler,\n true,\n );\n\n kwin.document.addEventListener(\n \"focusout\",\n kwin.__keyborgData.focusOutHandler,\n true,\n );\n\n function focus(this: HTMLElement) {\n const keyborgNativeFocusEvent = (kwin as WindowWithKeyborgFocusEvent)\n .__keyborgData;\n\n if (keyborgNativeFocusEvent) {\n keyborgNativeFocusEvent.lastFocusedProgrammatically = new WeakRefInstance(\n this,\n );\n }\n\n // eslint-disable-next-line prefer-rest-params\n return origFocus.apply(this, arguments);\n }\n\n let activeElement = kwin.document.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 keyborgNativeFocusEvent = kwin.__keyborgData;\n\n if (keyborgNativeFocusEvent) {\n kwin.document.removeEventListener(\n \"focusin\",\n keyborgNativeFocusEvent.focusInHandler,\n true,\n );\n\n kwin.document.removeEventListener(\n \"focusout\",\n keyborgNativeFocusEvent.focusOutHandler,\n true,\n );\n\n for (const shadow of keyborgNativeFocusEvent.shadowTargets) {\n shadow.removeEventListener(\n \"focusin\",\n keyborgNativeFocusEvent.focusInHandler,\n true,\n );\n shadow.removeEventListener(\n \"focusout\",\n keyborgNativeFocusEvent.focusOutHandler,\n true,\n );\n }\n\n keyborgNativeFocusEvent.shadowTargets.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 keyborgNativeFocusEvent = (win as WindowWithKeyborgFocusEvent)\n .__keyborgData;\n\n return keyborgNativeFocusEvent\n ? keyborgNativeFocusEvent.lastFocusedProgrammatically?.deref() || null\n : undefined;\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n disposeFocusEvent,\n KeyborgFocusInEvent,\n KEYBORG_FOCUSIN,\n setupFocusEvent,\n} from \"./FocusEvent\";\nimport { Disposable, WeakRefInstance } from \"./WeakRefInstance\";\n\ninterface WindowWithKeyborg extends Window {\n __keyborg?: {\n core: KeyborgCore;\n refs: { [id: string]: Keyborg };\n };\n}\n\nconst _dismissTimeout = 500; // When a key from dismissKeys is pressed and the focus is not moved\n// during _dismissTimeout time, dismiss the keyboard navigation mode.\n\nlet _lastId = 0;\n\nexport interface KeyborgProps {\n // Keys to be used to trigger keyboard navigation mode. By default, any key will trigger\n // it. Could be limited to, for example, just Tab (or Tab and arrow keys).\n triggerKeys?: number[];\n // Keys to be used to dismiss keyboard navigation mode using keyboard (in addition to\n // mouse clicks which dismiss it). For example, Esc could be used to dismiss.\n dismissKeys?: number[];\n}\n\nexport type KeyborgCallback = (isNavigatingWithKeyboard: boolean) => void;\n\n/**\n * Source of truth for all the keyborg core instances and the current keyboard navigation state\n */\nexport class KeyborgState {\n private __keyborgCoreRefs: { [id: string]: WeakRefInstance<KeyborgCore> } =\n {};\n private _isNavigatingWithKeyboard = false;\n\n add(keyborg: KeyborgCore): void {\n const id = keyborg.id;\n\n if (!(id in this.__keyborgCoreRefs)) {\n this.__keyborgCoreRefs[id] = new WeakRefInstance<KeyborgCore>(keyborg);\n }\n }\n\n remove(id: string): void {\n delete this.__keyborgCoreRefs[id];\n\n if (Object.keys(this.__keyborgCoreRefs).length === 0) {\n this._isNavigatingWithKeyboard = false;\n }\n }\n\n setVal(isNavigatingWithKeyboard: boolean): void {\n if (this._isNavigatingWithKeyboard === isNavigatingWithKeyboard) {\n return;\n }\n\n this._isNavigatingWithKeyboard = isNavigatingWithKeyboard;\n\n for (const id of Object.keys(this.__keyborgCoreRefs)) {\n const ref = this.__keyborgCoreRefs[id];\n const keyborg = ref.deref();\n\n if (keyborg) {\n keyborg.update(isNavigatingWithKeyboard);\n } else {\n this.remove(id);\n }\n }\n }\n\n getVal(): boolean {\n return this._isNavigatingWithKeyboard;\n }\n}\n\nconst _state = new KeyborgState();\n\n/**\n * Manages a collection of Keyborg instances in a window/document and updates keyborg state\n */\nclass KeyborgCore implements Disposable {\n readonly id: string;\n\n private _win?: WindowWithKeyborg;\n private _isMouseUsedTimer: number | undefined;\n private _dismissTimer: number | undefined;\n private _triggerKeys?: Set<number>;\n private _dismissKeys?: Set<number>;\n\n constructor(win: WindowWithKeyborg, props?: KeyborgProps) {\n this.id = \"c\" + ++_lastId;\n this._win = win;\n const doc = win.document;\n\n if (props) {\n const triggerKeys = props.triggerKeys;\n const dismissKeys = props.dismissKeys;\n\n if (triggerKeys?.length) {\n this._triggerKeys = new Set(triggerKeys);\n }\n\n if (dismissKeys?.length) {\n this._dismissKeys = new Set(dismissKeys);\n }\n }\n\n doc.addEventListener(KEYBORG_FOCUSIN, this._onFocusIn, true); // Capture!\n doc.addEventListener(\"mousedown\", this._onMouseDown, true); // Capture!\n win.addEventListener(\"keydown\", this._onKeyDown, true); // Capture!\n\n setupFocusEvent(win);\n\n _state.add(this);\n }\n\n dispose(): void {\n const win = this._win;\n\n if (win) {\n if (this._isMouseUsedTimer) {\n win.clearTimeout(this._isMouseUsedTimer);\n this._isMouseUsedTimer = undefined;\n }\n\n if (this._dismissTimer) {\n win.clearTimeout(this._dismissTimer);\n this._dismissTimer = undefined;\n }\n\n disposeFocusEvent(win);\n\n const doc = win.document;\n\n doc.removeEventListener(KEYBORG_FOCUSIN, this._onFocusIn, true); // Capture!\n doc.removeEventListener(\"mousedown\", this._onMouseDown, true); // Capture!\n win.removeEventListener(\"keydown\", this._onKeyDown, true); // Capture!\n\n delete this._win;\n\n _state.remove(this.id);\n }\n }\n\n isDisposed(): boolean {\n return !!this._win;\n }\n\n /**\n * Updates all keyborg instances with the keyboard navigation state\n */\n update(isNavigatingWithKeyboard: boolean): void {\n const keyborgs = this._win?.__keyborg?.refs;\n\n if (keyborgs) {\n for (const id of Object.keys(keyborgs)) {\n Keyborg.update(keyborgs[id], isNavigatingWithKeyboard);\n }\n }\n }\n\n private _onFocusIn = (e: KeyborgFocusInEvent) => {\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 swallow\n // the events when the screen reader shortcuts are used). The screen reader\n // usage is keyboard navigation.\n\n if (this._isMouseUsedTimer) {\n // There was a mouse event recently.\n return;\n }\n\n if (_state.getVal()) {\n return;\n }\n\n const details = e.detail;\n\n if (!details.relatedTarget) {\n return;\n }\n\n if (\n details.isFocusedProgrammatically ||\n details.isFocusedProgrammatically === undefined\n ) {\n // The element is focused programmatically, or the programmatic focus detection\n // is not working.\n return;\n }\n\n _state.setVal(true);\n };\n\n private _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 perform\n // an action on an element, do not dismiss the keyboard navigation mode.\n return;\n }\n\n const win = this._win;\n\n if (win) {\n if (this._isMouseUsedTimer) {\n win.clearTimeout(this._isMouseUsedTimer);\n }\n\n this._isMouseUsedTimer = win.setTimeout(() => {\n delete this._isMouseUsedTimer;\n }, 1000); // Keeping the indication of the mouse usage for some time.\n }\n\n _state.setVal(false);\n };\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n const isNavigatingWithKeyboard = _state.getVal();\n\n if (isNavigatingWithKeyboard) {\n if (this._shouldDismissKeyboardNavigation(e)) {\n this._scheduleDismiss();\n }\n } else {\n if (this._shouldTriggerKeyboardNavigation(e)) {\n _state.setVal(true);\n }\n }\n };\n\n /**\n * @returns whether the keyboard event should trigger keyboard navigation mode\n */\n private _shouldTriggerKeyboardNavigation(e: KeyboardEvent) {\n // TODO Some rich text fields can allow Tab key for indentation so it doesn't\n // need to be a navigation key. If there is a bug regarding that we should revisit\n if (e.key === \"Tab\") {\n return true;\n }\n\n const activeElement = this._win?.document\n .activeElement as HTMLElement | null;\n const isTriggerKey = !this._triggerKeys || this._triggerKeys.has(e.keyCode);\n\n const isEditable =\n activeElement &&\n (activeElement.tagName === \"INPUT\" ||\n activeElement.tagName === \"TEXTAREA\" ||\n activeElement.isContentEditable);\n\n return isTriggerKey && !isEditable;\n }\n\n /**\n * @returns whether the keyboard event should dismiss keyboard navigation mode\n */\n private _shouldDismissKeyboardNavigation(e: KeyboardEvent) {\n return this._dismissKeys?.has(e.keyCode);\n }\n\n private _scheduleDismiss(): void {\n const win = this._win;\n\n if (win) {\n if (this._dismissTimer) {\n win.clearTimeout(this._dismissTimer);\n this._dismissTimer = undefined;\n }\n\n const was = win.document.activeElement;\n\n this._dismissTimer = win.setTimeout(() => {\n this._dismissTimer = undefined;\n\n const cur = win.document.activeElement;\n\n if (was && cur && was === cur) {\n // Esc was pressed, currently focused element hasn't changed.\n // Just dismiss the keyboard navigation mode.\n _state.setVal(false);\n }\n }, _dismissTimeout);\n }\n }\n}\n\n/**\n * Used to determine the keyboard navigation state\n */\nexport class Keyborg {\n private _id: string;\n private _win?: WindowWithKeyborg;\n private _core?: KeyborgCore;\n private _cb: KeyborgCallback[] = [];\n\n static create(win: WindowWithKeyborg, props?: KeyborgProps): Keyborg {\n return new Keyborg(win, props);\n }\n\n static dispose(instance: Keyborg): void {\n instance.dispose();\n }\n\n /**\n * Updates all subscribed callbacks with the keyboard navigation state\n */\n static update(instance: Keyborg, isNavigatingWithKeyboard: boolean): void {\n instance._cb.forEach((callback) => callback(isNavigatingWithKeyboard));\n }\n\n private constructor(win: WindowWithKeyborg, props?: KeyborgProps) {\n this._id = \"k\" + ++_lastId;\n this._win = win;\n\n const current = win.__keyborg;\n\n if (current) {\n this._core = current.core;\n current.refs[this._id] = this;\n } else {\n this._core = new KeyborgCore(win, props);\n win.__keyborg = {\n core: this._core,\n refs: { [this._id]: this },\n };\n }\n }\n\n private dispose(): void {\n const current = this._win?.__keyborg;\n\n if (current?.refs[this._id]) {\n delete current.refs[this._id];\n\n if (Object.keys(current.refs).length === 0) {\n current.core.dispose();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n delete this._win!.__keyborg;\n }\n } else if (process.env.NODE_ENV !== \"production\") {\n console.error(\n `Keyborg instance ${this._id} is being disposed incorrectly.`,\n );\n }\n\n this._cb = [];\n delete this._core;\n delete this._win;\n }\n\n /**\n * @returns Whether the user is navigating with keyboard\n */\n isNavigatingWithKeyboard(): boolean {\n return _state.getVal();\n }\n\n /**\n * @param callback - Called when the keyboard navigation state changes\n */\n subscribe(callback: KeyborgCallback): void {\n this._cb.push(callback);\n }\n\n /**\n * @param callback - Registered with subscribe\n */\n unsubscribe(callback: KeyborgCallback): void {\n const index = this._cb.indexOf(callback);\n\n if (index >= 0) {\n this._cb.splice(index, 1);\n }\n }\n\n /**\n * Manually set the keyboard navigtion state\n */\n setVal(isNavigatingWithKeyboard: boolean): void {\n _state.setVal(isNavigatingWithKeyboard);\n }\n}\n\nexport function createKeyborg(win: Window, props?: KeyborgProps): Keyborg {\n return Keyborg.create(win, props);\n}\n\nexport function disposeKeyborg(instance: Keyborg) {\n Keyborg.dispose(instance);\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport type { Keyborg, KeyborgCallback } from \"./Keyborg\";\nexport { createKeyborg, disposeKeyborg } from \"./Keyborg\";\n\nexport type {\n KeyborgFocusInEvent,\n KeyborgFocusInEventDetails,\n KeyborgFocusOutEvent,\n KeyborgFocusOutEventDetails,\n} from \"./FocusEvent\";\nexport {\n getLastFocusedProgrammatically,\n nativeFocus,\n KEYBORG_FOCUSIN,\n KEYBORG_FOCUSOUT,\n} from \"./FocusEvent\";\n\nexport const version = process.env.PKG_VERSION;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/WeakRefInstance.ts","../../src/FocusEvent.ts","../../src/Keyborg.ts","../../src/index.ts"],"sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// IE11 compat, checks if WeakRef is supported\nexport const _canUseWeakRef = typeof WeakRef !== \"undefined\";\n\n/**\n * Allows disposable instances to be used\n */\nexport interface Disposable {\n isDisposed?(): boolean;\n}\n\n/**\n * WeakRef wrapper around a HTMLElement that also supports IE11\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef}\n * @internal\n */\nexport class WeakRefInstance<T extends Disposable | object> {\n private _weakRef?: WeakRef<T>;\n private _instance?: T;\n\n constructor(instance: T) {\n if (_canUseWeakRef && typeof instance === \"object\") {\n this._weakRef = new WeakRef(instance);\n } else {\n this._instance = instance;\n }\n }\n\n /**\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef/deref}\n */\n deref(): T | undefined {\n let instance: T | undefined;\n\n if (this._weakRef) {\n instance = this._weakRef?.deref();\n\n if (!instance) {\n delete this._weakRef;\n }\n } else {\n instance = this._instance;\n if ((instance as Disposable)?.isDisposed?.()) {\n delete this._instance;\n }\n }\n\n return instance;\n }\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { WeakRefInstance } from \"./WeakRefInstance\";\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\ninterface KeyborgFocusEventData {\n focusInHandler: (e: FocusEvent) => void;\n focusOutHandler: (e: FocusEvent) => void;\n lastFocusedProgrammatically?: WeakRefInstance<HTMLElement>;\n shadowTargets: Set<WeakRefInstance<ShadowRoot>>;\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\n 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\n if (!_canOverrideNativeFocus) {\n _canOverrideNativeFocus = canOverrideNativeFocus(kwin);\n }\n\n const origFocus = kwin.HTMLElement.prototype.focus;\n\n if ((origFocus as KeyborgFocus).__keyborgNativeFocus) {\n // Already set up.\n return;\n }\n\n kwin.HTMLElement.prototype.focus = focus;\n\n const shadowTargets: Set<WeakRefInstance<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 shadowRoot.removeEventListener(\"focusin\", focusInHandler, true);\n shadowRoot.removeEventListener(\"focusout\", focusOutHandler, true);\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 shadowRoot.addEventListener(\"focusin\", focusInHandler, true);\n shadowRoot.addEventListener(\"focusout\", focusOutHandler, true);\n\n shadowTargets.add(new WeakRefInstance(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.lastFocusedProgrammatically) {\n details.isFocusedProgrammatically =\n target === data.lastFocusedProgrammatically?.deref();\n\n data.lastFocusedProgrammatically = undefined;\n }\n\n target.dispatchEvent(event);\n };\n\n const data: KeyborgFocusEventData = (kwin.__keyborgData = {\n focusInHandler,\n focusOutHandler,\n shadowTargets,\n });\n\n kwin.document.addEventListener(\n \"focusin\",\n kwin.__keyborgData.focusInHandler,\n true,\n );\n\n kwin.document.addEventListener(\n \"focusout\",\n kwin.__keyborgData.focusOutHandler,\n true,\n );\n\n function focus(this: HTMLElement) {\n const keyborgNativeFocusEvent = (kwin as WindowWithKeyborgFocusEvent)\n .__keyborgData;\n\n if (keyborgNativeFocusEvent) {\n keyborgNativeFocusEvent.lastFocusedProgrammatically = new WeakRefInstance(\n this,\n );\n }\n\n // eslint-disable-next-line prefer-rest-params\n return origFocus.apply(this, arguments);\n }\n\n let activeElement = kwin.document.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 keyborgNativeFocusEvent = kwin.__keyborgData;\n\n if (keyborgNativeFocusEvent) {\n kwin.document.removeEventListener(\n \"focusin\",\n keyborgNativeFocusEvent.focusInHandler,\n true,\n );\n\n kwin.document.removeEventListener(\n \"focusout\",\n keyborgNativeFocusEvent.focusOutHandler,\n true,\n );\n\n for (const shadowRootWeakRef of keyborgNativeFocusEvent.shadowTargets) {\n const shadowRoot = shadowRootWeakRef.deref();\n\n if (shadowRoot) {\n shadowRoot.removeEventListener(\n \"focusin\",\n keyborgNativeFocusEvent.focusInHandler,\n true,\n );\n shadowRoot.removeEventListener(\n \"focusout\",\n keyborgNativeFocusEvent.focusOutHandler,\n true,\n );\n }\n }\n\n keyborgNativeFocusEvent.shadowTargets.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 keyborgNativeFocusEvent = (win as WindowWithKeyborgFocusEvent)\n .__keyborgData;\n\n return keyborgNativeFocusEvent\n ? keyborgNativeFocusEvent.lastFocusedProgrammatically?.deref() || null\n : undefined;\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n disposeFocusEvent,\n KeyborgFocusInEvent,\n KEYBORG_FOCUSIN,\n setupFocusEvent,\n} from \"./FocusEvent\";\nimport { Disposable } from \"./WeakRefInstance\";\n\ninterface WindowWithKeyborg extends Window {\n __keyborg?: {\n core: KeyborgCore;\n refs: { [id: string]: Keyborg };\n };\n}\n\nconst _dismissTimeout = 500; // When a key from dismissKeys is pressed and the focus is not moved\n// during _dismissTimeout time, dismiss the keyboard navigation mode.\n\nlet _lastId = 0;\n\nexport interface KeyborgProps {\n // Keys to be used to trigger keyboard navigation mode. By default, any key will trigger\n // it. Could be limited to, for example, just Tab (or Tab and arrow keys).\n triggerKeys?: number[];\n // Keys to be used to dismiss keyboard navigation mode using keyboard (in addition to\n // mouse clicks which dismiss it). For example, Esc could be used to dismiss.\n dismissKeys?: number[];\n}\n\nexport type KeyborgCallback = (isNavigatingWithKeyboard: boolean) => void;\n\n/**\n * Manages a collection of Keyborg instances in a window/document and updates keyborg state\n */\nclass KeyborgCore implements Disposable {\n readonly id: string;\n\n private _win?: WindowWithKeyborg;\n private _isMouseUsedTimer: number | undefined;\n private _dismissTimer: number | undefined;\n private _triggerKeys?: Set<number>;\n private _dismissKeys?: Set<number>;\n private _isNavigatingWithKeyboard_DO_NOT_USE = false;\n\n constructor(win: WindowWithKeyborg, props?: KeyborgProps) {\n this.id = \"c\" + ++_lastId;\n this._win = win;\n const doc = win.document;\n\n if (props) {\n const triggerKeys = props.triggerKeys;\n const dismissKeys = props.dismissKeys;\n\n if (triggerKeys?.length) {\n this._triggerKeys = new Set(triggerKeys);\n }\n\n if (dismissKeys?.length) {\n this._dismissKeys = new Set(dismissKeys);\n }\n }\n\n doc.addEventListener(KEYBORG_FOCUSIN, this._onFocusIn, true); // Capture!\n doc.addEventListener(\"mousedown\", this._onMouseDown, true); // Capture!\n win.addEventListener(\"keydown\", this._onKeyDown, true); // Capture!\n\n setupFocusEvent(win);\n }\n\n get isNavigatingWithKeyboard() {\n return this._isNavigatingWithKeyboard_DO_NOT_USE;\n }\n\n set isNavigatingWithKeyboard(val: boolean) {\n if (this._isNavigatingWithKeyboard_DO_NOT_USE !== val) {\n this._isNavigatingWithKeyboard_DO_NOT_USE = val;\n this.update();\n }\n }\n\n dispose(): void {\n const win = this._win;\n\n if (win) {\n if (this._isMouseUsedTimer) {\n win.clearTimeout(this._isMouseUsedTimer);\n this._isMouseUsedTimer = undefined;\n }\n\n if (this._dismissTimer) {\n win.clearTimeout(this._dismissTimer);\n this._dismissTimer = undefined;\n }\n\n disposeFocusEvent(win);\n\n const doc = win.document;\n\n doc.removeEventListener(KEYBORG_FOCUSIN, this._onFocusIn, true); // Capture!\n doc.removeEventListener(\"mousedown\", this._onMouseDown, true); // Capture!\n win.removeEventListener(\"keydown\", this._onKeyDown, true); // Capture!\n\n delete this._win;\n }\n }\n\n isDisposed(): boolean {\n return !!this._win;\n }\n\n /**\n * Updates all keyborg instances with the keyboard navigation state\n */\n update(): void {\n const keyborgs = this._win?.__keyborg?.refs;\n\n if (keyborgs) {\n for (const id of Object.keys(keyborgs)) {\n Keyborg.update(keyborgs[id], this.isNavigatingWithKeyboard);\n }\n }\n }\n\n private _onFocusIn = (e: KeyborgFocusInEvent) => {\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 swallow\n // the events when the screen reader shortcuts are used). The screen reader\n // usage is keyboard navigation.\n\n if (this._isMouseUsedTimer) {\n // There was a mouse event recently.\n return;\n }\n\n if (this.isNavigatingWithKeyboard) {\n return;\n }\n\n const details = e.detail;\n\n if (!details.relatedTarget) {\n return;\n }\n\n if (\n details.isFocusedProgrammatically ||\n details.isFocusedProgrammatically === undefined\n ) {\n // The element is focused programmatically, or the programmatic focus detection\n // is not working.\n return;\n }\n\n this.isNavigatingWithKeyboard = true;\n };\n\n private _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 perform\n // an action on an element, do not dismiss the keyboard navigation mode.\n return;\n }\n\n const win = this._win;\n\n if (win) {\n if (this._isMouseUsedTimer) {\n win.clearTimeout(this._isMouseUsedTimer);\n }\n\n this._isMouseUsedTimer = win.setTimeout(() => {\n delete this._isMouseUsedTimer;\n }, 1000); // Keeping the indication of the mouse usage for some time.\n }\n\n this.isNavigatingWithKeyboard = false;\n };\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n const isNavigatingWithKeyboard = this.isNavigatingWithKeyboard;\n\n if (isNavigatingWithKeyboard) {\n if (this._shouldDismissKeyboardNavigation(e)) {\n this._scheduleDismiss();\n }\n } else {\n if (this._shouldTriggerKeyboardNavigation(e)) {\n this.isNavigatingWithKeyboard = true;\n }\n }\n };\n\n /**\n * @returns whether the keyboard event should trigger keyboard navigation mode\n */\n private _shouldTriggerKeyboardNavigation(e: KeyboardEvent) {\n // TODO Some rich text fields can allow Tab key for indentation so it doesn't\n // need to be a navigation key. If there is a bug regarding that we should revisit\n if (e.key === \"Tab\") {\n return true;\n }\n\n const activeElement = this._win?.document\n .activeElement as HTMLElement | null;\n const isTriggerKey = !this._triggerKeys || this._triggerKeys.has(e.keyCode);\n\n const isEditable =\n activeElement &&\n (activeElement.tagName === \"INPUT\" ||\n activeElement.tagName === \"TEXTAREA\" ||\n activeElement.isContentEditable);\n\n return isTriggerKey && !isEditable;\n }\n\n /**\n * @returns whether the keyboard event should dismiss keyboard navigation mode\n */\n private _shouldDismissKeyboardNavigation(e: KeyboardEvent) {\n return this._dismissKeys?.has(e.keyCode);\n }\n\n private _scheduleDismiss(): void {\n const win = this._win;\n\n if (win) {\n if (this._dismissTimer) {\n win.clearTimeout(this._dismissTimer);\n this._dismissTimer = undefined;\n }\n\n const was = win.document.activeElement;\n\n this._dismissTimer = win.setTimeout(() => {\n this._dismissTimer = undefined;\n\n const cur = win.document.activeElement;\n\n if (was && cur && was === cur) {\n // Esc was pressed, currently focused element hasn't changed.\n // Just dismiss the keyboard navigation mode.\n this.isNavigatingWithKeyboard = false;\n }\n }, _dismissTimeout);\n }\n }\n}\n\n/**\n * Used to determine the keyboard navigation state\n */\nexport class Keyborg {\n private _id: string;\n private _win?: WindowWithKeyborg;\n private _core?: KeyborgCore;\n private _cb: KeyborgCallback[] = [];\n\n static create(win: WindowWithKeyborg, props?: KeyborgProps): Keyborg {\n return new Keyborg(win, props);\n }\n\n static dispose(instance: Keyborg): void {\n instance.dispose();\n }\n\n /**\n * Updates all subscribed callbacks with the keyboard navigation state\n */\n static update(instance: Keyborg, isNavigatingWithKeyboard: boolean): void {\n instance._cb.forEach((callback) => callback(isNavigatingWithKeyboard));\n }\n\n private constructor(win: WindowWithKeyborg, props?: KeyborgProps) {\n this._id = \"k\" + ++_lastId;\n this._win = win;\n\n const current = win.__keyborg;\n\n if (current) {\n this._core = current.core;\n current.refs[this._id] = this;\n } else {\n this._core = new KeyborgCore(win, props);\n win.__keyborg = {\n core: this._core,\n refs: { [this._id]: this },\n };\n }\n }\n\n private dispose(): void {\n const current = this._win?.__keyborg;\n\n if (current?.refs[this._id]) {\n delete current.refs[this._id];\n\n if (Object.keys(current.refs).length === 0) {\n current.core.dispose();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n delete this._win!.__keyborg;\n }\n } else if (process.env.NODE_ENV !== \"production\") {\n console.error(\n `Keyborg instance ${this._id} is being disposed incorrectly.`,\n );\n }\n\n this._cb = [];\n delete this._core;\n delete this._win;\n }\n\n /**\n * @returns Whether the user is navigating with keyboard\n */\n isNavigatingWithKeyboard(): boolean {\n return !!this._core?.isNavigatingWithKeyboard;\n }\n\n /**\n * @param callback - Called when the keyboard navigation state changes\n */\n subscribe(callback: KeyborgCallback): void {\n this._cb.push(callback);\n }\n\n /**\n * @param callback - Registered with subscribe\n */\n unsubscribe(callback: KeyborgCallback): void {\n const index = this._cb.indexOf(callback);\n\n if (index >= 0) {\n this._cb.splice(index, 1);\n }\n }\n\n /**\n * Manually set the keyboard navigtion state\n */\n setVal(isNavigatingWithKeyboard: boolean): void {\n if (this._core) {\n this._core.isNavigatingWithKeyboard = isNavigatingWithKeyboard;\n }\n }\n}\n\nexport function createKeyborg(win: Window, props?: KeyborgProps): Keyborg {\n return Keyborg.create(win, props);\n}\n\nexport function disposeKeyborg(instance: Keyborg) {\n Keyborg.dispose(instance);\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport type { Keyborg, KeyborgCallback } from \"./Keyborg\";\nexport { createKeyborg, disposeKeyborg } from \"./Keyborg\";\n\nexport type {\n KeyborgFocusInEvent,\n KeyborgFocusInEventDetails,\n KeyborgFocusOutEvent,\n KeyborgFocusOutEventDetails,\n} from \"./FocusEvent\";\nexport {\n getLastFocusedProgrammatically,\n nativeFocus,\n KEYBORG_FOCUSIN,\n KEYBORG_FOCUSOUT,\n} from \"./FocusEvent\";\n\nexport const version = process.env.PKG_VERSION;\n"],"mappings":"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","names":[]}
package/dist/index.d.mts CHANGED
@@ -33,13 +33,16 @@ declare class KeyborgCore implements Disposable {
33
33
  private _dismissTimer;
34
34
  private _triggerKeys?;
35
35
  private _dismissKeys?;
36
+ private _isNavigatingWithKeyboard_DO_NOT_USE;
36
37
  constructor(win: WindowWithKeyborg, props?: KeyborgProps);
38
+ get isNavigatingWithKeyboard(): boolean;
39
+ set isNavigatingWithKeyboard(val: boolean);
37
40
  dispose(): void;
38
41
  isDisposed(): boolean;
39
42
  /**
40
43
  * Updates all keyborg instances with the keyboard navigation state
41
44
  */
42
- update(isNavigatingWithKeyboard: boolean): void;
45
+ update(): void;
43
46
  private _onFocusIn;
44
47
  private _onMouseDown;
45
48
  private _onKeyDown;
package/dist/index.d.ts CHANGED
@@ -33,13 +33,16 @@ declare class KeyborgCore implements Disposable {
33
33
  private _dismissTimer;
34
34
  private _triggerKeys?;
35
35
  private _dismissKeys?;
36
+ private _isNavigatingWithKeyboard_DO_NOT_USE;
36
37
  constructor(win: WindowWithKeyborg, props?: KeyborgProps);
38
+ get isNavigatingWithKeyboard(): boolean;
39
+ set isNavigatingWithKeyboard(val: boolean);
37
40
  dispose(): void;
38
41
  isDisposed(): boolean;
39
42
  /**
40
43
  * Updates all keyborg instances with the keyboard navigation state
41
44
  */
42
- update(isNavigatingWithKeyboard: boolean): void;
45
+ update(): void;
43
46
  private _onFocusIn;
44
47
  private _onMouseDown;
45
48
  private _onKeyDown;
package/dist/index.js CHANGED
@@ -116,7 +116,7 @@ function setupFocusEvent(win) {
116
116
  if (!target) {
117
117
  return;
118
118
  }
119
- let node = target;
119
+ let node = e.composedPath()[0];
120
120
  const currentShadows = /* @__PURE__ */ new Set();
121
121
  while (node) {
122
122
  if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
@@ -126,11 +126,14 @@ function setupFocusEvent(win) {
126
126
  node = node.parentNode;
127
127
  }
128
128
  }
129
- for (const shadow of shadowTargets) {
130
- if (!currentShadows.has(shadow)) {
131
- shadow.removeEventListener("focusin", focusInHandler, true);
132
- shadow.removeEventListener("focusout", focusOutHandler, true);
133
- shadowTargets.delete(shadow);
129
+ for (const shadowRootWeakRef of shadowTargets) {
130
+ const shadowRoot = shadowRootWeakRef.deref();
131
+ if (!shadowRoot || !currentShadows.has(shadowRoot)) {
132
+ shadowTargets.delete(shadowRootWeakRef);
133
+ if (shadowRoot) {
134
+ shadowRoot.removeEventListener("focusin", focusInHandler, true);
135
+ shadowRoot.removeEventListener("focusout", focusOutHandler, true);
136
+ }
134
137
  }
135
138
  }
136
139
  onFocusIn(target, e.relatedTarget || void 0);
@@ -139,12 +142,14 @@ function setupFocusEvent(win) {
139
142
  var _a;
140
143
  const shadowRoot = target.shadowRoot;
141
144
  if (shadowRoot) {
142
- if (shadowTargets.has(shadowRoot)) {
143
- return;
145
+ for (const shadowRootWeakRef of shadowTargets) {
146
+ if (shadowRootWeakRef.deref() === shadowRoot) {
147
+ return;
148
+ }
144
149
  }
145
150
  shadowRoot.addEventListener("focusin", focusInHandler, true);
146
151
  shadowRoot.addEventListener("focusout", focusOutHandler, true);
147
- shadowTargets.add(shadowRoot);
152
+ shadowTargets.add(new WeakRefInstance(shadowRoot));
148
153
  return;
149
154
  }
150
155
  const details = {
@@ -212,17 +217,20 @@ function disposeFocusEvent(win) {
212
217
  keyborgNativeFocusEvent.focusOutHandler,
213
218
  true
214
219
  );
215
- for (const shadow of keyborgNativeFocusEvent.shadowTargets) {
216
- shadow.removeEventListener(
217
- "focusin",
218
- keyborgNativeFocusEvent.focusInHandler,
219
- true
220
- );
221
- shadow.removeEventListener(
222
- "focusout",
223
- keyborgNativeFocusEvent.focusOutHandler,
224
- true
225
- );
220
+ for (const shadowRootWeakRef of keyborgNativeFocusEvent.shadowTargets) {
221
+ const shadowRoot = shadowRootWeakRef.deref();
222
+ if (shadowRoot) {
223
+ shadowRoot.removeEventListener(
224
+ "focusin",
225
+ keyborgNativeFocusEvent.focusInHandler,
226
+ true
227
+ );
228
+ shadowRoot.removeEventListener(
229
+ "focusout",
230
+ keyborgNativeFocusEvent.focusOutHandler,
231
+ true
232
+ );
233
+ }
226
234
  }
227
235
  keyborgNativeFocusEvent.shadowTargets.clear();
228
236
  delete kwin.__keyborgData;
@@ -240,50 +248,14 @@ function getLastFocusedProgrammatically(win) {
240
248
  // src/Keyborg.ts
241
249
  var _dismissTimeout = 500;
242
250
  var _lastId = 0;
243
- var KeyborgState = class {
244
- constructor() {
245
- this.__keyborgCoreRefs = {};
246
- this._isNavigatingWithKeyboard = false;
247
- }
248
- add(keyborg) {
249
- const id = keyborg.id;
250
- if (!(id in this.__keyborgCoreRefs)) {
251
- this.__keyborgCoreRefs[id] = new WeakRefInstance(keyborg);
252
- }
253
- }
254
- remove(id) {
255
- delete this.__keyborgCoreRefs[id];
256
- if (Object.keys(this.__keyborgCoreRefs).length === 0) {
257
- this._isNavigatingWithKeyboard = false;
258
- }
259
- }
260
- setVal(isNavigatingWithKeyboard) {
261
- if (this._isNavigatingWithKeyboard === isNavigatingWithKeyboard) {
262
- return;
263
- }
264
- this._isNavigatingWithKeyboard = isNavigatingWithKeyboard;
265
- for (const id of Object.keys(this.__keyborgCoreRefs)) {
266
- const ref = this.__keyborgCoreRefs[id];
267
- const keyborg = ref.deref();
268
- if (keyborg) {
269
- keyborg.update(isNavigatingWithKeyboard);
270
- } else {
271
- this.remove(id);
272
- }
273
- }
274
- }
275
- getVal() {
276
- return this._isNavigatingWithKeyboard;
277
- }
278
- };
279
- var _state = new KeyborgState();
280
251
  var KeyborgCore = class {
281
252
  constructor(win, props) {
253
+ this._isNavigatingWithKeyboard_DO_NOT_USE = false;
282
254
  this._onFocusIn = (e) => {
283
255
  if (this._isMouseUsedTimer) {
284
256
  return;
285
257
  }
286
- if (_state.getVal()) {
258
+ if (this.isNavigatingWithKeyboard) {
287
259
  return;
288
260
  }
289
261
  const details = e.detail;
@@ -293,7 +265,7 @@ var KeyborgCore = class {
293
265
  if (details.isFocusedProgrammatically || details.isFocusedProgrammatically === void 0) {
294
266
  return;
295
267
  }
296
- _state.setVal(true);
268
+ this.isNavigatingWithKeyboard = true;
297
269
  };
298
270
  this._onMouseDown = (e) => {
299
271
  if (e.buttons === 0 || e.clientX === 0 && e.clientY === 0 && e.screenX === 0 && e.screenY === 0) {
@@ -308,17 +280,17 @@ var KeyborgCore = class {
308
280
  delete this._isMouseUsedTimer;
309
281
  }, 1e3);
310
282
  }
311
- _state.setVal(false);
283
+ this.isNavigatingWithKeyboard = false;
312
284
  };
313
285
  this._onKeyDown = (e) => {
314
- const isNavigatingWithKeyboard = _state.getVal();
286
+ const isNavigatingWithKeyboard = this.isNavigatingWithKeyboard;
315
287
  if (isNavigatingWithKeyboard) {
316
288
  if (this._shouldDismissKeyboardNavigation(e)) {
317
289
  this._scheduleDismiss();
318
290
  }
319
291
  } else {
320
292
  if (this._shouldTriggerKeyboardNavigation(e)) {
321
- _state.setVal(true);
293
+ this.isNavigatingWithKeyboard = true;
322
294
  }
323
295
  }
324
296
  };
@@ -339,7 +311,15 @@ var KeyborgCore = class {
339
311
  doc.addEventListener("mousedown", this._onMouseDown, true);
340
312
  win.addEventListener("keydown", this._onKeyDown, true);
341
313
  setupFocusEvent(win);
342
- _state.add(this);
314
+ }
315
+ get isNavigatingWithKeyboard() {
316
+ return this._isNavigatingWithKeyboard_DO_NOT_USE;
317
+ }
318
+ set isNavigatingWithKeyboard(val) {
319
+ if (this._isNavigatingWithKeyboard_DO_NOT_USE !== val) {
320
+ this._isNavigatingWithKeyboard_DO_NOT_USE = val;
321
+ this.update();
322
+ }
343
323
  }
344
324
  dispose() {
345
325
  const win = this._win;
@@ -358,7 +338,6 @@ var KeyborgCore = class {
358
338
  doc.removeEventListener("mousedown", this._onMouseDown, true);
359
339
  win.removeEventListener("keydown", this._onKeyDown, true);
360
340
  delete this._win;
361
- _state.remove(this.id);
362
341
  }
363
342
  }
364
343
  isDisposed() {
@@ -367,12 +346,12 @@ var KeyborgCore = class {
367
346
  /**
368
347
  * Updates all keyborg instances with the keyboard navigation state
369
348
  */
370
- update(isNavigatingWithKeyboard) {
349
+ update() {
371
350
  var _a, _b;
372
351
  const keyborgs = (_b = (_a = this._win) == null ? void 0 : _a.__keyborg) == null ? void 0 : _b.refs;
373
352
  if (keyborgs) {
374
353
  for (const id of Object.keys(keyborgs)) {
375
- Keyborg.update(keyborgs[id], isNavigatingWithKeyboard);
354
+ Keyborg.update(keyborgs[id], this.isNavigatingWithKeyboard);
376
355
  }
377
356
  }
378
357
  }
@@ -408,7 +387,7 @@ var KeyborgCore = class {
408
387
  this._dismissTimer = void 0;
409
388
  const cur = win.document.activeElement;
410
389
  if (was && cur && was === cur) {
411
- _state.setVal(false);
390
+ this.isNavigatingWithKeyboard = false;
412
391
  }
413
392
  }, _dismissTimeout);
414
393
  }
@@ -465,7 +444,8 @@ var Keyborg = class _Keyborg {
465
444
  * @returns Whether the user is navigating with keyboard
466
445
  */
467
446
  isNavigatingWithKeyboard() {
468
- return _state.getVal();
447
+ var _a;
448
+ return !!((_a = this._core) == null ? void 0 : _a.isNavigatingWithKeyboard);
469
449
  }
470
450
  /**
471
451
  * @param callback - Called when the keyboard navigation state changes
@@ -486,7 +466,9 @@ var Keyborg = class _Keyborg {
486
466
  * Manually set the keyboard navigtion state
487
467
  */
488
468
  setVal(isNavigatingWithKeyboard) {
489
- _state.setVal(isNavigatingWithKeyboard);
469
+ if (this._core) {
470
+ this._core.isNavigatingWithKeyboard = isNavigatingWithKeyboard;
471
+ }
490
472
  }
491
473
  };
492
474
  function createKeyborg(win, props) {
@@ -497,7 +479,7 @@ function disposeKeyborg(instance) {
497
479
  }
498
480
 
499
481
  // src/index.ts
500
- var version = "2.5.0-canary.0";
482
+ var version = "2.5.0";
501
483
  // Annotate the CommonJS export names for ESM import in node:
502
484
  0 && (module.exports = {
503
485
  KEYBORG_FOCUSIN,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/WeakRefInstance.ts","../src/FocusEvent.ts","../src/Keyborg.ts"],"sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport type { Keyborg, KeyborgCallback } from \"./Keyborg\";\nexport { createKeyborg, disposeKeyborg } from \"./Keyborg\";\n\nexport type {\n KeyborgFocusInEvent,\n KeyborgFocusInEventDetails,\n KeyborgFocusOutEvent,\n KeyborgFocusOutEventDetails,\n} from \"./FocusEvent\";\nexport {\n getLastFocusedProgrammatically,\n nativeFocus,\n KEYBORG_FOCUSIN,\n KEYBORG_FOCUSOUT,\n} from \"./FocusEvent\";\n\nexport const version = process.env.PKG_VERSION;\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// IE11 compat, checks if WeakRef is supported\nexport const _canUseWeakRef = typeof WeakRef !== \"undefined\";\n\n/**\n * Allows disposable instances to be used\n */\nexport interface Disposable {\n isDisposed?(): boolean;\n}\n\n/**\n * WeakRef wrapper around a HTMLElement that also supports IE11\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef}\n * @internal\n */\nexport class WeakRefInstance<T extends Disposable | object> {\n private _weakRef?: WeakRef<T>;\n private _instance?: T;\n\n constructor(instance: T) {\n if (_canUseWeakRef && typeof instance === \"object\") {\n this._weakRef = new WeakRef(instance);\n } else {\n this._instance = instance;\n }\n }\n\n /**\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef/deref}\n */\n deref(): T | undefined {\n let instance: T | undefined;\n\n if (this._weakRef) {\n instance = this._weakRef?.deref();\n\n if (!instance) {\n delete this._weakRef;\n }\n } else {\n instance = this._instance;\n if ((instance as Disposable)?.isDisposed?.()) {\n delete this._instance;\n }\n }\n\n return instance;\n }\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { WeakRefInstance } from \"./WeakRefInstance\";\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\ninterface KeyborgFocusEventData {\n focusInHandler: (e: FocusEvent) => void;\n focusOutHandler: (e: FocusEvent) => void;\n lastFocusedProgrammatically?: WeakRefInstance<HTMLElement>;\n shadowTargets: Set<ShadowRoot>;\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\n 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\n if (!_canOverrideNativeFocus) {\n _canOverrideNativeFocus = canOverrideNativeFocus(kwin);\n }\n\n const origFocus = kwin.HTMLElement.prototype.focus;\n\n if ((origFocus as KeyborgFocus).__keyborgNativeFocus) {\n // Already set up.\n return;\n }\n\n kwin.HTMLElement.prototype.focus = focus;\n\n const shadowTargets: Set<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 = target;\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 shadow of shadowTargets) {\n if (!currentShadows.has(shadow)) {\n shadow.removeEventListener(\"focusin\", focusInHandler, true);\n shadow.removeEventListener(\"focusout\", focusOutHandler, true);\n shadowTargets.delete(shadow);\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 if (shadowTargets.has(shadowRoot)) {\n return;\n }\n\n shadowRoot.addEventListener(\"focusin\", focusInHandler, true);\n shadowRoot.addEventListener(\"focusout\", focusOutHandler, true);\n\n shadowTargets.add(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.lastFocusedProgrammatically) {\n details.isFocusedProgrammatically =\n target === data.lastFocusedProgrammatically?.deref();\n\n data.lastFocusedProgrammatically = undefined;\n }\n\n target.dispatchEvent(event);\n };\n\n const data: KeyborgFocusEventData = (kwin.__keyborgData = {\n focusInHandler,\n focusOutHandler,\n shadowTargets,\n });\n\n kwin.document.addEventListener(\n \"focusin\",\n kwin.__keyborgData.focusInHandler,\n true,\n );\n\n kwin.document.addEventListener(\n \"focusout\",\n kwin.__keyborgData.focusOutHandler,\n true,\n );\n\n function focus(this: HTMLElement) {\n const keyborgNativeFocusEvent = (kwin as WindowWithKeyborgFocusEvent)\n .__keyborgData;\n\n if (keyborgNativeFocusEvent) {\n keyborgNativeFocusEvent.lastFocusedProgrammatically = new WeakRefInstance(\n this,\n );\n }\n\n // eslint-disable-next-line prefer-rest-params\n return origFocus.apply(this, arguments);\n }\n\n let activeElement = kwin.document.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 keyborgNativeFocusEvent = kwin.__keyborgData;\n\n if (keyborgNativeFocusEvent) {\n kwin.document.removeEventListener(\n \"focusin\",\n keyborgNativeFocusEvent.focusInHandler,\n true,\n );\n\n kwin.document.removeEventListener(\n \"focusout\",\n keyborgNativeFocusEvent.focusOutHandler,\n true,\n );\n\n for (const shadow of keyborgNativeFocusEvent.shadowTargets) {\n shadow.removeEventListener(\n \"focusin\",\n keyborgNativeFocusEvent.focusInHandler,\n true,\n );\n shadow.removeEventListener(\n \"focusout\",\n keyborgNativeFocusEvent.focusOutHandler,\n true,\n );\n }\n\n keyborgNativeFocusEvent.shadowTargets.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 keyborgNativeFocusEvent = (win as WindowWithKeyborgFocusEvent)\n .__keyborgData;\n\n return keyborgNativeFocusEvent\n ? keyborgNativeFocusEvent.lastFocusedProgrammatically?.deref() || null\n : undefined;\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n disposeFocusEvent,\n KeyborgFocusInEvent,\n KEYBORG_FOCUSIN,\n setupFocusEvent,\n} from \"./FocusEvent\";\nimport { Disposable, WeakRefInstance } from \"./WeakRefInstance\";\n\ninterface WindowWithKeyborg extends Window {\n __keyborg?: {\n core: KeyborgCore;\n refs: { [id: string]: Keyborg };\n };\n}\n\nconst _dismissTimeout = 500; // When a key from dismissKeys is pressed and the focus is not moved\n// during _dismissTimeout time, dismiss the keyboard navigation mode.\n\nlet _lastId = 0;\n\nexport interface KeyborgProps {\n // Keys to be used to trigger keyboard navigation mode. By default, any key will trigger\n // it. Could be limited to, for example, just Tab (or Tab and arrow keys).\n triggerKeys?: number[];\n // Keys to be used to dismiss keyboard navigation mode using keyboard (in addition to\n // mouse clicks which dismiss it). For example, Esc could be used to dismiss.\n dismissKeys?: number[];\n}\n\nexport type KeyborgCallback = (isNavigatingWithKeyboard: boolean) => void;\n\n/**\n * Source of truth for all the keyborg core instances and the current keyboard navigation state\n */\nexport class KeyborgState {\n private __keyborgCoreRefs: { [id: string]: WeakRefInstance<KeyborgCore> } =\n {};\n private _isNavigatingWithKeyboard = false;\n\n add(keyborg: KeyborgCore): void {\n const id = keyborg.id;\n\n if (!(id in this.__keyborgCoreRefs)) {\n this.__keyborgCoreRefs[id] = new WeakRefInstance<KeyborgCore>(keyborg);\n }\n }\n\n remove(id: string): void {\n delete this.__keyborgCoreRefs[id];\n\n if (Object.keys(this.__keyborgCoreRefs).length === 0) {\n this._isNavigatingWithKeyboard = false;\n }\n }\n\n setVal(isNavigatingWithKeyboard: boolean): void {\n if (this._isNavigatingWithKeyboard === isNavigatingWithKeyboard) {\n return;\n }\n\n this._isNavigatingWithKeyboard = isNavigatingWithKeyboard;\n\n for (const id of Object.keys(this.__keyborgCoreRefs)) {\n const ref = this.__keyborgCoreRefs[id];\n const keyborg = ref.deref();\n\n if (keyborg) {\n keyborg.update(isNavigatingWithKeyboard);\n } else {\n this.remove(id);\n }\n }\n }\n\n getVal(): boolean {\n return this._isNavigatingWithKeyboard;\n }\n}\n\nconst _state = new KeyborgState();\n\n/**\n * Manages a collection of Keyborg instances in a window/document and updates keyborg state\n */\nclass KeyborgCore implements Disposable {\n readonly id: string;\n\n private _win?: WindowWithKeyborg;\n private _isMouseUsedTimer: number | undefined;\n private _dismissTimer: number | undefined;\n private _triggerKeys?: Set<number>;\n private _dismissKeys?: Set<number>;\n\n constructor(win: WindowWithKeyborg, props?: KeyborgProps) {\n this.id = \"c\" + ++_lastId;\n this._win = win;\n const doc = win.document;\n\n if (props) {\n const triggerKeys = props.triggerKeys;\n const dismissKeys = props.dismissKeys;\n\n if (triggerKeys?.length) {\n this._triggerKeys = new Set(triggerKeys);\n }\n\n if (dismissKeys?.length) {\n this._dismissKeys = new Set(dismissKeys);\n }\n }\n\n doc.addEventListener(KEYBORG_FOCUSIN, this._onFocusIn, true); // Capture!\n doc.addEventListener(\"mousedown\", this._onMouseDown, true); // Capture!\n win.addEventListener(\"keydown\", this._onKeyDown, true); // Capture!\n\n setupFocusEvent(win);\n\n _state.add(this);\n }\n\n dispose(): void {\n const win = this._win;\n\n if (win) {\n if (this._isMouseUsedTimer) {\n win.clearTimeout(this._isMouseUsedTimer);\n this._isMouseUsedTimer = undefined;\n }\n\n if (this._dismissTimer) {\n win.clearTimeout(this._dismissTimer);\n this._dismissTimer = undefined;\n }\n\n disposeFocusEvent(win);\n\n const doc = win.document;\n\n doc.removeEventListener(KEYBORG_FOCUSIN, this._onFocusIn, true); // Capture!\n doc.removeEventListener(\"mousedown\", this._onMouseDown, true); // Capture!\n win.removeEventListener(\"keydown\", this._onKeyDown, true); // Capture!\n\n delete this._win;\n\n _state.remove(this.id);\n }\n }\n\n isDisposed(): boolean {\n return !!this._win;\n }\n\n /**\n * Updates all keyborg instances with the keyboard navigation state\n */\n update(isNavigatingWithKeyboard: boolean): void {\n const keyborgs = this._win?.__keyborg?.refs;\n\n if (keyborgs) {\n for (const id of Object.keys(keyborgs)) {\n Keyborg.update(keyborgs[id], isNavigatingWithKeyboard);\n }\n }\n }\n\n private _onFocusIn = (e: KeyborgFocusInEvent) => {\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 swallow\n // the events when the screen reader shortcuts are used). The screen reader\n // usage is keyboard navigation.\n\n if (this._isMouseUsedTimer) {\n // There was a mouse event recently.\n return;\n }\n\n if (_state.getVal()) {\n return;\n }\n\n const details = e.detail;\n\n if (!details.relatedTarget) {\n return;\n }\n\n if (\n details.isFocusedProgrammatically ||\n details.isFocusedProgrammatically === undefined\n ) {\n // The element is focused programmatically, or the programmatic focus detection\n // is not working.\n return;\n }\n\n _state.setVal(true);\n };\n\n private _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 perform\n // an action on an element, do not dismiss the keyboard navigation mode.\n return;\n }\n\n const win = this._win;\n\n if (win) {\n if (this._isMouseUsedTimer) {\n win.clearTimeout(this._isMouseUsedTimer);\n }\n\n this._isMouseUsedTimer = win.setTimeout(() => {\n delete this._isMouseUsedTimer;\n }, 1000); // Keeping the indication of the mouse usage for some time.\n }\n\n _state.setVal(false);\n };\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n const isNavigatingWithKeyboard = _state.getVal();\n\n if (isNavigatingWithKeyboard) {\n if (this._shouldDismissKeyboardNavigation(e)) {\n this._scheduleDismiss();\n }\n } else {\n if (this._shouldTriggerKeyboardNavigation(e)) {\n _state.setVal(true);\n }\n }\n };\n\n /**\n * @returns whether the keyboard event should trigger keyboard navigation mode\n */\n private _shouldTriggerKeyboardNavigation(e: KeyboardEvent) {\n // TODO Some rich text fields can allow Tab key for indentation so it doesn't\n // need to be a navigation key. If there is a bug regarding that we should revisit\n if (e.key === \"Tab\") {\n return true;\n }\n\n const activeElement = this._win?.document\n .activeElement as HTMLElement | null;\n const isTriggerKey = !this._triggerKeys || this._triggerKeys.has(e.keyCode);\n\n const isEditable =\n activeElement &&\n (activeElement.tagName === \"INPUT\" ||\n activeElement.tagName === \"TEXTAREA\" ||\n activeElement.isContentEditable);\n\n return isTriggerKey && !isEditable;\n }\n\n /**\n * @returns whether the keyboard event should dismiss keyboard navigation mode\n */\n private _shouldDismissKeyboardNavigation(e: KeyboardEvent) {\n return this._dismissKeys?.has(e.keyCode);\n }\n\n private _scheduleDismiss(): void {\n const win = this._win;\n\n if (win) {\n if (this._dismissTimer) {\n win.clearTimeout(this._dismissTimer);\n this._dismissTimer = undefined;\n }\n\n const was = win.document.activeElement;\n\n this._dismissTimer = win.setTimeout(() => {\n this._dismissTimer = undefined;\n\n const cur = win.document.activeElement;\n\n if (was && cur && was === cur) {\n // Esc was pressed, currently focused element hasn't changed.\n // Just dismiss the keyboard navigation mode.\n _state.setVal(false);\n }\n }, _dismissTimeout);\n }\n }\n}\n\n/**\n * Used to determine the keyboard navigation state\n */\nexport class Keyborg {\n private _id: string;\n private _win?: WindowWithKeyborg;\n private _core?: KeyborgCore;\n private _cb: KeyborgCallback[] = [];\n\n static create(win: WindowWithKeyborg, props?: KeyborgProps): Keyborg {\n return new Keyborg(win, props);\n }\n\n static dispose(instance: Keyborg): void {\n instance.dispose();\n }\n\n /**\n * Updates all subscribed callbacks with the keyboard navigation state\n */\n static update(instance: Keyborg, isNavigatingWithKeyboard: boolean): void {\n instance._cb.forEach((callback) => callback(isNavigatingWithKeyboard));\n }\n\n private constructor(win: WindowWithKeyborg, props?: KeyborgProps) {\n this._id = \"k\" + ++_lastId;\n this._win = win;\n\n const current = win.__keyborg;\n\n if (current) {\n this._core = current.core;\n current.refs[this._id] = this;\n } else {\n this._core = new KeyborgCore(win, props);\n win.__keyborg = {\n core: this._core,\n refs: { [this._id]: this },\n };\n }\n }\n\n private dispose(): void {\n const current = this._win?.__keyborg;\n\n if (current?.refs[this._id]) {\n delete current.refs[this._id];\n\n if (Object.keys(current.refs).length === 0) {\n current.core.dispose();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n delete this._win!.__keyborg;\n }\n } else if (process.env.NODE_ENV !== \"production\") {\n console.error(\n `Keyborg instance ${this._id} is being disposed incorrectly.`,\n );\n }\n\n this._cb = [];\n delete this._core;\n delete this._win;\n }\n\n /**\n * @returns Whether the user is navigating with keyboard\n */\n isNavigatingWithKeyboard(): boolean {\n return _state.getVal();\n }\n\n /**\n * @param callback - Called when the keyboard navigation state changes\n */\n subscribe(callback: KeyborgCallback): void {\n this._cb.push(callback);\n }\n\n /**\n * @param callback - Registered with subscribe\n */\n unsubscribe(callback: KeyborgCallback): void {\n const index = this._cb.indexOf(callback);\n\n if (index >= 0) {\n this._cb.splice(index, 1);\n }\n }\n\n /**\n * Manually set the keyboard navigtion state\n */\n setVal(isNavigatingWithKeyboard: boolean): void {\n _state.setVal(isNavigatingWithKeyboard);\n }\n}\n\nexport function createKeyborg(win: Window, props?: KeyborgProps): Keyborg {\n return Keyborg.create(win, props);\n}\n\nexport function disposeKeyborg(instance: Keyborg) {\n Keyborg.dispose(instance);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/WeakRefInstance.ts","../src/FocusEvent.ts","../src/Keyborg.ts"],"sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport type { Keyborg, KeyborgCallback } from \"./Keyborg\";\nexport { createKeyborg, disposeKeyborg } from \"./Keyborg\";\n\nexport type {\n KeyborgFocusInEvent,\n KeyborgFocusInEventDetails,\n KeyborgFocusOutEvent,\n KeyborgFocusOutEventDetails,\n} from \"./FocusEvent\";\nexport {\n getLastFocusedProgrammatically,\n nativeFocus,\n KEYBORG_FOCUSIN,\n KEYBORG_FOCUSOUT,\n} from \"./FocusEvent\";\n\nexport const version = process.env.PKG_VERSION;\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// IE11 compat, checks if WeakRef is supported\nexport const _canUseWeakRef = typeof WeakRef !== \"undefined\";\n\n/**\n * Allows disposable instances to be used\n */\nexport interface Disposable {\n isDisposed?(): boolean;\n}\n\n/**\n * WeakRef wrapper around a HTMLElement that also supports IE11\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef}\n * @internal\n */\nexport class WeakRefInstance<T extends Disposable | object> {\n private _weakRef?: WeakRef<T>;\n private _instance?: T;\n\n constructor(instance: T) {\n if (_canUseWeakRef && typeof instance === \"object\") {\n this._weakRef = new WeakRef(instance);\n } else {\n this._instance = instance;\n }\n }\n\n /**\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef/deref}\n */\n deref(): T | undefined {\n let instance: T | undefined;\n\n if (this._weakRef) {\n instance = this._weakRef?.deref();\n\n if (!instance) {\n delete this._weakRef;\n }\n } else {\n instance = this._instance;\n if ((instance as Disposable)?.isDisposed?.()) {\n delete this._instance;\n }\n }\n\n return instance;\n }\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\nimport { WeakRefInstance } from \"./WeakRefInstance\";\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\ninterface KeyborgFocusEventData {\n focusInHandler: (e: FocusEvent) => void;\n focusOutHandler: (e: FocusEvent) => void;\n lastFocusedProgrammatically?: WeakRefInstance<HTMLElement>;\n shadowTargets: Set<WeakRefInstance<ShadowRoot>>;\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\n 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\n if (!_canOverrideNativeFocus) {\n _canOverrideNativeFocus = canOverrideNativeFocus(kwin);\n }\n\n const origFocus = kwin.HTMLElement.prototype.focus;\n\n if ((origFocus as KeyborgFocus).__keyborgNativeFocus) {\n // Already set up.\n return;\n }\n\n kwin.HTMLElement.prototype.focus = focus;\n\n const shadowTargets: Set<WeakRefInstance<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 shadowRoot.removeEventListener(\"focusin\", focusInHandler, true);\n shadowRoot.removeEventListener(\"focusout\", focusOutHandler, true);\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 shadowRoot.addEventListener(\"focusin\", focusInHandler, true);\n shadowRoot.addEventListener(\"focusout\", focusOutHandler, true);\n\n shadowTargets.add(new WeakRefInstance(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.lastFocusedProgrammatically) {\n details.isFocusedProgrammatically =\n target === data.lastFocusedProgrammatically?.deref();\n\n data.lastFocusedProgrammatically = undefined;\n }\n\n target.dispatchEvent(event);\n };\n\n const data: KeyborgFocusEventData = (kwin.__keyborgData = {\n focusInHandler,\n focusOutHandler,\n shadowTargets,\n });\n\n kwin.document.addEventListener(\n \"focusin\",\n kwin.__keyborgData.focusInHandler,\n true,\n );\n\n kwin.document.addEventListener(\n \"focusout\",\n kwin.__keyborgData.focusOutHandler,\n true,\n );\n\n function focus(this: HTMLElement) {\n const keyborgNativeFocusEvent = (kwin as WindowWithKeyborgFocusEvent)\n .__keyborgData;\n\n if (keyborgNativeFocusEvent) {\n keyborgNativeFocusEvent.lastFocusedProgrammatically = new WeakRefInstance(\n this,\n );\n }\n\n // eslint-disable-next-line prefer-rest-params\n return origFocus.apply(this, arguments);\n }\n\n let activeElement = kwin.document.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 keyborgNativeFocusEvent = kwin.__keyborgData;\n\n if (keyborgNativeFocusEvent) {\n kwin.document.removeEventListener(\n \"focusin\",\n keyborgNativeFocusEvent.focusInHandler,\n true,\n );\n\n kwin.document.removeEventListener(\n \"focusout\",\n keyborgNativeFocusEvent.focusOutHandler,\n true,\n );\n\n for (const shadowRootWeakRef of keyborgNativeFocusEvent.shadowTargets) {\n const shadowRoot = shadowRootWeakRef.deref();\n\n if (shadowRoot) {\n shadowRoot.removeEventListener(\n \"focusin\",\n keyborgNativeFocusEvent.focusInHandler,\n true,\n );\n shadowRoot.removeEventListener(\n \"focusout\",\n keyborgNativeFocusEvent.focusOutHandler,\n true,\n );\n }\n }\n\n keyborgNativeFocusEvent.shadowTargets.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 keyborgNativeFocusEvent = (win as WindowWithKeyborgFocusEvent)\n .__keyborgData;\n\n return keyborgNativeFocusEvent\n ? keyborgNativeFocusEvent.lastFocusedProgrammatically?.deref() || null\n : undefined;\n}\n","/*!\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n disposeFocusEvent,\n KeyborgFocusInEvent,\n KEYBORG_FOCUSIN,\n setupFocusEvent,\n} from \"./FocusEvent\";\nimport { Disposable } from \"./WeakRefInstance\";\n\ninterface WindowWithKeyborg extends Window {\n __keyborg?: {\n core: KeyborgCore;\n refs: { [id: string]: Keyborg };\n };\n}\n\nconst _dismissTimeout = 500; // When a key from dismissKeys is pressed and the focus is not moved\n// during _dismissTimeout time, dismiss the keyboard navigation mode.\n\nlet _lastId = 0;\n\nexport interface KeyborgProps {\n // Keys to be used to trigger keyboard navigation mode. By default, any key will trigger\n // it. Could be limited to, for example, just Tab (or Tab and arrow keys).\n triggerKeys?: number[];\n // Keys to be used to dismiss keyboard navigation mode using keyboard (in addition to\n // mouse clicks which dismiss it). For example, Esc could be used to dismiss.\n dismissKeys?: number[];\n}\n\nexport type KeyborgCallback = (isNavigatingWithKeyboard: boolean) => void;\n\n/**\n * Manages a collection of Keyborg instances in a window/document and updates keyborg state\n */\nclass KeyborgCore implements Disposable {\n readonly id: string;\n\n private _win?: WindowWithKeyborg;\n private _isMouseUsedTimer: number | undefined;\n private _dismissTimer: number | undefined;\n private _triggerKeys?: Set<number>;\n private _dismissKeys?: Set<number>;\n private _isNavigatingWithKeyboard_DO_NOT_USE = false;\n\n constructor(win: WindowWithKeyborg, props?: KeyborgProps) {\n this.id = \"c\" + ++_lastId;\n this._win = win;\n const doc = win.document;\n\n if (props) {\n const triggerKeys = props.triggerKeys;\n const dismissKeys = props.dismissKeys;\n\n if (triggerKeys?.length) {\n this._triggerKeys = new Set(triggerKeys);\n }\n\n if (dismissKeys?.length) {\n this._dismissKeys = new Set(dismissKeys);\n }\n }\n\n doc.addEventListener(KEYBORG_FOCUSIN, this._onFocusIn, true); // Capture!\n doc.addEventListener(\"mousedown\", this._onMouseDown, true); // Capture!\n win.addEventListener(\"keydown\", this._onKeyDown, true); // Capture!\n\n setupFocusEvent(win);\n }\n\n get isNavigatingWithKeyboard() {\n return this._isNavigatingWithKeyboard_DO_NOT_USE;\n }\n\n set isNavigatingWithKeyboard(val: boolean) {\n if (this._isNavigatingWithKeyboard_DO_NOT_USE !== val) {\n this._isNavigatingWithKeyboard_DO_NOT_USE = val;\n this.update();\n }\n }\n\n dispose(): void {\n const win = this._win;\n\n if (win) {\n if (this._isMouseUsedTimer) {\n win.clearTimeout(this._isMouseUsedTimer);\n this._isMouseUsedTimer = undefined;\n }\n\n if (this._dismissTimer) {\n win.clearTimeout(this._dismissTimer);\n this._dismissTimer = undefined;\n }\n\n disposeFocusEvent(win);\n\n const doc = win.document;\n\n doc.removeEventListener(KEYBORG_FOCUSIN, this._onFocusIn, true); // Capture!\n doc.removeEventListener(\"mousedown\", this._onMouseDown, true); // Capture!\n win.removeEventListener(\"keydown\", this._onKeyDown, true); // Capture!\n\n delete this._win;\n }\n }\n\n isDisposed(): boolean {\n return !!this._win;\n }\n\n /**\n * Updates all keyborg instances with the keyboard navigation state\n */\n update(): void {\n const keyborgs = this._win?.__keyborg?.refs;\n\n if (keyborgs) {\n for (const id of Object.keys(keyborgs)) {\n Keyborg.update(keyborgs[id], this.isNavigatingWithKeyboard);\n }\n }\n }\n\n private _onFocusIn = (e: KeyborgFocusInEvent) => {\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 swallow\n // the events when the screen reader shortcuts are used). The screen reader\n // usage is keyboard navigation.\n\n if (this._isMouseUsedTimer) {\n // There was a mouse event recently.\n return;\n }\n\n if (this.isNavigatingWithKeyboard) {\n return;\n }\n\n const details = e.detail;\n\n if (!details.relatedTarget) {\n return;\n }\n\n if (\n details.isFocusedProgrammatically ||\n details.isFocusedProgrammatically === undefined\n ) {\n // The element is focused programmatically, or the programmatic focus detection\n // is not working.\n return;\n }\n\n this.isNavigatingWithKeyboard = true;\n };\n\n private _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 perform\n // an action on an element, do not dismiss the keyboard navigation mode.\n return;\n }\n\n const win = this._win;\n\n if (win) {\n if (this._isMouseUsedTimer) {\n win.clearTimeout(this._isMouseUsedTimer);\n }\n\n this._isMouseUsedTimer = win.setTimeout(() => {\n delete this._isMouseUsedTimer;\n }, 1000); // Keeping the indication of the mouse usage for some time.\n }\n\n this.isNavigatingWithKeyboard = false;\n };\n\n private _onKeyDown = (e: KeyboardEvent): void => {\n const isNavigatingWithKeyboard = this.isNavigatingWithKeyboard;\n\n if (isNavigatingWithKeyboard) {\n if (this._shouldDismissKeyboardNavigation(e)) {\n this._scheduleDismiss();\n }\n } else {\n if (this._shouldTriggerKeyboardNavigation(e)) {\n this.isNavigatingWithKeyboard = true;\n }\n }\n };\n\n /**\n * @returns whether the keyboard event should trigger keyboard navigation mode\n */\n private _shouldTriggerKeyboardNavigation(e: KeyboardEvent) {\n // TODO Some rich text fields can allow Tab key for indentation so it doesn't\n // need to be a navigation key. If there is a bug regarding that we should revisit\n if (e.key === \"Tab\") {\n return true;\n }\n\n const activeElement = this._win?.document\n .activeElement as HTMLElement | null;\n const isTriggerKey = !this._triggerKeys || this._triggerKeys.has(e.keyCode);\n\n const isEditable =\n activeElement &&\n (activeElement.tagName === \"INPUT\" ||\n activeElement.tagName === \"TEXTAREA\" ||\n activeElement.isContentEditable);\n\n return isTriggerKey && !isEditable;\n }\n\n /**\n * @returns whether the keyboard event should dismiss keyboard navigation mode\n */\n private _shouldDismissKeyboardNavigation(e: KeyboardEvent) {\n return this._dismissKeys?.has(e.keyCode);\n }\n\n private _scheduleDismiss(): void {\n const win = this._win;\n\n if (win) {\n if (this._dismissTimer) {\n win.clearTimeout(this._dismissTimer);\n this._dismissTimer = undefined;\n }\n\n const was = win.document.activeElement;\n\n this._dismissTimer = win.setTimeout(() => {\n this._dismissTimer = undefined;\n\n const cur = win.document.activeElement;\n\n if (was && cur && was === cur) {\n // Esc was pressed, currently focused element hasn't changed.\n // Just dismiss the keyboard navigation mode.\n this.isNavigatingWithKeyboard = false;\n }\n }, _dismissTimeout);\n }\n }\n}\n\n/**\n * Used to determine the keyboard navigation state\n */\nexport class Keyborg {\n private _id: string;\n private _win?: WindowWithKeyborg;\n private _core?: KeyborgCore;\n private _cb: KeyborgCallback[] = [];\n\n static create(win: WindowWithKeyborg, props?: KeyborgProps): Keyborg {\n return new Keyborg(win, props);\n }\n\n static dispose(instance: Keyborg): void {\n instance.dispose();\n }\n\n /**\n * Updates all subscribed callbacks with the keyboard navigation state\n */\n static update(instance: Keyborg, isNavigatingWithKeyboard: boolean): void {\n instance._cb.forEach((callback) => callback(isNavigatingWithKeyboard));\n }\n\n private constructor(win: WindowWithKeyborg, props?: KeyborgProps) {\n this._id = \"k\" + ++_lastId;\n this._win = win;\n\n const current = win.__keyborg;\n\n if (current) {\n this._core = current.core;\n current.refs[this._id] = this;\n } else {\n this._core = new KeyborgCore(win, props);\n win.__keyborg = {\n core: this._core,\n refs: { [this._id]: this },\n };\n }\n }\n\n private dispose(): void {\n const current = this._win?.__keyborg;\n\n if (current?.refs[this._id]) {\n delete current.refs[this._id];\n\n if (Object.keys(current.refs).length === 0) {\n current.core.dispose();\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n delete this._win!.__keyborg;\n }\n } else if (process.env.NODE_ENV !== \"production\") {\n console.error(\n `Keyborg instance ${this._id} is being disposed incorrectly.`,\n );\n }\n\n this._cb = [];\n delete this._core;\n delete this._win;\n }\n\n /**\n * @returns Whether the user is navigating with keyboard\n */\n isNavigatingWithKeyboard(): boolean {\n return !!this._core?.isNavigatingWithKeyboard;\n }\n\n /**\n * @param callback - Called when the keyboard navigation state changes\n */\n subscribe(callback: KeyborgCallback): void {\n this._cb.push(callback);\n }\n\n /**\n * @param callback - Registered with subscribe\n */\n unsubscribe(callback: KeyborgCallback): void {\n const index = this._cb.indexOf(callback);\n\n if (index >= 0) {\n this._cb.splice(index, 1);\n }\n }\n\n /**\n * Manually set the keyboard navigtion state\n */\n setVal(isNavigatingWithKeyboard: boolean): void {\n if (this._core) {\n this._core.isNavigatingWithKeyboard = isNavigatingWithKeyboard;\n }\n }\n}\n\nexport function createKeyborg(win: Window, props?: KeyborgProps): Keyborg {\n return Keyborg.create(win, props);\n}\n\nexport function disposeKeyborg(instance: Keyborg) {\n Keyborg.dispose(instance);\n}\n"],"mappings":"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","names":[]}
@@ -31,13 +31,15 @@ declare class KeyborgCore implements Disposable {
31
31
  private _dismissTimer;
32
32
  private _triggerKeys?;
33
33
  private _dismissKeys?;
34
+ private _isNavigatingWithKeyboard_DO_NOT_USE;
34
35
  constructor(win: WindowWithKeyborg, props?: KeyborgProps);
36
+ isNavigatingWithKeyboard: boolean;
35
37
  dispose(): void;
36
38
  isDisposed(): boolean;
37
39
  /**
38
40
  * Updates all keyborg instances with the keyboard navigation state
39
41
  */
40
- update(isNavigatingWithKeyboard: boolean): void;
42
+ update(): void;
41
43
  private _onFocusIn;
42
44
  private _onMouseDown;
43
45
  private _onKeyDown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keyborg",
3
- "version": "2.5.0-canary.0",
3
+ "version": "2.5.0",
4
4
  "description": "Keyboard Navigation Detection for Web",
5
5
  "author": "Marat Abdullin <marata@microsoft.com>",
6
6
  "license": "MIT",