import {
  __decorateClass,
  __privateAdd,
  __privateGet
} from "../../chunks/chunk.QU3DSPNU.js";
var _slotRef, _handleSelect;
import { property } from "lit/decorators.js";
import { createRef, ref } from "lit/directives/ref.js";
import { GdsElement } from "../../gds-element.js";
import { gdsCustomElement, html } from "../../scoping.js";
import { TransitionalStyles } from "../../transitional-styles.js";
import {
  ListboxKbNavController
} from "../../utils/controllers/listbox-kb-nav-controller.js";
import { watch } from "../../utils/decorators/watch.js";
import { unwrap } from "../../utils/helpers/unwrap-slots.js";
import ListboxStyles from "./listbox.styles.js";
import { GdsOption } from "./option.component.js";
let GdsListbox = class extends GdsElement {
  constructor() {
    super();
    this.multiple = false;
    this.compareWith = (a, b) => a === b;
    __privateAdd(this, _slotRef, createRef());
    __privateAdd(this, _handleSelect, (e) => {
      const option = e.target;
      if (this.multiple) option.selected = !option.selected;
      else {
        option.selected = true;
        Array.from(this.options).forEach((el) => {
          if (el !== option) el.selected = false;
        });
      }
      ;
      this.ariaActiveDescendantElement = option;
      this.dispatchCustomEvent("change", {
        bubbles: false,
        composed: false
      });
    });
    new ListboxKbNavController(this);
  }
  get navigableItems() {
    return this.visibleOptionElements;
  }
  /**
   * Returns a list of all `gds-option` elements in the listbox.
   */
  get options() {
    if (!__privateGet(this, _slotRef).value) return [];
    return unwrap(__privateGet(this, _slotRef).value).assignedElements().filter(
      (o) => !o.hasAttribute("isplaceholder") && o.gdsElementName === "gds-option"
    ) || [];
  }
  /**
   * Returns a list of all visible `gds-option` elements in the listbox.
   */
  get visibleOptionElements() {
    return this.options.filter((el) => !el.hidden);
  }
  /**
   * Returns a list of all visible `gds-option` elements in the listbox.
   */
  get visibleSelectedOptionElements() {
    return this.options.filter((el) => el.selected && !el.hidden);
  }
  /**
   * Returns a list of all selected `gds-option` elements in the listbox.
   */
  get selection() {
    return this.options.filter((el) => el.selected);
  }
  set selection(values) {
    this.options.forEach((el) => {
      el.selected = values.some((v) => this.compareWith(v, el.value));
    });
  }
  connectedCallback() {
    super.connectedCallback();
    this.setAttribute("role", "listbox");
    TransitionalStyles.instance.apply(this, "gds-listbox");
    this.addEventListener("gds-select", __privateGet(this, _handleSelect));
  }
  /**
   * Focuses the first selected option in the listbox.
   * If no option is selected, the first visible option is focused.
   */
  focus() {
    ;
    (this.visibleSelectedOptionElements[0] || this.visibleOptionElements[0])?.focus();
  }
  render() {
    return html`<slot ${ref(__privateGet(this, _slotRef))}></slot>`;
  }
  _rerenderOptions() {
    this.options.forEach((el) => {
      el.requestUpdate();
    });
  }
};
_slotRef = new WeakMap();
_handleSelect = new WeakMap();
GdsListbox.styles = ListboxStyles;
__decorateClass([
  property({
    type: Boolean,
    reflect: true,
    attribute: "aria-multiselectable",
    converter: {
      fromAttribute: Boolean,
      toAttribute: (value) => value.toString()
    }
  })
], GdsListbox.prototype, "multiple", 2);
__decorateClass([
  property()
], GdsListbox.prototype, "compareWith", 2);
__decorateClass([
  watch("multiple")
], GdsListbox.prototype, "_rerenderOptions", 1);
GdsListbox = __decorateClass([
  gdsCustomElement("gds-listbox", { dependsOn: [GdsOption] })
], GdsListbox);
export {
  GdsListbox
};
