<script setup lang="ts">
import { useId, useSlots } from 'vue'

defineProps<{
  label?: string
  placeholder?: string
  type?: 'text' | 'password' | 'email' | 'number' | 'search'
  error?: string
}>()

const model = defineModel<string | number>()
const id = useId()
const slots = useSlots()
</script>

<template>
  <div class="input-group">
    <label v-if="label" :for="id" class="label">
      {{ label }}
    </label>
    <div class="input-wrapper">
      <div v-if="slots.prefix" class="prefix-wrapper">
        <slot name="prefix"></slot>
      </div>
      <input
        :id="id"
        v-model="model"
        :type="type || 'text'"
        :placeholder="placeholder"
        :class="{ input: true, 'has-prefix': !!slots.prefix, 'has-error': !!error }"
      />
    </div>
    <span v-if="error" class="error-text">{{ error }}</span>
  </div>
</template>

<style scoped lang="scss">
.input-group {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  width: 100%;
  margin-bottom: 1rem;
}

.label {
  font-size: 0.875rem;
  font-weight: 600;
  color: hsl(var(--text));
  margin-left: 0.125rem;
}

.input-wrapper {
  position: relative;
  width: 100%;

  display: flex;
  align-items: center;

  border-radius: var(--radius-md);
  border: 1px solid hsla(var(--surface2) / 0.5);
  background-color: hsl(var(--surface0) / 0.3);

  outline: 2px solid transparent;
  outline-offset: 4px;

  &:hover {
    background-color: hsl(var(--surface0));
    border-color: hsl(var(--surface2));
  }
  &:focus-within {
    background-color: hsl(var(--base));
    outline-color: hsl(var(--accent));
    outline-offset: 2px;
  }
  &:has(.has-error) {
    border-color: hsl(var(--red));
    color: hsl(var(--red));
    &:focus-visible {
      box-shadow: 0 0 0 3px hsla(var(--red) / 0.15);
    }
  }
}

.input {
  color: hsl(var(--text));
  font-size: 1rem;
  font-family: inherit;
  background: transparent;
  border: none;
  width: 100%;
  padding: 0.75rem 1rem;

  outline: none;

  &.has-prefix {
    padding-left: 0;
  }

  &:focus-visible {
    outline: none;
  }

  &::placeholder {
    color: hsl(var(--overlay0));
  }
}

.prefix-wrapper {
  height: 100%;
  display: flex;
  align-items: center;
  color: hsl(var(--overlay0));
  min-width: 2.5rem;
  justify-content: center;
}

.error-text {
  font-size: 0.75rem;
  color: hsl(var(--red));
  font-weight: 600;
  margin-left: 0.125rem;
}
</style>
