import {
  __decorateClass,
  __privateAdd,
  __privateGet,
  __privateMethod,
  __privateSet
} from "../../chunks/chunk.QU3DSPNU.js";
var _charCounterComputed, _Textarea_instances, shouldShowFooter_fn, _handleOnInput, _handleOnChange, _handleOnPaste, _handleFieldClick, _handleClearBtnClick, renderFieldContents_fn, renderSlotLead_fn, renderSlotTrail_fn, renderNativeTextarea_fn, renderClearButton_fn;
import { localized, msg } from "@lit/localize";
import { property, query, queryAsync } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { when } from "lit/directives/when.js";
import { nothing } from "lit/html.js";
import { GdsFieldBase } from "../../primitives/field-base/field-base.component.js";
import { GdsFormControlFooter } from "../../primitives/form-control-footer/form-control-footer.component.js";
import { GdsFormControlHeader } from "../../primitives/form-control-header/form-control-header.component.js";
import { gdsCustomElement, html } from "../../scoping.js";
import formControlHostStyle from "../../shared-styles/form-control-host.style.js";
import { tokens } from "../../tokens.style.js";
import { watch } from "../../utils/decorators/index.js";
import { resizeObserver } from "../../utils/decorators/resize-observer.js";
import { styleExpressionProperty } from "../../utils/decorators/style-expression-property.js";
import {
  withLayoutChildProps,
  withMarginProps,
  withSizeXProps
} from "../../utils/mixins/declarative-layout-mixins.js";
import { GdsButton } from "../button/button.component.js";
import { GdsFormControlElement } from "../form/form-control.js";
import { IconCrossSmall } from "../icon/icons/cross-small.component.js";
import TextareaStyles from "./textarea.styles.js";
let Textarea = class extends GdsFormControlElement {
  constructor() {
    super();
    __privateAdd(this, _Textarea_instances);
    this._defaultRows = 4;
    this.rows = 4;
    this.supportingText = "";
    this.clearable = false;
    this.resizable = "auto";
    this.showExtendedSupportingText = false;
    this.maxlength = Number.MAX_SAFE_INTEGER;
    this.size = "large";
    this.plain = false;
    this.autocapitalize = "off";
    this.autocorrect = false;
    this.autofocus = false;
    this.spellcheck = true;
    this.charCounterCallback = charCounterCallbackDefault;
    __privateAdd(this, _charCounterComputed, this.charCounterCallback(this));
    this._handleSlotChange = () => {
      requestAnimationFrame(() => {
        this._handleResize();
      });
    };
    __privateAdd(this, _handleOnInput, (e) => {
      const element = e.target;
      this.value = element.value;
    });
    __privateAdd(this, _handleOnChange, (e) => {
      const element = e.target;
      this.value = element.value;
      this.dispatchStandardEvent("change", {
        bubbles: true,
        composed: true
      });
    });
    __privateAdd(this, _handleOnPaste, (e) => {
      requestAnimationFrame(() => {
        this._setAutoHeight();
      });
    });
    __privateAdd(this, _handleFieldClick, () => {
      this.elTextareaAsync.then((el) => el.focus());
    });
    __privateAdd(this, _handleClearBtnClick, () => {
      this.value = "";
      this.elTextareaAsync.then((element) => {
        if (this.resizable === "manual") {
          element.style.height = "";
        } else if (this.resizable === "false") {
          const rowsToUse = this._initialRows ?? this._defaultRows;
          this.rows = rowsToUse;
          element.style.setProperty("--_lines", rowsToUse.toString());
        } else {
          const rowsToUse = this._initialRows ?? this._defaultRows;
          this.rows = rowsToUse;
          element.style.setProperty("--_lines", rowsToUse.toString());
          element.style.height = "";
        }
      });
      this.dispatchCustomEvent("gds-input-cleared", {
        bubbles: true,
        composed: true
      });
      this.dispatchStandardEvent("input", {
        bubbles: true,
        composed: true
      });
    });
    this.value = "";
  }
  /**
   * A reference to the clear button element. Returns null if there is no clear button.
   * Intended for use in integration tests.
   */
  test_getClearButton() {
    return this.shadowRoot?.querySelector("#clear-button");
  }
  /**
   * A reference to the field element. This does not refer to the input element itself,
   * but the wrapper that makes up the visual field.
   * Intended for use in integration tests.
   */
  test_getFieldElement() {
    return this.shadowRoot?.querySelector("#field");
  }
  focus(options) {
    this._getValidityAnchor()?.focus(options);
  }
  /**
   * Selects all the text in the textarea element.
   */
  select() {
    this._getValidityAnchor()?.select();
  }
  /**
   * Sets the value of the textarea element, replacing a range of text.
   */
  setRangeText(...args) {
    this._getValidityAnchor()?.setRangeText(...args);
    this.value = this._getValidityAnchor()?.value || "";
  }
  /**
   * Sets the start and end positions of a selection in the textarea element.
   */
  setSelectionRange(...args) {
    this._getValidityAnchor()?.setSelectionRange(...args);
  }
  /** The position of the start of the current text selection in the textarea element. */
  get selectionStart() {
    return this._getValidityAnchor()?.selectionStart;
  }
  /** Sets the position of the start of the current text selection in the textarea element. */
  set selectionStart(value) {
    const anchor = this._getValidityAnchor();
    if (anchor) {
      anchor.selectionStart = value;
    }
  }
  /** The position of the end of the current text selection in the textarea element. */
  get selectionEnd() {
    return this._getValidityAnchor()?.selectionEnd;
  }
  /** Sets the position of the end of the current text selection in the textarea element. */
  set selectionEnd(value) {
    const anchor = this._getValidityAnchor();
    if (anchor) {
      anchor.selectionEnd = value;
    }
  }
  /** The direction of the current text selection in the textarea element. */
  get selectionDirection() {
    return this._getValidityAnchor()?.selectionDirection;
  }
  /** Sets the direction of the current text selection in the textarea element. */
  set selectionDirection(value) {
    const anchor = this._getValidityAnchor();
    if (anchor) {
      anchor.selectionDirection = value;
    }
  }
  _handleResize() {
    if (!this.fieldBase) return;
    Promise.resolve().then(() => {
      const fieldBaseShadowRoot = this.fieldBase?.shadowRoot;
      if (!fieldBaseShadowRoot) return;
      const rightDiv = fieldBaseShadowRoot.querySelector(
        ".right"
      );
      if (rightDiv) {
        const boundingBox = rightDiv.getBoundingClientRect();
        this.elTextarea.style.setProperty(
          "--padding-inline-end",
          `${boundingBox.width}px`
        );
      } else {
        this.elTextarea.style.removeProperty("--padding-inline-end");
      }
    });
  }
  connectedCallback() {
    super.connectedCallback();
    if (this.hasAttribute("rows")) {
      this._initialRows = this.rows;
    }
    this._setAutoHeight();
    this.addEventListener("slotchange", this._handleSlotChange);
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    this.removeEventListener("slotchange", this._handleSlotChange);
  }
  render() {
    return html`
      ${when(
      !this.plain,
      () => html`<gds-form-control-header
            class="size-${this.size}"
            .showExtendedSupportingText="${this.showExtendedSupportingText}"
          >
            <label for="input" slot="label">${this.label}</label>
            <span slot="supporting-text" id="supporting-text">
              ${this.supportingText}
            </span>
            <slot
              name="extended-supporting-text"
              slot="extended-supporting-text"
            ></slot>
          </gds-form-control-header>`
    )}

      <gds-field-base
        id="field"
        .disabled=${this.disabled}
        .invalid=${this.invalid}
        @click=${__privateGet(this, _handleFieldClick)}
        multiline
      >
        ${__privateMethod(this, _Textarea_instances, renderFieldContents_fn).call(this)}
      </gds-field-base>

      ${when(
      __privateMethod(this, _Textarea_instances, shouldShowFooter_fn).call(this),
      () => html`<gds-form-control-footer
            id="footer"
            class="size-${this.size}"
            .charCounter=${__privateGet(this, _charCounterComputed)}
            .errorMessage=${this.invalid ? this.errorMessage : void 0}
          ></gds-form-control-footer>`
    )}
    `;
  }
  _handleValueChange() {
    __privateSet(this, _charCounterComputed, this.charCounterCallback(this));
  }
  _getValidityAnchor() {
    return this.elTextarea;
  }
  _setAutoHeight() {
    this.elTextareaAsync.then((element) => {
      if (this.resizable === "false") {
        const rowsToUse = this._initialRows ?? this._defaultRows;
        this.rows = rowsToUse;
        element.style.setProperty("--_lines", rowsToUse.toString());
        return;
      }
      if (this.resizable === "manual") {
        return;
      }
      if (this.resizable === "auto") {
        if (element.value === "") {
          const rowsToUse = this._initialRows ?? this._defaultRows;
          this.rows = rowsToUse;
          element.style.setProperty("--_lines", rowsToUse.toString());
        } else {
          const computedStyle = getComputedStyle(element);
          const lineHeight = parseFloat(computedStyle.lineHeight);
          const contentHeight = element.scrollHeight;
          const requiredRows = Math.ceil(contentHeight / lineHeight);
          const minRows = this._initialRows ?? this._defaultRows;
          this.rows = Math.max(minRows, requiredRows);
          element.style.setProperty("--_lines", this.rows.toString());
        }
      }
    });
  }
  _handleRowsChange() {
    if (this.hasAttribute("rows")) {
      this._initialRows = this.rows;
    }
    this.elTextareaAsync.then((element) => {
      if (this.resizable === "false") {
        element.style.setProperty("--_lines", this.rows.toString());
      }
    });
  }
};
_charCounterComputed = new WeakMap();
_Textarea_instances = new WeakSet();
shouldShowFooter_fn = function() {
  return !this.plain;
};
_handleOnInput = new WeakMap();
_handleOnChange = new WeakMap();
_handleOnPaste = new WeakMap();
_handleFieldClick = new WeakMap();
_handleClearBtnClick = new WeakMap();
renderFieldContents_fn = function() {
  const elements = [
    __privateMethod(this, _Textarea_instances, renderSlotLead_fn).call(this),
    __privateMethod(this, _Textarea_instances, renderNativeTextarea_fn).call(this),
    __privateMethod(this, _Textarea_instances, renderClearButton_fn).call(this),
    __privateMethod(this, _Textarea_instances, renderSlotTrail_fn).call(this)
  ];
  return elements.map((element) => html`${element}`);
};
renderSlotLead_fn = function() {
  return html`<slot slot="lead" name="lead"></slot>`;
};
renderSlotTrail_fn = function() {
  return html`<slot slot="trail" name="trail"></slot>`;
};
renderNativeTextarea_fn = function() {
  return html`
      <textarea
        @input=${__privateGet(this, _handleOnInput)}
        @change=${__privateGet(this, _handleOnChange)}
        @paste=${__privateGet(this, _handleOnPaste)}
        .value=${this.value}
        id="input"
        class="native-control resize-${this.resizable}"
        aria-label=${this.plain && this.label || nothing}
        aria-describedby="supporting-text extended-supporting-text sub-label message"
        aria-errormessage="footer"
        placeholder=" "
        autocapitalize=${ifDefined(this.autocapitalize)}
        autocomplete=${ifDefined(this.autocomplete)}
        autocorrect=${ifDefined(this.autocorrect)}
        ?autofocus=${this.autofocus}
        spellcheck=${this.spellcheck}
        enterkeyhint=${ifDefined(this.enterkeyhint)}
        inputmode=${ifDefined(this.inputmode)}
        wrap=${ifDefined(this.wrap)}
        ?required=${this.required}
      ></textarea>
    `;
};
renderClearButton_fn = function() {
  if (this.clearable && (this.value?.length || 0) > 0)
    return html`
        <gds-button
          size="small"
          rank="tertiary"
          variant="${ifDefined(this.invalid ? "negative" : void 0)}"
          ?disabled="${this.disabled}"
          label="${msg("Clear input")}"
          @click=${__privateGet(this, _handleClearBtnClick)}
          slot="action"
          id="clear-button"
        >
          <gds-icon-cross-small></gds-icon-cross-small>
        </gds-button>
      `;
  else return nothing;
};
Textarea.styles = [tokens, formControlHostStyle, TextareaStyles];
__decorateClass([
  styleExpressionProperty({
    valueTemplate: (v) => v,
    selector: "textarea",
    styleTemplate: (_prop, values) => {
      const ROWS = values[0];
      return `min-height: calc(1lh * ${ROWS});`;
    }
  })
], Textarea.prototype, "rows", 2);
__decorateClass([
  property({ attribute: "supporting-text" })
], Textarea.prototype, "supportingText", 2);
__decorateClass([
  property({ type: Boolean })
], Textarea.prototype, "clearable", 2);
__decorateClass([
  property({ type: String })
], Textarea.prototype, "resizable", 2);
__decorateClass([
  property({
    attribute: "show-extended-supporting-text",
    type: Boolean,
    reflect: true
  })
], Textarea.prototype, "showExtendedSupportingText", 2);
__decorateClass([
  property({ type: Number })
], Textarea.prototype, "maxlength", 2);
__decorateClass([
  property({ type: String })
], Textarea.prototype, "size", 2);
__decorateClass([
  property({ type: Boolean })
], Textarea.prototype, "plain", 2);
__decorateClass([
  property()
], Textarea.prototype, "autocapitalize", 2);
__decorateClass([
  property({ type: Boolean })
], Textarea.prototype, "autocorrect", 2);
__decorateClass([
  property()
], Textarea.prototype, "autocomplete", 2);
__decorateClass([
  property({ type: Boolean })
], Textarea.prototype, "autofocus", 2);
__decorateClass([
  property({
    type: Boolean,
    converter: {
      // Allow "true|false" attribute values but keep the property boolean
      fromAttribute: (value) => !value || value === "false" ? false : true,
      toAttribute: (value) => value ? "true" : "false"
    }
  })
], Textarea.prototype, "spellcheck", 2);
__decorateClass([
  property()
], Textarea.prototype, "wrap", 2);
__decorateClass([
  property()
], Textarea.prototype, "enterkeyhint", 2);
__decorateClass([
  property()
], Textarea.prototype, "inputmode", 2);
__decorateClass([
  property({ attribute: false })
], Textarea.prototype, "charCounterCallback", 2);
__decorateClass([
  queryAsync("textarea")
], Textarea.prototype, "elTextareaAsync", 2);
__decorateClass([
  query("textarea")
], Textarea.prototype, "elTextarea", 2);
__decorateClass([
  query("gds-field-base")
], Textarea.prototype, "fieldBase", 2);
__decorateClass([
  resizeObserver()
], Textarea.prototype, "_handleResize", 1);
__decorateClass([
  watch("value")
], Textarea.prototype, "_handleValueChange", 1);
__decorateClass([
  watch("value")
], Textarea.prototype, "_setAutoHeight", 1);
__decorateClass([
  watch("rows")
], Textarea.prototype, "_handleRowsChange", 1);
Textarea = __decorateClass([
  localized()
], Textarea);
let GdsTextarea = class extends withLayoutChildProps(
  withSizeXProps(withMarginProps(Textarea))
) {
};
GdsTextarea = __decorateClass([
  gdsCustomElement("gds-textarea", {
    dependsOn: [
      GdsFormControlHeader,
      GdsFormControlFooter,
      GdsButton,
      GdsFieldBase,
      IconCrossSmall
    ]
  })
], GdsTextarea);
const charCounterCallbackDefault = (self) => {
  const badgeType = (self.value?.length || 0) >= self.maxlength ? "negative" : "positive";
  return [
    self.maxlength - (self.value?.length || 0),
    self.maxlength < Number.MAX_SAFE_INTEGER && badgeType
  ];
};
export {
  GdsTextarea,
  charCounterCallbackDefault
};
