<template>
  <span
    v-if="!props.highlightText"
    :class="cn('inline-block px-1 pb-1 highlight-all', props.class)"
  >
    {{ props.text }}
  </span>
  <span v-else>
    {{ beforeText }}
    <div :class="cn('inline-block highlight-all', props.class)">
      {{ props.highlightText }}
    </div>
    {{ afterText }}
  </span>
</template>

<script setup lang="ts">
import { computed, type HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'

interface Props {
  delay?: number
  duration?: number
  class?: HTMLAttributes['class']
  textEndColor?: string
  highlightText?: string
  text: string
}

const props = withDefaults(defineProps<Props>(), {
  delay: 0,
  duration: 2000,
  endColor: 'inherit',
})

const delayMs = computed(() => `${props.delay}ms`)
const durationMs = computed(() => `${props.duration}ms`)

const beforeText = computed(() => {
  if (!props.highlightText || !props.text) return ''

  const index = props.text.indexOf(props.highlightText)
  if (index === -1) return props.text

  return props.text.substring(0, index)
})

const afterText = computed(() => {
  if (!props.highlightText || !props.text) return ''

  const index = props.text.indexOf(props.highlightText)
  if (index === -1) return ''

  return props.text.substring(index + props.highlightText.length)
})
</script>

<style scoped>
@keyframes background-expand {
  0% {
    background-size: 0% 100%;
  }
  100% {
    background-size: 100% 100%;
  }
}

@keyframes text-color-change {
  0% {
    color: inherit;
  }
  100% {
    color: v-bind(textEndColor);
  }
}

span {
  background-size: 0% 100%;
  background-repeat: no-repeat;
  background-position: left center;
}

.highlight-all,
.highlight-text {
  animation:
    background-expand v-bind(durationMs) ease-in-out v-bind(delayMs) forwards,
    text-color-change v-bind(durationMs) ease-in-out v-bind(delayMs) forwards;
}
</style>
