what-input 5.2.12 → 6.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.
@@ -1,517 +1,301 @@
1
1
  /**
2
2
  * what-input - A global utility for tracking the current input method (mouse, keyboard or touch).
3
- * @version v5.2.12
3
+ * @version v6.0.0
4
4
  * @link https://github.com/ten1seven/what-input
5
5
  * @license MIT
6
6
  */
7
- (function webpackUniversalModuleDefinition(root, factory) {
8
- if(typeof exports === 'object' && typeof module === 'object')
9
- module.exports = factory();
10
- else if(typeof define === 'function' && define.amd)
11
- define("whatInput", [], factory);
12
- else if(typeof exports === 'object')
13
- exports["whatInput"] = factory();
14
- else
15
- root["whatInput"] = factory();
16
- })(this, function() {
17
- return /******/ (function(modules) { // webpackBootstrap
18
- /******/ // The module cache
19
- /******/ var installedModules = {};
20
-
21
- /******/ // The require function
22
- /******/ function __webpack_require__(moduleId) {
23
-
24
- /******/ // Check if module is in cache
25
- /******/ if(installedModules[moduleId])
26
- /******/ return installedModules[moduleId].exports;
27
-
28
- /******/ // Create a new module (and put it into the cache)
29
- /******/ var module = installedModules[moduleId] = {
30
- /******/ exports: {},
31
- /******/ id: moduleId,
32
- /******/ loaded: false
33
- /******/ };
34
-
35
- /******/ // Execute the module function
36
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
37
-
38
- /******/ // Flag the module as loaded
39
- /******/ module.loaded = true;
40
-
41
- /******/ // Return the exports of the module
42
- /******/ return module.exports;
43
- /******/ }
44
-
45
-
46
- /******/ // expose the modules object (__webpack_modules__)
47
- /******/ __webpack_require__.m = modules;
48
-
49
- /******/ // expose the module cache
50
- /******/ __webpack_require__.c = installedModules;
51
-
52
- /******/ // __webpack_public_path__
53
- /******/ __webpack_require__.p = "";
54
-
55
- /******/ // Load entry module and return exports
56
- /******/ return __webpack_require__(0);
57
- /******/ })
58
- /************************************************************************/
59
- /******/ ([
60
- /* 0 */
61
- /***/ (function(module, exports) {
62
-
63
- 'use strict';
64
-
65
- module.exports = function () {
66
- /*
67
- * bail out if there is no document or window
68
- * (i.e. in a node/non-DOM environment)
69
- *
70
- * Return a stubbed API instead
71
- */
72
- if (typeof document === 'undefined' || typeof window === 'undefined') {
73
- return {
74
- // always return "initial" because no interaction will ever be detected
75
- ask: function ask() {
76
- return 'initial';
77
- },
78
-
79
- // always return null
80
- element: function element() {
81
- return null;
82
- },
83
-
84
- // no-op
85
- ignoreKeys: function ignoreKeys() {},
86
-
87
- // no-op
88
- specificKeys: function specificKeys() {},
89
-
90
- // no-op
91
- registerOnChange: function registerOnChange() {},
92
-
93
- // no-op
94
- unRegisterOnChange: function unRegisterOnChange() {}
95
- };
96
- }
97
-
98
- /*
99
- * variables
100
- */
101
-
102
- // cache document.documentElement
103
- var docElem = document.documentElement;
104
-
105
- // currently focused dom element
106
- var currentElement = null;
107
-
108
- // last used input type
109
- var currentInput = 'initial';
110
-
111
- // last used input intent
112
- var currentIntent = currentInput;
113
-
114
- // UNIX timestamp of current event
115
- var currentTimestamp = Date.now();
116
-
117
- // check for a `data-whatpersist` attribute on either the `html` or `body` elements, defaults to `true`
118
- var shouldPersist = false;
119
-
120
- // form input types
121
- var formInputs = ['button', 'input', 'select', 'textarea'];
122
-
123
- // empty array for holding callback functions
124
- var functionList = [];
125
-
126
- // list of modifier keys commonly used with the mouse and
127
- // can be safely ignored to prevent false keyboard detection
128
- var ignoreMap = [16, // shift
129
- 17, // control
130
- 18, // alt
131
- 91, // Windows key / left Apple cmd
132
- 93 // Windows menu / right Apple cmd
133
- ];
134
-
135
- var specificMap = [];
136
-
137
- // mapping of events to input types
138
- var inputMap = {
139
- keydown: 'keyboard',
140
- keyup: 'keyboard',
141
- mousedown: 'mouse',
142
- mousemove: 'mouse',
143
- MSPointerDown: 'pointer',
144
- MSPointerMove: 'pointer',
145
- pointerdown: 'pointer',
146
- pointermove: 'pointer',
147
- touchstart: 'touch',
148
- touchend: 'touch'
149
-
150
- // boolean: true if the page is being scrolled
151
- };var isScrolling = false;
152
-
153
- // store current mouse position
154
- var mousePos = {
155
- x: null,
156
- y: null
157
-
158
- // map of IE 10 pointer events
159
- };var pointerMap = {
160
- 2: 'touch',
161
- 3: 'touch', // treat pen like touch
162
- 4: 'mouse'
163
-
164
- // check support for passive event listeners
165
- };var supportsPassive = false;
166
-
167
- try {
168
- var opts = Object.defineProperty({}, 'passive', {
169
- get: function get() {
170
- supportsPassive = true;
171
- }
172
- });
173
-
174
- window.addEventListener('test', null, opts);
175
- } catch (e) {}
176
- // fail silently
177
-
178
-
179
- /*
180
- * set up
181
- */
182
-
183
- var setUp = function setUp() {
184
- // add correct mouse wheel event mapping to `inputMap`
185
- inputMap[detectWheel()] = 'mouse';
186
-
187
- addListeners();
188
- };
189
-
190
- /*
191
- * events
192
- */
193
-
194
- var addListeners = function addListeners() {
195
- // `pointermove`, `MSPointerMove`, `mousemove` and mouse wheel event binding
196
- // can only demonstrate potential, but not actual, interaction
197
- // and are treated separately
198
- var options = supportsPassive ? { passive: true, capture: true } : true;
199
-
200
- document.addEventListener('DOMContentLoaded', setPersist, true);
201
-
202
- // pointer events (mouse, pen, touch)
203
- if (window.PointerEvent) {
204
- window.addEventListener('pointerdown', setInput, true);
205
- window.addEventListener('pointermove', setIntent, true);
206
- } else if (window.MSPointerEvent) {
207
- window.addEventListener('MSPointerDown', setInput, true);
208
- window.addEventListener('MSPointerMove', setIntent, true);
209
- } else {
210
- // mouse events
211
- window.addEventListener('mousedown', setInput, true);
212
- window.addEventListener('mousemove', setIntent, true);
213
-
214
- // touch events
215
- if ('ontouchstart' in window) {
216
- window.addEventListener('touchstart', setInput, options);
217
- window.addEventListener('touchend', setInput, true);
218
- }
219
- }
220
-
221
- // mouse wheel
222
- window.addEventListener(detectWheel(), setIntent, options);
223
-
224
- // keyboard events
225
- window.addEventListener('keydown', setInput, true);
226
- window.addEventListener('keyup', setInput, true);
227
-
228
- // focus events
229
- window.addEventListener('focusin', setElement, true);
230
- window.addEventListener('focusout', clearElement, true);
231
- };
232
-
233
- // checks if input persistence should happen and
234
- // get saved state from session storage if true (defaults to `false`)
235
- var setPersist = function setPersist() {
236
- shouldPersist = !(docElem.getAttribute('data-whatpersist') === 'false' || document.body.getAttribute('data-whatpersist') === 'false');
237
-
238
- if (shouldPersist) {
239
- // check for session variables and use if available
240
- try {
241
- if (window.sessionStorage.getItem('what-input')) {
242
- currentInput = window.sessionStorage.getItem('what-input');
243
- }
244
-
245
- if (window.sessionStorage.getItem('what-intent')) {
246
- currentIntent = window.sessionStorage.getItem('what-intent');
247
- }
248
- } catch (e) {
249
- // fail silently
250
- }
251
- }
252
-
253
- // always run these so at least `initial` state is set
254
- doUpdate('input');
255
- doUpdate('intent');
256
- };
257
-
258
- // checks conditions before updating new input
259
- var setInput = function setInput(event) {
260
- var eventKey = event.which;
261
- var value = inputMap[event.type];
262
-
263
- if (value === 'pointer') {
264
- value = pointerType(event);
265
- }
266
-
267
- var ignoreMatch = !specificMap.length && ignoreMap.indexOf(eventKey) === -1;
268
-
269
- var specificMatch = specificMap.length && specificMap.indexOf(eventKey) !== -1;
270
-
271
- var shouldUpdate = value === 'keyboard' && eventKey && (ignoreMatch || specificMatch) || value === 'mouse' || value === 'touch';
272
-
273
- // prevent touch detection from being overridden by event execution order
274
- if (validateTouch(value)) {
275
- shouldUpdate = false;
276
- }
277
-
278
- if (shouldUpdate && currentInput !== value) {
279
- currentInput = value;
280
-
281
- persistInput('input', currentInput);
282
- doUpdate('input');
283
- }
284
-
285
- if (shouldUpdate && currentIntent !== value) {
286
- // preserve intent for keyboard interaction with form fields
287
- var activeElem = document.activeElement;
288
- var notFormInput = activeElem && activeElem.nodeName && (formInputs.indexOf(activeElem.nodeName.toLowerCase()) === -1 || activeElem.nodeName.toLowerCase() === 'button' && !checkClosest(activeElem, 'form'));
289
-
290
- if (notFormInput) {
291
- currentIntent = value;
292
-
293
- persistInput('intent', currentIntent);
294
- doUpdate('intent');
295
- }
296
- }
297
- };
298
-
299
- // updates the doc and `inputTypes` array with new input
300
- var doUpdate = function doUpdate(which) {
301
- docElem.setAttribute('data-what' + which, which === 'input' ? currentInput : currentIntent);
302
-
303
- fireFunctions(which);
304
- };
305
-
306
- // updates input intent for `mousemove` and `pointermove`
307
- var setIntent = function setIntent(event) {
308
- var value = inputMap[event.type];
309
-
310
- if (value === 'pointer') {
311
- value = pointerType(event);
312
- }
313
-
314
- // test to see if `mousemove` happened relative to the screen to detect scrolling versus mousemove
315
- detectScrolling(event);
316
-
317
- // only execute if scrolling isn't happening
318
- if ((!isScrolling && !validateTouch(value) || isScrolling && event.type === 'wheel' || event.type === 'mousewheel' || event.type === 'DOMMouseScroll') && currentIntent !== value) {
319
- currentIntent = value;
320
-
321
- persistInput('intent', currentIntent);
322
- doUpdate('intent');
323
- }
324
- };
325
-
326
- var setElement = function setElement(event) {
327
- if (!event.target.nodeName) {
328
- // If nodeName is undefined, clear the element
329
- // This can happen if click inside an <svg> element.
330
- clearElement();
331
- return;
332
- }
333
-
334
- currentElement = event.target.nodeName.toLowerCase();
335
- docElem.setAttribute('data-whatelement', currentElement);
336
-
337
- if (event.target.classList && event.target.classList.length) {
338
- docElem.setAttribute('data-whatclasses', event.target.classList.toString().replace(' ', ','));
339
- }
340
- };
341
-
342
- var clearElement = function clearElement() {
343
- currentElement = null;
344
-
345
- docElem.removeAttribute('data-whatelement');
346
- docElem.removeAttribute('data-whatclasses');
347
- };
348
-
349
- var persistInput = function persistInput(which, value) {
350
- if (shouldPersist) {
351
- try {
352
- window.sessionStorage.setItem('what-' + which, value);
353
- } catch (e) {
354
- // fail silently
355
- }
356
- }
357
- };
358
-
359
- /*
360
- * utilities
361
- */
362
-
363
- var pointerType = function pointerType(event) {
364
- if (typeof event.pointerType === 'number') {
365
- return pointerMap[event.pointerType];
366
- } else {
367
- // treat pen like touch
368
- return event.pointerType === 'pen' ? 'touch' : event.pointerType;
369
- }
370
- };
371
-
372
- // prevent touch detection from being overridden by event execution order
373
- var validateTouch = function validateTouch(value) {
374
- var timestamp = Date.now();
375
-
376
- var touchIsValid = value === 'mouse' && currentInput === 'touch' && timestamp - currentTimestamp < 200;
377
-
378
- currentTimestamp = timestamp;
379
-
380
- return touchIsValid;
381
- };
382
-
383
- // detect version of mouse wheel event to use
384
- // via https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
385
- var detectWheel = function detectWheel() {
386
- var wheelType = null;
387
-
388
- // Modern browsers support "wheel"
389
- if ('onwheel' in document.createElement('div')) {
390
- wheelType = 'wheel';
391
- } else {
392
- // Webkit and IE support at least "mousewheel"
393
- // or assume that remaining browsers are older Firefox
394
- wheelType = document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll';
395
- }
396
-
397
- return wheelType;
398
- };
399
-
400
- // runs callback functions
401
- var fireFunctions = function fireFunctions(type) {
402
- for (var i = 0, len = functionList.length; i < len; i++) {
403
- if (functionList[i].type === type) {
404
- functionList[i].fn.call(undefined, type === 'input' ? currentInput : currentIntent);
405
- }
406
- }
407
- };
408
-
409
- // finds matching element in an object
410
- var objPos = function objPos(match) {
411
- for (var i = 0, len = functionList.length; i < len; i++) {
412
- if (functionList[i].fn === match) {
413
- return i;
414
- }
415
- }
416
- };
417
-
418
- var detectScrolling = function detectScrolling(event) {
419
- if (mousePos.x !== event.screenX || mousePos.y !== event.screenY) {
420
- isScrolling = false;
421
-
422
- mousePos.x = event.screenX;
423
- mousePos.y = event.screenY;
424
- } else {
425
- isScrolling = true;
426
- }
427
- };
428
-
429
- // manual version of `closest()`
430
- var checkClosest = function checkClosest(elem, tag) {
431
- var ElementPrototype = window.Element.prototype;
432
-
433
- if (!ElementPrototype.matches) {
434
- ElementPrototype.matches = ElementPrototype.msMatchesSelector || ElementPrototype.webkitMatchesSelector;
435
- }
436
-
437
- if (!ElementPrototype.closest) {
438
- do {
439
- if (elem.matches(tag)) {
440
- return elem;
441
- }
442
-
443
- elem = elem.parentElement || elem.parentNode;
444
- } while (elem !== null && elem.nodeType === 1);
445
-
446
- return null;
447
- } else {
448
- return elem.closest(tag);
449
- }
450
- };
451
-
452
- /*
453
- * init
454
- */
455
-
456
- // don't start script unless browser cuts the mustard
457
- // (also passes if polyfills are used)
458
- if ('addEventListener' in window && Array.prototype.indexOf) {
459
- setUp();
460
- }
461
-
462
- /*
463
- * api
464
- */
465
-
466
- return {
467
- // returns string: the current input type
468
- // opt: 'intent'|'input'
469
- // 'input' (default): returns the same value as the `data-whatinput` attribute
470
- // 'intent': includes `data-whatintent` value if it's different than `data-whatinput`
471
- ask: function ask(opt) {
472
- return opt === 'intent' ? currentIntent : currentInput;
473
- },
474
-
475
- // returns string: the currently focused element or null
476
- element: function element() {
477
- return currentElement;
478
- },
479
-
480
- // overwrites ignored keys with provided array
481
- ignoreKeys: function ignoreKeys(arr) {
482
- ignoreMap = arr;
483
- },
484
-
485
- // overwrites specific char keys to update on
486
- specificKeys: function specificKeys(arr) {
487
- specificMap = arr;
488
- },
489
-
490
- // attach functions to input and intent "events"
491
- // funct: function to fire on change
492
- // eventType: 'input'|'intent'
493
- registerOnChange: function registerOnChange(fn, eventType) {
494
- functionList.push({
495
- fn: fn,
496
- type: eventType || 'input'
497
- });
498
- },
499
-
500
- unRegisterOnChange: function unRegisterOnChange(fn) {
501
- var position = objPos(fn);
502
-
503
- if (position || position === 0) {
504
- functionList.splice(position, 1);
505
- }
506
- },
507
-
508
- clearStorage: function clearStorage() {
509
- window.sessionStorage.clear();
510
- }
511
- };
512
- }();
513
-
514
- /***/ })
515
- /******/ ])
516
- });
517
- ;
7
+ ;(function (root, factory) {
8
+ if (typeof exports === 'object' && typeof module === 'object') {
9
+ module.exports = factory()
10
+ } else if (typeof define === 'function' && define.amd) {
11
+ define('whatInput', [], factory)
12
+ } else {
13
+ root.whatInput = factory()
14
+ }
15
+ })(
16
+ typeof globalThis !== 'undefined' ? globalThis : typeof self !== 'undefined' ? self : this,
17
+ function () {
18
+ var __whatInput
19
+ "use strict";
20
+ (() => {
21
+ // src/what-input.ts
22
+ var ATTRIBUTE_PREFIX = "data-what";
23
+ var STORAGE_KEYS = {
24
+ input: "what-input",
25
+ intent: "what-intent"
26
+ };
27
+ var INPUT_METHODS = /* @__PURE__ */ new Set([
28
+ "initial",
29
+ "mouse",
30
+ "keyboard",
31
+ "touch"
32
+ ]);
33
+ var POINTER_TYPES = {
34
+ mouse: "mouse",
35
+ pen: "touch",
36
+ touch: "touch"
37
+ };
38
+ var DEFAULT_IGNORED_KEYS = [
39
+ "Shift",
40
+ "Control",
41
+ "Alt",
42
+ "Meta",
43
+ // Windows key / Apple command
44
+ "ContextMenu"
45
+ // Windows menu key
46
+ ];
47
+ var TEXT_ENTRY_ELEMENTS = /* @__PURE__ */ new Set(["input", "select", "textarea"]);
48
+ var TOGGLE_INPUT_TYPES = /* @__PURE__ */ new Set(["checkbox", "radio"]);
49
+ var FREEZE_SELECTOR = "[data-whatfreeze]";
50
+ var HINT_QUERIES = {
51
+ touch: "(pointer: coarse)",
52
+ mouse: "(pointer: fine)"
53
+ };
54
+ var hasDom = () => typeof window !== "undefined" && typeof document !== "undefined";
55
+ var isInputMethod = (value) => typeof value === "string" && INPUT_METHODS.has(value);
56
+ var deepActiveElement = () => {
57
+ let element = document.activeElement;
58
+ while (element?.shadowRoot?.activeElement) {
59
+ element = element.shadowRoot.activeElement;
60
+ }
61
+ return element;
62
+ };
63
+ var isTextEntry = (element) => {
64
+ if (!element) return false;
65
+ const tag = element.localName;
66
+ if (tag === "input") return !TOGGLE_INPUT_TYPES.has(element.type);
67
+ if (TEXT_ENTRY_ELEMENTS.has(tag)) return true;
68
+ if (tag === "button" && element.closest("form") !== null) return true;
69
+ if (element.isContentEditable === true) return true;
70
+ if (element.closest(FREEZE_SELECTOR) !== null) return true;
71
+ return element.constructor.formAssociated === true;
72
+ };
73
+ var hintQueries = () => typeof window.matchMedia === "function" ? Object.values(HINT_QUERIES).map((query) => window.matchMedia(query)) : [];
74
+ var readHint = () => {
75
+ if (typeof window.matchMedia !== "function") return "unknown";
76
+ for (const [hint, query] of Object.entries(HINT_QUERIES)) {
77
+ if (window.matchMedia(query).matches) return hint;
78
+ }
79
+ return "unknown";
80
+ };
81
+ var eventTarget = (event) => {
82
+ const target = event.composedPath()[0] ?? event.target;
83
+ return target instanceof Element ? target : null;
84
+ };
85
+ var WhatInput = class extends EventTarget {
86
+ #state = {
87
+ input: "initial",
88
+ intent: "initial",
89
+ hint: "unknown"
90
+ };
91
+ #element = null;
92
+ #persist = false;
93
+ #ignoredKeys = DEFAULT_IGNORED_KEYS;
94
+ #specificKeys = [];
95
+ #callbacks = {
96
+ input: /* @__PURE__ */ new Set(),
97
+ intent: /* @__PURE__ */ new Set(),
98
+ hint: /* @__PURE__ */ new Set()
99
+ };
100
+ #controller = null;
101
+ #lastPointerPosition = { x: NaN, y: NaN };
102
+ constructor() {
103
+ super();
104
+ if (hasDom()) this.#start();
105
+ }
106
+ ask(strategy = "input") {
107
+ return this.#state[strategy];
108
+ }
109
+ /** The tag name of the currently focused element, or `null`. */
110
+ element() {
111
+ return this.#element;
112
+ }
113
+ /**
114
+ * Replaces the list of keys that are ignored (do not switch to `keyboard`)
115
+ * when pressed. Defaults to the modifier keys.
116
+ */
117
+ ignoreKeys(keys) {
118
+ this.#ignoredKeys = [...keys];
119
+ }
120
+ /**
121
+ * Replaces the list of keys that are the *only* keys that switch to
122
+ * `keyboard`. When set, this overrides `ignoreKeys()`. Pass an empty array
123
+ * to restore the `ignoreKeys()` behavior.
124
+ */
125
+ specificKeys(keys) {
126
+ this.#specificKeys = [...keys];
127
+ }
128
+ registerOnChange(callback, strategy = "input") {
129
+ this.#callbacks[strategy].add(callback);
130
+ }
131
+ /** Removes a callback added with `registerOnChange()`. */
132
+ unRegisterOnChange(callback) {
133
+ for (const callbacks of Object.values(this.#callbacks)) {
134
+ callbacks.delete(callback);
135
+ }
136
+ }
137
+ /** Removes the persisted input and intent from session storage. */
138
+ clearStorage() {
139
+ try {
140
+ for (const key of Object.values(STORAGE_KEYS)) {
141
+ window.sessionStorage.removeItem(key);
142
+ }
143
+ } catch {
144
+ }
145
+ }
146
+ /**
147
+ * Stops listening, removes the `data-what*` attributes from `<html>` and
148
+ * drops every registered callback. Useful for tests and app teardown.
149
+ */
150
+ destroy() {
151
+ this.#controller?.abort();
152
+ this.#controller = null;
153
+ for (const callbacks of Object.values(this.#callbacks)) {
154
+ callbacks.clear();
155
+ }
156
+ if (!hasDom()) return;
157
+ const html = document.documentElement;
158
+ for (const name of ["input", "intent", "hint", "element", "classes"]) {
159
+ html.removeAttribute(ATTRIBUTE_PREFIX + name);
160
+ }
161
+ }
162
+ /*
163
+ * set up
164
+ */
165
+ #start() {
166
+ const controller = new AbortController();
167
+ const { signal } = controller;
168
+ this.#controller = controller;
169
+ const options = { capture: true, passive: true, signal };
170
+ window.addEventListener("pointerdown", this.#onPointerDown, options);
171
+ window.addEventListener("keydown", this.#onKey, options);
172
+ window.addEventListener("keyup", this.#onKey, options);
173
+ window.addEventListener("pointermove", this.#onPointerMove, options);
174
+ window.addEventListener("wheel", this.#onWheel, options);
175
+ window.addEventListener("focusin", this.#onFocusIn, options);
176
+ window.addEventListener("focusout", this.#onFocusOut, options);
177
+ for (const query of hintQueries()) {
178
+ query.addEventListener("change", this.#onHintChange, { signal });
179
+ }
180
+ if (document.readyState === "loading") {
181
+ document.addEventListener("DOMContentLoaded", this.#init, { once: true, signal });
182
+ } else {
183
+ this.#init();
184
+ }
185
+ }
186
+ /** Restores persisted state (if allowed) and publishes the initial state. */
187
+ #init = () => {
188
+ const { documentElement, body } = document;
189
+ this.#persist = documentElement.dataset.whatpersist !== "false" && body?.dataset.whatpersist !== "false";
190
+ if (this.#persist) {
191
+ for (const strategy of ["input", "intent"]) {
192
+ const stored = this.#restore(strategy);
193
+ if (stored && this.#state[strategy] === "initial") {
194
+ this.#state[strategy] = stored;
195
+ }
196
+ }
197
+ }
198
+ this.#state.hint = readHint();
199
+ this.#publish("input");
200
+ this.#publish("intent");
201
+ this.#publish("hint");
202
+ };
203
+ /*
204
+ * events
205
+ */
206
+ #onPointerDown = (event) => {
207
+ const value = POINTER_TYPES[event.pointerType];
208
+ if (!value) return;
209
+ this.#set("input", value);
210
+ this.#set("intent", value);
211
+ };
212
+ #onPointerMove = (event) => {
213
+ const value = POINTER_TYPES[event.pointerType];
214
+ if (!value) return;
215
+ const { x, y } = this.#lastPointerPosition;
216
+ this.#lastPointerPosition = { x: event.screenX, y: event.screenY };
217
+ if (event.screenX === x && event.screenY === y) return;
218
+ this.#set("intent", value);
219
+ };
220
+ #onWheel = () => {
221
+ this.#set("intent", "mouse");
222
+ };
223
+ #onHintChange = () => {
224
+ this.#set("hint", readHint());
225
+ };
226
+ #onKey = (event) => {
227
+ if (!this.#isCountedKey(event)) return;
228
+ this.#set("input", "keyboard");
229
+ if (!isTextEntry(deepActiveElement())) {
230
+ this.#set("intent", "keyboard");
231
+ }
232
+ };
233
+ #onFocusIn = (event) => {
234
+ const target = eventTarget(event);
235
+ if (!target) {
236
+ this.#onFocusOut();
237
+ return;
238
+ }
239
+ const html = document.documentElement;
240
+ this.#element = target.localName;
241
+ html.setAttribute(ATTRIBUTE_PREFIX + "element", this.#element);
242
+ if (target.classList.length) {
243
+ html.setAttribute(ATTRIBUTE_PREFIX + "classes", Array.from(target.classList).join(","));
244
+ } else {
245
+ html.removeAttribute(ATTRIBUTE_PREFIX + "classes");
246
+ }
247
+ };
248
+ #onFocusOut = () => {
249
+ const html = document.documentElement;
250
+ this.#element = null;
251
+ html.removeAttribute(ATTRIBUTE_PREFIX + "element");
252
+ html.removeAttribute(ATTRIBUTE_PREFIX + "classes");
253
+ };
254
+ /*
255
+ * state
256
+ */
257
+ #isCountedKey(event) {
258
+ const matches = (key) => typeof key === "number" ? key === event.keyCode : key === event.key || key === event.code;
259
+ return this.#specificKeys.length ? this.#specificKeys.some(matches) : !this.#ignoredKeys.some(matches);
260
+ }
261
+ #set(channel, value) {
262
+ if (this.#state[channel] === value) return;
263
+ this.#state[channel] = value;
264
+ this.#store(channel, value);
265
+ this.#publish(channel);
266
+ }
267
+ /** Writes the attribute, runs the callbacks and dispatches the event. */
268
+ #publish(channel) {
269
+ const value = this.#state[channel];
270
+ document.documentElement.setAttribute(ATTRIBUTE_PREFIX + channel, value);
271
+ for (const callback of this.#callbacks[channel]) {
272
+ ;
273
+ callback(value);
274
+ }
275
+ this.dispatchEvent(new CustomEvent(channel, { detail: value }));
276
+ }
277
+ #store(channel, value) {
278
+ if (channel === "hint" || !this.#persist) return;
279
+ try {
280
+ window.sessionStorage.setItem(STORAGE_KEYS[channel], value);
281
+ } catch {
282
+ }
283
+ }
284
+ #restore(strategy) {
285
+ try {
286
+ const value = window.sessionStorage.getItem(STORAGE_KEYS[strategy]);
287
+ return isInputMethod(value) ? value : null;
288
+ } catch {
289
+ return null;
290
+ }
291
+ }
292
+ };
293
+ var whatInput = new WhatInput();
294
+ var what_input_default = whatInput;
295
+
296
+ // scripts/umd-entry.ts
297
+ __whatInput = what_input_default;
298
+ })();
299
+ return __whatInput
300
+ },
301
+ )