Two teams try and fill in any horizontal, vertical, or diagonal line on a bingo board by playing maps on osu!
osu.bingo
osu
1<script lang="ts">
2 import { browser } from '$app/environment';
3 import { goto } from '$app/navigation';
4 import { promise } from '$lib/toast';
5 import { Trash2Icon } from 'lucide-svelte';
6 import { cubicOut } from 'svelte/easing';
7 import { tweened } from 'svelte/motion';
8
9 const confirm_time = 2_000;
10
11 let clicked = false;
12 const action = async () => {
13 clicked = true;
14
15 const body = new FormData();
16 const p = fetch('?/delete_game', { method: 'POST', body });
17
18 p.then(() => {
19 setTimeout(() => {
20 if (browser) goto('/games');
21 }, 1000);
22 });
23
24 promise(p, {
25 progress: 'Deleting Game...'
26 });
27 };
28
29 const progress = tweened(0, {
30 easing: cubicOut,
31 duration: confirm_time
32 });
33
34 const size = 24;
35
36 let timeout: NodeJS.Timer;
37 const mousedown = () => {
38 timeout = setTimeout(action, confirm_time);
39 progress.set(1, { duration: confirm_time });
40 };
41 const mouseup = () => {
42 clearTimeout(timeout);
43 if (!clicked) progress.set(0, { duration: 100 });
44 };
45</script>
46
47<button
48 style="--s: {size}px"
49 class="group relative overflow-hidden rounded-lg bg-zinc-900 p-[calc(var(--s)/2)] text-red-400 transition hover:bg-red-500 hover:text-zinc-300"
50 on:mousedown={mousedown}
51 on:mouseup={mouseup}
52 on:mouseleave={mouseup}
53>
54 <div
55 class="absolute left-0 top-0 h-full bg-red-400"
56 style="width: calc(100% * {$progress})"
57 ></div>
58 <div
59 class="relative grid h-[--s] w-[--s] overflow-hidden transition-all group-hover:w-[calc(var(--s)*10)]"
60 >
61 <div class="flex h-[--s] w-[--s] justify-center transition group-hover:-translate-y-[100%]">
62 <Trash2Icon />
63 </div>
64 <div class="h-[--s] font-black uppercase transition group-hover:-translate-y-[100%]">
65 Delete game
66 </div>
67 </div>
68</button>