# `Xenia.Shortcuts`
[🔗](https://github.com/uzaydurdu/xenia/blob/v0.1.1/lib/xenia/core/shortcuts.ex#L1)

Keyboard shortcuts for a JS island, handled in your LiveView.

    <.monaco id="editor" shortcuts={%{"mod+s" => "save", "mod+shift+." => "bigger"}} />

    def handle_event("save", %{"shortcut" => "mod+s"}, socket), do: ...

Every Xenia component takes `shortcuts`: a map from a key combination to
the LiveView event it sends. Xenia listens only **while focus is inside the
component**, so the same keys do their usual thing everywhere else on the
page. A matched combination is handled before the JavaScript library sees
it, and the browser doesn't act on it either.

Before the shortcut's event, the component's pending events are sent. So
`mod+s` right after typing saves what was typed.

## Writing a combination

Modifiers, then one key, joined with `+`:

  * `mod` is Cmd on a Mac and Ctrl elsewhere. Use it for the usual app
    shortcuts: `mod+s`, `mod+k`.
  * `ctrl`, `alt`, `shift` and `meta` mean those keys exactly. `cmd` is
    `meta`, `option` is `alt`.
  * The key is a letter, a digit, a symbol such as `.` or `/`, or a name:
    `enter`, `escape`, `tab`, `space`, `backspace`, `delete`, `home`, `end`,
    `pageup`, `pagedown`, `arrowup`, `arrowdown`, `arrowleft`, `arrowright`,
    `f1` to `f12`, and `plus` for `+`.
  * With `shift`, write the key itself, not what Shift makes of it:
    `mod+shift+.`, not `mod+>`.

Case and spaces don't matter: `"Mod + Shift + S"` is `"mod+shift+s"`.

## Browser shortcuts are not available

Xenia doesn't take over the shortcuts people use to control the browser
and their computer. Using one raises an error:

  * zoom: `mod+=`, `mod+-`, `mod+0`, `mod+plus`
  * tabs and windows: `mod+t`, `mod+n`, `mod+w`, `mod+q`, `mod+1` to
    `mod+9`, `ctrl+tab`, `ctrl+pageup`, `ctrl+pagedown`
  * reloading: `mod+r`, `f5`
  * the address bar: `mod+l`, `alt+d`, `f6`
  * back and forward: `alt+arrowleft`, `alt+arrowright`, `mod+[`, `mod+]`
  * full screen and developer tools: `f11`, `f12`, `mod+alt+i`,
    `mod+shift+i`
  * downloads and history: `mod+j`, `mod+h`, `mod+shift+delete`

The full list is `reserved/0`.

# `normalize!`

```elixir
@spec normalize!(map(), String.t() | nil) :: %{required(String.t()) =&gt; String.t()}
```

Normalizes a `shortcuts` map: each combination in its one written form,
each event name checked.

    iex> Xenia.Shortcuts.normalize!(%{"Shift + Mod + S" => "save"})
    %{"mod+shift+s" => "save"}

Raises `ArgumentError` for an invalid combination, a browser shortcut, two
spellings of one combination, or an event name that isn't a string. `id`
names the component in the message.

# `reserved`

```elixir
@spec reserved() :: [String.t()]
```

The browser and system shortcuts Xenia refuses, as written in `shortcuts`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
