Code Monkey home page Code Monkey logo

svelte-keydown's Introduction

svelte-keydown

NPM

Utility to listen for keyboard events.

Utility component leveraging the svelte:body API to listen for keydown events.

Try it in the Svelte REPL.

Use Cases

  • toggle modals
  • capture a combination of keys (i.e., "Meta-s")

Installation

Yarn

yarn add -D svelte-keydown

NPM

npm i -D svelte-keydown

pnpm

pnpm i -D svelte-keydown

Usage

Basic

<script>
  import Keydown from "svelte-keydown";

  let events = [];
</script>

<Keydown
  on:Enter={() => {
    events = [...events, "enter"];
  }}
/>

Press "enter": {events.join(", ")}

Pause on input

Set pauseOnInput to prevent the utility from capturing keydown events on input events.

<script>
  import Keydown from "svelte-keydown";

  let evt = [];
</script>

<Keydown
  pauseOnInput
  on:key={(e) => {
    evt = [...evt, e.detail];
  }}
/>

<input placeholder="Type here..." />

{evt.join("")}

Preventing the default behavior

This component forward the on:keyup and on:keydown events.

You can use on:keydown to prevent the default behavior for certain keys.

In the following example, pressing "Space" should not cause the browser page to scroll.

<Keydown
  on:keydown={(e) => {
    if (e.key === " ") e.preventDefault();
  }}
  on:Space={(e) => {
    console.log("key", "Space");
  }}
/>

Examples

Escape to close a modal

In this use case, keydown events are paused if the modal is not open.

<script>
  import Keydown from "svelte-keydown";

  let showModal = true;
</script>

<Keydown paused={!showModal} on:Escape={() => (showModal = false)} />

<button on:click={() => (showModal = !showModal)}>Toggled? {showModal}</button>

on:combo

Use the combo dispatched event to listen for a combination of keys.

<script>
  import Keydown from "svelte-keydown";

  let combo = [];
</script>

<Keydown on:combo={(e) => (combo = [...combo, e.detail])} />

{combo.join(", ")}

separator

Use the separator property to customize the separating key between multiple keys.

<script>
  import Keydown from "svelte-keydown";

  let combo = [];
</script>

<Keydown separator="+" on:combo={(e) => (combo = [...combo, e.detail])} />

{combo.join(", ")}

API

Prop Type Default value
paused boolean false
pauseOnInput boolean false
separator string -

Forwarded events

  • on:keyup
  • on:keydown

Dispatched events

on:[Key]

Example:

<Keydown on:Enter />
<Keydown on:Escape />
<Keydown on:Space />

on:key

Alternative API to on:[Key].

Example:

<script>
  import Keydown from "svelte-keydown";

  let keys = [];
</script>

<Keydown on:key={({ detail }) => (keys = [...keys, detail])} />

<pre>{JSON.stringify(keys, null, 2)}</pre>

on:combo

Triggered when a sequence of keys are pressed and cleared when a keyup event is fired.

Examples:

  • "Shift-S"
  • "Meta-c" (Copy)
  • "Meta-v" (Paste)
<script>
  import Keydown from "svelte-keydown";

  let combos = [];
</script>

<Keydown on:combo={({ detail }) => (combos = [...combos, detail])} />

<pre>{JSON.stringify(combos, null, 2)}</pre>

TypeScript

Svelte version 3.31 or greater is required to use this component with TypeScript.

TypeScript definitions are located in the types folder.

Changelog

CHANGELOG.md

License

MIT

svelte-keydown's People

Contributors

dependabot[bot] avatar jkoking avatar mattpilott avatar metonym 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

Watchers

 avatar  avatar

svelte-keydown's Issues

[Suggestion] Don't run the command while any text is selected on the page

I have a suggestion for improvement.

The blockIfAnyTextboxSelected attribute - if true, it does not run the command as long as any text box is selected on the page (input[type=text], [contexteditable=true], textarea).

<Keydown blockIfAnyTextboxSelected={true} on:key={ ({detail})=> detail==="w"&& fun() } />

The point is that the command should not be invoked when typing in a text field.

But input input[type=number] would not be taken into account by blockIfAnyTextboxSelected - or block it in a separate way, maybe with a separate attribute...
Without it, you have to prepare a complex checking function and add it to the command.


Another improvement would be to make a 'detail' attribute which causes the command to only run if detail matches:

<Keydown detail="w" on:key={()=> fun() } />

or

<Keydown details={["w","s"]} on:key={()=> fun() } />

...thanks to this, the function itself can be simplified - as you can see.

You can think of better names for blockIfAnyTextboxSelected and detail/details. :)

What do you think?

`on:combo` bug - `Shift-ArrowRight` multiple times...

Code:

<Keydown
	pauseOnInput
	paused={isSelectActive}
	on:combo={ e => ["Shift-ArrowRight","Shift-d"].includes(e.detail)&& nCanal() }
/> 

Steps:

  1. Press and hold Shift
  2. At the same time, I press ArrowRight
  3. I release ArrowRight
  4. Press ArrowRight
  5. I release ArrowRight

Effect:

  1. Shift
  2. Shift-ArrowRight
  3. _
  4. ArrowRight
  5. _

So you can't repeat Shift-ArrowRight while holding Shift all the time.

Want:
To make pressing ArrowRight again to do the Shift-ArrowRight combo.


Additionally:
You might think of a syntax like this:

<KeydownD
	pauseOnInput
	paused={isSelectActive}
	details={["Shift-ArrowRight","Shift-d"]}
	fn={nKanal}
/>

Or also:

<KeydownD
	pauseOnInput
	paused={isSelectActive}
	details={e=>e.detail>=1 && e.detail<=canals.length}
	fn={fn}
/>

It's about separating the function call from the condition. This gives more transparency.

Event should fire on `keydown`, not `keyup`

There's a subtle, rather significant, UX difference between the two.

The event should fire on keydown and not on the keyup event.

E.g.,

if (
  document.activeElement instanceof HTMLInputElement ||
  document.activeElement instanceof HTMLTextAreaElement
) {
  // Exit early if an inputtable element is already focused.
  return;
}

if ((e.metaKey && e.key === 'k') || e.key === '/') {
  e.preventDefault();
  // Fire matching event
}

Allow user to prevent default behavior

From Svelte documentation (https://svelte.dev/docs#run-time-svelte-createeventdispatcher)

Component events created with createEventDispatcher create a CustomEvent. These events do not bubble and are not cancellable with event.preventDefault()

However, if you pass a function which calls the original keyboard events preventDefault , you can use it from
svelte-keydown event handler. I just missed that one to prevent site scrolling on space key

Keydown.svelte

  on:keydown={(evt) => {
    let { key, target} = evt
...

  dispatch("key",   { key, preventDefault: () => evt.preventDefault() });
}

App.svelte


<Keydown
  pauseOnInput
  on:key={(e) => {
      e.detail.preventDefault()

      console.log("Keydown event, key: ", e.detail.key)
  }}
/>

something like that

Originally posted by @notYou263 in #9 (comment)

space key / dispatch 'Space'

The keyboard event for space key is
KeyboardEvent: key=' ' | code='Space'

This leads to call of dispatch with key value ' ' for space key.
Mapping it to 'Space' would be great so one can use on:Space on a component as like for Enter and Escape

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.