Giter Club home page Giter Club logo

keystrokes's People

Contributors

bradennapier avatar colinsullivan avatar dependabot[bot] avatar elliot67 avatar robertwhurst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

keystrokes's Issues

Create bindings using KeyboardEvent#code value

Describe the bug
Library doesn't support code or which property to make hotkey language agnostic. It compare event key by value due to works with only one keyboard layout.

To Reproduce
Imagine you have keyboard with 2 layouts: native language and english (i.e. French and English).

Steps to reproduce the behavior:

  1. Bind event
import { bindKey } from '@rwh/keystrokes'

bindKey('H', {
	onPressed: () => {
		...
	},
	onReleased: () => {
		...
	},
});
  1. Press H button in English layout. It works
  2. Change active keybord layout to French. Press physically same button. It doesn't work what is obviously is not clear for any user.

Expected behavior
Library should work with code property (physical id of the button) and not with a key (it contains value, changable thing), otherwise library would be used only for few countries where people use english as a native language.

`keyRemap` option is not being applied

Description
When setting the options of Keystrokes (whether in the constructor or through bindEnvironment()), keyRemap fails to be applied.

Reproducible Example

const keystrokes = new Keystrokes({
    keyRemap: { ' ': 'space' },
});

// No message is logged when pressing spacebar
keystrokes.bindKeyCombo('space', console.log);

Temporary Workaround
Directly setting the private attribute _keyRemap seems to fix the issue:

const keystrokes = new Keystrokes();

// @ts-expect-error
keystrokes._keyRemap = { ' ': 'space' };

// This now works
keystrokes.bindKeyCombo('space', console.log);

bindKey and bindKeyCombo support array combination

Keystroke can, like KeyboarJs, support merging strings and data, as shown in the following example:

KeyboarJs:
keyboardJS.bind('a + b > c', (e) => {
console.log('a and b then c is pressed');
});
keyboardJS.bind(['a + b > c', 'z + y > z'], (e) => {
console.log('a and b then c or z and y then z is pressed');
});

Keystroke:
bindKey('a', , () =>
console.log('You're pressing "a"'))
bindKey(['a', 'b'] () =>
console.log('You're pressing "a" or "b"'))

Unable to type Shift + "+" combination

Describe the bug
I'm unable to bind a key combination of "Shift + +" with error cannot have two operators in a row

To Reproduce
Steps to reproduce the behavior:

  1. Call bindKeyCombo("Shift + +")
  2. Throws

Expected behavior
The lib recognises a + followed by a + means to bind every second + in a sequence as a key instead of an operator. It should probably do the same with combinations involving > and , keys too so you can have combinations like "Shift + , , , + Shift".

Additional context
Might be also be useful to have some sort of opt-in to use a keys .code instead of just .key because as far as i can see, it's impossible to specify specific keys like ShiftLeft for eg.

`preventDefault` seems to have no effect

Describe the bug

I'd like to prevent the browser from presenting a "Save Page" dialog when pressingh Ctrl/Cmd + S. With mousetrap, this is possible via simple e.preventDefault(), but this library does not expose such a function and trying to to it on the various originalEvent seems to not work at all.

To Reproduce

  1. Open https://codesandbox.io/s/admiring-lamport-jh8k7h?file=/src/index.js
  2. Focus the preview frame, hit "Ctrl + S" or "Cmd + S"

Expected behavior

No "Save Page" dialog to be shown.

Additional context

A more ergonomic e.preventDefault without having to use originalEvent would be nice.

Switch to vite

I love parcel, but vite seems much more stable and reliable in my experience using it for other projects. I believe it's time to switch over.

The test instance of keystrokes does not implement the interface of browser binding sourced events

Originally reported by @noahbrom in #19

Describe the bug
If you use the keystrokes test instance, it will not implement the same interface for events that the browser bindings, which are used by Keystrokes by default. The typescript types also do not reflect this discrepancy.

To Reproduce
Write a unit test using a test instance of keystrokes, and attempt to use a browser binding sourced property on the event.

Expected behavior
The property should be the same as if used with the browser bindings (unless overridden).

Cancel key combo when switching to a different window

When I switch to a different window via keyboard (e.g. Alt+Tab), then return to the original window without using the keyboard (e.g. via clicking on it), the active key combo becomes stuck at the state before I left the window (e.g. at Alt), until I press and release the key again. This behaviour may confuse users into thinking that the key combos have stopped working.

It would be great if the active key combo automatically cancels when the window loses focus.

Here is a temporary solution that seems to work on keyboard shortcuts for tabbing out of the active window (I only tested on Windows though):

const keystrokes = new Keystrokes({
    selfReleasingKeys: [
        'ctrl', 'meta', 'alt', 'tab',
    ],
    keyRemap: {
        control: 'ctrl',
        os: 'meta',     // For Firefox
    },
});

addEventListener('blur', () => {
    // Prevent getting stuck in a key sequence after tabbing to a different window
    // @ts-expect-error
    keystrokes._tryReleaseSelfReleasingKeys();
});

Unexpected behavior with useEffect + useState

I have a Next.js canvas drawing app and I am trying to use Keystrokes to control state.

Unless I am not using this correctly, I expect it to work like addEventListener in a useEffect and only run once when I hit the key combo. However, it often runs multiple times and even bypasses the index > 0 condition becoming negative when I control+z. Also, my streamActions function to redraw the updated state is seemingly stale even though the index is changing.

I have tried the react hook, it was working a bit better but was still running into the issue where it runs multiple times and index goes to zero.

Here is a snippet of the code:

const [history, setHistory] = useState<Rough.ActionHistory[]>([]);
const [index, setIndex] = useState<number>(0);

// ....

useEffect(() => {
  const onPressedHandler = (e: KeyComboEvent<KeyboardEvent>) => {
    // undo and redo
    if (!roughRef.current) return;

    switch (e.keyCombo) {
      case "control+z":
        index > 0 && setIndex((i) => i - 1);
        break;
      case "control+y":
        index < history.length && setIndex((i) => i + 1);
        break;
    }
  };

  const onReleasedHandler = (e: KeyComboEvent<KeyboardEvent>) => {
    if (!roughRef.current) return;
    streamActions(roughRef.current);
  };

  bindKeyCombo("control+z", {
    onPressed: onPressedHandler,
    onReleased: onReleasedHandler,
  });
  bindKeyCombo("control+y", {
    onPressed: onPressedHandler,
    onReleased: onReleasedHandler,
  });

  return () => {
    unbindKeyCombo("control+z");
    unbindKeyCombo("control+y");
  };
}, [index]);

Enhancements to sequential key combos

Hi @RobertWHurst!

Is your feature request related to a problem? Please describe.
For context, I want to build "vim-like" shortcuts into a web app. That means working a lot with sequential key combos (e.g. useKeyCombo('g,o') where g is pressed and released, and then o is pressed and release). Keystrokes supports sequential key combos (which is great!), but there are a few usecases that I did not immediately see Keystrokes support.

Describe the solution you'd like
Specifically:

  1. I'd like to be able to "peek" into the current sequential key combos that Keystrokes has partially matched, e.g. using the useKeyCombo('g,o') example again, if I press and release g, I'd like to be able to ask Keystrokes "what sequential key combos have been partially matched?" and it would return a list of registered sequential key combos that begin with g.
  • Ideally, it would also be able to return the keys actually matched, e.g. if I had useKeyCombo('g,o,t') and pressed/released g and then pressed/released o, then asking for partially matched sequential key combos would return the currently matched keys (g,o) along with the list of registered sequential combos that partially match (useKeyCombo('g,o,t'))

Why
I want to be able to display the currently accumulated/matched key sequence the user has typed somewhere on the page (kind of how vim does at the bottom of the editor).

  1. I'd also like to have the ability to cancel sequential key combo matching midway. Specifically, I'd like to map the Esc key to clear the currently accumulated key sequence. Using Keystrokes, I seem to be able to type g, then any number of keys, and finally o and Keystrokes still happily executes the key combo. e.g. if I registered g,o and I type g,t,w,r,o, Keystrokes still interprets that as if I typed g,o (aside: not sure if this was intended, or if this is a bug).
  • Ideally, there would be a setting that allows for an optional timeout for when Keystrokes should stop listening for an accumulated key sequence. This is not completely necessary as long as there's some facility for Keystrokes to "cancel" the currently accumulated key sequence.

These features may already exist in Keystrokes, but I wasn't able to find them with a cursory look.

Thanks for the help and for your work on this lib!

Unable to import Keystrokes class

Describe the bug

The Keystrokes class is no longer exported in the index.ts file, preventing the creation of custom instances.

Additional context

I assume this was unintentional since it's still being referenced in the docs.

Failed to resolve entry for package "@rwh/vue-keystrokes"

Describe the bug
Failed to resolve entry for package "@rwh/vue-keystrokes". The package may have incorrect main/module/exports specified in its package.json.

To Reproduce
Steps to reproduce the behavior:

  1. Install
  2. See error

Expected behavior

Additional context

1
2

Separately bound keys are not firing together

Describe the bug
If you are binding some keys separately, e.g.

const coords = { x: 0, y: 0 };

bindKey('w', () => coords.x += 1  );
bindKey('a', () => coords.y -= 1  );
bindKey('s', () => coords.x -= 1  );
bindKey('d', () => coords.y += 1  );

While pressing 2 keys (or more), only one of the callback is triggered. (But all should be triggered, imo)

Expected behavior
I expect both callbacks to be triggered at the same time, cause 2 buttons are still pressed.

Why
Imagine a videogame, e.g. a shooter game. User is moving using WASD alongside with "space" for a jump, "G" for throwing grenade and etc. It's literary impossible to bind every combo. Instead the binds should be independent from each other ("W" moves forward, "A" moves left, so eventually user will be moved forward and left) .

To Reproduce
An example at stackblitz:
https://stackblitz.com/edit/vitejs-vite-iunkan?file=src%2Fmain.ts

You can move the "Actor" red square using WASD, but cannot move it in a diagonal direction.

P.S. used version 1.5.6

`keyup` listener

Is your feature request related to a problem? Please describe.

I'd like to track the "down" state of the shift key, and for that a way to define a keyUp listener would be necessary. With keyboardjs I do:

let shiftDown = false;
keyboardjs.bind("shift", () => {shiftDown = true});
keyboardjs.bind("shift", null, () => {shiftDown = false});

Describe the solution you'd like

Some way to define for which event to listen, for example with an options argument:

bindKey("shift", () => {}, {event: "keydown"});
bindKey("shift", () => {}, {event: "keyup"});

originalEvent.composedPath() return empty array

Describe the bug
when use composedPath in bindKeyCombo callback, return empty array.

bindKeyCombo('Meta + z', (e) => {
    const path = e.originalEvent.composedPath(); // path is []
});

The issue seems to be that callback exec in next micro task
https://stackoverflow.com/questions/62181537/why-does-composedpath-on-event-returns-different-value-when-delayed

Expected behavior
return true array

Additional context
Add any other context about the problem here.

Gmail style key combinations allow other keys

Describe the bug

I'm attempting to define Gmail style key combinations such as "g i", "g l", etc. However, the event triggers even if another letter was type inbetween.

To Reproduce

  bindKeyCombo("g, i", () => {
    console.log("goto inbox");
  });

Pressing g, release, press i works as expected.

However, typing "g x i", or "g a i", etc also triggers the event which is not expected.

Expected behavior

Sequences such as "g a i" should not trigger the event.

Other observations

There does not appear to be a timeout. I can press g, then hit i 10 or so seconds later and it triggers.

Thanks!

Arrow keys not detected with checkKey

Arrow keys are not detected in checkKey , but they are properly detected with bindKey.
Using checkKeyCombo works fine.

Made a reproduction on jsfiddle with the following code :

import * as rwhkeystrokes from 'https://esm.run/@rwh/keystrokes';

rwhkeystrokes.bindKey('a', () => console.log('bind a'))
rwhkeystrokes.bindKey('ArrowRight', () => console.log('bind ArrowRight'))

const int = window.setInterval(() => {
  if (rwhkeystrokes.checkKey('a')) {
    console.log('a is pressed')
  }
  
  
  if (rwhkeystrokes.checkKey('ArrowRight')) {
  //if (rwhkeystrokes.checkKeyCombo('ArrowRight')) {
    console.log('ArrowRight is pressed')
  }
}, 100)

Bug with self releasing keys feature

Describe the bug
Crash when using self-releasing keys feature

To Reproduce
Steps to reproduce the behavior:
Use self-releasing keys with a key combo
Note error in console

Expected behavior
Feature works

Additional context

The issue is here:

https://github.com/RobertWHurst/Keystrokes/blob/master/packages/keystrokes/src/keystrokes.ts#L435

Note the objects in _activeKeyPresses are already in the form of { key: "z", event: { ... } }. Then the crash occurs here:

https://github.com/RobertWHurst/Keystrokes/blob/master/packages/keystrokes/src/keystrokes.ts#L340

Because event.key.toLowerCase is undefined

Fire multiple events when pressing combo without releasing all keys

Describe the bug
Consider this code: useKeyCombo("meta + enter"). When I use this sequence:

  • press meta
  • press enter - event fires
  • release enter
  • press enter - event does not fire.

I see that sometimes such behavior might be desired, but sometimes not (I even think it is not desired in most cases). I did not find a way to change it in the library (which is amazing btw). Would it be possible to have it? Without it, some actions in GUI are not programmable with a good UX and thus I think this should be considered a bug.

Odd behaviour with Control/Command key on Mac

Describe the bug

There seems to be some odd behaviour around the Command and Control keys on Mac:

To Reproduce

  1. On Mac, open https://codesandbox.io/s/quizzical-nightingale-c6t37s
  2. Input control+s, it's logged correctly
  3. Input meta+s (Command+s), it's logged correctly
  4. Input control+s, it's logged as meta+s and subsequent presses no longer log at all
{"keyCombo":"control+s"} // ok
{"keyCombo":"meta+s"} // ok
{"keyCombo":"meta+s"} // not what I pressed

Expected behavior
These combos to be detected the same way they are entered.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.