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

const props = defineProps<{
  placeholder?: string
  modelValue?: string  | null
  class?: HTMLAttributes['class']
  spellcheck?: false
}>()

const text = ref<string>(props.modelValue || '')
const editable = useTemplateRef('editable')

onMounted(() => {
  setText(props.modelValue || '')
})

watch(props, () => { setText(props.modelValue || '') }, { deep: true, immediate: false })

const emits = defineEmits<{
  (e: 'input:modelValue', payload: string): void
  (e: 'change:modelValue', payload: string): void
}>()

const setText = (value: string) => {
  if (!editable.value) return
  editable.value.innerText = value
}

const input = () => {
  let newValue = editable.value?.textContent || ''
  text.value = newValue
  emits('input:modelValue', newValue)
}

const blur = () => {
  emits('change:modelValue', text.value)
}

const isEmpty = computed(() => {
  return text.value === undefined || text.value === null || text.value.trim() === ''
},)

</script>

<template>
  <div class="relative">
    <span v-if="isEmpty" :class="cn('absolute text-muted-foreground! pointer-events-none italic', props.class)">
      {{ placeholder }}
    </span>

    <div ref="editable" contenteditable="plaintext-only" :spellcheck="props.spellcheck" @blur="blur" @input="input"
      :class="cn(
        'min-w-60 min-h-4 border-input rounded-md border text-base transition-[color] outline-none disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
        'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
        'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
        'my-0 px-2 ml-[calc(var(--spacing)*-2-1px)] hover:bg-input border-transparent hover:border-border', props.class)">
    </div>
  </div>

</template>