/**
 * Copyright IBM Corp. 2026
 *
 * This source code is licensed under the Apache-2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 */

import "../../globals/settings.js";
import { filter } from "../../globals/internal/collection-helpers.js";
import { carbonElement } from "../../globals/decorators/carbon-element.js";
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.js";
import iconLoader from "../../globals/internal/icon-loader.js";
import FormMixin from "../../globals/mixins/form.js";
import if_non_empty_default from "../../globals/directives/if-non-empty.js";
import select_default$1 from "./select.scss.js";
import { LitElement, html } from "lit";
import { property, query, queryAll } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { ifDefined } from "lit/directives/if-defined.js";
import WarningFilled16 from "@carbon/icons/es/warning--filled/16.js";
import WarningAltFilled16 from "@carbon/icons/es/warning--alt--filled/16.js";
import ChevronDown16 from "@carbon/icons/es/chevron--down/16.js";
//#region src/components/select/select.ts
/**
* Copyright IBM Corp. 2020, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Select box.
*
* @element cds-select
* @fires cds-select-selected
*   The name of the custom event fired after an item is selected.
* @slot helper-text - The helper text.
* @slot label-text - The label text.
* @slot validity-message - The validity message. If present and non-empty, this input shows the UI of its invalid state.
*/
let CDSSelect = class CDSSelect extends FormMixin(LitElement) {
	constructor(..._args) {
		super(..._args);
		this._hasAILabel = false;
		this._observerMutation = null;
		this._placeholderItemValue = `__cds-select-placeholder_${Math.random().toString(36).slice(2)}`;
		this.isFluid = false;
		this._handleMutation = () => {
			this.requestUpdate();
		};
		this.autofocus = false;
		this.disabled = false;
		this.helperText = "";
		this.hideLabel = false;
		this.id = "select";
		this.invalid = false;
		this.invalidText = "";
		this.warn = false;
		this.warnText = "";
		this.labelText = "";
		this.labelStylesDisable = false;
		this.inline = false;
		this.name = "";
		this.pattern = "";
		this.placeholder = "";
		this.readonly = false;
		this.required = false;
		this.requiredValidityMessage = "Please fill out this field.";
		this.value = "";
	}
	/**
	* Handles `oninput` event on the `<input>`.
	*
	* @param event The event.
	* @param event.target The event target.
	*/
	_handleInput({ target }) {
		const { value } = target;
		this.value = value;
		const { eventSelect } = this.constructor;
		this.dispatchEvent(new CustomEvent(eventSelect, {
			bubbles: true,
			composed: true,
			detail: { value }
		}));
	}
	/**
	* @param element The parent element containing pseudo `<optgroup>`/`<option>`.
	* @returns The template containing child `<optgroup>`/`<option>` that will be rendered to shadow DOM.
	*/
	_renderItems(element) {
		const { selectorItem, selectorLeafItem } = this.constructor;
		return html`
      ${filter(element.childNodes, (item) => item.nodeType === Node.ELEMENT_NODE && item.matches(selectorItem)).map((item) => {
			const disabled = item.hasAttribute("disabled");
			const label = item.getAttribute("label");
			const selected = item.hasAttribute("selected");
			const value = item.getAttribute("value");
			const { textContent } = item;
			return item.matches(selectorLeafItem) ? html`
              <option
                class="${"cds"}--select-option"
                ?disabled="${disabled}"
                label="${if_non_empty_default(label)}"
                ?selected="${selected}"
                value="${ifDefined(value)}">
                ${textContent}
              </option>
            ` : html`
              <optgroup
                class="${"cds"}--select-optgroup"
                ?disabled="${disabled}"
                label="${ifDefined(label)}">
                ${this._renderItems(item)}
              </optgroup>
            `;
		})}
    `;
	}
	_handleFormdata(event) {
		const { formData } = event;
		const { disabled, name, value } = this;
		if (!disabled) formData.append(name, value);
	}
	/**
	* Handles `slotchange` event.
	*/
	_handleAILabelSlotChange({ target }) {
		const hasContent = target.assignedNodes().filter((elem) => elem.matches !== void 0 ? elem.matches(this.constructor.aiLabelItem) || elem.matches(this.constructor.slugItem) : false);
		this._hasAILabel = Boolean(hasContent);
		this.setAttribute("slug", `${this._hasAILabel}`);
		hasContent[0].setAttribute("size", "mini");
		this.requestUpdate();
	}
	/**
	* The count of child `<option>`s.
	* If the placeholder is in effect, it includes the `<option>` for the placeholder.
	*/
	get length() {
		return this._selectNode.length;
	}
	/**
	* The child `<option>`s.
	*/
	get options() {
		return this._selectNode.options;
	}
	/**
	* This form control's type.
	*/
	get type() {
		return this._selectNode.type;
	}
	/**
	* `true` to enable multiple selection.
	*/
	get multiple() {
		return false;
	}
	/**
	* The selected index.
	*/
	get selectedIndex() {
		return this._selectNode?.selectedIndex;
	}
	set selectedIndex(value) {
		this._selectNode.selectedIndex = value;
		this.value = this._selectNode.value;
	}
	connectedCallback() {
		super.connectedCallback();
		this._observerMutation = new MutationObserver(this._handleMutation);
		this._observerMutation.observe(this, {
			attributes: true,
			childList: true,
			subtree: true
		});
	}
	disconnectedCallback() {
		if (this._observerMutation) {
			this._observerMutation.disconnect();
			this._observerMutation = null;
		}
		super.disconnectedCallback();
	}
	updated(changedProperties) {
		if (changedProperties.has("value")) {
			const { value, _placeholderItemValue: placeholderItemValue } = this;
			const lastOption = this._selectedOptionNodes?.[this._selectedOptionNodes?.length - 1]?.["value"];
			if (value) this._selectNode.value = value;
			else if (lastOption) this._selectNode.value = lastOption;
			else this._selectNode.value = placeholderItemValue;
		}
		const label = this.shadowRoot?.querySelector("slot[name='ai-label']");
		if (label) {
			if (label.assignedNodes()?.length) this._selectNode?.classList.add(`cds--select-input-has--ai-label`);
			label?.classList.toggle(`cds--slug--revert`, this.querySelector(`cds-ai-label`)?.hasAttribute("revert-active"));
		} else this.shadowRoot?.querySelector("slot[name='slug']")?.classList.toggle(`cds--slug--revert`, this.querySelector(`cds-slug`)?.hasAttribute("revert-active"));
	}
	render() {
		const { disabled, helperText, hideLabel, id, inline, invalid, invalidText, labelStylesDisable, labelText, placeholder, readonly, size, warn, warnText, value, _placeholderItemValue: placeholderItemValue, _handleInput: handleInput, _handleAILabelSlotChange: handleAILabelSlotChange } = this;
		const normalizedProps = {
			disabled: !readonly && disabled,
			invalid: !readonly && !disabled && invalid,
			warn: !readonly && !invalid && !disabled && warn
		};
		const inputClasses = classMap({
			[`cds--select-input`]: true,
			[`cds--select-input--${size}`]: size !== void 0
		});
		const labelClasses = classMap({
			[`cds--label`]: !labelStylesDisable,
			[`cds--label--disabled`]: normalizedProps.disabled,
			[`cds--visually-hidden`]: hideLabel
		});
		const helperTextClasses = classMap({
			[`cds--form__helper-text`]: true,
			[`cds--form__helper-text--disabled`]: normalizedProps.disabled
		});
		const supplementalText = helperText ? html`
          <div id="helper-text" class="${helperTextClasses}">
            <slot name="helper-text"> ${helperText} </slot>
          </div>
        ` : null;
		const errorText = normalizedProps.invalid || normalizedProps.warn ? html` <div id="error-text" class="${"cds"}--form-requirement">
            ${normalizedProps.invalid ? invalidText : warnText}
          </div>` : null;
		let describedBy;
		if (normalizedProps.invalid || normalizedProps.warn) describedBy = "error-text";
		else if (helperText) describedBy = "helper-text";
		const input = html`
      <select
        id="${id}"
        class="${inputClasses}"
        ?disabled="${disabled}"
        title="${value}"
        aria-readonly="${String(readonly)}"
        aria-invalid="${String(normalizedProps.invalid)}"
        aria-describedby="${ifDefined(describedBy)}"
        @input="${handleInput}">
        ${!placeholder || value ? void 0 : html`
              <option
                disabled
                hidden
                class="${"cds"}--select-option"
                value="${placeholderItemValue}">
                ${placeholder}
              </option>
            `}
        ${this._renderItems(this)}
      </select>
      ${iconLoader(ChevronDown16, {
			class: `cds--select__arrow`,
			"aria-hidden": "true"
		})}
      <slot
        name="ai-label"
        style="--${"cds"}-show-before: ${normalizedProps.warn || normalizedProps.invalid ? "block" : "none"}"
        @slotchange=${handleAILabelSlotChange}></slot>
      <slot name="slug" @slotchange=${handleAILabelSlotChange}></slot>
      ${!normalizedProps.invalid ? void 0 : iconLoader(WarningFilled16, { class: `cds--select__invalid-icon` })}
      ${!normalizedProps.invalid && normalizedProps.warn ? iconLoader(WarningAltFilled16, { class: `cds--select__invalid-icon cds--select__invalid-icon--warning` }) : null}
    `;
		return html`
      <label class="${labelClasses}" for=${id}>
        <slot name="label-text">${labelText}</slot>
      </label>

      ${inline ? html`<div
            class="${"cds"}--select-input--inline__wrapper"
            ?data-invalid="${normalizedProps.invalid}">
            <div
              class="${"cds"}--select-input__wrapper"
              ?data-invalid="${normalizedProps.invalid}">
              ${input}
            </div>
          </div>` : html`<div
            class="${"cds"}--select-input__wrapper"
            ?data-invalid="${normalizedProps.invalid}">
            ${input}
            ${this.isFluid ? html`
                  <hr class="${"cds"}--select__divider" />
                  ${errorText ? errorText : null}
                ` : null}
          </div> `}
      ${!this.isFluid && errorText ? errorText : supplementalText}
    `;
	}
	/**
	* A selector selecting child pseudo `<optgroup>`/`<option>`.
	*/
	static get selectorItem() {
		return `cds-select-item-group,cds-select-item`;
	}
	/**
	* A selector selecting child pseudo `<option>`.
	*/
	static get selectorLeafItem() {
		return `cds-select-item`;
	}
	/**
	* A selector that will return the slug item.
	*
	* remove in v12
	*/
	static get slugItem() {
		return `cds-slug`;
	}
	/**
	* A selector that will return the AI Label item.
	*/
	static get aiLabelItem() {
		return `cds-ai-label`;
	}
	/**
	* The name of the custom event fired after item is selected.
	*/
	static get eventSelect() {
		return `cds-select-selected`;
	}
	static {
		this.shadowRootOptions = {
			...LitElement.shadowRootOptions,
			delegatesFocus: true
		};
	}
	static {
		this.styles = select_default$1;
	}
};
__decorate([query("select")], CDSSelect.prototype, "_selectNode", void 0);
__decorate([queryAll(`.cds--select-option[selected]`)], CDSSelect.prototype, "_selectedOptionNodes", void 0);
__decorate([property({ type: Boolean })], CDSSelect.prototype, "isFluid", void 0);
__decorate([property({ type: Boolean })], CDSSelect.prototype, "autofocus", void 0);
__decorate([property({
	type: Boolean,
	reflect: true
})], CDSSelect.prototype, "disabled", void 0);
__decorate([property({ attribute: "helper-text" })], CDSSelect.prototype, "helperText", void 0);
__decorate([property({
	type: Boolean,
	attribute: "hide-label"
})], CDSSelect.prototype, "hideLabel", void 0);
__decorate([property()], CDSSelect.prototype, "id", void 0);
__decorate([property({
	type: Boolean,
	reflect: true
})], CDSSelect.prototype, "invalid", void 0);
__decorate([property({ attribute: "invalid-text" })], CDSSelect.prototype, "invalidText", void 0);
__decorate([property({
	type: Boolean,
	reflect: true
})], CDSSelect.prototype, "warn", void 0);
__decorate([property({ attribute: "warn-text" })], CDSSelect.prototype, "warnText", void 0);
__decorate([property({ attribute: "label-text" })], CDSSelect.prototype, "labelText", void 0);
__decorate([property({
	type: Boolean,
	attribute: "label-styles-disable"
})], CDSSelect.prototype, "labelStylesDisable", void 0);
__decorate([property({
	type: Boolean,
	reflect: true
})], CDSSelect.prototype, "inline", void 0);
__decorate([property({ type: Boolean })], CDSSelect.prototype, "multiple", null);
__decorate([property()], CDSSelect.prototype, "name", void 0);
__decorate([property()], CDSSelect.prototype, "pattern", void 0);
__decorate([property({ reflect: true })], CDSSelect.prototype, "placeholder", void 0);
__decorate([property({
	type: Boolean,
	reflect: true
})], CDSSelect.prototype, "readonly", void 0);
__decorate([property({
	type: Boolean,
	reflect: true
})], CDSSelect.prototype, "required", void 0);
__decorate([property({ attribute: "required-validity-message" })], CDSSelect.prototype, "requiredValidityMessage", void 0);
__decorate([property({ type: Number })], CDSSelect.prototype, "selectedIndex", null);
__decorate([property({ reflect: true })], CDSSelect.prototype, "size", void 0);
__decorate([property({ reflect: true })], CDSSelect.prototype, "value", void 0);
CDSSelect = __decorate([carbonElement(`cds-select`)], CDSSelect);
var select_default = CDSSelect;
//#endregion
export { select_default as default };

//# sourceMappingURL=select.js.map