keyborg 2.326.0-canary.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +347 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +62 -0
- package/dist/index.d.ts +38 -106
- package/dist/index.js +325 -491
- package/dist/index.js.map +1 -1
- package/package.json +44 -33
- package/dist/esm/index.js +0 -474
- package/dist/esm/index.js.map +0 -1
- package/dist/index.d.mts +0 -130
- package/dist/ts3.9/index.d.ts +0 -123
package/dist/index.js
CHANGED
|
@@ -1,506 +1,340 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
-
for (let key of __getOwnPropNames(from))
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
-
}
|
|
15
|
-
return to;
|
|
1
|
+
//#region src/dom.mts
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
+
* Licensed under the MIT License.
|
|
5
|
+
*/
|
|
6
|
+
const addEventListener = (target, type, handler) => {
|
|
7
|
+
target.addEventListener(type, handler, true);
|
|
16
8
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// src/index.ts
|
|
20
|
-
var src_exports = {};
|
|
21
|
-
__export(src_exports, {
|
|
22
|
-
KEYBORG_FOCUSIN: () => KEYBORG_FOCUSIN,
|
|
23
|
-
KEYBORG_FOCUSOUT: () => KEYBORG_FOCUSOUT,
|
|
24
|
-
createKeyborg: () => createKeyborg,
|
|
25
|
-
disposeKeyborg: () => disposeKeyborg,
|
|
26
|
-
getLastFocusedProgrammatically: () => getLastFocusedProgrammatically,
|
|
27
|
-
nativeFocus: () => nativeFocus,
|
|
28
|
-
version: () => version
|
|
29
|
-
});
|
|
30
|
-
module.exports = __toCommonJS(src_exports);
|
|
31
|
-
|
|
32
|
-
// src/WeakRefInstance.ts
|
|
33
|
-
var _canUseWeakRef = typeof WeakRef !== "undefined";
|
|
34
|
-
var WeakRefInstance = class {
|
|
35
|
-
constructor(instance) {
|
|
36
|
-
if (_canUseWeakRef && typeof instance === "object") {
|
|
37
|
-
this._weakRef = new WeakRef(instance);
|
|
38
|
-
} else {
|
|
39
|
-
this._instance = instance;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef/deref}
|
|
44
|
-
*/
|
|
45
|
-
deref() {
|
|
46
|
-
var _a, _b;
|
|
47
|
-
let instance;
|
|
48
|
-
if (this._weakRef) {
|
|
49
|
-
instance = (_a = this._weakRef) == null ? void 0 : _a.deref();
|
|
50
|
-
if (!instance) {
|
|
51
|
-
delete this._weakRef;
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
instance = this._instance;
|
|
55
|
-
if ((_b = instance == null ? void 0 : instance.isDisposed) == null ? void 0 : _b.call(instance)) {
|
|
56
|
-
delete this._instance;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return instance;
|
|
60
|
-
}
|
|
9
|
+
const removeEventListener = (target, type, handler) => {
|
|
10
|
+
target.removeEventListener(type, handler, true);
|
|
61
11
|
};
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
var _canOverrideNativeFocus = false;
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/FocusEvent.mts
|
|
14
|
+
/*!
|
|
15
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
16
|
+
* Licensed under the MIT License.
|
|
17
|
+
*/
|
|
18
|
+
const KEYBORG_FOCUSIN = "keyborg:focusin";
|
|
19
|
+
const KEYBORG_FOCUSOUT = "keyborg:focusout";
|
|
20
|
+
const FOCUS_IN_HANDLER = 0;
|
|
21
|
+
const FOCUS_OUT_HANDLER = 1;
|
|
22
|
+
const SHADOW_TARGETS = 2;
|
|
23
|
+
const LAST_FOCUSED_PROGRAMMATICALLY = 3;
|
|
24
|
+
/**
|
|
25
|
+
* Guarantees that the native `focus` will be used
|
|
26
|
+
*/
|
|
79
27
|
function nativeFocus(element) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
} else {
|
|
84
|
-
element.focus();
|
|
85
|
-
}
|
|
28
|
+
const focus = element.focus;
|
|
29
|
+
if (focus.__keyborgNativeFocus) focus.__keyborgNativeFocus.call(element);
|
|
30
|
+
else element.focus();
|
|
86
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Overrides the native `focus` and setups the keyborg focus event
|
|
34
|
+
*/
|
|
87
35
|
function setupFocusEvent(win) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
36
|
+
const kwin = win;
|
|
37
|
+
const doc = kwin.document;
|
|
38
|
+
const proto = kwin.HTMLElement.prototype;
|
|
39
|
+
const origFocus = proto.focus;
|
|
40
|
+
if (origFocus.__keyborgNativeFocus) return;
|
|
41
|
+
proto.focus = focus;
|
|
42
|
+
const shadowTargets = /* @__PURE__ */ new Set();
|
|
43
|
+
const focusOutHandler = (e) => {
|
|
44
|
+
const target = e.target;
|
|
45
|
+
if (!target) return;
|
|
46
|
+
const event = new CustomEvent(KEYBORG_FOCUSOUT, {
|
|
47
|
+
cancelable: true,
|
|
48
|
+
bubbles: true,
|
|
49
|
+
composed: true,
|
|
50
|
+
detail: { originalEvent: e }
|
|
51
|
+
});
|
|
52
|
+
target.dispatchEvent(event);
|
|
53
|
+
};
|
|
54
|
+
const focusInHandler = (e) => {
|
|
55
|
+
const target = e.target;
|
|
56
|
+
if (!target) return;
|
|
57
|
+
let node = e.composedPath()[0];
|
|
58
|
+
const currentShadows = /* @__PURE__ */ new Set();
|
|
59
|
+
while (node) if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
|
60
|
+
currentShadows.add(node);
|
|
61
|
+
node = node.host;
|
|
62
|
+
} else node = node.parentNode;
|
|
63
|
+
for (const shadowRootWeakRef of shadowTargets) {
|
|
64
|
+
const shadowRoot = shadowRootWeakRef.deref();
|
|
65
|
+
if (!shadowRoot || !currentShadows.has(shadowRoot)) {
|
|
66
|
+
shadowTargets.delete(shadowRootWeakRef);
|
|
67
|
+
if (shadowRoot) {
|
|
68
|
+
removeEventListener(shadowRoot, "focusin", focusInHandler);
|
|
69
|
+
removeEventListener(shadowRoot, "focusout", focusOutHandler);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
onFocusIn(target, e.relatedTarget || void 0);
|
|
74
|
+
};
|
|
75
|
+
const onFocusIn = (target, relatedTarget, originalEvent) => {
|
|
76
|
+
const shadowRoot = target.shadowRoot;
|
|
77
|
+
if (shadowRoot) {
|
|
78
|
+
/**
|
|
79
|
+
* https://bugs.chromium.org/p/chromium/issues/detail?id=1512028
|
|
80
|
+
* focusin events don't bubble up through an open shadow root once focus is inside
|
|
81
|
+
* once focus moves into a shadow root - we drop the same focusin handler there
|
|
82
|
+
* keyborg's custom event will still bubble up since it is composed
|
|
83
|
+
* event handlers should be cleaned up once focus leaves the shadow root.
|
|
84
|
+
*
|
|
85
|
+
* When a focusin event is dispatched from a shadow root, its target is the shadow root parent.
|
|
86
|
+
* Each shadow root encounter requires a new capture listener.
|
|
87
|
+
* Why capture? - we want to follow the focus event in order or descending nested shadow roots
|
|
88
|
+
* When there are no more shadow root targets - dispatch the keyborg:focusin event
|
|
89
|
+
*
|
|
90
|
+
* 1. no focus event
|
|
91
|
+
* > document - capture listener ✅
|
|
92
|
+
* > shadow root 1
|
|
93
|
+
* > shadow root 2
|
|
94
|
+
* > shadow root 3
|
|
95
|
+
* > focused element
|
|
96
|
+
*
|
|
97
|
+
* 2. focus event received by document listener
|
|
98
|
+
* > document - capture listener ✅ (focus event here)
|
|
99
|
+
* > shadow root 1 - capture listener ✅
|
|
100
|
+
* > shadow root 2
|
|
101
|
+
* > shadow root 3
|
|
102
|
+
* > focused element
|
|
103
|
+
*
|
|
104
|
+
* 3. focus event received by root l1 listener
|
|
105
|
+
* > document - capture listener ✅
|
|
106
|
+
* > shadow root 1 - capture listener ✅ (focus event here)
|
|
107
|
+
* > shadow root 2 - capture listener ✅
|
|
108
|
+
* > shadow root 3
|
|
109
|
+
* > focused element
|
|
110
|
+
*
|
|
111
|
+
* 4. focus event received by root l2 listener
|
|
112
|
+
* > document - capture listener ✅
|
|
113
|
+
* > shadow root 1 - capture listener ✅
|
|
114
|
+
* > shadow root 2 - capture listener ✅ (focus event here)
|
|
115
|
+
* > shadow root 3 - capture listener ✅
|
|
116
|
+
* > focused element
|
|
117
|
+
*
|
|
118
|
+
* 5. focus event received by root l3 listener, no more shadow root targets
|
|
119
|
+
* > document - capture listener ✅
|
|
120
|
+
* > shadow root 1 - capture listener ✅
|
|
121
|
+
* > shadow root 2 - capture listener ✅
|
|
122
|
+
* > shadow root 3 - capture listener ✅ (focus event here)
|
|
123
|
+
* > focused element ✅ (no shadow root - dispatch keyborg event)
|
|
124
|
+
*/
|
|
125
|
+
for (const shadowRootWeakRef of shadowTargets) if (shadowRootWeakRef.deref() === shadowRoot) return;
|
|
126
|
+
addEventListener(shadowRoot, "focusin", focusInHandler);
|
|
127
|
+
addEventListener(shadowRoot, "focusout", focusOutHandler);
|
|
128
|
+
shadowTargets.add(new WeakRef(shadowRoot));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const details = {
|
|
132
|
+
relatedTarget,
|
|
133
|
+
originalEvent
|
|
134
|
+
};
|
|
135
|
+
const event = new CustomEvent(KEYBORG_FOCUSIN, {
|
|
136
|
+
cancelable: true,
|
|
137
|
+
bubbles: true,
|
|
138
|
+
composed: true,
|
|
139
|
+
detail: details
|
|
140
|
+
});
|
|
141
|
+
details.isFocusedProgrammatically = target === data[LAST_FOCUSED_PROGRAMMATICALLY]?.deref();
|
|
142
|
+
data[LAST_FOCUSED_PROGRAMMATICALLY] = void 0;
|
|
143
|
+
target.dispatchEvent(event);
|
|
144
|
+
};
|
|
145
|
+
const data = [
|
|
146
|
+
focusInHandler,
|
|
147
|
+
focusOutHandler,
|
|
148
|
+
shadowTargets
|
|
149
|
+
];
|
|
150
|
+
kwin.__keyborgData = data;
|
|
151
|
+
addEventListener(doc, "focusin", focusInHandler);
|
|
152
|
+
addEventListener(doc, "focusout", focusOutHandler);
|
|
153
|
+
function focus() {
|
|
154
|
+
const d = kwin.__keyborgData;
|
|
155
|
+
if (d) d[LAST_FOCUSED_PROGRAMMATICALLY] = new WeakRef(this);
|
|
156
|
+
return origFocus.apply(this, arguments);
|
|
157
|
+
}
|
|
158
|
+
let activeElement = doc.activeElement;
|
|
159
|
+
while (activeElement && activeElement.shadowRoot) {
|
|
160
|
+
onFocusIn(activeElement);
|
|
161
|
+
activeElement = activeElement.shadowRoot.activeElement;
|
|
162
|
+
}
|
|
163
|
+
focus.__keyborgNativeFocus = origFocus;
|
|
203
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Removes keyborg event listeners and custom focus override
|
|
167
|
+
* @param win The window that stores keyborg focus events
|
|
168
|
+
*/
|
|
204
169
|
function disposeFocusEvent(win) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
"focusin",
|
|
225
|
-
keyborgNativeFocusEvent.focusInHandler,
|
|
226
|
-
true
|
|
227
|
-
);
|
|
228
|
-
shadowRoot.removeEventListener(
|
|
229
|
-
"focusout",
|
|
230
|
-
keyborgNativeFocusEvent.focusOutHandler,
|
|
231
|
-
true
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
keyborgNativeFocusEvent.shadowTargets.clear();
|
|
236
|
-
delete kwin.__keyborgData;
|
|
237
|
-
}
|
|
238
|
-
if (origFocus) {
|
|
239
|
-
proto.focus = origFocus;
|
|
240
|
-
}
|
|
170
|
+
const kwin = win;
|
|
171
|
+
const proto = kwin.HTMLElement.prototype;
|
|
172
|
+
const origFocus = proto.focus.__keyborgNativeFocus;
|
|
173
|
+
const data = kwin.__keyborgData;
|
|
174
|
+
if (data) {
|
|
175
|
+
const doc = kwin.document;
|
|
176
|
+
removeEventListener(doc, "focusin", data[FOCUS_IN_HANDLER]);
|
|
177
|
+
removeEventListener(doc, "focusout", data[FOCUS_OUT_HANDLER]);
|
|
178
|
+
for (const shadowRootWeakRef of data[SHADOW_TARGETS]) {
|
|
179
|
+
const shadowRoot = shadowRootWeakRef.deref();
|
|
180
|
+
if (shadowRoot) {
|
|
181
|
+
removeEventListener(shadowRoot, "focusin", data[FOCUS_IN_HANDLER]);
|
|
182
|
+
removeEventListener(shadowRoot, "focusout", data[FOCUS_OUT_HANDLER]);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
data[SHADOW_TARGETS].clear();
|
|
186
|
+
delete kwin.__keyborgData;
|
|
187
|
+
}
|
|
188
|
+
if (origFocus) proto.focus = origFocus;
|
|
241
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* @param win The window that stores keyborg focus events
|
|
192
|
+
* @returns The last element focused with element.focus()
|
|
193
|
+
*/
|
|
242
194
|
function getLastFocusedProgrammatically(win) {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
return keyborgNativeFocusEvent ? ((_a = keyborgNativeFocusEvent.lastFocusedProgrammatically) == null ? void 0 : _a.deref()) || null : void 0;
|
|
195
|
+
const data = win.__keyborgData;
|
|
196
|
+
return data ? data[LAST_FOCUSED_PROGRAMMATICALLY]?.deref() || null : void 0;
|
|
246
197
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
const activeElement = (_a = this._win) == null ? void 0 : _a.document.activeElement;
|
|
376
|
-
const isTriggerKey = !this._triggerKeys || this._triggerKeys.has(e.keyCode);
|
|
377
|
-
const isEditable = activeElement && (activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || activeElement.isContentEditable);
|
|
378
|
-
return isTriggerKey && !isEditable;
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* @returns whether the keyboard event should dismiss keyboard navigation mode
|
|
382
|
-
*/
|
|
383
|
-
_shouldDismissKeyboardNavigation(e) {
|
|
384
|
-
var _a;
|
|
385
|
-
return (_a = this._dismissKeys) == null ? void 0 : _a.has(e.keyCode);
|
|
386
|
-
}
|
|
387
|
-
_scheduleDismiss() {
|
|
388
|
-
const win = this._win;
|
|
389
|
-
if (win) {
|
|
390
|
-
if (this._dismissTimer) {
|
|
391
|
-
win.clearTimeout(this._dismissTimer);
|
|
392
|
-
this._dismissTimer = void 0;
|
|
393
|
-
}
|
|
394
|
-
const was = win.document.activeElement;
|
|
395
|
-
this._dismissTimer = win.setTimeout(() => {
|
|
396
|
-
this._dismissTimer = void 0;
|
|
397
|
-
const cur = win.document.activeElement;
|
|
398
|
-
if (was && cur && was === cur) {
|
|
399
|
-
this.isNavigatingWithKeyboard = false;
|
|
400
|
-
}
|
|
401
|
-
}, _dismissTimeout);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
};
|
|
405
|
-
var Keyborg = class _Keyborg {
|
|
406
|
-
constructor(win, props) {
|
|
407
|
-
this._cb = [];
|
|
408
|
-
this._id = "k" + ++_lastId;
|
|
409
|
-
this._win = win;
|
|
410
|
-
const current = win.__keyborg;
|
|
411
|
-
if (current) {
|
|
412
|
-
this._core = current.core;
|
|
413
|
-
current.refs[this._id] = this;
|
|
414
|
-
} else {
|
|
415
|
-
this._core = new KeyborgCore(win, props);
|
|
416
|
-
win.__keyborg = {
|
|
417
|
-
core: this._core,
|
|
418
|
-
refs: { [this._id]: this }
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
static create(win, props) {
|
|
423
|
-
return new _Keyborg(win, props);
|
|
424
|
-
}
|
|
425
|
-
static dispose(instance) {
|
|
426
|
-
instance.dispose();
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Updates all subscribed callbacks with the keyboard navigation state
|
|
430
|
-
*/
|
|
431
|
-
static update(instance, isNavigatingWithKeyboard) {
|
|
432
|
-
instance._cb.forEach((callback) => callback(isNavigatingWithKeyboard));
|
|
433
|
-
}
|
|
434
|
-
dispose() {
|
|
435
|
-
var _a;
|
|
436
|
-
const current = (_a = this._win) == null ? void 0 : _a.__keyborg;
|
|
437
|
-
if (current == null ? void 0 : current.refs[this._id]) {
|
|
438
|
-
delete current.refs[this._id];
|
|
439
|
-
if (Object.keys(current.refs).length === 0) {
|
|
440
|
-
current.core.dispose();
|
|
441
|
-
delete this._win.__keyborg;
|
|
442
|
-
}
|
|
443
|
-
} else if (process.env.NODE_ENV !== "production") {
|
|
444
|
-
console.error(
|
|
445
|
-
`Keyborg instance ${this._id} is being disposed incorrectly.`
|
|
446
|
-
);
|
|
447
|
-
}
|
|
448
|
-
this._cb = [];
|
|
449
|
-
delete this._core;
|
|
450
|
-
delete this._win;
|
|
451
|
-
}
|
|
452
|
-
/**
|
|
453
|
-
* @returns Whether the user is navigating with keyboard
|
|
454
|
-
*/
|
|
455
|
-
isNavigatingWithKeyboard() {
|
|
456
|
-
var _a;
|
|
457
|
-
return !!((_a = this._core) == null ? void 0 : _a.isNavigatingWithKeyboard);
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* @param callback - Called when the keyboard navigation state changes
|
|
461
|
-
*/
|
|
462
|
-
subscribe(callback) {
|
|
463
|
-
this._cb.push(callback);
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* @param callback - Registered with subscribe
|
|
467
|
-
*/
|
|
468
|
-
unsubscribe(callback) {
|
|
469
|
-
const index = this._cb.indexOf(callback);
|
|
470
|
-
if (index >= 0) {
|
|
471
|
-
this._cb.splice(index, 1);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Manually set the keyboard navigtion state
|
|
476
|
-
*/
|
|
477
|
-
setVal(isNavigatingWithKeyboard) {
|
|
478
|
-
if (this._core) {
|
|
479
|
-
this._core.isNavigatingWithKeyboard = isNavigatingWithKeyboard;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
function createKeyborg(win, props) {
|
|
484
|
-
return Keyborg.create(win, props);
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region src/Keyborg.mts
|
|
200
|
+
/*!
|
|
201
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
202
|
+
* Licensed under the MIT License.
|
|
203
|
+
*/
|
|
204
|
+
let _lastId = 0;
|
|
205
|
+
function createKeyborgCore(targetWindow) {
|
|
206
|
+
let currentTargetWindow = targetWindow;
|
|
207
|
+
let isNavigating = false;
|
|
208
|
+
let isMouseOrTouchUsedTimer;
|
|
209
|
+
const broadcast = () => {
|
|
210
|
+
const refs = currentTargetWindow?.__keyborg?.refs;
|
|
211
|
+
if (refs) for (const id of Object.keys(refs)) refs[id]._cb.forEach((cb) => cb(isNavigating));
|
|
212
|
+
};
|
|
213
|
+
const setNavigating = (val) => {
|
|
214
|
+
if (isNavigating !== val) {
|
|
215
|
+
isNavigating = val;
|
|
216
|
+
broadcast();
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
const shouldTrigger = (e) => {
|
|
220
|
+
if (e.key === "Tab") return true;
|
|
221
|
+
const active = currentTargetWindow?.document.activeElement;
|
|
222
|
+
return !(active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA" || active.isContentEditable));
|
|
223
|
+
};
|
|
224
|
+
const onFocusIn = (e) => {
|
|
225
|
+
if (isMouseOrTouchUsedTimer) return;
|
|
226
|
+
if (isNavigating) return;
|
|
227
|
+
const details = e.detail;
|
|
228
|
+
if (!details.relatedTarget) return;
|
|
229
|
+
if (details.isFocusedProgrammatically || details.isFocusedProgrammatically === void 0) return;
|
|
230
|
+
setNavigating(true);
|
|
231
|
+
};
|
|
232
|
+
const onMouseOrTouch = () => {
|
|
233
|
+
if (currentTargetWindow) {
|
|
234
|
+
if (isMouseOrTouchUsedTimer) currentTargetWindow.clearTimeout(isMouseOrTouchUsedTimer);
|
|
235
|
+
isMouseOrTouchUsedTimer = currentTargetWindow.setTimeout(() => {
|
|
236
|
+
isMouseOrTouchUsedTimer = void 0;
|
|
237
|
+
}, 1e3);
|
|
238
|
+
}
|
|
239
|
+
setNavigating(false);
|
|
240
|
+
};
|
|
241
|
+
const onMouseDown = (e) => {
|
|
242
|
+
if (e.buttons === 0 || e.clientX === 0 && e.clientY === 0 && e.screenX === 0 && e.screenY === 0) return;
|
|
243
|
+
onMouseOrTouch();
|
|
244
|
+
};
|
|
245
|
+
const onKeyDown = (e) => {
|
|
246
|
+
if (!isNavigating && shouldTrigger(e)) setNavigating(true);
|
|
247
|
+
};
|
|
248
|
+
const targetDocument = targetWindow.document;
|
|
249
|
+
addEventListener(targetDocument, KEYBORG_FOCUSIN, onFocusIn);
|
|
250
|
+
addEventListener(targetDocument, "mousedown", onMouseDown);
|
|
251
|
+
addEventListener(targetWindow, "keydown", onKeyDown);
|
|
252
|
+
addEventListener(targetDocument, "touchstart", onMouseOrTouch);
|
|
253
|
+
addEventListener(targetDocument, "touchend", onMouseOrTouch);
|
|
254
|
+
addEventListener(targetDocument, "touchcancel", onMouseOrTouch);
|
|
255
|
+
setupFocusEvent(targetWindow);
|
|
256
|
+
const dispose = () => {
|
|
257
|
+
if (!currentTargetWindow) return;
|
|
258
|
+
if (isMouseOrTouchUsedTimer) {
|
|
259
|
+
currentTargetWindow.clearTimeout(isMouseOrTouchUsedTimer);
|
|
260
|
+
isMouseOrTouchUsedTimer = void 0;
|
|
261
|
+
}
|
|
262
|
+
disposeFocusEvent(currentTargetWindow);
|
|
263
|
+
const targetDocument = currentTargetWindow.document;
|
|
264
|
+
removeEventListener(targetDocument, KEYBORG_FOCUSIN, onFocusIn);
|
|
265
|
+
removeEventListener(targetDocument, "mousedown", onMouseDown);
|
|
266
|
+
removeEventListener(currentTargetWindow, "keydown", onKeyDown);
|
|
267
|
+
removeEventListener(targetDocument, "touchstart", onMouseOrTouch);
|
|
268
|
+
removeEventListener(targetDocument, "touchend", onMouseOrTouch);
|
|
269
|
+
removeEventListener(targetDocument, "touchcancel", onMouseOrTouch);
|
|
270
|
+
currentTargetWindow = void 0;
|
|
271
|
+
};
|
|
272
|
+
return {
|
|
273
|
+
dispose,
|
|
274
|
+
get isNavigatingWithKeyboard() {
|
|
275
|
+
return isNavigating;
|
|
276
|
+
},
|
|
277
|
+
set isNavigatingWithKeyboard(val) {
|
|
278
|
+
setNavigating(val);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function createKeyborg(win) {
|
|
283
|
+
const kwin = win;
|
|
284
|
+
const id = "k" + ++_lastId;
|
|
285
|
+
let localWin = kwin;
|
|
286
|
+
let core;
|
|
287
|
+
const callbacks = [];
|
|
288
|
+
const existing = kwin.__keyborg;
|
|
289
|
+
if (existing) core = existing.core;
|
|
290
|
+
else core = createKeyborgCore(kwin);
|
|
291
|
+
const instance = {
|
|
292
|
+
isNavigatingWithKeyboard() {
|
|
293
|
+
return !!core?.isNavigatingWithKeyboard;
|
|
294
|
+
},
|
|
295
|
+
subscribe(callback) {
|
|
296
|
+
callbacks.push(callback);
|
|
297
|
+
},
|
|
298
|
+
unsubscribe(callback) {
|
|
299
|
+
const index = callbacks.indexOf(callback);
|
|
300
|
+
if (index >= 0) callbacks.splice(index, 1);
|
|
301
|
+
},
|
|
302
|
+
setVal(val) {
|
|
303
|
+
if (core) core.isNavigatingWithKeyboard = val;
|
|
304
|
+
},
|
|
305
|
+
_cb: callbacks,
|
|
306
|
+
dispose() {
|
|
307
|
+
const wkb = localWin?.__keyborg;
|
|
308
|
+
if (wkb?.refs[id]) {
|
|
309
|
+
delete wkb.refs[id];
|
|
310
|
+
if (Object.keys(wkb.refs).length === 0) {
|
|
311
|
+
wkb.core.dispose();
|
|
312
|
+
delete localWin.__keyborg;
|
|
313
|
+
}
|
|
314
|
+
} else if (process.env.NODE_ENV !== "production") console.error(`Keyborg instance ${id} is being disposed incorrectly.`);
|
|
315
|
+
callbacks.length = 0;
|
|
316
|
+
core = void 0;
|
|
317
|
+
localWin = void 0;
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
if (existing) existing.refs[id] = instance;
|
|
321
|
+
else kwin.__keyborg = {
|
|
322
|
+
core,
|
|
323
|
+
refs: { [id]: instance }
|
|
324
|
+
};
|
|
325
|
+
return instance;
|
|
485
326
|
}
|
|
486
327
|
function disposeKeyborg(instance) {
|
|
487
|
-
|
|
328
|
+
instance.dispose();
|
|
488
329
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
var version = "2.326.0-canary.0";
|
|
492
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
493
|
-
0 && (module.exports = {
|
|
494
|
-
KEYBORG_FOCUSIN,
|
|
495
|
-
KEYBORG_FOCUSOUT,
|
|
496
|
-
createKeyborg,
|
|
497
|
-
disposeKeyborg,
|
|
498
|
-
getLastFocusedProgrammatically,
|
|
499
|
-
nativeFocus,
|
|
500
|
-
version
|
|
501
|
-
});
|
|
330
|
+
//#endregion
|
|
331
|
+
//#region src/index.mts
|
|
502
332
|
/*!
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
333
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
334
|
+
* Licensed under the MIT License.
|
|
335
|
+
*/
|
|
336
|
+
const version = "3.0.0";
|
|
337
|
+
//#endregion
|
|
338
|
+
export { KEYBORG_FOCUSIN, KEYBORG_FOCUSOUT, createKeyborg, disposeKeyborg, getLastFocusedProgrammatically, nativeFocus, version };
|
|
339
|
+
|
|
506
340
|
//# sourceMappingURL=index.js.map
|