@svelte-put/shortcut GitHub

add keyboard shortcuts to node

@svelte-put/shortcut @svelte-put/shortcut @svelte-put/shortcut changelog

Installation

terminal

npm install --save-dev @svelte-put/shortcut

Quick Start

quick start

<script lang="ts">
  import { shortcut, type ShortcutEventDetail } from '@svelte-put/shortcut';

  function handleK(detail: ShortcutEventDetail) {
    console.log('attached node:', detail.node);
    console.log('original trigger config:', detail.trigger);
  }
</script>

<svelte:window
  use:shortcut={{
    trigger: {
      key: 'k',
      modifier: ['ctrl', 'meta'],
      callback: handleK,
    },
  }}
/>

Key Combination

In each use:shortcut, one or an array of ShortcutTrigger can be provided to the trigger parameter.

key

<script>
  import { shortcut } from '@svelte-put/shortcut';
</script>

<svelte:window
  use:shortcut={{ trigger: { key: 'k', modifier: 'ctrl' } }}
  use:shortcut={{
    trigger: [
      { key: 'k', modifier: 'ctrl' },
      { key: 'l', modifier: 'meta' },
    ],
  }}
/>

One or multiple modifiers ( ctrl, meta, alt, shift ) can be provided to trigger.modifier in both and & or fashions.

modifier

<script>
  import { shortcut } from '@svelte-put/shortcut';
</script>

<svelte:window
  use:shortcut={{
    // listen for one of many modifiers (or)
    // ctrl+k or meta+k
    trigger: {
      key: 'k',
      modifier: ['ctrl', 'meta'],
    },
  }}
  use:shortcut={{
    // listen for a combination of multiple modifiers (and)
    // ctrl+shift+k
    trigger: {
      key: 'k',
      modifier: [['ctrl', 'shift']],
    },
  }}
  use:shortcut={{
    // mix & match
    // ctrl+shift+k or meta+k
    trigger: {
      key: 'k',
      modifier: [['ctrl', 'shift'], ['meta']],
    },
  }}
/>

Event vs Callback

In cases where multiple key combinations are registered. You can either:

  1. provide a callback for each combination via trigger.callback, or
  2. use the on:shortcut CustomEvent , in which case it is recommended to give each trigger a unique id for easier identification in the event handler.

event vs callback

<script lang="ts">
  import { shortcut, type ShortcutEventDetail } from '@svelte-put/shortcut';

  let commandPalette = false;
  function onOpenCommandPalette() {
    commandPalette = true;
  }
  function onCloseCommandPalette() {
    commandPalette = false;
  }

  function doSomethingElse(details: ShortcutEventDetail) {
    console.log('Action was placed on:', details.node);
    console.log('Trigger:', details.trigger);
  }

  function onShortcut(event: CustomEvent<ShortcutEventDetail>) {
    if (event.detail.trigger.id === 'do-something-else') {
      console.log('Same as doSomethingElse()');
      // be careful here doSomethingElse would have been called too
    }
  }
</script>

<svelte:window
  use:shortcut={{
    trigger: [
      {
        key: 'k',
        // trigger if either ctrl or meta is pressed
        modifier: ['ctrl', 'meta'],

        callback: onOpenCommandPalette,
        preventDefault: true,
      },
      {
        key: 'Escape',
        // preferably avoid arrow functions here for better performance,
        // with arrow functions the action has to be updated more frequently
        callback: onCloseCommandPalette,
        enabled: commandPalette,
        preventDefault: true,
      },
      {
        key: 'k',
        // trigger if both ctrl & shift are pressed
        modifier: [['ctrl', 'shift']],
        id: 'do-something-else',
        callback: doSomethingElse,
      },
    ],
  }}
  on:shortcut={onShortcut}
/>

Original KeyboardEvent

You can access the original KeyboardEvent via detail.originalEvent from ShortcutEventDetail, helpful for things like checking target or invoking preventDefault.

Be aware that the event listener is placed on the node the action is attached to. For example, if you use the action on svelte:window, calling stopPropagation or preventDefault on originalEvent might not result in the behavior you would expected. By the time the provided callback or on:shortcut event handler executes, the event has already reached window.

original KeyboardEvent

<script lang="ts">
  import type { ShortcutEventDetail } from '@svelte-put/shortcut';
  import { shortcut } from '@svelte-put/shortcut';

  function onShortcut(event: CustomEvent<ShortcutEventDetail>) {
    const keyboardEvent = event.detail.originalEvent;
    // be cautious: `keyboardEvent` has already reached window here

    keyboardEvent.preventDefault(); // prevent browser default

    if ((keyboardEvent.target as HTMLElement)?.tagName === 'INPUT') {
      console.log('some input is focused, should skip');
      return;
    }
    // do things
  }
</script>

<svelte:window
  use:shortcut={{
    trigger: {
      key: 'k',
      modifier: ['ctrl', 'meta'],
    },
  }}
  on:shortcut={onShortcut}
/>
mouse click faster

Happy making shortcuts! 👨‍💻

Edit this page on GitHub