first commit

This commit is contained in:
2026-05-25 19:07:12 +07:00
commit f29c67bff4
62 changed files with 13196 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
<script setup>
import { computed, watch } from 'vue'
import { useInterval } from '@vueuse/core'
const props = defineProps({
active: { type: Boolean, default: false },
seconds: { type: Number, default: 3 },
})
const emit = defineEmits(['finished'])
const { counter, pause, resume, reset } = useInterval(1000, {
controls: true,
immediate: false,
})
const remaining = computed(() => Math.max(props.seconds - counter.value, 0))
watch(
() => props.active,
(value) => {
if (value) {
reset()
resume()
return
}
pause()
},
{ immediate: true },
)
watch(remaining, (value) => {
if (!props.active) return
if (value === 0) {
pause()
emit('finished')
}
})
</script>
<template>
<div v-if="active" class="countdown">
<span
v-motion
:initial="{ scale: 0.6, opacity: 0 }"
:enter="{ scale: 1, opacity: 1, transition: { type: 'spring', stiffness: 300, damping: 16 } }"
:key="remaining"
class="countdown-number"
>
{{ remaining }}
</span>
</div>
</template>
<style scoped>
.countdown {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 32px;
background: rgba(255, 230, 239, 0.65);
backdrop-filter: blur(2px);
}
.countdown-number {
font-size: clamp(2.5rem, 6vw, 4.5rem);
font-weight: 700;
color: #8e2c4a;
}
</style>