'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const index = require('./index-305226cb.js');

const bsDropdownCss = ".bs-dropdown-parent{display:inline-block;position:relative}.bs-dropdown{--dropdown-bottom:0;--dropdown-left:0;--dropdown-top:auto;--dropdown-width:100%;background-color:var(--bs-bg-base-elevated);border-radius:4px;bottom:var(--dropdown-bottom);box-shadow:var(--bs-shadow-contentMedium);left:var(--dropdown-left);line-height:1.5rem;margin:0;opacity:0;overflow-y:auto;position:fixed;top:var(--dropdown-top);transform:translateY(100%);transform-origin:center bottom;transition-duration:75ms;transition-property:opacity, transform;transition-timing-function:ease-in-out;width:var(--dropdown-width);z-index:-1}.bs-dropdown>:where(header){border-bottom:1px solid var(--bs-border-base);padding:1.5rem}.bs-dropdown>:where(header) :where(h3){font-size:1.25rem}.bs-dropdown>:where(header) :where(p){font-size:1rem}.bs-dropdown :where(.bs-dropdown-search){padding:1.5rem 1.5rem 0 1.5rem}.bs-dropdown :where(.bs-dropdown-search bs-input-search){margin-bottom:1rem;margin-left:-0.75rem;width:calc(100% + 1.5rem)}.bs-dropdown:where([data-search]) :where(.bs-dropdown-options){--options-height-max:11.5rem}.bs-dropdown:where([data-shown]){opacity:1;transform:translateY(0);z-index:999}@media (min-width: 752px){.bs-dropdown{--dropdown-bottom:var(--dropdown-wscreen-bottom, auto);--dropdown-left:var(--dropdown-wscreen-left, initial);--dropdown-top:var(--dropdown-wscreen-top, calc(100% + 0.5rem));--dropdown-width:var(--dropdown-wscreen-width, initial);position:absolute;transform:initial}.bs-dropdown>:where(header){display:none}.bs-dropdown:where([data-width=\"sm\"]){--dropdown-wscreen-width:10rem}.bs-dropdown:where([data-width=\"md\"]),.bs-dropdown:where(:not([data-width])){--dropdown-wscreen-width:20rem}.bs-dropdown:where([data-width=\"lg\"]){--dropdown-wscreen-width:40rem}.bs-dropdown:where([data-width=\"content\"]){--dropdown-wscreen-width:auto}.bs-dropdown-parent:where([data-width=\"toggle\"]) :where(.bs-dropdown){--dropdown-wscreen-width:100%}.bs-dropdown:where([data-shown]){opacity:1}.bs-dropdown:where([data-top]){--dropdown-wscreen-bottom:calc(100% + 0.5rem);--dropdown-wscreen-top:auto}.bs-dropdown-parent:where([data-center]) :where(.bs-dropdown){--dropdown-wscreen-left:50%;transform:translateX(-50%)}.bs-dropdown :where(.bs-dropdown-options){--options-height-max:20rem}.bs-dropdown:where([data-search]) :where(.bs-dropdown-options){--options-height-max:17.25rem}}bs-dropdown{display:block}";

const BsDropdown = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.close = index.createEvent(this, "close", 7);
    this.enterend = index.createEvent(this, "enterend", 3);
    this.leaveend = index.createEvent(this, "leaveend", 3);
    this.isVisible = false;
    this.width = undefined;
    this.top = false;
    this.center = false;
    this.toggleId = undefined;
    this.containerId = undefined;
    this.helperText = undefined;
    this.helperDescription = undefined;
    this.enterControlled = false;
    this.enterTrigger = false;
    this.leaveTrigger = false;
  }
  componentDidLoad() {
    if (this.containerId) {
      this.containerEl = document.getElementById(this.containerId);
    }
    this.toggleEl = document.getElementById(this.toggleId);
    this.setPosition();
    this.setWidth();
  }
  componentDidUpdate() {
    this.setPosition();
    this.setWidth();
  }
  /**
   * Dynamically set position based on toggle element. Doing this rather than
   * relying on CSS since the dropdown's container could live anywhere on the
   * DOM (in the case of teleporting the dropdown to a higher DOM level).
   *
   * Use custom properties rather than explicit properties to allow for
   * us to ignore them on mobile.
   */
  setPosition() {
    const containerRect = this.containerEl.getBoundingClientRect();
    const toggleRect = this.toggleEl.getBoundingClientRect();
    const dropdownRect = this.dropdownDiv.getBoundingClientRect();
    // Calculate top/bottom position relative to target container
    if (this.top) {
      const bottom = containerRect.bottom - toggleRect.bottom;
      this.dropdownDiv.style.setProperty('--dropdown-wscreen-top', 'auto');
      this.dropdownDiv.style.setProperty('--dropdown-wscreen-bottom', `${bottom + toggleRect.height + 8}px`);
    }
    else {
      const top = toggleRect.top - containerRect.top;
      this.dropdownDiv.style.setProperty('--dropdown-wscreen-top', `${top + toggleRect.height + 8}px`);
      this.dropdownDiv.style.setProperty('--dropdown-wscreen-bottom', 'auto');
    }
    // Calculate left position relative to target container
    const left = toggleRect.left - containerRect.left;
    if (this.center) {
      const offset = (toggleRect.width - dropdownRect.width) / 2;
      this.dropdownDiv.style.setProperty('--dropdown-wscreen-left', `${left + offset}px`);
    }
    else {
      this.dropdownDiv.style.setProperty('--dropdown-wscreen-left', `${left}px`);
    }
  }
  /**
   * Special case when width is "toggle".
   * Dynamically set width based on toggle element. Doing this rather than
   * relying on CSS since the dropdown's container could live anywhere on the
   * DOM (in the case of teleporting the dropdown to a higher DOM level).
   */
  setWidth() {
    if (this.width === 'toggle') {
      const toggleRect = this.toggleEl.getBoundingClientRect();
      this.dropdownDiv.style.setProperty('--dropdown-wscreen-width', `${toggleRect.width}px`);
    }
    else {
      this.dropdownDiv.style.setProperty('--dropdown-wscreen-width', '');
    }
  }
  /** Close the dropdown on Escape key. */
  handleEscape(ev) {
    if (this.isVisible && ev.key === 'Escape') {
      this.close.emit();
    }
  }
  /** Close the dropdown when clicking outside of it or the toggle element. */
  handleClickOutside(ev) {
    if (this.isVisible) {
      const toggleEl = document.getElementById(this.toggleId);
      if (!this.dropdownDiv.contains(ev.target) &&
        !toggleEl.contains(ev.target)) {
        this.close.emit();
      }
    }
  }
  handleEnterEnd() {
    this.isVisible = true;
    this.enterend.emit();
  }
  render() {
    // Don't set data-width in the special 'toggle' width case
    const width = this.width === 'toggle' ? undefined : this.width;
    const dropdownJsx = (index.h("bs-transition", { enterAttribute: "data-shown", enterDuration: 75, enterControlled: this.enterControlled, enterTrigger: this.enterTrigger, leaveTrigger: this.leaveTrigger, onEnterend: () => this.handleEnterEnd(), onLeaveend: () => this.leaveend.emit() }, index.h("div", { class: "bs-dropdown", "data-width": width, ref: (el) => this.dropdownDiv = el }, this.helperText && (index.h("header", null, index.h("h3", null, this.helperText), this.helperDescription && index.h("p", null, this.helperDescription))), index.h("slot", null))));
    return (index.h(index.Host, null, this.containerId && dropdownJsx, !this.containerId && (index.h("div", { style: { position: 'relative' }, ref: (el) => this.containerEl = el }, dropdownJsx))));
  }
  get hostEl() { return index.getElement(this); }
};
BsDropdown.style = bsDropdownCss;

const bsDropdownOptionListCss = ".bs-dropdown-options{list-style:none;margin-bottom:0.25rem;margin-top:0.25rem;max-height:var(--options-height-max, 20rem);overflow-y:auto;padding:0}.bs-dropdown-options :where(li:first-child){margin-top:0.5rem}.bs-dropdown-options :where(li){align-items:center;border-bottom:2px solid transparent;border-left:4px solid transparent;border-radius:3px;border-right:2px solid transparent;border-top:2px solid transparent;color:var(--bs-ink-base);column-gap:0.5rem;cursor:pointer;display:grid;margin-bottom:0.5rem;padding-bottom:0.25rem;padding-left:1.25rem;padding-right:1.375rem;padding-top:0.25rem;row-gap:0.125rem;word-break:break-word;word-wrap:break-word}.bs-dropdown-options :where(li[data-variant~=\"2-col\"]){grid-template-columns:min-content 1fr}.bs-dropdown-options :where(li:not([data-variant~=\"2-col\"])[data-variant~=\"description\"] :nth-child(2)){color:var(--bs-ink-light);font-size:var(--bs-text-xs);min-height:1.125rem;line-height:1.125rem}.bs-dropdown-options :where(li[data-variant~=\"2-col\"][data-variant~=\"description\"] :nth-child(3)){color:var(--bs-ink-light);font-size:var(--bs-text-xs);grid-column-start:2;min-height:1.125rem;line-height:1.125rem}.bs-dropdown-options :where(li:hover),.bs-dropdown-options :where(li[data-selected]){background-color:var(--bs-bg-medium);border-left:4px solid var(--bs-blue-base);color:var(--bs-blue-base);outline:none}.bs-dropdown-options :where(li[data-variant~=\"negative\"]:hover),.bs-dropdown-options :where(li[data-variant~=\"negative\"][data-selected]),.bs-dropdown-options :where(li[data-variant~=\"negative\"][data-selected]:hover){background-color:rgba(248, 169, 170, 0.25);border-left:4px solid var(--bs-red-500);color:var(--bs-red-500)}.bs-dropdown-options :where(li:not([data-variant~=\"2-col\"])[data-variant~=\"description\"]:hover :nth-child(2)),.bs-dropdown-options :where(li[data-variant~=\"2-col\"][data-variant~=\"description\"]:hover :nth-child(3)),.bs-dropdown-options :where(li:not([data-variant~=\"2-col\"])[data-variant~=\"description\"][data-selected] :nth-child(2)),.bs-dropdown-options :where(li[data-variant~=\"2-col\"][data-variant~=\"description\"][data-selected] :nth-child(3)){color:var(--bs-blue-base)}.bs-dropdown-options :where(li[data-variant~=\"negative\"]:not([data-variant~=\"2-col\"])[data-variant~=\"description\"]:hover :nth-child(2)),.bs-dropdown-options :where(li[data-variant~=\"negative\"][data-variant~=\"2-col\"][data-variant~=\"description\"]:hover :nth-child(3)),.bs-dropdown-options :where(li[data-variant~=\"negative\"]:not([data-variant~=\"2-col\"])[data-variant~=\"description\"][data-selected] :nth-child(2)),.bs-dropdown-options :where(li[data-variant~=\"negative\"][data-variant~=\"2-col\"][data-variant~=\"description\"][data-selected] :nth-child(3)){color:var(--bs-red-500)}.bs-dropdown-options :where(li:focus:not(:focus-visible)){outline:none}.bs-dropdown-options :where(li[data-variant~=\"negative\"]:focus:not(:focus-visible)){outline:none}.bs-dropdown-options :where(li:focus-visible){--focus-border-color:var(--bs-blue-base);border:2px solid var(--focus-border-color);outline:none;padding-left:0.625rem}.bs-dropdown-options :where(li[data-selected]:focus-visible){border-left:4px solid var(--focus-border-color);padding-left:0.5rem}.bs-dropdown-options :where(li[data-variant~=\"negative\"]:focus-visible){--focus-border-color:var(--bs-red-200)}@media (min-width: 752px){.bs-dropdown-options :where(li){padding-left:0.5rem;padding-right:0.75rem}.bs-dropdown-options :where(li:focus-visible){padding-left:0.625rem}.bs-dropdown-options :where(li[data-selected]:focus-visible){padding-left:0.5rem}}bs-dropdown-option-list{display:block}";

const BsDropdownOptionList = class {
  constructor(hostRef) {
    index.registerInstance(this, hostRef);
    this.optselected = index.createEvent(this, "optselected", 7);
    this.close = index.createEvent(this, "close", 7);
    /** Track which option is focused */
    this.focusedIndex = -1;
    /** Track selected option */
    this.selectedIndex = -1;
    /** Will observe for child option updates */
    this.mutationObserver = null;
    this.optionsId = undefined;
    this.visible = false;
    this.focusDelay = 75;
    this.label = undefined;
    this.selectedValue = undefined;
    this.activeDescendantId = undefined;
  }
  componentDidLoad() {
    this.passOptionProps();
    // Set selected and focus on mount, if possible
    this.handleVisible();
    this.mutationObserverSetup();
  }
  /** Pass down relevant props */
  passOptionProps() {
    this.optionEls.forEach((el, index) => {
      el.setAttribute('index', String(index));
      // Stencil Vue wrappers have an issue with camelCase props currently
      // So, sending both attributes
      el.setAttribute('options-id', this.optionsId);
      el.setAttribute('optionsid', this.optionsId);
    });
  }
  /** Watch for options being added/removed */
  mutationObserverSetup() {
    this.mutationObserver = new MutationObserver(() => {
      this._optionEls = null;
      this.passOptionProps();
    });
    this.mutationObserver.observe(this.optionsEl, { childList: true });
  }
  disconnectedCallback() {
    var _a, _b;
    // Clean up mutation observer
    (_b = (_a = this.mutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect) === null || _b === void 0 ? void 0 : _b.call(_a);
    this.mutationObserver = null;
  }
  /** Get the dropdown option elements. */
  get optionEls() {
    if (!this._optionEls) {
      const els = this.optionsEl.querySelectorAll('bs-dropdown-option');
      this._optionEls = Array.from(els);
    }
    return this._optionEls;
  }
  /** Removes focus from the currently focused option, if applicable */
  removeCurrentFocus() {
    var _a;
    if (this.focusedIndex > -1) {
      (_a = this.optionEls[this.focusedIndex]) === null || _a === void 0 ? void 0 : _a.removeAttribute('focused');
    }
  }
  /** Handles all applicable navigation key presses for dropdown accessibility */
  handleKeyDown(ev) {
    if (this.visible) {
      switch (ev.key) {
        case 'ArrowDown':
          this.traverse('down');
          ev.preventDefault();
          break;
        case 'ArrowUp':
          this.traverse('up');
          ev.preventDefault();
          break;
        case 'Home':
          this.traverse('home');
          ev.preventDefault();
          break;
        case 'End':
          this.traverse('end');
          ev.preventDefault();
          break;
        case 'Tab':
          // Prevent tab from doing anything while dropdown is open
          ev.preventDefault();
          break;
      }
    }
  }
  /** Traverses focus of the option list via keyboard navigation */
  traverse(direction) {
    let newIndex;
    switch (direction) {
      case 'up':
        newIndex = (this.focusedIndex - 1 < 0) ?
          this.optionEls.length - 1 :
          this.focusedIndex - 1;
        break;
      case 'down':
        newIndex = (this.focusedIndex + 1) % this.optionEls.length;
        break;
      case 'home':
        newIndex = 0;
        break;
      case 'end':
        newIndex = this.optionEls.length - 1;
        break;
    }
    this.removeCurrentFocus();
    this.optionEls[newIndex].setAttribute('focused', 'true');
    this.focusedIndex = newIndex;
  }
  /** Handles moving focus on mouse hover */
  handleMouseFocus(ev) {
    if (this.visible) {
      this.removeCurrentFocus();
      this.focusedIndex = ev.detail;
    }
  }
  /**
   * Handles selection by updating various internal states and emitting to
   * parent
   */
  handleSelect(ev) {
    this.activeDescendantId = ev.detail.id;
    this.optselected.emit(ev.detail.value);
    this.removeCurrentFocus();
    this.close.emit();
  }
  /** Focuses and sets selected on a selected option on when visible */
  handleVisible() {
    var _a, _b, _c;
    if (this.visible) {
      // Find selected index
      this.selectedIndex = this.optionEls.findIndex((el) => el.getAttribute('value') === this.selectedValue);
      // Set selected / focused when applicable
      if (this.selectedIndex > -1) {
        (_a = this.optionEls[this.selectedIndex]) === null || _a === void 0 ? void 0 : _a.setAttribute('selected', 'true');
        this.focusedIndex = this.selectedIndex;
        if (this.focusDelay > 0) {
          setTimeout(() => {
            var _a;
            (_a = this.optionEls[this.selectedIndex]) === null || _a === void 0 ? void 0 : _a.setAttribute('focused', 'true');
          }, this.focusDelay);
        }
        else {
          (_b = this.optionEls[this.selectedIndex]) === null || _b === void 0 ? void 0 : _b.setAttribute('focused', 'true');
        }
      }
    }
    else {
      // Clear out selected item when not visible
      (_c = this.optionEls[this.selectedIndex]) === null || _c === void 0 ? void 0 : _c.removeAttribute('selected');
    }
  }
  render() {
    return (index.h(index.Host, null, index.h("ul", { class: "bs-dropdown-options", role: "listbox", id: this.optionsId, "aria-label": this.label || undefined, "aria-activedescendant": this.activeDescendantId || undefined, ref: el => this.optionsEl = el }, index.h("slot", null))));
  }
  get hostEl() { return index.getElement(this); }
  static get watchers() { return {
    "visible": ["handleVisible"]
  }; }
};
BsDropdownOptionList.style = bsDropdownOptionListCss;

exports.bs_dropdown = BsDropdown;
exports.bs_dropdown_option_list = BsDropdownOptionList;

//# sourceMappingURL=bs-dropdown_2.cjs.entry.js.map