import { computed, onMounted, onUnmounted, ref, unref, watch } from 'vue' export default function useTimer(expirationTime) { const now = ref(Date.now()) const remainingTime = ref(calcRemainingTime()) const requestId = ref() const isPaused = computed(() => !requestId.value) const isPassed = computed(() => remainingTime.value === 0) function calcRemainingTime() { return Math.max(Math.ceil((unref(expirationTime) - now.value) / 1000), 0) } function update() { now.value = Date.now() const newRemainingTime = calcRemainingTime() if (newRemainingTime !== remainingTime.value) remainingTime.value = newRemainingTime if (remainingTime.value > 0) requestId.value = window.requestAnimationFrame(update) } function start() { requestId.value = requestAnimationFrame(update) } function stop() { cancelAnimationFrame(requestId.value) requestId.value = null } watch(expirationTime, () => { if (!isPaused.value) { remainingTime.value = calcRemainingTime() stop() start() } }) onMounted(() => { start() }) onUnmounted(() => { stop() }) return { remainingTime, isPaused, isPassed, start, stop, } }