UNPKG

coherent-gameface-interaction-manager

Version:
3 lines (2 loc) 41.1 kB
var S=class l{constructor(){this.actions=[],this.keyboardFunctions=[],this.gamepadFunctions=[]}init(){window._IM||(window._IM=new l)}getKeys(e){return _IM.keyboardFunctions.filter(t=>t.keys.every(i=>e.includes(i)))}getKeysIndex(e){return _IM.keyboardFunctions.findIndex(t=>t.keys.every(i=>e.includes(i)))}getGamepadAction({actions:e,type:t}){return _IM.gamepadFunctions.find(i=>i.actions.every(s=>e.includes(s))&&i.type===t&&i.actions.length===e.length)}getGamepadActions(e){return _IM.gamepadFunctions.filter(t=>t.actions.every(i=>e.includes(i))&&t.actions.length===e.length)}getGamepadActionIndex(e){return _IM.gamepadFunctions.findIndex(t=>t.actions.every(i=>e.includes(i)))}getAction(e){return _IM.actions.find(t=>t.name===e)}getActionIndex(e){return _IM.actions.findIndex(t=>t.name===e)}},g=new S;var L={ALT:18,ARROW_DOWN:40,ARROW_LEFT:37,ARROW_RIGHT:39,ARROW_UP:38,BACKSPACE:8,CAPS_LOCK:20,CTRL:17,DELETE:46,END:35,ENTER:13,ESC:27,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,HOME:36,INSERT:45,NUM_LOCK:144,NUMPAD_ENTER:13,NUMPAD_DASH:109,NUMPAD_STAR:106,NUMPAD_DOT:110,NUMPAD_FORWARD_SLASH:111,NUMPAD_PLUS:107,NUMPAD_0:96,NUMPAD_1:97,NUMPAD_2:98,NUMPAD_3:99,NUMPAD_4:100,NUMPAD_5:101,NUMPAD_6:102,NUMPAD_7:103,NUMPAD_8:104,NUMPAD_9:105,PAGE_DOWN:34,PAGE_UP:33,PAUSE:19,PRINT_SCRN:44,SCROLL_LOCK:145,SHIFT:16,SPACEBAR:32,TAB:9,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,0:48,QUOTE:222,DASH:189,COMMA:188,DOT:190,FORWARD_SLASH:191,SEMI_COLON:186,SQUARE_BRACKET_LEFT:219,SQUARE_BRACKET_RIGHT:221,BACKWARD_SLASH:220,BACKTICK:192,EQUAL:187,SYSTEM:91};var w=class{register(e,t){if(g.getAction(e))return console.error(`The following action "${e}" is already registered!`);_IM.actions.push({name:e,callback:t})}remove(e){let t=g.getActionIndex(e);if(t===-1)return console.error(`${e} is not a registered action!`);_IM.actions.splice(t,1)}execute(e,t){let i=g.getAction(e);if(!i)return console.error(`${e} is not a registered action!`);i.callback(t)}},h=new w;var C=class{constructor(){this.mappings=L,this.eventListenerAttached=!1,this.keysPressed=new Set,this.onKeyDown=this.onKeyDown.bind(this),this.onKeyUp=this.onKeyUp.bind(this),window.KEYS||(window.KEYS=L)}on(e){e.keys=[...new Set(e.keys.map(i=>(i=typeof i=="number"?this.keyCodeToString(i):i,i.toUpperCase())))];let t=e.keys.filter(i=>!this.mappings[i]);if(t.length>0)return console.error(`The following keys [${t.join(", ")}] you have entered are incorrect! `);this.eventListenerAttached||(document.addEventListener("keydown",this.onKeyDown),document.addEventListener("keyup",this.onKeyUp),this.eventListenerAttached=!0),Array.isArray(e.type)||(e.type=[e.type]),e.type.forEach(i=>{let s=g.getKeys(e.keys);if(s.length>0&&s.some(o=>o.type===i))return console.error("You are trying to overwrite an existing key combination! To do that, first remove it with .off([keys]) then add it again");if(i==="lift"&&e.keys.length>1)return console.error("You can only have a single key trigger an action on lift");_IM.keyboardFunctions.push({...e,type:i})})}off(e){e=[...new Set(e.map(i=>(i=typeof i=="number"?this.keyCodeToString(i):i,i.toUpperCase())))];let t=g.getKeys(e).length;if(t===0)return console.error("You are trying to remove a non-existent key combination!");for(;t>0;){let i=g.getKeysIndex(e);_IM.keyboardFunctions.splice(i,1),t--}_IM.keyboardFunctions.length===0&&(document.removeEventListener("keydown",this.onKeyDown),document.removeEventListener("keyup",this.onKeyUp),this.eventListenerAttached=!1)}onKeyDown(e){let t=this.keyCodeToString(e.keyCode);this.keysPressed.add(t);let i=g.getKeys([...this.keysPressed]);i.length!==0&&i.forEach(s=>{s.type==="press"&&e.repeat||s.type!=="press"&&s.type!=="hold"||s.type==="hold"&&!e.repeat||this.executeCallback(e,s)})}onKeyUp(e){let t=this.keyCodeToString(e.keyCode);this.keysPressed.delete(t);let i=g.getKeys(t);i.length!==0&&i.forEach(s=>{s.type==="lift"&&s.keys.indexOf(t)!==-1&&this.executeCallback(e,s)})}keyCodeToString(e){return Object.keys(this.mappings).find(t=>this.mappings[t]===e)}executeCallback(e,t){if(typeof t.callback=="string")return h.execute(t.callback,e);t.callback(e)}},A=new C;var B={FACE_BUTTON_DOWN:0,FACE_BUTTON_RIGHT:1,FACE_BUTTON_LEFT:2,FACE_BUTTON_TOP:3,LEFT_SHOULDER:4,RIGHT_SHOULDER:5,LEFT_SHOULDER_BOTTOM:6,RIGHT_SHOULDER_BOTTOM:7,SELECT:8,START:9,LEFT_ANALOGUE_STICK:10,RIGHT_ANALOGUE_STICK:11,PAD_UP:12,PAD_DOWN:13,PAD_LEFT:14,PAD_RIGHT:15,CENTER_BUTTON:16,aliases:{"face-button-down":"FACE_BUTTON_DOWN","face-button-left":"FACE_BUTTON_LEFT","face-button-right":"FACE_BUTTON_RIGHT","face-button-top":"FACE_BUTTON_TOP","left-sholder":"LEFT_SHOULDER","right-sholder":"RIGHT_SHOULDER","left-sholder-bottom":"LEFT_SHOULDER_BOTTOM","right-sholder-bottom":"RIGHT_SHOULDER_BOTTOM",select:"SELECT",start:"START","left-analogue-stick":"LEFT_ANALOGUE_STICK","right-analogue-stick":"RIGHT_ANALOGUE_STICK","pad-up":"PAD_UP","pad-down":"PAD_DOWN","pad-left":"PAD_LEFT","pad-right":"PAD_RIGHT","center-button":"CENTER_BUTTON","playstation.x":"FACE_BUTTON_DOWN","playstation.square":"FACE_BUTTON_LEFT","playstation.circle":"FACE_BUTTON_RIGHT","playstation.triangle":"FACE_BUTTON_TOP","playstation.l1":"LEFT_SHOULDER","playstation.r1":"RIGHT_SHOULDER","playstation.l2":"LEFT_SHOULDER_BOTTOM","playstation.r2":"RIGHT_SHOULDER_BOTTOM","playstation.share":"SELECT","playstation.options":"START","playstation.l3":"LEFT_ANALOGUE_STICK","playstation.r3":"RIGHT_ANALOGUE_STICK","playstation.d-pad-up":"PAD_UP","playstation.d-pad-down":"PAD_DOWN","playstation.d-pad-left":"PAD_LEFT","playstation.d-pad-right":"PAD_RIGHT","playstation.center":"CENTER_BUTTON","xbox.a":"FACE_BUTTON_DOWN","xbox.x":"FACE_BUTTON_LEFT","xbox.b":"FACE_BUTTON_RIGHT","xbox.y":"FACE_BUTTON_TOP","xbox.lb":"LEFT_SHOULDER","xbox.rb":"RIGHT_SHOULDER","xbox.lt":"LEFT_SHOULDER_BOTTOM","xbox.rt":"RIGHT_SHOULDER_BOTTOM","xbox.view":"SELECT","xbox.menu":"START","xbox.left-thumbstick":"LEFT_ANALOGUE_STICK","xbox.right-thumbstick":"RIGHT_ANALOGUE_STICK","xbox.d-pad-up":"PAD_UP","xbox.d-pad-down":"PAD_DOWN","xbox.d-pad-left":"PAD_LEFT","xbox.d-pad-right":"PAD_RIGHT","xbox.center":"CENTER_BUTTON"},axisAliases:["right.joystick","left.joystick","left.joystick.down","left.joystick.up","left.joystick.left","left.joystick.right","right.joystick.down","right.joystick.up","right.joystick.left","right.joystick.right"]};var E=.9,q=["press","hold"],I=class{constructor(){this.mappings=B,this.pollingStarted=!1,this.gamepadEnabled=!1,this.onGamepadConnected=this.onGamepadConnected.bind(this),this.sanitizeAction=this.sanitizeAction.bind(this),this.pollingInterval=200,this._pressedAction=null}set enabled(e){this.gamepadEnabled=e,this.gamepadEnabled?this.init():this.deinit()}init(){window.addEventListener("gamepadconnected",this.onGamepadConnected)}deinit(){window.removeEventListener("gamepadconnected",this.onGamepadConnected)}onGamepadConnected(){this.pollingStarted||(this.pollingStarted=!0,this.startPolling())}on(e){e.actions=e.actions.map(this.sanitizeAction);let t=this.mappings.axisAliases.some(i=>e.actions.includes(i));if((!e.type||!q.includes(e.type))&&(e.type="hold"),e.type==="press"&&t)return console.error("You can't use an axis action with a 'press' type!");if(e.actions.length>1&&t)return console.error("You can't use an axis action in a combination with a button action");if(g.getGamepadAction(e))return console.error("You have already registered a callback for this action. If you want to overwrite it, remove it first with .off([actions])");_IM.gamepadFunctions.push(e)}off(e){let t=g.getGamepadActionIndex(e.map(this.sanitizeAction));if(t===-1)return console.error("You are trying to remove a non-existent action!");_IM.gamepadFunctions.splice(t,1)}startPolling(){let e=navigator.getGamepads();if(e.length===0){this.pollingStarted=!1;return}e.forEach((t,i)=>{t&&(this.handleButtons(t.buttons,i),this.handleJoysticks(t.axes))}),setTimeout(this.startPolling.bind(this),this.pollingInterval)}handleButtons(e){let t=e.reduce((s,o,n)=>(o.pressed&&(s.buttonIndexes.push(n),s.buttons.push(o)),s),{buttonIndexes:[],buttons:[]}),i=g.getGamepadActions(t.buttonIndexes);!i.length!==0&&(this._pressedAction&&(i.includes(this._pressedAction)||this.executeCallback(this._pressedAction,this._pressedAction.actions),this._pressedAction=null),i.forEach(s=>{if(s.type==="press"){this._pressedAction=s;return}this.executeCallback(s,t.buttons)}))}handleJoysticks(e){this.getJoystickActions().forEach(i=>{switch(i.actions[0]){case"left.joystick":return this.executeCallback(i,[e[0],e[1]]);case"right.joystick":return this.executeCallback(i,[e[2],e[3]]);case"left.joystick.down":if(e[1]>E)return this.executeCallback(i,[e[0],e[1]]);break;case"left.joystick.up":if(e[1]<-E)return this.executeCallback(i,[e[0],e[1]]);break;case"left.joystick.left":if(e[0]<-E)return this.executeCallback(i,[e[0],e[1]]);break;case"left.joystick.right":if(e[0]>E)return this.executeCallback(i,[e[0],e[1]]);break;case"right.joystick.down":if(e[3]>E)return this.executeCallback(i,[e[2],e[3]]);break;case"right.joystick.up":if(e[3]<-E)return this.executeCallback(i,[e[2],e[3]]);break;case"right.joystick.left":if(e[2]<-E)return this.executeCallback(i,[e[2],e[3]]);break;case"right.joystick.right":if(e[2]>E)return this.executeCallback(i,[e[2],e[3]]);break}})}sanitizeAction(e){if(typeof e=="number")return e;if(this.mappings.axisAliases.includes(e.toLowerCase()))return e.toLowerCase();if(typeof e=="string"){let t=this.mappings.aliases[e.toLowerCase()];return t?this.mappings[t]:console.error(`You have entered a non-supported button alias ${e}`)}return e}getJoystickActions(){return _IM.gamepadFunctions.filter(e=>this.mappings.axisAliases.includes(e.actions[0]))}executeCallback(e,t){if(typeof e.callback=="string")return h.execute(e.callback,t);e.callback(t)}},_=new I;function M(l){return l*180/Math.PI}function v(l,e,t){return Math.min(Math.max(l,e),t)}function y(){return(Math.random()+1).toString(36).substring(7)}function x(l,e,t,i){let s=l-t,o=e-i;return Math.hypot(s,o)}function G(l,e,t,i){return{x:(l+t)/2,y:(e+i)/2}}var k=["down","up","left","right"],$={up:["arrow_up"],down:["arrow_down"],right:["arrow_right"],left:["arrow_left"]},N=class{constructor(){this.enabled=!1,this.navigatableElements={default:{elements:[],distance:0,overflow:{x:0,y:0}}},this.registeredKeys=new Set,this.clearCurrentActiveKeys=!1,this.overlapPercentage=.5,this.lastFocusedElement=null}init(e=[],t){this.enabled||(this.enabled=!0,this.add(e),this.activeKeys=JSON.parse(JSON.stringify($)),this.registerKeyActions(),t&&0<=t&&t<=1&&(this.overlapPercentage=t))}deinit(){this.enabled&&(this.enabled=!1,this.navigatableElements={default:{elements:[],distance:0,overflow:{x:0,y:0}}},this.removeKeyActions(),this.overlapPercentage=.5,this.lastFocusedElement=null)}add(e){this.enabled&&e.forEach(t=>{typeof t=="string"?this.handleString(t):this.handleObject(t)})}remove(e="default"){if(this.enabled){if(!this.navigatableElements[e])return console.error(`The area '${e}' you are trying to remove doesn't exist`);this.navigatableElements[e].elements.forEach(t=>t.removeAttribute("tabindex")),this.navigatableElements[e]={}}}handleString(e){let t=document.querySelectorAll(e);if(t.length===0)return console.error(`${e} is either not a correct selector or the element is not present in the DOM.`);t.forEach(this.makeFocusable),this.setNavigationAreaProperties("default",t)}handleObject(e){let t=e.elements.reduce((i,s)=>{let o=document.querySelectorAll(s);return o.forEach(this.makeFocusable),i.push(...o),i},[]);if(t.length===0)return console.error(`${e.elements.join(", ")} are either not a correct selectors or the elements are not present in the DOM.`);this.navigatableElements[e.area]||(this.navigatableElements[e.area]={elements:[],distance:0}),this.setNavigationAreaProperties(e.area,t)}setNavigationAreaProperties(e,t){this.navigatableElements[e].elements.push(...t),this.navigatableElements[e].distance=this.getElementsDistance(this.navigatableElements[e].elements),this.navigatableElements[e].overflow=this.setOverflowValues(t[0].parentElement)}getElementsDistance(e){return e.reduce((t,i)=>{let{x:s,y:o}=i.getBoundingClientRect(),n=Math.hypot(s,o);return t<n?n:t},0)}setOverflowValues(e){if(!e)return{x:0,y:0};let{scrollWidth:t,scrollHeight:i}=e,s=Math.max(0,t-window.innerWidth),o=Math.max(0,i-window.innerHeight);return s>0||o>0?{x:s,y:o}:this.setOverflowValues(e.parentElement)}makeFocusable(e){e.setAttribute("tabindex",1)}getFocusableGroup(e,t,i){return t.reduce((s,o)=>{if(o!==e&&!o.hasAttribute("disabled")){let{x:n,y:r,height:c,width:a}=o.getBoundingClientRect();s.push({element:o,x:n+i,y:r+i,height:c,width:a})}return s},[])}getCurrentArea(e){return Object.values(this.navigatableElements).find(t=>{if(t.elements.includes(e))return!0})}getClosestToEdge(e,t,i,s,o){let n,r,c=window.innerHeight+s+o.y,a=window.innerWidth+s+o.x;return t.reduce((d,u)=>{switch(e){case"down":n=Math.hypot(u.x-i.x,u.y),r=Math.hypot(d.x-i.x,d.y);break;case"up":n=Math.hypot(u.x-i.x,c-u.y),r=Math.hypot(d.x-i.x,c-d.y);break;case"right":n=Math.hypot(u.x,u.y-i.y),r=Math.hypot(d.x,d.y-i.y);break;case"left":n=Math.hypot(a-u.x,u.y-i.y),r=Math.hypot(a-d.x,d.y-i.y);break}return d=n<r?u:d,d})}moveFocus(e){if(!this.enabled)return;let t=this.checkActiveElementInGroup(),i=this.getCurrentArea(t);if(!i)return console.error("The active element is not in a focusable area!");let{elements:s,distance:o,overflow:n}=i,r=this.getFocusableGroup(t,s,o),{x:c,y:a,width:d,height:u}=t.getBoundingClientRect(),m={x:c+o,y:a+o,width:d,height:u};if(r.length===0)return;let T=this.filterGroupByCurrentAxis(e,r,m);if(!T.length)return;let f=this.findNextElement(e,T,m.x,m.y);f||(f=this.getClosestToEdge(e,T,m,o,n)),f&&(f.element.focus(),this.lastFocusedElement=f.element)}filterGroupByCurrentAxis(e,t,i){return t.filter(s=>e==="left"||e==="right"?this.isOverlappingX(i,s):this.isOverlappingY(i,s))}isOverlappingX(e,t){let i=Math.min(e.y+e.height,t.y+t.height),s=Math.max(e.y,t.y),o=Math.max(0,i-s),n=Math.min(e.height,t.height);return o/n>=this.overlapPercentage}isOverlappingY(e,t){let i=Math.min(e.x+e.width,t.x+t.width),s=Math.max(e.x,t.x),o=Math.max(0,i-s),n=Math.min(e.width,t.width);return o/n>=this.overlapPercentage}findNextElement(e,t,i,s){return t.reduce((o,n)=>{let r=n.x-i,c=n.y-s,a=M(Math.atan2(c,r));if(this.getDirectionAngle(e,a)){o||(o=n);let d=Math.hypot(r,c),u=Math.hypot(o.x-i,o.y-s);o=d<u?n:o}return o},null)}getDirectionAngle(e,t){switch(e){case"down":return t>0&&t<180;case"up":return t>-180&&t<0;case"left":return t<-90||t>90;case"right":return t>-90&&t<90}}registerKeyActions(){k.forEach(e=>{let t=()=>{this.moveFocus(e)};h.register(`move-focus-${e}`,t);let i=this.activeKeys[e];for(let s of i)A.on({keys:[s],callback:`move-focus-${e}`,type:["press","hold"]}),this.registeredKeys.add(s);_.on({actions:[`playstation.d-pad-${e}`],callback:`move-focus-${e}`})})}resetKeys(){this.removeKeyActions(),this.activeKeys=JSON.parse(JSON.stringify($)),this.registerKeyActions()}changeKeys(e,t={clearCurrentActiveKeys:!1}){let i=Object.keys(e);if(i.length===0)return;let s=i.filter(o=>!k.includes(o));if(s.length>0)return console.error(`The following directions: [${s.join(", ")}] you have entered are incorrect! `);this.clearCurrentActiveKeys=t.clearCurrentActiveKeys,this.removeKeyActions();for(let o in this.activeKeys){let n=e[o];typeof n=="string"&&!this.activeKeys[o].includes(n)&&this.activeKeys[o].push(n.toUpperCase())}this.registerKeyActions()}removeKeyActions(){this.registeredKeys.size!==0&&(this.registeredKeys.forEach(e=>A.off([e])),this.registeredKeys.clear(),k.forEach(e=>{h.remove(`move-focus-${e}`),_.off([`playstation.d-pad-${e}`]),this.clearCurrentActiveKeys&&(this.activeKeys[e]=[])}))}focusFirst(e="default"){let t=this.navigatableElements[e].elements;if(!t||t.length===0)return console.error(`The area '${e}' you are trying to focus doesn't exist or the spatial navigation hasn't been initialized`);if(this.lastFocusedElement=t.find(i=>!i.hasAttribute("disabled")),!this.lastFocusedElement)return console.error(`The area '${e}' you are trying to focus doesn't have any focusable elements`);this.lastFocusedElement.focus()}focusLast(e="default"){if(!this.enabled)return;let t=this.navigatableElements[e].elements;if(!t||t.length===0)return console.error(`The area '${e}' you are trying to focus doesn't exist or the spatial navigation hasn't been initialized`);let i;for(let s=t.length-1;s>=0;s--)if(!t[s].hasAttribute("disabled")){i=t[s];break}if(this.lastFocusedElement=i,!this.lastFocusedElement)return console.error(`The area '${e}' you are trying to focus doesn't have any focusable elements`);this.lastFocusedElement.focus()}switchArea(e){this.focusFirst(e)}isActiveElementInGroup(){return Object.values(this.navigatableElements).some(e=>e.elements.includes(document.activeElement))}checkActiveElementInGroup(){return this.isActiveElementInGroup(document.activeElement)?document.activeElement:this.lastFocusedElement}clearFocus(){this.isActiveElementInGroup()&&document.activeElement.blur()}},J=new N;var F=class{constructor(e){this.draggableElements=[],this.draggedElement=null,this.enabled=!1,this.onMouseDown=this.onMouseDown.bind(this),this.onMouseMove=this.onMouseMove.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this.options=e}get draggedItemIndex(){return[...this.draggableElements].indexOf(this.draggedElement)}get bodyScrollOffset(){return{x:document.body.scrollLeft,y:document.body.scrollTop}}setPointerOffset(e,t,i){let{x:s,y:o}=i.getBoundingClientRect();this.offset={x:e-s,y:t-o}}},O=F;function Y(l,e){if(e<0&&l>-200&&l<200)return"top";if(e>0&&l>-200&&l<200)return"bottom";if(l<0&&e>-200&&e<200)return"left";if(l>0&&e>-200&&e<200)return"right";if(l<=-200&&e<=-200)return"top-left";if(l>=200&&e<=-200)return"top-right";if(l<=-200&&e>=200)return"bottom-left";if(l>=200&&e>=200)return"bottom-right"}function b(l){return l instanceof HTMLElement?l:document.querySelector(l)}var D=2,P=class{constructor(){this.activeTouches=new Map}hold(e){if(!e)return console.error("Options not provided for hold!");let t,i=b(e.element);if(!i)return console.error("Element not found!");let s=({touches:n})=>{this.activeTouches.set(n[0].identifier,n[0]),t=setTimeout(()=>{e.callback&&e.callback()},e.time||1e3)},o=({touches:n})=>{this.activeTouches.delete(n[0].identifier),clearTimeout(t)};return i.addEventListener("touchstart",s),i.addEventListener("touchend",o),{remove(){i.removeEventListener("touchstart",s),i.removeEventListener("touchend",o)}}}tap(e){if(!e)return console.error("Options not provided for tap!");let t,i,s=!0,o=e.tapsNumber||1,n=b(e.element);if(!n)return console.error("Element not found!");let r=({touches:a})=>{this.activeTouches.set(a[0].identifier,a[0]),clearTimeout(i),s=!0,t=setTimeout(()=>{s=!1},e.tapTime||200)},c=({touches:a})=>{this.activeTouches.delete(a[0].identifier),clearTimeout(t),s&&(o--,i=setTimeout(()=>{o=e.tapsNumber||1,clearTimeout(i)},e.betweenTapsTime||500),!(o!==0||!e.callback)&&(e.callback(),s=!0,clearTimeout(t),o=e.tapsNumber||1))};return n.addEventListener("touchstart",r),n.addEventListener("touchend",c),{remove(){n.removeEventListener("touchstart",r),n.removeEventListener("touchend",c)}}}drag(e){if(!e)return console.error("Options not provided for drag!");let t=b(e.element);if(!t)return console.error("Element not found!");let i=({touches:n,target:r,currentTarget:c})=>{this.activeTouches.set(n[0].identifier,n[0]),document.addEventListener("touchmove",s),document.addEventListener("touchend",o),e.onDragStart&&e.onDragStart({x:n[0].clientX,y:n[0].clientY,target:r,currentTarget:c})},s=({touches:n})=>{this.activeTouches.has(n[0].identifier)&&e.onDrag&&e.onDrag({x:n[0].clientX,y:n[0].clientY})},o=({touches:n})=>{this.activeTouches.delete(n[0].identifier),document.removeEventListener("touchmove",s),document.removeEventListener("touchend",o),e.onDragEnd&&e.onDragEnd({x:n[0].clientX,y:n[0].clientY})};return t.addEventListener("touchstart",i),{remove(){t.removeEventListener("touchstart",i)}}}swipe(e){if(!e)return console.error("Options not provided for swipe!");let t,i,s,o=!0,n=100;e.touchNumber||=1;let r=b(e.element);if(!r)return console.error("Element not found!");let c=({touches:m})=>{this.activeTouches.set(m[0].identifier,m[0]),this.activeTouches.size>e.touchNumber&&(document.removeEventListener("touchmove",a),document.removeEventListener("touchend",d)),this.activeTouches.size===e.touchNumber&&(t=setTimeout(()=>{o=!1,clearTimeout(t),t=null},1e3),document.addEventListener("touchmove",a),document.addEventListener("touchend",d))},a=({touches:m})=>{if(!this.activeTouches.has(m[0].identifier))return;let{clientX:T,clientY:f}=this.activeTouches.get(m[0].identifier),X=m[0].clientX-T,j=m[0].clientY-f;i=Y(X,j),s=x(T,f,m[0].clientX,m[0].clientY)},d=({touches:m})=>{this.activeTouches.delete(m[0].identifier),this.activeTouches.size===0&&(document.removeEventListener("touchmove",a),document.removeEventListener("touchend",d),u()&&e.callback(i),clearTimeout(t),o=!0,t=null)},u=()=>o&&e.callback&&i&&s>n;return r.addEventListener("touchstart",c),{remove(){r.removeEventListener("touchstart",c)}}}pinch(e){if(!e)return console.error("Options not provided for pinch!");let t,i=40,s=b(e.element);if(!s)return console.error("Element not found!");let o=({touches:c})=>{this.activeTouches.set(c[0].identifier,c[0]),!(this.activeTouches.size<D)&&(document.addEventListener("touchmove",n),document.addEventListener("touchend",r),t=x(this.activeTouches.get(0).clientX,this.activeTouches.get(0).clientY,this.activeTouches.get(1).clientX,this.activeTouches.get(1).clientY))},n=({touches:c})=>{if(this.activeTouches.size!==D)return;this.activeTouches.set(c[0].identifier,c[0]);let a=x(this.activeTouches.get(0).clientX,this.activeTouches.get(0).clientY,this.activeTouches.get(1).clientX,this.activeTouches.get(1).clientY),d=Math.sign(a-t)*i;t=a;let u=G(this.activeTouches.get(0).clientX,this.activeTouches.get(0).clientY,this.activeTouches.get(1).clientX,this.activeTouches.get(1).clientY);e.callback&&e.callback({pinchDelta:d,midpoint:u})},r=({touches:c})=>{this.activeTouches.delete(c[0].identifier),this.activeTouches.size===0&&(document.removeEventListener("touchmove",n),document.removeEventListener("touchend",r))};return s.addEventListener("touchstart",o),{remove(){s.removeEventListener("touchstart",o)}}}rotate(e){if(!e)return console.error("Options not provided for rotate!");let t=0,i,s=b(e.element);if(!s)return console.error("Element not found!");let o=({touches:a})=>{this.activeTouches.size<D||(this.activeTouches.set(a[0].identifier,a[0]),t=c()-i,e.callback&&e.callback(t))},n=({touches:a})=>{this.activeTouches.set(a[0].identifier,a[0]),this.activeTouches.size===D&&(i=c()-t,document.addEventListener("touchmove",o),document.addEventListener("touchend",r))},r=({touches:a})=>{this.activeTouches.delete(a[0].identifier),document.removeEventListener("touchmove",o),document.removeEventListener("touchend",r)};s.addEventListener("touchstart",n);let c=()=>{let u=this.activeTouches.get(0).clientY-this.activeTouches.get(1).clientY,m=this.activeTouches.get(0).clientX-this.activeTouches.get(1).clientX;return(M(Math.atan2(u,m))+360+90)%360};return{remove(){s.removeEventListener("touchstart",n)}}}},p=new P;var Z=["x","y"],R=class extends O{constructor(e){super(e);let t=y();this.actionName=`drag-around-${t}`,this.restrict={top:0,left:0,right:1/0,bottom:1/0},this._touchEnabled=!1,this.touchEvents=[],this.init()}set touchEnabled(e){this._touchEnabled!==e&&(this._touchEnabled=e,this._touchEnabled?this.addTouchEvents():this.removeTouchEvents())}init(){if(!this.enabled){if(this.draggableElements=document.querySelectorAll(this.options.element),this.draggableElements.length===0)return console.error(`${this.options.element} is not a valid element selector.`);this.draggableElements.forEach(e=>e.addEventListener("mousedown",this.onMouseDown)),this.registerDragActions(),this.enabled=!0}}deinit(){this.enabled&&(this.enabled=!1,this.draggableElements.forEach(e=>e.removeEventListener("mousedown",this.onMouseDown)),this.removeDragActions())}onMouseDown(e){this.draggedElement=e.currentTarget,this.draggedElement.style.position="absolute",this.elementRect=this.draggedElement.getBoundingClientRect(),this.setRestriction(),this.setPointerOffset(e.clientX,e.clientY,this.draggedElement),h.execute(this.actionName,{x:e.clientX+this.bodyScrollOffset.x-this.offset.x,y:e.clientY+this.bodyScrollOffset.y-this.offset.y,index:this.draggedItemIndex}),this.options.dragClass&&this.draggedElement.classList.add(this.options.dragClass),this.options.onDragStart&&this.options.onDragStart(this.draggedElement),document.addEventListener("mousemove",this.onMouseMove),document.addEventListener("mouseup",this.onMouseUp)}onMouseMove(e){h.execute(this.actionName,{x:e.clientX+this.bodyScrollOffset.x-this.offset.x,y:e.clientY+this.bodyScrollOffset.y-this.offset.y,index:this.draggedItemIndex})}onMouseUp(){document.removeEventListener("mousemove",this.onMouseMove),document.removeEventListener("mouseup",this.onMouseUp),this.options.onDragEnd&&this.options.onDragEnd(this.draggedElement),this.options.dragClass&&this.draggedElement.classList.remove(this.options.dragClass),this.draggedElement=null}registerDragActions(){h.register(this.actionName,({x:e,y:t,index:i})=>{if(!this.draggableElements[i])return console.error(`There is no draggable element at index ${i}`);this.options.lockAxis&&Z.includes(this.options.lockAxis)&&(e=this.options.lockAxis==="y"?this.elementRect.x:e,t=this.options.lockAxis==="x"?this.elementRect.y:t),this.draggableElements[i].style.left=`${v(e,this.restrict.left,this.restrict.right)}px`,this.draggableElements[i].style.top=`${v(t,this.restrict.top,this.restrict.bottom)}px`,this.options.onDragMove&&this.options.onDragMove({x:e,y:t})})}removeDragActions(){h.remove(this.actionName)}addTouchEvents(){this.draggableElements.forEach(e=>{this.touchEvents.push(p.drag({element:e,onDragStart:t=>{this.onMouseDown({currentTarget:t.currentTarget,clientX:t.x,clientY:t.y})},onDrag:({x:t,y:i})=>{this.onMouseMove({clientX:t,clientY:i})},onDragEnd:()=>{this.onMouseUp()}}))})}removeTouchEvents(){this.touchEvents.forEach(e=>e.remove()),this.touchEvents=[]}setRestriction(){if(!this.options.restrictTo)return;let e=document.querySelector(this.options.restrictTo);if(!e)return console.error(`The element ${this.options.restrictTo} you trying to restrict dragging to is not a valid element`);let{x:t,y:i,height:s,width:o}=e.getBoundingClientRect();this.restrict={top:i,left:t,right:o+t-this.elementRect.width,bottom:s+i-this.elementRect.height}}},Q=R;var U=class extends O{constructor(e){super(e);let t=y();this.dropzones=[],this.draggedOver=null,this.actionName=`drag-and-drop-${t}`,this.automaticAction=`move-to-${t}`,this.onMouseEnter=this.onMouseEnter.bind(this),this.onMouseLeave=this.onMouseLeave.bind(this),this._touchEnabled=!1,this.touchEvents=[],this.init()}set touchEnabled(e){this._touchEnabled!==e&&(this._touchEnabled=e,this._touchEnabled?this.addTouchEvents():this.removeTouchEvents())}init(){if(!this.enabled){if(this.draggableElements=document.querySelectorAll(this.options.element),this.draggableElements.length===0)return console.error(`${this.options.element} is not a valid element selector.`);this.draggableElements.forEach(e=>e.addEventListener("mousedown",this.onMouseDown)),this.createDropzones(),this.dropzones.length!==0&&(this.dropzones.forEach(e=>{e.addEventListener("mouseenter",this.onMouseEnter),e.addEventListener("mouseleave",this.onMouseLeave)}),this.registerDragActions(),this.enabled=!0)}}deinit(){this.enabled&&(this.draggableElements.forEach(e=>e.removeEventListener("mousedown",this.onMouseDown)),this.dropzones.forEach(e=>{e.removeEventListener("mouseenter",this.onMouseEnter),e.removeEventListener("mouseleave",this.onMouseLeave)}),this.removeActions(),this.enabled=!1)}onMouseDown(e){this.draggedElement=e.currentTarget,this.draggedElement.style.position="absolute",this.draggedElement.style.pointerEvents="none",this.setPointerOffset(e.clientX,e.clientY,this.draggedElement),h.execute(this.actionName,{x:e.clientX+this.bodyScrollOffset.x-this.offset.x,y:e.clientY+this.bodyScrollOffset.y-this.offset.y,index:this.draggedItemIndex}),this.options.dragStyle&&this.draggedElement.classList.add(this.options.dragStyle),this.options.onDragStart&&this.options.onDragStart(this.draggedElement),document.addEventListener("mousemove",this.onMouseMove),document.addEventListener("mouseup",this.onMouseUp)}onMouseMove(e){h.execute(this.actionName,{x:e.clientX+this.bodyScrollOffset.x-this.offset.x,y:e.clientY+this.bodyScrollOffset.y-this.offset.y,index:this.draggedItemIndex})}onMouseUp(){document.removeEventListener("mousemove",this.onMouseMove),document.removeEventListener("mouseup",this.onMouseUp),this.draggedElement.style.position="",this.draggedElement.style.pointerEvents="",this.draggedElement.style.left="",this.draggedElement.style.top="",this.options.onDragEnd&&this.options.onDragEnd(this.draggedElement),this.options.dragStyle&&this.draggedElement.classList.remove(this.options.dragStyle),this.draggedOver&&this.handleDrop(),this.draggedElement=null}onMouseEnter(e){this.draggedElement&&(this.draggedOver=e.currentTarget,this.options.dropzoneActiveClass&&this.draggedOver.classList.add(this.options.dropzoneActiveClass))}onMouseLeave(){this.draggedElement&&(this.options.dropzoneActiveClass&&this.draggedOver&&this.draggedOver.classList.remove(this.options.dropzoneActiveClass),this.draggedOver=null)}registerDragActions(){h.register(this.actionName,({x:e,y:t,index:i})=>{if(!this.draggableElements[i])return console.error(`There is no draggable element at index ${i}`);this.draggableElements[i].style.left=`${e}px`,this.draggableElements[i].style.top=`${t}px`,this.options.onDragMove&&this.options.onDragMove({x:e,y:t})}),h.register(this.automaticAction,this.automaticMove.bind(this)),this.actionsRegistered=!0}removeActions(){h.remove(this.actionName),h.remove(this.automaticAction)}addTouchEvents(){this.draggableElements.forEach(e=>{this.touchEvents.push(p.drag({element:e,onDragStart:t=>{this.onMouseDown({currentTarget:t.currentTarget,clientX:t.x,clientY:t.y})},onDrag:({x:t,y:i})=>{this.onMouseMove({clientX:t,clientY:i});let s=document.elementFromPoint(t,i),o=this.options.dropzones.reduce((n,r)=>n||(n=s.closest(r)),null);if(o||(o=this.dropzones.includes(s)?s:null),o){this.onMouseEnter({currentTarget:o});return}this.onMouseLeave()},onDragEnd:()=>{this.onMouseUp()}}))})}removeTouchEvents(){this.touchEvents.forEach(e=>e.remove()),this.touchEvents=[]}automaticMove({elementIndex:e,dropzoneIndex:t}){let{x:i,y:s}=this.dropzones[t].getBoundingClientRect(),{x:o,y:n}=this.draggableElements[e].getBoundingClientRect(),r={x:Math.sign(i-o),y:Math.sign(s-n)};this.draggableElements[e].style.position="absolute";let c=(a,d)=>{if(a===i&&d===s){this.dropzones[t].appendChild(this.draggableElements[e]),this.draggableElements[e].style.position="";return}a=a!==i?r.x+a:a,d=d!==s?r.y+d:d,this.draggableElements[e].style.left=`${a}px`,this.draggableElements[e].style.top=`${d}px`,(a!==i||d!==s)&&requestAnimationFrame(()=>c(a,d))};c(o,n)}createDropzones(){this.dropzones=this.options.dropzones.reduce((e,t)=>{let i=[...document.querySelectorAll(t)];return i.length===0&&console.error(`${t} is not a valid html element to be used as a dropzone`),e.concat(i)},[])}handleDrop(){let e=this.options.dropType,t={preventDefault:()=>{e="ignore"},target:this.draggedElement,dropzone:this.draggedOver};if(this.options.onDrop&&this.options.onDrop(t),e!=="ignore"){switch(this.draggedOver.children.length===0&&(e="add"),e){case"add":this.draggedOver.appendChild(this.draggedElement);break;case"shift":this.shiftElements();break;case"switch":this.draggedElement.parentNode.appendChild(this.draggedOver.children[0]),this.draggedOver.appendChild(this.draggedElement);break;case"none":break;default:break}this.onMouseLeave()}}shiftElements(){let e=this.dropzones.findIndex(n=>n===this.draggedOver),t=this.dropzones.map(n=>n.children[0]===this.draggedElement?[]:[...n.children]),i=t.reduce((n,r,c)=>(r.length===0&&(n=Math.abs(e-c)<Math.abs(e-n)?c:n),n),1e5),s=Math.sign(e-i)>0?0:1,o=Math.sign(e-i)<0?0:1;t.splice(e+o,0,[this.draggedElement]),t.splice(i+s,1),t.forEach((n,r)=>{n.forEach(c=>this.dropzones[r].appendChild(c))})}},V=U;var z=360,ee=90,K=class{constructor(e){let t=y();this.options=e,this.rotatingElement=null,this.elementPosition={x:0,y:0},this.angle=0,this.enabled=!1,this.actionName=`rotate-${t}`,this.onMouseDown=this.onMouseDown.bind(this),this.onMouseMove=this.onMouseMove.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this._touchEnabled=!1,this.touchEvents=null,this.init()}set touchEnabled(e){this._touchEnabled!==e&&(this._touchEnabled=e,this._touchEnabled?this.addTouchEvents():this.removeTouchEvents())}init(){if(!this.enabled){if(this.rotatingElement=this.rotatingElement||document.querySelector(this.options.element),!this.rotatingElement)return console.error(`${this.options.element} is not a valid element selector`);this.rotatingElement.addEventListener("mousedown",this.onMouseDown),this.registerAction(),this.enabled=!0}}deinit(){this.enabled&&(this.rotatingElement.removeEventListener("mousedown",this.onMouseDown),this.removeActions(),this.enabled=!1)}onMouseDown(e){document.addEventListener("mousemove",this.onMouseMove),document.addEventListener("mouseup",this.onMouseUp);let{x:t,y:i,height:s,width:o}=this.rotatingElement.getBoundingClientRect();this.elementPosition={x:t+o/2,y:i+s/2};let n=this.getAngle(e.clientX,e.clientY);this.initalAngle=n-this.angle}onMouseMove(e){this.angle=this.getAngle(e.clientX,e.clientY)-this.initalAngle,this.options.snapAngle&&(this.angle=Math.floor(this.angle/this.options.snapAngle)*this.options.snapAngle),h.execute(this.actionName,this.angle)}onMouseUp(){document.removeEventListener("mousemove",this.onMouseMove),document.removeEventListener("mouseup",this.onMouseUp)}registerAction(){h.register(this.actionName,e=>{this.rotatingElement.style.transform=`rotate(${e}deg)`,this.options.onRotation&&this.options.onRotation(e<0?z+e:e)})}removeActions(){h.remove(this.actionName)}addTouchEvents(){this.touchEvents=p.drag({element:this.rotatingElement,onDragStart:({x:e,y:t})=>{this.onMouseDown({clientX:e,clientY:t})},onDrag:({x:e,y:t})=>{this.onMouseMove({clientX:e,clientY:t})},onDragEnd:()=>{this.onMouseUp()}})}removeTouchEvents(){this.touchEvents.remove(),this.touchEvents=null}getAngle(e,t){let i=e-this.elementPosition.x,s=t-this.elementPosition.y;return(M(Math.atan2(s,i))+z+ee)%z}},te=K;var H=class{constructor(e){this.options=e,this.options.edgeWidth=e.edgeWidth||5,this.options.heightMin=this.options.heightMin||50,this.options.heightMax=this.options.heightMax||window.innerHeight,this.options.widthMin=this.options.widthMin||50,this.options.widthMax=this.options.widthMax||window.innerWidth,this.resizableElement=null,this.enabled=!1,this.activeEdge=null,this.edges={bottom:null,right:null,bottomRight:null};let t=y();this.heightAction=`resize-height-${t}`,this.widthAction=`resize-width-${t}`,this.onMouseDown=this.onMouseDown.bind(this),this.onMouseMove=this.onMouseMove.bind(this),this.onMouseUp=this.onMouseUp.bind(this),this._touchEnabled=!1,this.touchEvents=null,this.init()}set touchEnabled(e){this._touchEnabled!==e&&(this._touchEnabled=e,this._touchEnabled?this.addTouchEvents():this.removeTouchEvents())}init(){if(!this.enabled){if(this.resizableElement=document.querySelector(this.options.element),!this.resizableElement)return console.error(`${this.options.element} is not a correct selector`);this.resizableElement.addEventListener("mousedown",this.onMouseDown),this.addEdges(),this.registerActions(),this.enabled=!0}}deinit(){this.enabled&&(this.resizableElement.removeEventListener("mousedown",this.onMouseDown),this.removeEdges(),this.removeActions(),this.enabled=!1)}onMouseDown(e){if(this.activeEdge=this.setEdge(e.target),!this.activeEdge)return;let{x:t,y:i}=this.resizableElement.getBoundingClientRect();this.elementRect={x:t,y:i},document.addEventListener("mousemove",this.onMouseMove),document.addEventListener("mouseup",this.onMouseUp)}onMouseMove(e){let t=e.clientX-this.elementRect.x,i=e.clientY-this.elementRect.y;switch(this.activeEdge){case"bottom":h.execute(this.heightAction,i),this.options.onHeightChange&&this.options.onHeightChange(i);break;case"right":h.execute(this.widthAction,t),this.options.onWidthChange&&this.options.onWidthChange(t);break;case"bottomRight":h.execute(this.heightAction,i),h.execute(this.widthAction,t),this.options.onWidthChange&&this.options.onWidthChange(t),this.options.onHeightChange&&this.options.onHeightChange(i);break}}onMouseUp(){this.activeEdge=null,document.removeEventListener("mousemove",this.onMouseMove),document.removeEventListener("mouseup",this.onMouseUp)}addTouchEvents(){this.touchEvents=p.drag({element:this.resizableElement,onDragStart:e=>{this.onMouseDown(e)},onDrag:({x:e,y:t})=>{this.onMouseMove({clientX:e,clientY:t})},onDragEnd:()=>{this.onMouseUp()}})}removeTouchEvents(){this.touchEvents.remove(),this.touchEvents=null}setEdge(e){return e.dataset.edge?e.dataset.edge:null}checkPosition(){let{position:e}=getComputedStyle(this.resizableElement);e==="absolute"||e==="relative"||(this.resizableElement.style.position="relative")}addEdges(){this.checkPosition();let{width:e,height:t}=this.resizableElement.getBoundingClientRect();Object.entries(this.edges).forEach(([i,s])=>{switch(s=document.createElement("DIV"),s.dataset.edge=i,s.style.position="absolute",i){case"bottom":s.style.width=`${e-this.options.edgeWidth}px`,s.style.height=`${this.options.edgeWidth}px`,s.style.bottom=`-${this.options.edgeWidth}px`;break;case"bottomRight":s.style.width=`${this.options.edgeWidth}px`,s.style.height=`${this.options.edgeWidth}px`,s.style.bottom=`-${this.options.edgeWidth}px`,s.style.right=`-${this.options.edgeWidth}px`;break;case"right":s.style.width=`${this.options.edgeWidth}px`,s.style.height=`${t-this.options.edgeWidth}px`,s.style.right=`-${this.options.edgeWidth}px`;break}this.edges[i]=s,this.resizableElement.appendChild(s)})}removeEdges(){Object.values(this.edges).forEach(e=>{this.resizableElement.removeChild(e)})}registerActions(){h.register(this.heightAction,e=>{this.resizableElement.style.height=`${v(e,this.options.heightMin,this.options.heightMax)}px`,this.edges.right.style.height=`${v(e,this.options.heightMin,this.options.heightMax)-this.options.edgeWidth}px`}),h.register(this.widthAction,e=>{this.resizableElement.style.width=`${v(e,this.options.widthMin,this.options.widthMax)}px`,this.edges.bottom.style.width=`${v(e,this.options.widthMin,this.options.widthMax)-this.options.edgeWidth}px`})}removeActions(){h.remove(this.heightAction),h.remove(this.widthAction)}},ie=H;var W=class{constructor(e){let t=(Math.random()+1).toString(36).substring(7);this.options=e,this.options.maxZoom=this.options.maxZoom||1/0,this.options.minZoom=this.options.minZoom||.1,this.options.zoomFactor=this.options.zoomFactor||.1,this.enabled=!1,this.actionName=`pan-and-zoom-${t}`,this.offset={x:0,y:0},this.transform={x:0,y:0,scale:1},this.onWheel=this.onWheel.bind(this),this._touchEnabled=!1,this.touchEvents=null,this.init()}set touchEnabled(e){this._touchEnabled!==e&&(this._touchEnabled=e,this._touchEnabled?this.addTouchEvents():this.removeTouchEvents())}init(){if(!this.enabled){if(this.zoomableElement=document.querySelector(this.options.element),!this.zoomableElement)return console.error(`${this.options.element} is not a correct element selector`);this.zoomableElement.addEventListener("wheel",this.onWheel),this.registerActions(),this.zoomableElement.style.transformOrigin="top left",this.enabled=!0}}deinit(){this.enabled&&(this.zoomableElement.removeEventListener("wheel",this.onWheel),this.removeActions(),this.enabled=!1)}onWheel(e){e.preventDefault(),h.execute(this.actionName,{x:e.clientX,y:e.clientY,zoomDirection:Math.sign(e.deltaY)})}registerActions(){h.register(this.actionName,({x:e,y:t,zoomDirection:i})=>{let s=this.calculateOffsets(e,t);this.options.onZoom&&this.options.onZoom();let o=(this.transform.scale-i*this.options.zoomFactor).toFixed(5);if(o<this.options.minZoom||o>this.options.maxZoom)return;let n={x:s.x/this.transform.scale,y:s.y/this.transform.scale},r=this.transform;r.x+=n.x*(this.transform.scale-o),r.y+=n.y*(this.transform.scale-o),r.scale=o,this.zoomableElement.style.transform=`matrix(${r.scale}, 0, 0, ${r.scale}, ${r.x}, ${r.y})`,this.transform=r})}removeActions(){h.remove(this.actionName)}addTouchEvents(){this.touchEvents=p.pinch({element:this.zoomableElement,callback:({pinchDelta:e,midpoint:t})=>{h.execute(this.actionName,{x:t.x,y:t.y,zoomDirection:Math.sign(e)*-1})}})}removeTouchEvents(){this.touchEvents.remove(),this.touchEvents=null}calculateOffsets(e,t){let i=this.zoomableElement.getBoundingClientRect();return{x:e-i.x,y:t-i.y}}},se=W;g.init();export{h as actions,Q as draggable,V as dropzone,_ as gamepad,A as keyboard,ie as resize,te as rotate,J as spatialNavigation,p as touchGestures,se as zoom}; //# sourceMappingURL=interaction-manager.min.js.map