Py.Cafe

maartenbreddels/

solara-howto-component-vue-B

Interactive Button Confetti

DocsPricing
  • app.py
  • button-confetti.vue
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import solara
from typing import Callable

@solara.component_vue("button-confetti.vue")
def ButtonConfetti(
    label: str = "Default label",
    event_click: Callable = None,
    ):
    ...

@solara.component
def Page():
   ButtonConfetti(label="Click me", event_click=print)
button-confetti.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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<template>
    <button class="button-confetti" @click="clickHandler">
        {{label}}
    </button>
</template>
<script>
module.exports = {
    created() {
        console.log("button-confetti: created");
        this.loadedConfetti = this.loadConfetti();
    },
    mounted() {
        console.log("button-confetti: mounted");
    },
    watch: {
        label() {
            console.log("button-confetti: label changed");
        }
    },
    methods: {
        clickHandler() {
            if(this.click) {
                this.click({extra: 'foo'}) 
            }
            this.showConfetti();
        },
        async showConfetti() {
            // make sure it is loaded by waiting on the Promise
            await this.loadedConfetti;
            await new Promise((resolve) => setTimeout(resolve, 1000))
            confetti();
        },
        /* begin boilerplate */
        async loadConfetti() {
            let confettiUrl = "https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.3/dist/confetti.browser.min.js";
            require.config({
                map: {
                    '*': {
                        'confetti': confettiUrl,
                    }
                }
            })            
            await new Promise((resolve, reject) => {
                require(['confetti'], (confettiModule) => {
                    resolve(confettiModule);
                }, reject)
            });
        },
        /* end boilerplate */
    },
}
</script>
<style id="button-confetti">
    .button-confetti {
        background-color: lightblue;
        margin: 10px;
        padding: 4px;
        border: 1px solid black;
    }
</style>