<script setup lang="ts">
const props = defineProps<{ value: string }>()
const root = ref<HTMLElement>()
const shown = ref(props.value)
let observer: IntersectionObserver | undefined

onMounted(() => {
  const match = props.value.match(/^(\d+)(.*)$/)
  if (!match || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return
  const target = Number(match[1])
  const suffix = match[2]
  shown.value = `0${suffix}`
  observer = new IntersectionObserver(([entry]) => {
    if (!entry?.isIntersecting) return
    observer?.disconnect()
    const startedAt = performance.now()
    const duration = 620
    const tick = (now: number) => {
      const progress = Math.min(1, (now - startedAt) / duration)
      const eased = 1 - Math.pow(1 - progress, 3)
      shown.value = `${Math.round(target * eased)}${suffix}`
      if (progress < 1) requestAnimationFrame(tick)
    }
    requestAnimationFrame(tick)
  }, { threshold: 0.7 })
  if (root.value) observer.observe(root.value)
})

onBeforeUnmount(() => observer?.disconnect())
</script>

<template><strong ref="root">{{ shown }}</strong></template>
