<script setup>
import { computed, useSlots } from "vue";
const props = defineProps({
  fallback: { type: String, required: false, default: () => void 0 },
  tag: { type: String, default: () => "span" },
  template: { type: String, required: true },
  values: { type: Object, required: false, default: () => ({}) }
});
const slots = useSlots();
const contentParts = computed(() => {
  const regex = /:([a-zA-Z0-9_]+):/g;
  const parts = [];
  let lastIndex = 0;
  let match;
  while ((match = regex.exec(props.template)) !== null) {
    const [fullMatch, key] = match;
    const index = match.index;
    if (index > lastIndex) {
      parts.push(props.template.slice(lastIndex, index));
    }
    if (slots[key]) {
      parts.push({ slotName: key });
    } else {
      const value = props.values?.[key];
      parts.push(value != null ? String(value) : props.fallback ?? fullMatch);
    }
    lastIndex = index + fullMatch.length;
  }
  if (lastIndex < props.template.length) {
    parts.push(props.template.slice(lastIndex));
  }
  return parts;
});
</script>

<template>
  <component :is="props.tag">
    <template v-for="(part, i) in contentParts" :key="i">
      <template v-if="typeof part === 'string'">
        <span v-text="part" />
      </template>

      <template v-else>
        <slot :name="part.slotName" />
      </template>
    </template>
  </component>
</template>
