<script>
import theme from "#build/b24ui/textarea";
</script>

<script setup>
import { useTemplateRef, computed, onMounted, nextTick, watch } from "vue";
import { Primitive } from "reka-ui";
import { useVModel } from "@vueuse/core";
import { useAppConfig } from "#imports";
import { useComponentProps } from "../composables/useComponentProps";
import { useComponentIcons } from "../composables/useComponentIcons";
import { useFormField } from "../composables/useFormField";
import { looseToNumber } from "../utils";
import { tv } from "../utils/tv";
import B24Badge from "./Badge.vue";
import B24Avatar from "./Avatar.vue";
defineOptions({ inheritAttrs: false });
const _props = defineProps({
  as: { type: null, required: false },
  id: { type: String, required: false },
  name: { type: String, required: false },
  placeholder: { type: String, required: false },
  color: { type: null, required: false },
  noPadding: { type: Boolean, required: false },
  noBorder: { type: Boolean, required: false },
  underline: { type: Boolean, required: false },
  rounded: { type: Boolean, required: false },
  required: { type: Boolean, required: false },
  autofocus: { type: Boolean, required: false },
  autofocusDelay: { type: Number, required: false, default: 0 },
  autoresize: { type: Boolean, required: false },
  autoresizeDelay: { type: Number, required: false, default: 0 },
  disabled: { type: Boolean, required: false },
  rows: { type: Number, required: false, default: 3 },
  maxrows: { type: Number, required: false, default: 0 },
  tag: { type: String, required: false },
  tagColor: { type: null, required: false },
  highlight: { type: Boolean, required: false },
  fixed: { type: Boolean, required: false },
  defaultValue: { type: null, required: false },
  modelValue: { type: null, required: false },
  modelModifiers: { type: null, required: false },
  class: { type: null, required: false },
  b24ui: { type: Object, required: false },
  icon: { type: [Function, Object], required: false },
  avatar: { type: Object, required: false },
  loading: { type: Boolean, required: false },
  trailing: { type: Boolean, required: false },
  trailingIcon: { type: [Function, Object], required: false }
});
const emits = defineEmits(["update:modelValue", "blur", "change"]);
const slots = defineSlots();
const props = useComponentProps("textarea", _props);
const modelValue = useVModel(props, "modelValue", emits, { defaultValue: props.defaultValue });
const appConfig = useAppConfig();
const { emitFormFocus, emitFormBlur, emitFormInput, emitFormChange, color, id, name, highlight, disabled, ariaAttrs } = useFormField(_props, { deferInputValidation: true });
const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props);
const isTag = computed(() => {
  return props.tag;
});
const b24ui = computed(() => tv({ extend: tv(theme), ...appConfig.b24ui?.textarea || {} })({
  color: color.value ?? props.color,
  // size: size?.value ?? props.size,
  loading: props.loading,
  highlight: highlight.value ?? props.highlight,
  fixed: props.fixed,
  autoresize: Boolean(props.autoresize),
  rounded: Boolean(props.rounded),
  noPadding: Boolean(props.noPadding),
  noBorder: Boolean(props.noBorder),
  underline: Boolean(props.underline),
  leading: Boolean(isLeading.value || !!props.avatar || !!slots.leading),
  trailing: Boolean(isTrailing.value || !!slots.trailing)
}));
const textareaRef = useTemplateRef("textareaRef");
function updateInput(value) {
  if (props.modelModifiers?.trim && (typeof value === "string" || value === null || value === void 0)) {
    value = value?.trim() ?? null;
  }
  if (props.modelModifiers?.number) {
    value = looseToNumber(value);
  }
  if (props.modelModifiers?.nullable) {
    value ||= null;
  }
  if (props.modelModifiers?.optional && !props.modelModifiers?.nullable && value !== null) {
    value ||= void 0;
  }
  modelValue.value = value;
  emitFormInput();
}
function onInput(event) {
  autoResize();
  if (!props.modelModifiers?.lazy) {
    updateInput(event.target.value);
  }
}
function onChange(event) {
  const value = event.target.value;
  if (props.modelModifiers?.lazy) {
    updateInput(value);
  }
  if (props.modelModifiers?.trim) {
    event.target.value = value.trim();
  }
  emitFormChange();
  emits("change", event);
}
function onBlur(event) {
  emitFormBlur();
  emits("blur", event);
}
function autoFocus() {
  if (props.autofocus) {
    textareaRef.value?.focus();
  }
}
function autoResize() {
  if (props.autoresize && textareaRef.value) {
    textareaRef.value.rows = props.rows;
    const overflow = textareaRef.value.style.overflow;
    textareaRef.value.style.overflow = "hidden";
    const styles = window.getComputedStyle(textareaRef.value);
    const paddingTop = Number.parseInt(styles.paddingTop);
    const paddingBottom = Number.parseInt(styles.paddingBottom);
    const padding = paddingTop + paddingBottom;
    const lineHeight = Number.parseInt(styles.lineHeight);
    const { scrollHeight } = textareaRef.value;
    const newRows = (scrollHeight - padding) / lineHeight;
    if (newRows > props.rows) {
      textareaRef.value.rows = props.maxrows ? Math.min(newRows, props.maxrows) : newRows;
    }
    textareaRef.value.style.overflow = overflow;
  }
}
watch(modelValue, () => {
  nextTick(autoResize);
});
onMounted(() => {
  setTimeout(() => {
    autoFocus();
  }, props.autofocusDelay);
  setTimeout(() => {
    autoResize();
  }, props.autoresizeDelay);
});
defineExpose({
  textareaRef,
  autoResize
});
</script>

<template>
  <Primitive :as="props.as" data-slot="root" :class="b24ui.root({ class: [props.b24ui?.root, props.class] })">
    <B24Badge
      v-if="isTag"
      data-slot="tag"
      :class="b24ui.tag({ class: props.b24ui?.tag })"
      :color="props.tagColor"
      :label="props.tag"
      size="xs"
    />

    <textarea
      :id="id"
      ref="textareaRef"
      :value="modelValue"
      :name="name"
      :rows="props.rows"
      :placeholder="props.placeholder"
      data-slot="base"
      :class="b24ui.base({ class: props.b24ui?.base })"
      :disabled="disabled"
      :required="props.required"
      v-bind="{ ...$attrs, ...ariaAttrs }"
      @input="onInput"
      @blur="onBlur"
      @change="onChange"
      @focus="emitFormFocus"
    />

    <slot :b24ui="b24ui" />

    <span v-if="isLeading || !!props.avatar || !!slots.leading" data-slot="leading" :class="b24ui.leading({ class: props.b24ui?.leading })">
      <slot name="leading" :b24ui="b24ui">
        <Component
          :is="leadingIconName"
          v-if="isLeading && leadingIconName"
          data-slot="leadingIcon"
          :class="b24ui.leadingIcon({ class: props.b24ui?.leadingIcon })"
        />
        <B24Avatar
          v-else-if="!!props.avatar"
          :size="props.b24ui?.leadingAvatarSize || b24ui.leadingAvatarSize()"
          v-bind="props.avatar"
          data-slot="leadingAvatar"
          :class="b24ui.leadingAvatar({ class: props.b24ui?.leadingAvatar })"
        />
      </slot>
    </span>

    <span v-if="isTrailing || !!slots.trailing" data-slot="trailing" :class="b24ui.trailing({ class: props.b24ui?.trailing })">
      <slot name="trailing" :b24ui="b24ui">
        <Component
          :is="trailingIconName"
          v-if="trailingIconName"
          data-slot="trailingIcon"
          :class="b24ui.trailingIcon({ class: props.b24ui?.trailingIcon })"
        />
      </slot>
    </span>
  </Primitive>
</template>
