@hydroperx/inputaction
Advanced tools
+27
-9
| import { InputActionAtom, InputActionKeyName } from "./InputAction"; | ||
| import { TypedEventTarget } from "@hydroperx/event"; | ||
| declare const Input_base: TypedEventTarget<{ | ||
| inputPressed: Event; | ||
| inputReleased: Event; | ||
| actionsUpdated: Event; | ||
| }>; | ||
| declare const Input_base: TypedEventTarget<InputEventMap>; | ||
| /** | ||
@@ -17,5 +13,5 @@ * The `Input` class handles action mapping and user input event listening. | ||
| * ```ts | ||
| * import { Input } from "@hydroperx/inputaction"; | ||
| * import { input } from "@hydroperx/inputaction"; | ||
| * | ||
| * Input.input.setActions({ | ||
| * input.setActions({ | ||
| * "moveLeft": [ | ||
@@ -39,4 +35,4 @@ * { key: "a" }, | ||
| * | ||
| * Input.input.addEventListener("inputPressed", () => { | ||
| * const shouldMoveRight = Input.input.isPressed("moveRight"); | ||
| * input.on("inputPressed", () => { | ||
| * const shouldMoveRight = input.isPressed("moveRight"); | ||
| * }); | ||
@@ -107,3 +103,25 @@ * ``` | ||
| justPressed(name: string): boolean; | ||
| /** | ||
| * Shortcut for the `addEventListener()` method. | ||
| */ | ||
| on<T extends keyof InputEventMap>(type: T, listener: (event: (InputEventMap[T] extends Event ? InputEventMap[T] : never)) => void, options?: boolean | AddEventListenerOptions): void; | ||
| on(type: string, listener: Function, options?: boolean | AddEventListenerOptions): void; | ||
| /** | ||
| * Shortcut for the `removeEventListener()` method. | ||
| */ | ||
| off<T extends keyof InputEventMap>(type: T, listener: (event: (InputEventMap[T] extends Event ? InputEventMap[T] : never)) => void, options?: boolean | EventListenerOptions): void; | ||
| off(type: string, listener: Function, options?: boolean | EventListenerOptions): void; | ||
| } | ||
| /** | ||
| * Event types dispatched by `Input`. | ||
| */ | ||
| export type InputEventMap = { | ||
| inputPressed: Event; | ||
| inputReleased: Event; | ||
| actionsUpdated: Event; | ||
| }; | ||
| /** | ||
| * The singleton instance of the `Input` class. | ||
| */ | ||
| export declare const input: Input; | ||
| export {}; |
+91
-77
@@ -12,5 +12,5 @@ import { navigatorKeyToThis, } from "./InputAction"; | ||
| * ```ts | ||
| * import { Input } from "@hydroperx/inputaction"; | ||
| * import { input } from "@hydroperx/inputaction"; | ||
| * | ||
| * Input.input.setActions({ | ||
| * input.setActions({ | ||
| * "moveLeft": [ | ||
@@ -34,4 +34,4 @@ * { key: "a" }, | ||
| * | ||
| * Input.input.addEventListener("inputPressed", () => { | ||
| * const shouldMoveRight = Input.input.isPressed("moveRight"); | ||
| * input.on("inputPressed", () => { | ||
| * const shouldMoveRight = input.isPressed("moveRight"); | ||
| * }); | ||
@@ -65,8 +65,11 @@ * ``` | ||
| */ | ||
| export default class Input extends EventTarget { | ||
| class Input extends EventTarget { | ||
| constructor() { | ||
| super(...arguments); | ||
| // Actions map | ||
| this.mMap = { | ||
| ...Input.builtin(), | ||
| }; | ||
| } | ||
| /** | ||
| * The singleton instance of the `Input` class. | ||
| */ | ||
| static input = new Input(); | ||
| /** | ||
| * Returns the display text of a shortcut, such as `"Ctrl+A"`. | ||
@@ -78,3 +81,3 @@ * | ||
| if (typeof param == "string") { | ||
| return Input.display(Input.input.getActions()[param]); | ||
| return Input.display(input.getActions()[param]); | ||
| } | ||
@@ -141,6 +144,2 @@ if (!param) | ||
| } | ||
| // Actions map | ||
| mMap = { | ||
| ...Input.builtin(), | ||
| }; | ||
| /** | ||
@@ -174,65 +173,2 @@ * Returns the current action map in read-only mode. | ||
| } | ||
| // Static pressed state pool | ||
| static mPressedStatePoolKeys = new Map(); | ||
| static { | ||
| if (typeof window !== "undefined") { | ||
| window.addEventListener("keydown", (evt) => { | ||
| const keyName = navigatorKeyToThis(evt.key); | ||
| if (keyName !== undefined) { | ||
| // Mutate pressed state | ||
| let state = Input.mPressedStatePoolKeys.get(keyName); | ||
| if (state === undefined) { | ||
| state = { | ||
| pressed: false, | ||
| pressedTimestamp: 0, | ||
| control: false, | ||
| shift: false, | ||
| alt: false, | ||
| }; | ||
| Input.mPressedStatePoolKeys.set(keyName, state); | ||
| } | ||
| state.pressed = true; | ||
| state.pressedTimestamp = Date.now(); | ||
| state.control = evt.ctrlKey; | ||
| state.shift = evt.shiftKey; | ||
| state.alt = evt.altKey; | ||
| // Dispatch pressed event | ||
| const evt1 = new Event("inputPressed", { cancelable: true }); | ||
| const r = Input.input.dispatchEvent(evt1); | ||
| if (evt1.defaultPrevented) { | ||
| evt.preventDefault(); | ||
| } | ||
| return r; | ||
| } | ||
| }); | ||
| window.addEventListener("keyup", (evt) => { | ||
| const keyName = navigatorKeyToThis(evt.key); | ||
| if (keyName !== undefined) { | ||
| // Mutate pressed state | ||
| let state = Input.mPressedStatePoolKeys.get(keyName); | ||
| if (state === undefined) { | ||
| state = { | ||
| pressed: false, | ||
| pressedTimestamp: 0, | ||
| control: false, | ||
| shift: false, | ||
| alt: false, | ||
| }; | ||
| Input.mPressedStatePoolKeys.set(keyName, state); | ||
| } | ||
| state.pressed = false; | ||
| state.control = false; | ||
| state.shift = false; | ||
| state.alt = false; | ||
| // Dispatch released event | ||
| const evt1 = new Event("inputReleased", { cancelable: true }); | ||
| const r = Input.input.dispatchEvent(evt1); | ||
| if (evt1.defaultPrevented) { | ||
| evt.preventDefault(); | ||
| } | ||
| return r; | ||
| } | ||
| }); | ||
| } | ||
| } | ||
| /** | ||
@@ -288,2 +224,80 @@ * Determines whether an action is pressed. | ||
| } | ||
| on(type, listener, options) { | ||
| this.addEventListener(type, listener, options); | ||
| } | ||
| off(type, listener, options) { | ||
| this.removeEventListener(type, listener, options); | ||
| } | ||
| } | ||
| /** | ||
| * The singleton instance of the `Input` class. | ||
| */ | ||
| Input.input = new Input(); | ||
| // Static pressed state pool | ||
| Input.mPressedStatePoolKeys = new Map(); | ||
| (() => { | ||
| if (typeof window !== "undefined") { | ||
| window.addEventListener("keydown", (evt) => { | ||
| const keyName = navigatorKeyToThis(evt.key); | ||
| if (keyName !== undefined) { | ||
| // Mutate pressed state | ||
| let state = Input.mPressedStatePoolKeys.get(keyName); | ||
| if (state === undefined) { | ||
| state = { | ||
| pressed: false, | ||
| pressedTimestamp: 0, | ||
| control: false, | ||
| shift: false, | ||
| alt: false, | ||
| }; | ||
| Input.mPressedStatePoolKeys.set(keyName, state); | ||
| } | ||
| state.pressed = true; | ||
| state.pressedTimestamp = Date.now(); | ||
| state.control = evt.ctrlKey; | ||
| state.shift = evt.shiftKey; | ||
| state.alt = evt.altKey; | ||
| // Dispatch pressed event | ||
| const evt1 = new Event("inputPressed", { cancelable: true }); | ||
| const r = input.dispatchEvent(evt1); | ||
| if (evt1.defaultPrevented) { | ||
| evt.preventDefault(); | ||
| } | ||
| return r; | ||
| } | ||
| }); | ||
| window.addEventListener("keyup", (evt) => { | ||
| const keyName = navigatorKeyToThis(evt.key); | ||
| if (keyName !== undefined) { | ||
| // Mutate pressed state | ||
| let state = Input.mPressedStatePoolKeys.get(keyName); | ||
| if (state === undefined) { | ||
| state = { | ||
| pressed: false, | ||
| pressedTimestamp: 0, | ||
| control: false, | ||
| shift: false, | ||
| alt: false, | ||
| }; | ||
| Input.mPressedStatePoolKeys.set(keyName, state); | ||
| } | ||
| state.pressed = false; | ||
| state.control = false; | ||
| state.shift = false; | ||
| state.alt = false; | ||
| // Dispatch released event | ||
| const evt1 = new Event("inputReleased", { cancelable: true }); | ||
| const r = input.dispatchEvent(evt1); | ||
| if (evt1.defaultPrevented) { | ||
| evt.preventDefault(); | ||
| } | ||
| return r; | ||
| } | ||
| }); | ||
| } | ||
| })(); | ||
| export default Input; | ||
| /** | ||
| * The singleton instance of the `Input` class. | ||
| */ | ||
| export const input = Input.input; |
+4
-3
| { | ||
| "name": "@hydroperx/inputaction", | ||
| "version": "1.0.3", | ||
| "version": "1.1.0", | ||
| "description": "Input actions library.", | ||
| "repository": "https://github.com/hydroperx/inputaction", | ||
| "repository": "https://github.com/hydroperx/inputaction.js", | ||
| "license": "Apache-2.0", | ||
@@ -25,4 +25,5 @@ "author": "Hydroper <HydroperFox@gmail.com>", | ||
| "devDependencies": { | ||
| "@types/assert": "^1.5.10" | ||
| "@types/assert": "^1.5.10", | ||
| "typescript": "~5.6.2" | ||
| } | ||
| } |
+4
-4
@@ -16,5 +16,5 @@ # Input action | ||
| ```ts | ||
| import { Input } from "@hydroperx/inputaction"; | ||
| import { input } from "@hydroperx/inputaction"; | ||
| Input.input.setActions({ | ||
| input.setActions({ | ||
| "moveLeft": [ | ||
@@ -38,6 +38,6 @@ { key: "a" }, | ||
| Input.input.addEventListener("inputPressed", () => { | ||
| input.on("inputPressed", () => { | ||
| // use isPressed() or justPressed() | ||
| const shouldMoveRight = Input.input.justPressed("moveRight"); | ||
| const shouldMoveRight = input.justPressed("moveRight"); | ||
| }); | ||
| ``` |
| /** | ||
| * Clones a plain object. `deep` is `false` by default. | ||
| */ | ||
| export default function clonePlainObject(object: any, deep?: boolean): any; |
| /** | ||
| * Clones a plain object. `deep` is `false` by default. | ||
| */ | ||
| export default function clonePlainObject(object, deep = false) { | ||
| if (deep) { | ||
| return clonePlainObjectDeep(object); | ||
| } | ||
| const r = {}; | ||
| for (const k in object) { | ||
| r[k] = object[k]; | ||
| } | ||
| return r; | ||
| } | ||
| function clonePlainObjectDeep(object) { | ||
| const r = {}; | ||
| for (const k in object) { | ||
| const objectK = object[k]; | ||
| if (objectK instanceof Array) { | ||
| const newArray = []; | ||
| for (const el of objectK) { | ||
| newArray.push(clonePlainObjectDeep(el)); | ||
| } | ||
| r[k] = newArray; | ||
| } | ||
| else if (typeof objectK === "object") { | ||
| r[k] = clonePlainObjectDeep(objectK); | ||
| } | ||
| else { | ||
| r[k] = objectK; | ||
| } | ||
| } | ||
| return r; | ||
| } |
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
28722
-0.22%2
100%9
-18.18%483
-1.02%