Py.Cafe

maartenbreddels/

solara-hotkeys

HotKey Event Handler with Dialog in Solara

DocsPricing
  • app.py
  • hotkey.vue
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
from typing import Callable
import solara

show_dialog = solara.reactive(False)


@solara.component_vue("hotkey.vue")
def HotKeyRaw(
    key: str,
    ctrl: bool = False,
    shift: bool = False,
    meta: bool = False,
    prevent_default: bool = False,
    event_pressed: Callable[[], None] = None,
): ...


@solara.component
def HotKey(
    key: str,
    ctrl: bool = False,
    shift: bool = False,
    meta: bool = False,
    prevent_default: bool = False,
    on_press: Callable[[], None] = None
):
    # no args for the on_press
    HotKeyRaw(key=key,
        ctrl=ctrl,
        shift=shift,
        meta=meta,
        prevent_default=prevent_default,
        event_pressed=lambda *ignore: on_press())
    


@solara.component
def Page():
    with solara.Card("Hotkey demo"):
        solara.InputText("No focus")
        solara.Button("Show dialog (press o to open)", on_click=lambda: show_dialog.set(True))

        with solara.v.Dialog(
            v_model=show_dialog.value,
            on_v_model=show_dialog.set,
            persistent=True,
            max_width="500px",
        ):
            with solara.v.Sheet(class_="pa-4") as sheet:
                solara.InputText("Name", autofocus=True)
                solara.InputText("Surname")
                close = solara.Button("Close (press enter)", on_click=lambda: show_dialog.set(False))

        def close_dialog_on_q(widget, event, data):
            print("event", event)
            # if event.key == "Escape":
            show_dialog.set(False)

        HotKey(key="q", ctrl=True, on_press=lambda: show_dialog.set(False))
        HotKey(key="o", on_press=lambda: show_dialog.set(True))
        HotKey(key="Enter", on_press=lambda: show_dialog.set(False))
        HotKey(key="Escape", on_press=lambda: show_dialog.set(False))
hotkey.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<template>
    <span style="display: none;">key {{key}}</span>
</template>
<script>
module.exports = {
    mounted() {
        console.log("mounted", this.key)
        document.addEventListener('keydown', this.hotkeyPress);
    },
    destroyed() {
        document.removeEventListener('keydown', this.hotkeyPress);
    },
    methods: {
        hotkeyPress: function(e) {
            if (e.key === this.key) {
                console.log("key", this.key, e.key, e)
                if(this.metaKey && !e.metaKey) {
                    return
                }
                if(this.ctrl && !e.ctrlKey) {
                    return
                }
                if(this.shift && !e.shiftKey) {
                    return
                }
                if(this.alt && !e.altKey) {
                    return
                }
                if(this.meta && !e.metaKey) {
                    return
                }
                if(this. prevent_default) {
                    e.preventDefault()
                }
                console.log("pressed", this.key)
                this.pressed()
            }
        }
    }
};
</script>