This commit is contained in:
Nadar
2026-03-17 13:24:22 +03:00
commit 82e5ac9d81
554 changed files with 29637 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
<template>
<div
:class="[
cn.b(),
cn.is('timer', !indeterminate && remainingTime > 0),
cn.is('indeterminate', indeterminate),
]"
>
<svg :class="[cn.e('circle-wrapper')]">
<circle
:class="[cn.e('circle')]"
cx="50%"
cy="50%"
r="45%"
/>
<circle
:class="[cn.e('inner')]"
cx="50%"
cy="50%"
r="45%"
/>
</svg>
<div
v-if="showSeconds && remainingTime > 0"
:class="[cn.e('remaining-time')]"
>
{{ remainingTime }}
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import useClassname from '../../composables/use-classname.js'
export interface Props {
delay?: number
showSeconds?: boolean
}
defineOptions({
name: 'UiSpinner',
})
const props = withDefaults(defineProps<Props>(), {
delay: 0,
showSeconds: false,
})
const emit = defineEmits<{
done: []
}>()
const cn = useClassname('ui-spinner')
const remainingTime = ref(0)
const indeterminate = computed(() => props.delay === 0)
function countdown() {
let startTimestamp: number, elapsedTime: number
const step = (timestamp: number) => {
startTimestamp = startTimestamp || timestamp
elapsedTime = timestamp - startTimestamp
remainingTime.value = Math.ceil(props.delay - elapsedTime / 1000)
if (elapsedTime < props.delay * 1000)
window.requestAnimationFrame(step)
else
emit('done')
}
window.requestAnimationFrame(step)
}
onMounted(() => {
if (props.delay > 0)
countdown()
})
</script>
<style lang="scss">
@use 'styles';
</style>