You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
1.8 KiB
89 lines
1.8 KiB
<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>
|
|
|