{"version":3,"file":"BFormTextarea-ClcoJrSM.mjs","names":[],"sources":["../src/composables/useTextareaResize.ts","../src/components/BFormTextarea/BFormTextarea.vue","../src/components/BFormTextarea/BFormTextarea.vue"],"sourcesContent":["import {useToNumber} from '@vueuse/core'\nimport type {Numberish} from '../types/CommonTypes'\nimport {\n  computed,\n  type CSSProperties,\n  type MaybeRefOrGetter,\n  nextTick,\n  onMounted,\n  ref,\n  type ShallowRef,\n  toValue,\n} from 'vue'\nimport {isVisible} from '../utils/dom'\n\nexport const useTextareaResize = (\n  input: Readonly<ShallowRef<HTMLTextAreaElement | null>>,\n  {\n    maxRows,\n    noAutoShrink,\n    rows,\n  }: {\n    rows: MaybeRefOrGetter<Numberish>\n    maxRows: MaybeRefOrGetter<Numberish | undefined>\n    noAutoShrink: MaybeRefOrGetter<boolean>\n  }\n) => {\n  const height = ref<number | null | string>(0)\n  const maxRowsNumber = useToNumber(\n    computed(() => toValue(maxRows) || Number.NaN),\n    {\n      method: 'parseInt',\n      nanToZero: true,\n    }\n  )\n  const rowsNumber = useToNumber(rows, {\n    method: 'parseInt',\n    nanToZero: true,\n  })\n  const computedMinRows = computed(() => Math.max(rowsNumber.value || 2, 2))\n  const computedMaxRows = computed(() => Math.max(computedMinRows.value, maxRowsNumber.value || 0))\n  const computedRows = computed(() =>\n    computedMinRows.value === computedMaxRows.value ? computedMinRows.value : null\n  )\n\n  const handleHeightChange = async () => {\n    // Element must be visible (not hidden) and in document\n    // Must be checked after above checks\n    if (!input.value || !isVisible(input.value)) {\n      height.value = null\n      return\n    }\n\n    // Get current computed styles\n    const computedStyle = getComputedStyle(input.value)\n    // Height of one line of text in px\n    const lineHeight = Number.parseFloat(computedStyle.lineHeight) || 1\n    // Calculate height of border and padding\n    const border =\n      (Number.parseFloat(computedStyle.borderTopWidth) || 0) +\n      (Number.parseFloat(computedStyle.borderBottomWidth) || 0)\n    const padding =\n      (Number.parseFloat(computedStyle.paddingTop) || 0) +\n      (Number.parseFloat(computedStyle.paddingBottom) || 0)\n    // Calculate offset\n    const offset = border + padding\n    // Minimum height for min rows (which must be 2 rows or greater for cross-browser support)\n    const minHeight = lineHeight * computedMinRows.value + offset\n\n    // Get the current style height (with `px` units)\n    const oldHeight = input.value.style.height || computedStyle.height\n    // Probe scrollHeight by temporarily changing the height to `auto`\n    height.value = 'auto'\n    await nextTick() // We need to wait for the dom to update. These cannot be batched in the same tick\n    // Re-check input.value after await since the element may have been unmounted\n    // (e.g., during SSR hydration when BFormGroup re-renders its wrapper element)\n    if (!input.value) return\n    const {scrollHeight} = input.value\n    // Place the original old height back on the element, just in case `computedProp`\n    // returns the same value as before\n    height.value = oldHeight\n    await nextTick() // We need to wait for the dom to update. These cannot be batched in the same tick\n    if (!input.value) return\n\n    // Calculate content height in 'rows' (scrollHeight includes padding but not border)\n    const contentRows = Math.max((scrollHeight - padding) / lineHeight, 2)\n    // Calculate number of rows to display (limited within min/max rows)\n    const rows = Math.min(Math.max(contentRows, computedMinRows.value), computedMaxRows.value)\n    // Calculate the required height of the textarea including border and padding (in pixels)\n    const newHeight = Math.max(Math.ceil(rows * lineHeight + offset), minHeight)\n\n    // Computed height remains the larger of `oldHeight` and new `height`,\n    // when height is in `sticky` mode (prop `no-auto-shrink` is true)\n    if (toValue(noAutoShrink) && (Number.parseFloat(oldHeight.toString()) || 0) > newHeight) {\n      height.value = oldHeight\n      return\n    }\n\n    // Return the new computed CSS height in px units\n    height.value = `${newHeight}px`\n  }\n\n  onMounted(handleHeightChange)\n\n  const computedStyles = computed<CSSProperties>(() => ({\n    resize: 'none',\n    height:\n      typeof height.value === 'string'\n        ? height.value\n        : height.value\n          ? `${height.value}px`\n          : undefined,\n  }))\n\n  return {\n    onInput: handleHeightChange,\n    computedStyles,\n    computedRows,\n  }\n}\n","<template>\n  <textarea\n    :id=\"computedId\"\n    ref=\"_input\"\n    :class=\"computedClasses\"\n    :name=\"props.name || undefined\"\n    :form=\"props.form || undefined\"\n    :value=\"modelValue ?? undefined\"\n    :disabled=\"isDisabled\"\n    :placeholder=\"props.placeholder\"\n    :required=\"props.required || undefined\"\n    :autocomplete=\"props.autocomplete || undefined\"\n    :readonly=\"props.readonly || props.plaintext\"\n    :aria-required=\"props.required || undefined\"\n    :aria-invalid=\"computedAriaInvalid\"\n    :rows=\"computedRows || 2\"\n    :style=\"computedStyles\"\n    :wrap=\"props.wrap || undefined\"\n    @input=\"\n      (e) => {\n        onInput(e)\n        handleHeightChange()\n      }\n    \"\n    @change=\"onChange\"\n    @blur=\"onBlur\"\n  />\n</template>\n\n<script setup lang=\"ts\">\nimport type {BFormTextareaProps} from '../../types/ComponentProps'\nimport {computed, type CSSProperties, useTemplateRef} from 'vue'\nimport {useDefaults} from '../../composables/useDefaults'\nimport {normalizeInput} from '../../utils/normalizeInput'\nimport {useFormInput} from '../../composables/useFormInput'\nimport {useTextareaResize} from '../../composables/useTextareaResize'\n\nconst _props = withDefaults(defineProps<Omit<BFormTextareaProps, 'modelValue'>>(), {\n  // CommonInputProps\n  ariaInvalid: undefined,\n  autocomplete: undefined,\n  autofocus: false,\n  debounce: 0,\n  debounceMaxWait: Number.NaN,\n  disabled: false,\n  form: undefined,\n  formatter: undefined,\n  id: undefined,\n  lazyFormatter: false,\n  list: undefined,\n  modelValue: '',\n  name: undefined,\n  placeholder: undefined,\n  plaintext: false,\n  readonly: false,\n  required: false,\n  size: undefined,\n  state: undefined,\n  // End CommonInputProps\n  noResize: false,\n  noAutoShrink: false,\n  maxRows: undefined,\n  rows: 2,\n  wrap: 'soft',\n})\nconst props = useDefaults(_props, 'BFormTextarea')\n\nconst [modelValue, modelModifiers] = defineModel<\n  Exclude<BFormTextareaProps['modelValue'], undefined>,\n  'trim' | 'lazy' | 'number'\n>({\n  default: '',\n  set: (v) => normalizeInput(v, modelModifiers),\n})\n\nconst input = useTemplateRef('_input')\n\nconst {\n  computedId,\n  computedAriaInvalid,\n  onInput,\n  stateClass,\n  onChange,\n  onBlur,\n  focus,\n  blur,\n  isDisabled,\n} = useFormInput(props, input, modelValue, modelModifiers)\n\nconst computedClasses = computed(() => [\n  stateClass.value,\n  props.plaintext ? 'form-control-plaintext' : 'form-control',\n  {\n    [`form-control-${props.size}`]: !!props.size,\n  },\n])\n\nconst {\n  computedStyles: resizeStyles,\n  onInput: handleHeightChange,\n  computedRows,\n} = useTextareaResize(input, {\n  maxRows: () => props.maxRows,\n  rows: () => props.rows,\n  noAutoShrink: () => props.noAutoShrink,\n})\n\nconst computedStyles = computed<CSSProperties>(() => ({\n  resize: props.noResize ? 'none' : undefined,\n  ...(props.maxRows || props.noAutoShrink ? resizeStyles.value : undefined),\n}))\n\ndefineExpose({\n  blur,\n  element: input,\n  flushDebounce: onBlur,\n  focus,\n})\n</script>\n","<template>\n  <textarea\n    :id=\"computedId\"\n    ref=\"_input\"\n    :class=\"computedClasses\"\n    :name=\"props.name || undefined\"\n    :form=\"props.form || undefined\"\n    :value=\"modelValue ?? undefined\"\n    :disabled=\"isDisabled\"\n    :placeholder=\"props.placeholder\"\n    :required=\"props.required || undefined\"\n    :autocomplete=\"props.autocomplete || undefined\"\n    :readonly=\"props.readonly || props.plaintext\"\n    :aria-required=\"props.required || undefined\"\n    :aria-invalid=\"computedAriaInvalid\"\n    :rows=\"computedRows || 2\"\n    :style=\"computedStyles\"\n    :wrap=\"props.wrap || undefined\"\n    @input=\"\n      (e) => {\n        onInput(e)\n        handleHeightChange()\n      }\n    \"\n    @change=\"onChange\"\n    @blur=\"onBlur\"\n  />\n</template>\n\n<script setup lang=\"ts\">\nimport type {BFormTextareaProps} from '../../types/ComponentProps'\nimport {computed, type CSSProperties, useTemplateRef} from 'vue'\nimport {useDefaults} from '../../composables/useDefaults'\nimport {normalizeInput} from '../../utils/normalizeInput'\nimport {useFormInput} from '../../composables/useFormInput'\nimport {useTextareaResize} from '../../composables/useTextareaResize'\n\nconst _props = withDefaults(defineProps<Omit<BFormTextareaProps, 'modelValue'>>(), {\n  // CommonInputProps\n  ariaInvalid: undefined,\n  autocomplete: undefined,\n  autofocus: false,\n  debounce: 0,\n  debounceMaxWait: Number.NaN,\n  disabled: false,\n  form: undefined,\n  formatter: undefined,\n  id: undefined,\n  lazyFormatter: false,\n  list: undefined,\n  modelValue: '',\n  name: undefined,\n  placeholder: undefined,\n  plaintext: false,\n  readonly: false,\n  required: false,\n  size: undefined,\n  state: undefined,\n  // End CommonInputProps\n  noResize: false,\n  noAutoShrink: false,\n  maxRows: undefined,\n  rows: 2,\n  wrap: 'soft',\n})\nconst props = useDefaults(_props, 'BFormTextarea')\n\nconst [modelValue, modelModifiers] = defineModel<\n  Exclude<BFormTextareaProps['modelValue'], undefined>,\n  'trim' | 'lazy' | 'number'\n>({\n  default: '',\n  set: (v) => normalizeInput(v, modelModifiers),\n})\n\nconst input = useTemplateRef('_input')\n\nconst {\n  computedId,\n  computedAriaInvalid,\n  onInput,\n  stateClass,\n  onChange,\n  onBlur,\n  focus,\n  blur,\n  isDisabled,\n} = useFormInput(props, input, modelValue, modelModifiers)\n\nconst computedClasses = computed(() => [\n  stateClass.value,\n  props.plaintext ? 'form-control-plaintext' : 'form-control',\n  {\n    [`form-control-${props.size}`]: !!props.size,\n  },\n])\n\nconst {\n  computedStyles: resizeStyles,\n  onInput: handleHeightChange,\n  computedRows,\n} = useTextareaResize(input, {\n  maxRows: () => props.maxRows,\n  rows: () => props.rows,\n  noAutoShrink: () => props.noAutoShrink,\n})\n\nconst computedStyles = computed<CSSProperties>(() => ({\n  resize: props.noResize ? 'none' : undefined,\n  ...(props.maxRows || props.noAutoShrink ? resizeStyles.value : undefined),\n}))\n\ndefineExpose({\n  blur,\n  element: input,\n  flushDebounce: onBlur,\n  focus,\n})\n</script>\n"],"mappings":"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"}