tiny-essentials
Version:
Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.
1 lines • 26.2 kB
JavaScript
(()=>{"use strict";var e={d:(t,n)=>{for(var i in n)e.o(n,i)&&!e.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:n[i]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{TinyGamepad:()=>i});class n{#e=!1;#t=new Set;#n=new Map;#i=new Map;#s=null;#a=[];#r={};#o=[];#p=null;#d=null;#c;#u;#l;#m;#h;#y;#f;#g;#v=[];#b=0;#w=0;#I=[];#E=0;#M=null;#S=new Set;#k=new Set;#T=new Map;#K=new Map;#A=new Map;static#C={" ":"Space","\n":"Enter","\r":"Enter","\t":"Tab","-":"Minus",_:"Minus","=":"Equal","+":"Equal","[":"BracketLeft","{":"BracketLeft","]":"BracketRight","}":"BracketRight","\\":"Backslash","|":"Backslash",";":"Semicolon",":":"Semicolon","'":"Quote",'"':"Quote",",":"Comma","<":"Comma",".":"Period",">":"Period","/":"Slash","?":"Slash","`":"Backquote","~":"Backquote"};static addSpecialKey(e,t){if("string"!=typeof e)throw new TypeError("Invalid char type: expected string, got "+typeof e);if(1!==e.length)throw new Error(`Invalid char length: "${e}" (must be exactly one character)`);if("string"!=typeof t)throw new TypeError("Invalid code type: expected string, got "+typeof t);n.#C[e]=t}static removeSpecialKey(e){if("string"!=typeof e)throw new TypeError("Invalid char type: expected string, got "+typeof e);if(1!==e.length)throw new Error(`Invalid char length: "${e}" (must be exactly one character)`);delete n.#C[e]}static getSpecialKey(e){if("string"!=typeof e)throw new TypeError("Invalid char type: expected string, got "+typeof e);if(1!==e.length)throw new Error(`Invalid char length: "${e}" (must be exactly one character)`);return n.#C[e]}static getAllSpecialKeys(){return{...n.#C}}static stringToKeys(e){if("string"!=typeof e)throw new TypeError("Invalid text type: expected string, got "+typeof e);if(!e.length)throw new Error("Invalid text: cannot be empty");return Array.from(e).map(e=>{const t=e.toUpperCase();if(t>="A"&&t<="Z")return`Key${t}`;if(t>="0"&&t<="9")return`Digit${t}`;const i=n.#C[e];if(void 0!==i)return i;throw new Error(`Unsupported character: "${e}"`)})}constructor({expectedId:e=null,inputMode:t="both",ignoreIds:n=[],deadZone:i=.1,axisActiveSensitivity:s=.3,timeoutComboKeys:a=500,allowMouse:r=!1,elementBase:o=window}={}){if(null!==e&&"string"!=typeof e)throw new TypeError('"expectedId" must be a string or null, received: '+typeof e);if(!["keyboard-only","gamepad-only","both"].includes(t))throw new TypeError(`"inputMode" must be 'keyboard-only', 'gamepad-only', or 'both', received: ${t}`);if(!Array.isArray(n)||!n.every(e=>"string"==typeof e))throw new TypeError('"ignoreIds" must be an array of strings');if("number"!=typeof i||i<0||i>1)throw new RangeError(`"deadZone" must be a number between 0 and 1, received: ${i}`);if("number"!=typeof s||s<0||s>1)throw new RangeError(`"axisActiveSensitivity" must be a number between 0 and 1, received: ${s}`);if("number"!=typeof a||a<0)throw new RangeError(`"timeoutComboKeys" must be a positive number, received: ${a}`);if("boolean"!=typeof r)throw new TypeError('"allowMouse" must be a boolean, received: '+typeof r);if(!(o instanceof Window||o instanceof Element))throw new TypeError('"elementBase" must be a Window or Element instance');this.#m=e,this.#c=t,this.#u=new Set(n),this.#l=i,this.#h=r,this.#y=o,this.#f=a,this.#g=s,["gamepad-only","both"].includes(this.#c)&&this.#N(),["keyboard-only","both"].includes(this.#c)&&this.#x()}#$=e=>this.#q(e.gamepad);#B=e=>this.#D(e.gamepad);#N(){window.addEventListener("gamepadconnected",this.#$),window.addEventListener("gamepaddisconnected",this.#B)}#q(e){this.#e||this.#u.has(e.id)||this.#m&&e.id!==this.#m||this.#s||(this.#s=e,this.#m=e.id,this.#G(),this.#H("connected",{id:e.id,gp:e,timestamp:e.timestamp}))}#D(e){this.#e||this.#s&&e.id===this.#s.id&&(this.#s=null,this.#p&&(cancelAnimationFrame(this.#p),this.#p=null),this.#H("disconnected",{id:e.id,gp:e,timestamp:e.timestamp}))}#G(){const e=()=>{this.#e||(this.#L(),this.#p=requestAnimationFrame(e))};e()}#L(){if(this.#e)return;const e=navigator.getGamepads(),t=Array.from(e).find(e=>e&&e.id===this.#m);t&&(this.#s=t,t.buttons.forEach((e,n)=>{const i=`Button${n}`,s=this.#a[n]?.pressed||!1;let a,r,o=!1;e.pressed&&!s?(r=1,a="down"):!e.pressed&&s?(r=0,a="up"):e.pressed&&s&&(r=1,a="hold"),e.pressed&&e.value>0&&e.value<1&&1!==e.value&&(r=e.value,o=!0),"number"==typeof r&&"string"==typeof a&&this.#j({key:i,source:"gamepad-button",value:r,value2:NaN,type:a,gp:t,isPressure:o,pressed:e.pressed,prevPressed:s,timestamp:t.timestamp,id:t.id}),this.#a[n]={pressed:e.pressed,value:"number"==typeof r?r:this.#a[n]?.value,value2:NaN}}),t.axes.forEach((e,n)=>{Math.abs(e)<this.#l&&(e=0);const i=`Axis${n}`;e!==(this.#o[n]??0)&&this.#j({key:i,source:"gamepad-analog",value:e,value2:NaN,type:"change",timestamp:t.timestamp,id:t.id,gp:t}),this.#o[n]=e}))}#z=e=>{if(!this.#e){if(!(e instanceof KeyboardEvent))throw new Error("Expected KeyboardEvent in keydown listener.");this.#t.has(e.code)||(this.#t.add(e.code),this.#j({event:e,key:e.code,source:"keyboard",value:1,value2:NaN,type:"down",pressed:!0,prevPressed:this.#r[e.code]?.pressed??!1,id:"native_keyboard",timestamp:e.timeStamp}),this.#r[e.code]={pressed:!0})}};#Z=e=>{if(!this.#e){if(!(e instanceof KeyboardEvent))throw new Error("Expected KeyboardEvent in keyup listener.");this.#t.has(e.code)&&(this.#t.delete(e.code),this.#j({event:e,key:e.code,source:"keyboard",value:0,value2:NaN,type:"up",pressed:!1,prevPressed:this.#r[e.code]?.pressed??!1,id:"native_keyboard",timestamp:e.timeStamp}),this.#r[e.code]={pressed:!1})}};#P=e=>{if(this.#e)return;if(!(e instanceof MouseEvent))throw new Error("Expected MouseEvent in mousedown listener.");const t=`Mouse${e.button}`;this.#t.add(t),this.#j({event:e,key:t,source:"mouse",value:1,value2:NaN,type:"down",pressed:!0,prevPressed:this.#r[t]?.pressed??!1,id:"native_mouse",timestamp:e.timeStamp}),this.#r[t]={pressed:!0}};#O=e=>{if(this.#e)return;if(!(e instanceof MouseEvent))throw new Error("Expected MouseEvent in mouseup listener.");const t=`Mouse${e.button}`;this.#t.delete(t),this.#j({event:e,key:t,source:"mouse",value:0,value2:NaN,type:"up",pressed:!1,prevPressed:this.#r[t]?.pressed??!1,id:"native_mouse",timestamp:e.timeStamp}),this.#r[t]={pressed:!1}};#F=e=>{if(!this.#e){if(!(e instanceof MouseEvent))throw new Error("Expected MouseEvent in mousemove listener.");if(0!==e.movementX||0!==e.movementY){const t="MouseMove",n=this.#r[t]??{pressed:!1,value:0,value2:0};this.#j({event:e,key:t,source:"mouse",value:e.movementX+(n.value??0),value2:e.movementY+(n.value??0),id:"native_mouse",type:"move",pressed:!0,prevPressed:null,timestamp:e.timeStamp}),this.#r[t]={pressed:!1,value:e.movementX,value2:e.movementY}}}};#x(){this.#y.addEventListener("keydown",this.#z),this.#y.addEventListener("keyup",this.#Z),this.#h&&(this.#y.addEventListener("mousedown",this.#P),this.#y.addEventListener("mouseup",this.#O),this.#y.addEventListener("mousemove",this.#F));const e=()=>{this.#e||(this.#t.forEach(e=>{const t=e.startsWith("Mouse")?"mouse":"keyboard";this.#j({key:e,source:t,id:`native_${t}`,value:1,value2:NaN,type:"hold",pressed:!0,prevPressed:this.#r[e]?.pressed??!1,timestamp:NaN})}),this.#d=requestAnimationFrame(e))};e()}#j(e){if(this.#e)return;const t=this.#i.get("input-*")||[],{pressed:n,key:i}=e,s=i.startsWith("Axis"),a="boolean"==typeof n&&n||s&&(e.value>this.#g||e.value<-Math.abs(this.#g)),r=s?`${i}${e.value>0?"+":e.value<0?"-":""}`:i;let o=null;if("move"!==e.type&&"hold"!==e.type){if(a){if(!s&&!this.#S.has(i)||s&&!this.#S.has(i)&&!this.#S.has(`${i}+`)&&!this.#S.has(`${i}-`)){0===this.#E&&(this.#E=Date.now()),this.#S.add(r),o=!0,this.#I.push(r),this.#v.length<1&&(this.#M&&clearTimeout(this.#M),this.#M=setTimeout(()=>this.resetComboMapped(),this.#f));const e=this.#i.get("mapped-key-start")??[];for(const t of e)t({key:r,activeTime:this.#E})}}else if(!s&&this.#S.has(i)||s&&(this.#S.has(i)||this.#S.has(`${i}+`)||this.#S.has(`${i}-`))){this.#S.delete(i),this.#S.delete(`${i}+`),this.#S.delete(`${i}-`),o=!1;const e=this.#i.get("mapped-key-end")??[];for(const t of e)t({key:r,activeTime:this.#E})}for(const{sequence:e,callback:t,triggered:n}of this.#K.values()){const i=this.#K.get(e.join("+"));if(!i)continue;const s=e.every((e,t)=>this.#I[t]===e);s&&!n?(i.triggered=!0,t(this.#E)):!s&&n&&(i.triggered=!1)}}for(const[n,p]of this.#n.entries()){const d=e=>"string"==typeof p&&e===p||Array.isArray(p)&&p.findIndex((t,n)=>e===p[n])>-1,c=d(r),u=s&&d(`${i}+`),l=s&&d(`${i}-`);if(c||u||l){if(a&&c){if(o||!this.#k.has(n)){0===this.#w&&(this.#w=Date.now()),this.#k.add(n),0===this.#b&&(this.#b=Date.now()),this.#M&&clearTimeout(this.#M),this.#v.push(n),this.#M=setTimeout(()=>this.resetComboMapped(),this.#f);const e=this.#i.get("mapped-input-start")??[];for(const t of e)t({logicalName:n,activeTime:this.#w,comboTime:this.#b})}}else if(!o||this.#k.has(n)){this.#k.delete(n),this.#k.size<1&&(this.#w=0);const e=this.#i.get("mapped-input-end")??[];for(const t of e)t({logicalName:n,activeTime:this.#w,comboTime:this.#b})}for(const{sequence:e,callback:t,triggered:n}of this.#T.values()){const i=this.#T.get(e.join("+"));if(!i)continue;const s=Array.from(this.#k),a=e.every((e,t)=>s[t]===e);a&&!n?(i.triggered=!0,t(this.#w)):!a&&n&&(i.triggered=!1)}}const m=[];if(s&&0===e.value){const{value:t}=this.#A.get(`${i}-`)??{value:0,value2:NaN},{value:n}=this.#A.get(`${i}+`)??{value:0,value2:NaN};e.value!==t&&m.push(`${i}-`),e.value!==n&&m.push(`${i}+`)}else m.push(r);m.forEach(i=>{if(!("*"===p||p===i||Array.isArray(p)&&p.includes(i)))return;const s=this.#i.get(`input-${e.type}-${n}`)||[],a=this.#i.get(`input-${n}`)||[];if(a.length<1&&s.length<1&&t.length<1)return;const r={...e,key:i,logicalName:n};for(const e of t)e(r);for(const e of a)e(r);for(const e of s)e(r);this.#A.set(i,{value:e.value,value2:e.value2})})}}#H(e,t){const n=this.#i.get(e)||[];for(const e of n)e(t)}#J(e,t,n){if("string"!=typeof e)throw new TypeError(`"logicalName" must be a string, received ${e}`);if("function"!=typeof t)throw new TypeError('"callback" must be a function, received '+typeof t);const i=n.replace("{logicalName}",e);let s=this.#i.get(i);Array.isArray(s)||(s=[],this.#i.set(i,s)),s.push(t)}#R(e,t,n){if("string"!=typeof e)throw new TypeError(`"logicalName" must be a string, received ${e}`);if("function"!=typeof t)throw new TypeError('"callback" must be a function, received '+typeof t);const i=s=>{this.#_(e,i,n),t(s)};this.#J(e,i,n)}#V(e,t,n){if("string"!=typeof e)throw new TypeError(`"logicalName" must be a string, received ${e}`);if("function"!=typeof t)throw new TypeError('"callback" must be a function, received '+typeof t);const i=n.replace("{logicalName}",e),s=this.#i.get(i)??[];s.unshift(t),this.#i.set(i,s)}#_(e,t,n){if("string"!=typeof e)throw new TypeError(`"logicalName" must be a string, received ${e}`);if("function"!=typeof t)throw new TypeError('"callback" must be a function, received '+typeof t);const i=n.replace("{logicalName}",e),s=this.#i.get(i);Array.isArray(s)&&this.#i.set(i,s.filter(e=>e!==t))}awaitInputMapping({timeout:e=1e4,eventName:t="MappingInput",canMove:n=!1}={}){return new Promise((i,s)=>{if("number"!=typeof e||Number.isNaN(e)||e<0)return s(new TypeError(`Invalid "timeout": expected a positive number, got ${e}`));if("string"!=typeof t||!t.trim())return s(new TypeError(`Invalid "eventName": expected a non-empty string, got ${t}`));if("boolean"!=typeof n)return s(new TypeError(`Invalid "canMove": expected a boolean, got ${n}`));const a={key:null,source:null},r=({key:e,type:s,source:p,gp:d,value:c})=>{(n||"move"!==s)&&(a.key=e,a.source=p,a.gp=d,clearTimeout(o),this.offInputStart(t,r),this.offInputChange(t,r),n&&this.offInputMove(t,r),i(a))},o=setTimeout(()=>i(a),e);this.mapInput(t,"*"),this.onInputStart(t,r),this.onInputChange(t,r),n&&this.onInputMove(t,r)})}mapInput(e,t){if("string"!=typeof e||!e.trim())throw new TypeError(`Invalid "logicalName": expected a non-empty string, got ${e}`);if(!("string"==typeof t||Array.isArray(t)&&t.every(e=>"string"==typeof e)))throw new TypeError(`Invalid "physicalInput": expected string or array of strings, got ${JSON.stringify(t)}`);this.#n.set(e,t)}unmapInput(e){if("string"!=typeof e||!e.trim())throw new TypeError(`Invalid "logicalName": expected a non-empty string, got ${e}`);this.#n.delete(e)}hasMappedInput(e){if("string"!=typeof e||!e.trim())throw new TypeError(`Invalid "logicalName": expected a non-empty string, got ${e}`);return this.#n.has(e)}getMappedInput(e){if("string"!=typeof e||!e.trim())throw new TypeError(`Invalid "logicalName": expected a non-empty string, got ${e}`);const t=this.#n.get(e);if(!t)throw new Error(`No physical input mapped for logicalName: "${e}"`);return t}clearMapInputs(){this.#n.clear()}registerInputSequence(e,t){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new TypeError(`'sequence' must be an array of strings, got: ${JSON.stringify(e)}`);if("function"!=typeof t)throw new TypeError("'callback' must be a function, got: "+typeof t);if(0===e.length)throw new Error("'sequence' must contain at least one input name.");const n=e.join("+");this.#T.set(n,{sequence:e,callback:t,triggered:!1})}unregisterInputSequence(e){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new TypeError(`'sequence' must be an array of strings, got: ${JSON.stringify(e)}`);const t=e.join("+");this.#T.delete(t)}unregisterAllInputSequences(){this.#T.clear()}hasInputSequence(e){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new TypeError(`'sequence' must be an array of strings, got: ${JSON.stringify(e)}`);const t=e.join("+");return this.#T.has(t)}registerKeySequence(e,t){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new TypeError(`'sequence' must be an array of strings, got: ${JSON.stringify(e)}`);if("function"!=typeof t)throw new TypeError("'callback' must be a function, got: "+typeof t);if(0===e.length)throw new Error("'sequence' must contain at least one input name.");const n=e.join("+");this.#K.set(n,{sequence:e,callback:t,triggered:!1})}unregisterKeySequence(e){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new TypeError(`'sequence' must be an array of strings, got: ${JSON.stringify(e)}`);const t=e.join("+");this.#K.delete(t)}unregisterAllKeySequences(){this.#K.clear()}hasKeySequence(e){if(!Array.isArray(e)||!e.every(e=>"string"==typeof e))throw new TypeError(`'sequence' must be an array of strings, got: ${JSON.stringify(e)}`);const t=e.join("+");return this.#K.has(t)}renewComboMapped(){this.#M&&(clearTimeout(this.#M),this.#M=setTimeout(()=>this.resetComboMapped(),this.#f))}resetComboMapped(){this.#M&&clearTimeout(this.#M),this.#I=[],this.#M=null,this.#E=0,this.#v=[],this.#b=0}onMappedKeyStart(e){return this.#J("",e,"mapped-key-start")}onceMappedKeyStart(e){return this.#R("",e,"mapped-key-start")}prependMappedKeyStart(e){return this.#V("",e,"mapped-key-start")}offMappedKeyStart(e){return this.#_("",e,"mapped-key-start")}offAllMappedKeyStart(){this.#i.delete("mapped-key-start")}onMappedKeyEnd(e){return this.#J("",e,"mapped-key-end")}onceMappedKeyEnd(e){return this.#R("",e,"mapped-key-end")}prependMappedKeyEnd(e){return this.#V("",e,"mapped-key-end")}offMappedKeyEnd(e){return this.#_("",e,"mapped-key-end")}offAllMappedKeyEnd(){this.#i.delete("mapped-key-end")}onMappedInputStart(e){return this.#J("",e,"mapped-input-start")}onceMappedInputStart(e){return this.#R("",e,"mapped-input-start")}prependMappedInputStart(e){return this.#V("",e,"mapped-input-start")}offMappedInputStart(e){return this.#_("",e,"mapped-input-start")}offAllMappedInputStart(){this.#i.delete("mapped-input-start")}onMappedInputEnd(e){return this.#J("",e,"mapped-input-end")}onceMappedInputEnd(e){return this.#R("",e,"mapped-input-end")}prependMappedInputEnd(e){return this.#V("",e,"mapped-input-end")}offMappedInputEnd(e){return this.#_("",e,"mapped-input-end")}offAllMappedInputEnd(){this.#i.delete("mapped-input-end")}onInput(e,t){return this.#J(e,t,"input-{logicalName}")}onceInput(e,t){return this.#R(e,t,"input-{logicalName}")}prependInput(e,t){return this.#V(e,t,"input-{logicalName}")}offInput(e,t){return this.#_(e,t,"input-{logicalName}")}onInputStart(e,t){return this.#J(e,t,"input-down-{logicalName}")}onceInputStart(e,t){return this.#R(e,t,"input-down-{logicalName}")}prependInputStart(e,t){return this.#V(e,t,"input-down-{logicalName}")}offInputStart(e,t){return this.#_(e,t,"input-down-{logicalName}")}onInputEnd(e,t){return this.#J(e,t,"input-up-{logicalName}")}onceInputEnd(e,t){return this.#R(e,t,"input-up-{logicalName}")}prependInputEnd(e,t){return this.#V(e,t,"input-up-{logicalName}")}offInputEnd(e,t){return this.#_(e,t,"input-up-{logicalName}")}onInputHold(e,t){return this.#J(e,t,"input-hold-{logicalName}")}onceInputHold(e,t){return this.#R(e,t,"input-hold-{logicalName}")}prependInputHold(e,t){return this.#V(e,t,"input-hold-{logicalName}")}offInputHold(e,t){return this.#_(e,t,"input-hold-{logicalName}")}onInputChange(e,t){return this.#J(e,t,"input-change-{logicalName}")}onceInputChange(e,t){return this.#R(e,t,"input-change-{logicalName}")}prependInputChange(e,t){return this.#V(e,t,"input-change-{logicalName}")}offInputChange(e,t){return this.#_(e,t,"input-change-{logicalName}")}onInputMove(e,t){return this.#J(e,t,"input-move-{logicalName}")}onceInputMove(e,t){return this.#R(e,t,"input-move-{logicalName}")}prependInputMove(e,t){return this.#V(e,t,"input-move-{logicalName}")}offInputMove(e,t){return this.#_(e,t,"input-move-{logicalName}")}getCalls(e,t="all"){if("string"!=typeof e||""===e.trim())throw new TypeError(`"logicalName" must be a non-empty string, received ${e}`);const n=["all","start","end","hold","change","move"];if(!n.includes(t))throw new TypeError(`"type" must be one of ${n.join(", ")}, received ${t}`);const i=`${{all:"input-",start:"input-down-",end:"input-up-",hold:"input-hold-",change:"input-change-",move:"input-move-"}[t]}${e}`,s=this.#i.get(i);return Array.isArray(s)?[...s]:[]}offAllInputs(e,t="all"){if("string"!=typeof e||""===e.trim())throw new TypeError(`"logicalName" must be a non-empty string, received ${e}`);const n=["all","start","end","hold","change","move"];if(!n.includes(t))throw new TypeError(`"type" must be one of ${n.join(", ")}, received ${t}`);const i={all:"input-",start:"input-down-",end:"input-up-",hold:"input-hold-",change:"input-change-",move:"input-move-"}[t];i&&this.#i.delete(`${i}${e}`)}getCallSize(e,t="all"){if("string"!=typeof e||""===e.trim())throw new TypeError(`"logicalName" must be a non-empty string, received ${e}`);const n=["all","start","end","hold","change","move"];if(!n.includes(t))throw new TypeError(`"type" must be one of ${n.join(", ")}, received ${t}`);const i={all:"input-",start:"input-down-",end:"input-up-",hold:"input-hold-",change:"input-change-",move:"input-move-"}[t],s=this.#i.get(`${i}${e}`);return Array.isArray(s)?s.length:0}#W={type:"dual-rumble",params:{startDelay:0,duration:200,weakMagnitude:.5,strongMagnitude:1}};get defaultHapticEffect(){return{type:this.#W.type,params:{...this.#W.params}}}setDefaultHapticEffect(e,t){if("string"!=typeof e)throw new TypeError(`"type" must be a valid GamepadHapticEffectType string, received ${e}`);if("object"!=typeof t||null===t)throw new TypeError(`"params" must be a non-null object, received ${t}`);this.#W.type=e,this.#W.params=t}hasHapticEffect(){const e=this.#s;return!!e&&e.vibrationActuator instanceof GamepadHapticActuator}vibrate(e,t){if(void 0!==e&&("object"!=typeof e||null===e))throw new TypeError(`"params" must be an object if provided, received ${e}`);if(void 0!==t&&"string"!=typeof t)throw new TypeError(`"type" must be a valid GamepadHapticEffectType string if provided, received ${t}`);const n=this.#s;if(!n)return new Promise(e=>e("complete"));const i=n.vibrationActuator;return i instanceof GamepadHapticActuator?i.playEffect(t??this.#W.type,{...this.#W.params,...e}):new Promise(e=>e("complete"))}ignoreId(e){if("string"!=typeof e||""===e.trim())throw new TypeError(`"id" must be a non-empty string, received ${e}`);this.#u.add(e)}unignoreId(e){if("string"!=typeof e||""===e.trim())throw new TypeError(`"id" must be a non-empty string, received ${e}`);this.#u.delete(e)}onConnected(e){return this.#J("",e,"connected")}onceConnected(e){return this.#R("",e,"connected")}prependConnected(e){return this.#V("",e,"connected")}offConnected(e){return this.#_("",e,"connected")}offAllConnected(){this.#i.delete("connected")}onDisconnected(e){return this.#J("",e,"disconnected")}onceDisconnected(e){return this.#R("",e,"disconnected")}prependDisconnected(e){return this.#V("",e,"disconnected")}offDisconnected(e){return this.#_("",e,"disconnected")}offAllDisconnected(){this.#i.delete("disconnected")}hasGamepad(){return this.#s instanceof Gamepad}getGamepad(){if(!this.#s)throw new Error("No gamepad is currently connected.");return this.#s}hasLastButtonState(e){return!!this.#a[e]}getLastButtonState(e){if(!this.#a[e])throw new Error(`No last button state found for index ${e}`);return{...this.#a[e]}}exportConfig(){return{expectedId:this.#m,ignoreIds:Array.from(this.#u),deadZone:this.#l,timeoutComboKeys:this.#f,axisActiveSensitivity:this.#g,inputMap:Array.from(this.#n.entries())}}importConfig(e){if("string"!=typeof e&&("object"!=typeof e||null===e))throw new TypeError(`"json" must be a string or a non-null object, received: ${e}`);const t="string"==typeof e?JSON.parse(e):e;if(void 0!==t.expectedId&&"string"!=typeof t.expectedId&&null!==t.expectedId)throw new TypeError('"expectedId" must be a string or null if provided');if(void 0!==t.ignoreIds&&!Array.isArray(t.ignoreIds))throw new TypeError('"ignoreIds" must be an array if provided');if(void 0!==t.deadZone&&"number"!=typeof t.deadZone)throw new TypeError('"deadZone" must be a number if provided');if(void 0!==t.timeoutComboKeys&&"number"!=typeof t.timeoutComboKeys)throw new TypeError('"timeoutComboKeys" must be a number if provided');if(void 0!==t.axisActiveSensitivity&&"number"!=typeof t.axisActiveSensitivity)throw new TypeError('"axisActiveSensitivity" must be a number if provided');if(void 0!==t.inputMap&&!Array.isArray(t.inputMap))throw new TypeError('"inputMap" must be an array if provided');void 0!==t.expectedId&&(this.#m=t.expectedId),Array.isArray(t.ignoreIds)&&(this.#u=new Set(t.ignoreIds)),"number"==typeof t.deadZone&&(this.#l=t.deadZone),"number"==typeof t.timeoutComboKeys&&(this.#f=t.timeoutComboKeys),"number"==typeof t.axisActiveSensitivity&&(this.#g=t.axisActiveSensitivity),Array.isArray(t.inputMap)&&(this.#n=new Map(t.inputMap))}get mappedKeyStartCalls(){const e=this.#i.get("mapped-key-start");return Array.isArray(e)?[...e]:[]}get mappedKeyEndCalls(){const e=this.#i.get("mapped-key-end");return Array.isArray(e)?[...e]:[]}get comboMappedKeys(){return[...this.#I]}get comboMappedInputs(){return[...this.#v]}get keySequenceSize(){return this.#K.size}get keySequences(){const e=[];for(const[,t]of this.#K.entries())e.push(t.callback);return e}get activeMappedKeys(){return[...this.#S]}get mappedInputStartCalls(){const e=this.#i.get("mapped-input-start");return Array.isArray(e)?[...e]:[]}get mappedInputEndCalls(){const e=this.#i.get("mapped-input-end");return Array.isArray(e)?[...e]:[]}get inputSequenceSize(){return this.#T.size}get inputSequences(){const e=[];for(const[,t]of this.#T.entries())e.push(t.callback);return e}get activeMappedInputs(){return[...this.#k]}get mappedInputs(){const e={};for(const[t,n]of this.#n.entries())e[t]=n;return e}get mappedInputSize(){return this.#n.size}get connectedCalls(){const e=this.#i.get("connected");return Array.isArray(e)?[...e]:[]}get disconnectedCalls(){const e=this.#i.get("disconnected");return Array.isArray(e)?[...e]:[]}get ignoredDeviceIds(){return[...this.#u]}get heldKeys(){return[...this.#t]}get eventsSize(){let e=0;return this.#i.forEach(t=>{e+=t.length}),e}get callSize(){return this.#i.size}get connectedCallSize(){const e=this.#i.get("connected");return Array.isArray(e)?e.length:0}get disconnectedCallSize(){const e=this.#i.get("disconnected");return Array.isArray(e)?e.length:0}get mappedKeyStartCallSize(){const e=this.#i.get("mapped-key-start");return Array.isArray(e)?e.length:0}get mappedKeyEndCallSize(){const e=this.#i.get("mapped-key-end");return Array.isArray(e)?e.length:0}get mappedInputStartCallSize(){const e=this.#i.get("mapped-input-start");return Array.isArray(e)?e.length:0}get mappedInputEndCallSize(){const e=this.#i.get("mapped-input-end");return Array.isArray(e)?e.length:0}get lastButtonStates(){const e=[];return this.#a.forEach(t=>{e.push({...t})}),e}get lastAxes(){return[...this.#o]}get inputMode(){return this.#c}get elementBase(){return this.#y}get timeComboInputs(){return this.#b}get timeComboKeys(){return this.#E}get timeMappedInputs(){return this.#w}get timeoutComboKeys(){return this.#f}set timeoutComboKeys(e){if("number"!=typeof e||e<0||!Number.isFinite(e))throw new TypeError("Timeout combo keys must be a non-negative finite number.");this.#f=e}get axisActiveSensitivity(){return this.#g}set axisActiveSensitivity(e){if("number"!=typeof e||e<0||e>1)throw new RangeError("Axis sensitivity must be a number between 0 and 1.");this.#g=e}get deadZone(){return this.#l}set deadZone(e){if("number"!=typeof e||e<0||e>1)throw new RangeError("Dead zone must be a number between 0 and 1.");this.#l=e}get expectedId(){return this.#m}set expectedId(e){if("string"!=typeof e)throw new TypeError("Expected device id be a string.");this.#m=e}get isDestroyed(){return this.#e}destroy(){this.#e||(this.#e=!0,this.#p&&cancelAnimationFrame(this.#p),this.#d&&cancelAnimationFrame(this.#d),this.#p=null,this.#d=null,["keyboard-only","both"].includes(this.#c)&&(this.#y.removeEventListener("keydown",this.#z),this.#y.removeEventListener("keyup",this.#Z),this.#h&&(this.#y.removeEventListener("mousedown",this.#P),this.#y.removeEventListener("mouseup",this.#O),this.#y.removeEventListener("mousemove",this.#F))),["gamepad-only","both"].includes(this.#c)&&(window.removeEventListener("gamepadconnected",this.#$),window.removeEventListener("gamepaddisconnected",this.#B)),this.resetComboMapped(),this.#n.clear(),this.#i.clear(),this.#t.clear(),this.#k.clear(),this.#S.clear(),this.#T.clear(),this.#K.clear(),this.#u.clear(),this.#A.clear(),this.#a=[],this.#o=[],this.#r={},this.#s=null,this.#m=null,this.#h=!1,this.#w=0)}}const i=n;window.TinyGamepad=t.TinyGamepad})();