UNPKG

@oiij/use

Version:

Som Composable Functions for Vue 3

113 lines (111 loc) 2.68 kB
import { createEventHook } from "@vueuse/core"; import { computed, nextTick, ref, watch } from "vue"; //#region src/composables/use-type-writer.ts function useTypeWriter(value, options) { const { step = 1, interval = 50, enabled = true } = options ?? {}; const typeIndex = ref(0); const paused = ref(false); const ended = ref(false); const isTyping = ref(false); const typedValue = computed(() => enabled ? value.value.slice(0, typeIndex.value) : value.value); const progress = computed(() => Number(Math.min(typeIndex.value / value.value.length * 100, 100).toFixed(2))); let timer = null; const onStatEvent = createEventHook(); const onStopEvent = createEventHook(); const onUpdateEvent = createEventHook(); watch(value, (newValue, oldValue) => { if (!oldValue) { typeIndex.value = 0; start(); return; } if (newValue.startsWith(oldValue)) start(); else { typeIndex.value = 0; start(); } }, { immediate: true }); function start() { if (timer) clearTimeout(timer); if (!enabled) { typeIndex.value = value.value.length; ended.value = true; isTyping.value = false; paused.value = false; onStopEvent.trigger(typedValue.value); return; } isTyping.value = true; paused.value = false; ended.value = false; onStatEvent.trigger(); function run() { typeIndex.value += step; onUpdateEvent.trigger({ index: typeIndex.value, value: typedValue.value }); if (typeIndex.value >= value.value.length) { typeIndex.value = value.value.length; ended.value = true; isTyping.value = false; onStopEvent.trigger(typedValue.value); return; } timer = setTimeout(run, interval); } timer = setTimeout(run, interval); } function pause() { if (timer) clearTimeout(timer); paused.value = true; isTyping.value = false; ended.value = false; } function resume() { if (timer) clearTimeout(timer); start(); } function restart() { if (timer) clearTimeout(timer); typeIndex.value = 0; nextTick(() => { start(); }); } function stop() { if (timer) clearTimeout(timer); isTyping.value = false; paused.value = false; ended.value = true; typeIndex.value = value.value.length; onStopEvent.trigger(typedValue.value); } function destroy() { if (timer) clearTimeout(timer); timer = null; isTyping.value = false; paused.value = false; ended.value = false; typeIndex.value = 0; } return { typeIndex, paused, ended, isTyping, typedValue, progress, start, pause, resume, restart, stop, destroy, onStat: onStatEvent.on, onStop: onStopEvent.on, onUpdate: onUpdateEvent.on }; } //#endregion export { useTypeWriter };