🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@hydroperx/inputaction

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@hydroperx/inputaction - npm Package Compare versions

Comparing version
1.0.0
to
1.0.1
+11
dist/index.d.ts
import Input from "./Input";
import { InputActionAtom, InputActionKeyName } from "./InputAction";
export { Input };
export type { InputActionAtom, InputActionKey, InputActionKeyName, } from "./InputAction";
/**
* Returns the display text of a shortcut, such as `"Ctrl+A"`.
*
* @param param Either an action name or a series of action atoms.
*/
export declare function shortcutDisplayText(param: string | InputActionAtom[]): string;
export declare function inputActionKeyNameDisplayText(name: InputActionKeyName): string;
import Input from "./Input";
export { Input };
/**
* Returns the display text of a shortcut, such as `"Ctrl+A"`.
*
* @param param Either an action name or a series of action atoms.
*/
export function shortcutDisplayText(param) {
if (typeof param == "string") {
return shortcutDisplayText(Input.input.getActions()[param]);
}
if (!param)
return "";
for (const atom of param) {
if (atom.hasOwnProperty("key")) {
const key = atom;
const parts = [];
if (key.control) {
parts.push("Ctrl");
}
if (key.alt) {
parts.push("Alt");
}
if (key.shift) {
parts.push("Shift");
}
parts.push(inputActionKeyNameDisplayText(key.key));
return parts.join("+");
}
}
return "";
}
export function inputActionKeyNameDisplayText(name) {
switch (name) {
case "leftArrow": return "Left";
case "rightArrow": return "Right";
case "upArrow": return "Up";
case "downArrow": return "Down";
case "spacebar": return "Space";
case "enter": return "Enter";
case "backspace": return "Backspace";
case "minus": return "Minus";
case "plus": return "Plus";
case "tab": return "Tab";
case "f1": return "F1";
case "f2": return "F2";
case "f3": return "F3";
case "f4": return "F4";
case "f5": return "F5";
case "f6": return "F6";
case "f7": return "F7";
case "f8": return "F8";
case "f9": return "F9";
case "f10": return "F10";
case "f11": return "F11";
case "f12": return "F12";
case "0": return "0";
case "1": return "1";
case "2": return "2";
case "3": return "3";
case "4": return "4";
case "5": return "5";
case "6": return "6";
case "7": return "7";
case "8": return "8";
case "9": return "9";
default: return name.toUpperCase();
}
}
import { InputActionAtom } from "./InputAction";
import { TypedEventTarget } from "@hydroperx/event";
declare const Input_base: TypedEventTarget<{
inputPressed: Event;
inputReleased: Event;
actionsUpdated: Event;
}>;
/**
* The `Input` class handles action mapping and user input event listening.
*
* # Getting started
*
* The following code demonstrates using arrows and WASD keys
* for entity movement:
*
* ```ts
* import { Input } from "@hydroperx/inputaction";
*
* Input.input.setActions({
* "moveLeft": [
* { key: "a" },
* { key: "leftArrow" },
* ],
* "moveRight": [
* { key: "d" },
* { key: "rightArrow" },
* ],
* "moveUp": [
* { key: "w" },
* { key: "upArrow" },
* ],
* "moveDown": [
* { key: "s" },
* { key: "downArrow" },
* ],
* });
*
* Input.input.addEventListener("inputPressed", () => {
* const shouldMoveRight = Input.input.isPressed("moveRight");
* });
* ```
*
* # Built-in actions
*
* The following actions are pre-defined in every action map
* and can be overriden:
*
* * `escape` - Used for escaping out in the user interface.
* * `navigateLeft` — Used for focusing the left neighbor of an user interface control.
* * `navigateRight` — Used for focusing the right neighbor of an user interface control.
* * `navigateUp` — Used for focusing the top neighbor of an user interface control.
* * `navigateDown` — Used for focusing the bottom neighbor of an user interface control.
*
* # Events
*
* This class extends `EventTarget` and may dispatch the following events:
*
* ```ts
* // Dispatched when user input starts being pressed or
* // is continuously pressed.
* inputPressed: Event;
* // Dispatched when any user input is released.
* inputReleased: Event;
* // Dispatched when the actions map is updated.
* actionsUpdated: Event;
* ```
*/
export default class Input extends Input_base {
/**
* The singleton instance of the `Input` class.
*/
static readonly input: Input;
private mMap;
/**
* Returns the current action map in read-only mode.
*/
getActions(): Record<string, InputActionAtom[]>;
/**
* Updates the action map.
* @fires Input#actionsUpdated
*/
setActions(map: Record<string, InputActionAtom[]>): void;
private static builtin;
private static readonly mPressedStatePoolKeys;
/**
* Determines whether an action is pressed.
* @throws Error Thrown if the action does not exist.
*/
isPressed(name: string): boolean;
/**
* Determines whether an action has been just pressed right now.
* @throws Error Thrown if the action does not exist.
*/
justPressed(name: string): boolean;
}
export {};
import clonePlainObject from "./util/clonePlainObject";
import { navigatorKeyToThis } from "./InputAction";
import assert from "assert";
/**
* The `Input` class handles action mapping and user input event listening.
*
* # Getting started
*
* The following code demonstrates using arrows and WASD keys
* for entity movement:
*
* ```ts
* import { Input } from "@hydroperx/inputaction";
*
* Input.input.setActions({
* "moveLeft": [
* { key: "a" },
* { key: "leftArrow" },
* ],
* "moveRight": [
* { key: "d" },
* { key: "rightArrow" },
* ],
* "moveUp": [
* { key: "w" },
* { key: "upArrow" },
* ],
* "moveDown": [
* { key: "s" },
* { key: "downArrow" },
* ],
* });
*
* Input.input.addEventListener("inputPressed", () => {
* const shouldMoveRight = Input.input.isPressed("moveRight");
* });
* ```
*
* # Built-in actions
*
* The following actions are pre-defined in every action map
* and can be overriden:
*
* * `escape` - Used for escaping out in the user interface.
* * `navigateLeft` — Used for focusing the left neighbor of an user interface control.
* * `navigateRight` — Used for focusing the right neighbor of an user interface control.
* * `navigateUp` — Used for focusing the top neighbor of an user interface control.
* * `navigateDown` — Used for focusing the bottom neighbor of an user interface control.
*
* # Events
*
* This class extends `EventTarget` and may dispatch the following events:
*
* ```ts
* // Dispatched when user input starts being pressed or
* // is continuously pressed.
* inputPressed: Event;
* // Dispatched when any user input is released.
* inputReleased: Event;
* // Dispatched when the actions map is updated.
* actionsUpdated: Event;
* ```
*/
export default class Input extends EventTarget {
/**
* The singleton instance of the `Input` class.
*/
static input = new Input;
// Actions map
mMap = {
...Input.builtin(),
};
/**
* Returns the current action map in read-only mode.
*/
getActions() {
return clonePlainObject(this.mMap, true);
}
/**
* Updates the action map.
* @fires Input#actionsUpdated
*/
setActions(map) {
// Update static map
this.mMap = {
...Input.builtin(),
...clonePlainObject(map, true),
};
// Dispatch update event
this.dispatchEvent(new Event("actionsUpdated"));
}
static builtin() {
return {
"escape": [{ key: "escape" }],
"navigateLeft": [{ key: "leftArrow" }],
"navigateRight": [{ key: "rightArrow" }],
"navigateUp": [{ key: "upArrow" }],
"navigateDown": [{ key: "downArrow" }],
};
}
// 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;
}
});
}
}
/**
* Determines whether an action is pressed.
* @throws Error Thrown if the action does not exist.
*/
isPressed(name) {
const action = this.mMap[name];
assert(action !== undefined, "The specified action for Input.isPressed(name) does not exist.");
for (const item of action) {
if (item.hasOwnProperty("key")) {
const inputActionKey = item;
const pressedState = Input.mPressedStatePoolKeys.get(inputActionKey.key);
const pressed = pressedState !== undefined && pressedState.pressed
&& (inputActionKey.control ? pressedState.control : !pressedState.control)
&& (inputActionKey.shift ? pressedState.shift : !pressedState.shift)
&& (inputActionKey.alt ? pressedState.alt : !pressedState.alt);
if (pressed) {
return true;
}
}
}
return false;
}
/**
* Determines whether an action has been just pressed right now.
* @throws Error Thrown if the action does not exist.
*/
justPressed(name) {
const action = this.mMap[name];
assert(action !== undefined, "The specified action for Input.isPressed(name) does not exist.");
for (const item of action) {
if (item.hasOwnProperty("key")) {
const inputActionKey = item;
const pressedState = Input.mPressedStatePoolKeys.get(inputActionKey.key);
const pressed = pressedState !== undefined && pressedState.pressed
&& (inputActionKey.control ? pressedState.control : !pressedState.control)
&& (inputActionKey.shift ? pressedState.shift : !pressedState.shift)
&& (inputActionKey.alt ? pressedState.alt : !pressedState.alt);
if (pressed && pressedState.pressedTimestamp > Date.now() - 15) {
return true;
}
}
}
return false;
}
}
/**
* Part of the `Input` class. It is used to describe a specific user input key or gamepad
* button.
*/
export type InputActionAtom = InputActionKey;
/**
* Part of the Input API. It is used to describe a specific user input key.
*/
export type InputActionKey = {
/**
* Identifies the input key.
*/
key: InputActionKeyName;
/**
* Whether the `Ctrl` key is used.
*/
control?: boolean;
/**
* Whether the `Alt` key is used.
*/
alt?: boolean;
/**
* Whether the `Shift` key is used.
*/
shift?: boolean;
};
/**
* Part of the Input API. It is used to identify the name of a specific user input key.
*/
export type InputActionKeyName = "leftArrow" | "rightArrow" | "upArrow" | "downArrow" | "spacebar" | "enter" | "backspace" | "minus" | "plus" | "tab" | "escape" | "assign" | "comma" | "dot" | "semicolon" | "f1" | "f2" | "f3" | "f4" | "f5" | "f6" | "f7" | "f8" | "f9" | "f10" | "f11" | "f12" | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
export declare function navigatorKeyToThis(name: string): InputActionKeyName | undefined;
const mapNavigatorKeyToThis = new Map([
["arrowleft", "leftArrow"],
["arrowright", "rightArrow"],
["arrowup", "upArrow"],
["arrowdown", "downArrow"],
["escape", "escape"],
[" ", "spacebar"],
["enter", "enter"],
["backspace", "backspace"],
["subtract", "minus"],
["add", "plus"],
["tab", "tab"],
["+", "plus"],
["-", "minus"],
["=", "assign"],
[",", "comma"],
[".", "dot"],
[";", "semicolon"],
]);
export function navigatorKeyToThis(name) {
name = name.toLowerCase();
if (/^([a-z0-9]|f\d\d?)$/.test(name)) {
return name;
}
return mapNavigatorKeyToThis.get(name);
}
/**
* 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;
}
+12
-3
{
"name": "@hydroperx/inputaction",
"version": "1.0.0",
"version": "1.0.1",
"description": "Input actions library.",
"main": "src/index.ts",
"repository": "https://github.com/hydroperx/inputaction",

@@ -10,3 +9,13 @@ "license": "Apache-2.0",

"keywords": ["input", "shortcut", "keyboard", "key combination"],
"scripts": {},
"files": ["/dist"],
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build"
},
"exports": {
".": {
"default": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"dependencies": {

@@ -13,0 +22,0 @@ "@hydroperx/event": "^1.0.0",

import Input from "./Input";
import { InputActionAtom, InputActionKey, InputActionKeyName } from "./InputAction";
export { Input };
export type {
InputActionAtom,
InputActionKey,
InputActionKeyName,
} from "./InputAction";
/**
* Returns the display text of a shortcut, such as `"Ctrl+A"`.
*
* @param param Either an action name or a series of action atoms.
*/
export function shortcutDisplayText(param: string | InputActionAtom[]): string {
if (typeof param == "string") {
return shortcutDisplayText(Input.input.getActions()[param]);
}
if (!param) return "";
for (const atom of param as InputActionAtom[]) {
if (atom.hasOwnProperty("key")) {
const key = atom as InputActionKey;
const parts = [];
if (key.control) {
parts.push("Ctrl");
}
if (key.alt) {
parts.push("Alt");
}
if (key.shift) {
parts.push("Shift");
}
parts.push(inputActionKeyNameDisplayText(key.key));
return parts.join("+");
}
}
return "";
}
export function inputActionKeyNameDisplayText(name: InputActionKeyName): string {
switch (name) {
case "leftArrow": return "Left";
case "rightArrow": return "Right";
case "upArrow": return "Up";
case "downArrow": return "Down";
case "spacebar": return "Space";
case "enter": return "Enter";
case "backspace": return "Backspace";
case "minus": return "Minus";
case "plus": return "Plus";
case "tab": return "Tab";
case "f1": return "F1";
case "f2": return "F2";
case "f3": return "F3";
case "f4": return "F4";
case "f5": return "F5";
case "f6": return "F6";
case "f7": return "F7";
case "f8": return "F8";
case "f9": return "F9";
case "f10": return "F10";
case "f11": return "F11";
case "f12": return "F12";
case "0": return "0";
case "1": return "1";
case "2": return "2";
case "3": return "3";
case "4": return "4";
case "5": return "5";
case "6": return "6";
case "7": return "7";
case "8": return "8";
case "9": return "9";
default: return name.toUpperCase();
}
}
import clonePlainObject from "./util/clonePlainObject";
import { InputActionAtom, InputActionKey, InputActionKeyName, navigatorKeyToThis } from "./InputAction";
import assert from "assert";
import { TypedEventTarget } from "@hydroperx/event";
/**
* The `Input` class handles action mapping and user input event listening.
*
* # Getting started
*
* The following code demonstrates using arrows and WASD keys
* for entity movement:
*
* ```ts
* import { Input } from "@hydroperx/inputaction";
*
* Input.input.setActions({
* "moveLeft": [
* { key: "a" },
* { key: "leftArrow" },
* ],
* "moveRight": [
* { key: "d" },
* { key: "rightArrow" },
* ],
* "moveUp": [
* { key: "w" },
* { key: "upArrow" },
* ],
* "moveDown": [
* { key: "s" },
* { key: "downArrow" },
* ],
* });
*
* Input.input.addEventListener("inputPressed", () => {
* const shouldMoveRight = Input.input.isPressed("moveRight");
* });
* ```
*
* # Built-in actions
*
* The following actions are pre-defined in every action map
* and can be overriden:
*
* * `escape` - Used for escaping out in the user interface.
* * `navigateLeft` — Used for focusing the left neighbor of an user interface control.
* * `navigateRight` — Used for focusing the right neighbor of an user interface control.
* * `navigateUp` — Used for focusing the top neighbor of an user interface control.
* * `navigateDown` — Used for focusing the bottom neighbor of an user interface control.
*
* # Events
*
* This class extends `EventTarget` and may dispatch the following events:
*
* ```ts
* // Dispatched when user input starts being pressed or
* // is continuously pressed.
* inputPressed: Event;
* // Dispatched when any user input is released.
* inputReleased: Event;
* // Dispatched when the actions map is updated.
* actionsUpdated: Event;
* ```
*/
export default class Input extends (EventTarget as TypedEventTarget<{
inputPressed: Event;
inputReleased: Event;
actionsUpdated: Event;
}>) {
/**
* The singleton instance of the `Input` class.
*/
public static readonly input = new Input;
// Actions map
private mMap: Record<string, InputActionAtom[]> = {
...Input.builtin(),
};
/**
* Returns the current action map in read-only mode.
*/
public getActions(): Record<string, InputActionAtom[]> {
return clonePlainObject(this.mMap, true);
}
/**
* Updates the action map.
* @fires Input#actionsUpdated
*/
public setActions(map: Record<string, InputActionAtom[]>) {
// Update static map
this.mMap = {
...Input.builtin(),
...clonePlainObject(map, true),
};
// Dispatch update event
this.dispatchEvent(new Event("actionsUpdated"));
}
private static builtin(): Record<string, InputActionAtom[]> {
return {
"escape": [ { key: "escape" } ],
"navigateLeft": [ { key: "leftArrow" } ],
"navigateRight": [ { key: "rightArrow" } ],
"navigateUp": [ { key: "upArrow" } ],
"navigateDown": [ { key: "downArrow" } ],
};
}
// Static pressed state pool
private static readonly mPressedStatePoolKeys: Map<InputActionKeyName, PressedState> = 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;
}
});
}
}
/**
* Determines whether an action is pressed.
* @throws Error Thrown if the action does not exist.
*/
public isPressed(name: string): boolean {
const action = this.mMap[name];
assert(action !== undefined, "The specified action for Input.isPressed(name) does not exist.");
for (const item of action!) {
if (item.hasOwnProperty("key")) {
const inputActionKey = item as InputActionKey;
const pressedState = Input.mPressedStatePoolKeys.get(inputActionKey.key);
const pressed = pressedState !== undefined && pressedState.pressed
&& (inputActionKey.control ? pressedState.control : !pressedState.control)
&& (inputActionKey.shift ? pressedState.shift : !pressedState.shift)
&& (inputActionKey.alt ? pressedState.alt : !pressedState.alt);
if (pressed) {
return true;
}
}
}
return false;
}
/**
* Determines whether an action has been just pressed right now.
* @throws Error Thrown if the action does not exist.
*/
public justPressed(name: string): boolean {
const action = this.mMap[name];
assert(action !== undefined, "The specified action for Input.isPressed(name) does not exist.");
for (const item of action!) {
if (item.hasOwnProperty("key")) {
const inputActionKey = item as InputActionKey;
const pressedState = Input.mPressedStatePoolKeys.get(inputActionKey.key);
const pressed = pressedState !== undefined && pressedState.pressed
&& (inputActionKey.control ? pressedState.control : !pressedState.control)
&& (inputActionKey.shift ? pressedState.shift : !pressedState.shift)
&& (inputActionKey.alt ? pressedState.alt : !pressedState.alt);
if (pressed && pressedState.pressedTimestamp > Date.now() - 15) {
return true;
}
}
}
return false;
}
}
type PressedState = {
pressed: boolean,
pressedTimestamp: number,
control: boolean,
shift: boolean,
alt: boolean,
};
/**
* Part of the `Input` class. It is used to describe a specific user input key or gamepad
* button.
*/
export type InputActionAtom =
| InputActionKey;
/**
* Part of the Input API. It is used to describe a specific user input key.
*/
export type InputActionKey = {
/**
* Identifies the input key.
*/
key: InputActionKeyName,
/**
* Whether the `Ctrl` key is used.
*/
control?: boolean,
/**
* Whether the `Alt` key is used.
*/
alt?: boolean,
/**
* Whether the `Shift` key is used.
*/
shift?: boolean,
};
/**
* Part of the Input API. It is used to identify the name of a specific user input key.
*/
export type InputActionKeyName =
| "leftArrow" | "rightArrow" | "upArrow" | "downArrow"
| "spacebar" | "enter" | "backspace"
| "minus" | "plus" | "tab" | "escape"
| "assign" | "comma" | "dot" | "semicolon"
| "f1" | "f2" | "f3" | "f4" | "f5" | "f6" | "f7" | "f8" | "f9" | "f10" | "f11" | "f12"
| "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
| "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m"
| "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z";
const mapNavigatorKeyToThis = new Map<string, InputActionKeyName>([
["arrowleft", "leftArrow"],
["arrowright", "rightArrow"],
["arrowup", "upArrow"],
["arrowdown", "downArrow"],
["escape", "escape"],
[" ", "spacebar"],
["enter", "enter"],
["backspace", "backspace"],
["subtract", "minus"],
["add", "plus"],
["tab", "tab"],
["+", "plus"],
["-", "minus"],
["=", "assign"],
[",", "comma"],
[".", "dot"],
[";", "semicolon"],
]);
export function navigatorKeyToThis(name: string): InputActionKeyName | undefined {
name = name.toLowerCase();
if (/^([a-z0-9]|f\d\d?)$/.test(name)) {
return name as any;
}
return mapNavigatorKeyToThis.get(name);
}
/**
* Clones a plain object. `deep` is `false` by default.
*/
export default function clonePlainObject(object: any, deep: boolean = false) {
if (deep) {
return clonePlainObjectDeep(object);
}
const r: any = {};
for (const k in object) {
r[k] = object[k];
}
return r;
}
function clonePlainObjectDeep(object: any) {
const r: any = {};
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;
}
{
"compilerOptions": {
"target": "ES2024",
"moduleResolution": "bundler",
"lib": ["es2017", "DOM", "ES2020.Intl"],
"strict": true,
"noEmit": true
}
}