/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { C as CSS_UTILITY, c as customElement } from "../../chunks/runtime.js";
import { ref } from "lit/directives/ref.js";
import { keyed } from "lit/directives/keyed.js";
import { a as calciteSize24, b as calciteSize32, d as calciteSize44 } from "../../chunks/core.js";
import { css, html } from "lit";
import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina";
import { useDirection } from "@arcgis/lumina/controllers";
import { C as filterDirectChildren, f as focusElementInGroup, i as focusElement } from "../../chunks/dom.js";
import { c as createObserver } from "../../chunks/observers.js";
import { u as useT9n } from "../../chunks/useT9n.js";
const ICON = {
  chevronRight: "chevron-right",
  chevronLeft: "chevron-left"
};
const CSS = {
  container: "container",
  scrollButton: "scroll-button",
  scrollButtonContainer: "scroll-button-container",
  scrollBackwardButton: "scroll-button--backward",
  scrollForwardButton: "scroll-button--forward",
  tabTitleSlotWrapper: "tab-titles-slot-wrapper",
  scale: (scale) => `scale-${scale}`,
  position: (position) => `position-${position}`
};
const styles = css`:host{position:relative;display:flex}:host([bordered]) .scroll-button--forward calcite-button{--calcite-internal-button-border-inline-end-color: var(--calcite-tab-border-color, var(--calcite-color-border-1))}:host([bordered]) .scroll-button--backward calcite-button{--calcite-internal-button-border-inline-start-color: var( --calcite-tab-border-color, var(--calcite-color-border-1) )}.scale-s{--calcite-internal-tab-nav-button-width: 24px;min-block-size:1.5rem}.scale-m{--calcite-internal-tab-nav-button-width: 32px;min-block-size:2rem}.scale-l{--calcite-internal-tab-nav-button-width: 44px;min-block-size:2.75rem}.container::-webkit-scrollbar{display:none;-ms-overflow-style:none;scrollbar-width:none}:host([layout=center]) ::slotted(calcite-tab-title){display:flex;flex-grow:1;flex-shrink:0;min-inline-size:auto;white-space:nowrap}:host([layout=center]) ::slotted(calcite-tab-title[selected]){overflow:unset}:host(:not([bordered])) .scale-l{--calcite-internal-tab-nav-gap: var(--calcite-spacing-xxl)}:host(:not([bordered])) .scale-m{--calcite-internal-tab-nav-gap: var(--calcite-spacing-xl)}:host(:not([bordered])) .scale-s{--calcite-internal-tab-nav-gap: var(--calcite-spacing-lg)}:host(:not([bordered])) .tab-titles-slot-wrapper{gap:var(--calcite-internal-tab-nav-gap)}:host([layout=center]:not([bordered])) .tab-titles-slot-wrapper{padding-inline:var(--calcite-spacing-xl)}.tab-titles-slot-wrapper{flex:1 1 0%}.container,.tab-titles-slot-wrapper{display:flex;inline-size:100%;justify-content:flex-start;overflow:hidden;white-space:nowrap}.scroll-button{position:absolute;inset-block:0px}.scroll-button calcite-button{--calcite-button-text-color: var(--calcite-tab-text-color, var(--calcite-color-text-3));--calcite-button-background-color: var(--calcite-color-transparent);--calcite-offset-invert-focus: 1;block-size:var(--calcite-container-size-content-fluid)}.scroll-button-container{display:flex;inset-block-start:var(--calcite-border-width-md);inset-block-end:var(--calcite-border-width-md);inset-inline-end:0;inline-size:calc(2 * var(--calcite-internal-tab-nav-button-width))}.scroll-button--forward{inset-inline-end:0;z-index:var(--calcite-z-index)}.scroll-button--backward{inset-inline-end:var(--calcite-internal-tab-nav-button-width);z-index:var(--calcite-z-index)}:host(:not([bordered])) .scroll-button--backward:before{background-color:var(--calcite-tab-border-color, var(--calcite-color-border-3));content:"";inline-size:var(--calcite-border-width-sm);inset-block-start:var(--calcite-border-width-md);inset-block-end:var(--calcite-border-width-md);position:absolute;inset-inline-start:0}:host([hidden]){display:none}[hidden]{display:none}`;
class TabNav extends LitElement {
  constructor() {
    super();
    this.direction = useDirection();
    this.effectiveDir = "ltr";
    this.lastScrollWheelAxis = "x";
    this.resizeObserver = createObserver("resize", () => {
      this.updateScrollingState();
    });
    this.makeFirstVisibleTabClosable = false;
    this.messages = useT9n();
    this.hasOverflowingEndTabTitle = false;
    this.hasOverflowingStartTabTitle = false;
    this.bordered = false;
    this.layout = "inline";
    this.position = "bottom";
    this.scale = "m";
    this.selectedTitle = null;
    this.calciteInternalTabChange = createEvent({ cancelable: false });
    this.calciteInternalTabNavSlotChange = createEvent();
    this.calciteTabChange = createEvent({ cancelable: false });
    this.listen("calciteInternalTabsFocusPrevious", this.focusPreviousTabHandler);
    this.listen("calciteInternalTabsFocusNext", this.focusNextTabHandler);
    this.listen("calciteInternalTabsFocusFirst", this.focusFirstTabHandler);
    this.listen("calciteInternalTabsFocusLast", this.focusLastTabHandler);
    this.listen("calciteInternalTabTitleRegister", this.updateTabTitles);
    this.listen("calciteInternalTabsActivate", this.internalActivateTabHandler);
    this.listen("calciteInternalTabsClose", this.internalCloseTabHandler);
    this.listenOn(document.body, "calciteInternalTabChange", this.globalInternalTabChangeHandler);
  }
  static {
    this.properties = { hasOverflowingEndTabTitle: [16, {}, { state: true }], hasOverflowingStartTabTitle: [16, {}, { state: true }], selectedTabId: [16, {}, { state: true }], bordered: [7, {}, { reflect: true, type: Boolean }], layout: [3, {}, { reflect: true }], messageOverrides: [0, {}, { attribute: false }], position: 1, scale: 1, selectedTitle: [0, {}, { attribute: false }], storageId: [3, {}, { reflect: true }], syncId: [3, {}, { reflect: true }] };
  }
  static {
    this.styles = styles;
  }
  connectedCallback() {
    super.connectedCallback();
    this.parentTabsEl = this.el.closest("calcite-tabs") ?? void 0;
    this.resizeObserver?.observe(this.el);
  }
  async load() {
    const storageKey = `calcite-tab-nav-${this.storageId}`;
    if (localStorage && this.storageId) {
      const storageItem = localStorage.getItem(storageKey);
      if (storageItem) {
        const storedTab = JSON.parse(storageItem);
        this.selectedTabId = storedTab;
      }
    }
  }
  willUpdate(changes) {
    if (changes.has("selectedTitle") && (this.hasUpdated || this.selectedTitle !== null)) {
      this.calciteInternalTabChange.emit({
        tab: this.selectedTabId
      });
    }
    if (changes.has("selectedTabId")) {
      this.selectedTabIdChanged();
    }
    const { parentTabsEl } = this;
    if (parentTabsEl) {
      this.layout = parentTabsEl.layout;
      this.bordered = parentTabsEl.bordered;
    }
    this.effectiveDir = this.direction;
  }
  loaded() {
    this.scrollTabTitleIntoView(this.selectedTitle, "instant");
    if (this.tabTitles.length && this.tabTitles.every((title) => !title.selected) && !this.selectedTabId) {
      this.tabTitles[0].getTabIdentifier().then((tab) => {
        this.calciteInternalTabChange.emit({
          tab
        });
      });
    }
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    this.resizeObserver?.disconnect();
  }
  get enabledTabTitles() {
    return filterDirectChildren(this.el, "calcite-tab-title:not([disabled])").filter((tabTitle) => !tabTitle.closed);
  }
  get scrollerButtonWidth() {
    const { scale } = this;
    return parseInt(scale === "s" ? calciteSize24 : scale === "m" ? calciteSize32 : calciteSize44);
  }
  get tabTitles() {
    return filterDirectChildren(this.el, "calcite-tab-title");
  }
  focusPreviousTabHandler(event) {
    this.handleTabFocus(event, event.target, "previous");
  }
  focusNextTabHandler(event) {
    this.handleTabFocus(event, event.target, "next");
  }
  focusFirstTabHandler(event) {
    this.handleTabFocus(event, event.target, "first");
  }
  focusLastTabHandler(event) {
    this.handleTabFocus(event, event.target, "last");
  }
  internalActivateTabHandler(event) {
    const activatedTabTitle = event.target;
    const currentSelectedTabTitle = this.selectedTitle;
    this.selectedTabId = event.detail.tab ? event.detail.tab : this.getIndexOfTabTitle(activatedTabTitle);
    event.stopPropagation();
    this.selectedTitle = activatedTabTitle;
    if (currentSelectedTabTitle?.id !== activatedTabTitle.id && event.detail.userTriggered) {
      this.calciteTabChange.emit();
    }
    this.scrollTabTitleIntoView(activatedTabTitle);
  }
  scrollTabTitleIntoView(activatedTabTitle, behavior = "smooth") {
    if (!activatedTabTitle) {
      return;
    }
    requestAnimationFrame(() => {
      const tabTitleContainer = this.tabTitleContainerEl;
      if (!tabTitleContainer) {
        return;
      }
      const containerBounds = tabTitleContainer.getBoundingClientRect();
      const tabTitleBounds = activatedTabTitle.getBoundingClientRect();
      const scrollPosition = tabTitleContainer.scrollLeft;
      if (tabTitleBounds.left < containerBounds.left) {
        const left = scrollPosition + (tabTitleBounds.left - containerBounds.left);
        tabTitleContainer.scrollTo({ left, behavior });
      } else if (tabTitleBounds.right > containerBounds.right) {
        const left = scrollPosition + (tabTitleBounds.right - containerBounds.right);
        tabTitleContainer.scrollTo({ left, behavior });
      }
    });
  }
  internalCloseTabHandler(event) {
    const closedTabTitleEl = event.target;
    this.handleTabTitleClose(closedTabTitleEl);
    event.stopPropagation();
  }
  async updateTabTitles(event) {
    if (event.target.selected) {
      this.selectedTabId = event.detail;
      this.selectedTitle = await this.getTabTitleById(this.selectedTabId);
    }
  }
  globalInternalTabChangeHandler(event) {
    if (this.syncId && event.target !== this.el && event.target.syncId === this.syncId && this.selectedTabId !== event.detail.tab) {
      this.selectedTabId = event.detail.tab;
    }
    event.stopPropagation();
  }
  async selectedTabIdChanged() {
    await this.componentOnReady();
    if (localStorage && this.storageId && this.selectedTabId !== void 0 && this.selectedTabId !== null) {
      localStorage.setItem(`calcite-tab-nav-${this.storageId}`, JSON.stringify(this.selectedTabId));
    }
    this.calciteInternalTabChange.emit({
      tab: this.selectedTabId
    });
  }
  onTabTitleWheel(event) {
    event.preventDefault();
    const { deltaX, deltaY } = event;
    const x = Math.abs(deltaX);
    const y = Math.abs(deltaY);
    let scrollBy;
    if (x === y) {
      scrollBy = this.lastScrollWheelAxis === "x" ? deltaX : deltaY;
    } else if (x > y) {
      scrollBy = deltaX;
      this.lastScrollWheelAxis = "x";
    } else {
      scrollBy = deltaY;
      this.lastScrollWheelAxis = "y";
    }
    const scrollByX = (this.effectiveDir === "rtl" ? -1 : 1) * scrollBy;
    event.currentTarget.scrollBy(scrollByX, 0);
  }
  onSlotChange() {
    this.intersectionObserver?.disconnect();
    const tabTitles = this.tabTitles;
    tabTitles.forEach((child) => {
      this.intersectionObserver?.observe(child);
    });
    const visibleTabTitlesIndices = this.getVisibleTabTitlesIndices(tabTitles);
    const totalVisibleTabTitles = visibleTabTitlesIndices.length;
    if (totalVisibleTabTitles > 1 && this.makeFirstVisibleTabClosable) {
      tabTitles[visibleTabTitlesIndices[0]].closable = true;
      this.makeFirstVisibleTabClosable = false;
    }
    this.calciteInternalTabNavSlotChange.emit(tabTitles);
  }
  setTabTitleContainerEl(el) {
    this.tabTitleContainerEl = el;
    this.intersectionObserver?.disconnect();
    if (el) {
      this.intersectionObserver = createObserver("intersection", () => this.updateScrollingState(), {
        root: el,
        threshold: [0, 0.5, 1]
      });
    }
  }
  updateScrollingState() {
    const tabTitleContainer = this.tabTitleContainerEl;
    if (!tabTitleContainer) {
      return;
    }
    let isOverflowStart;
    let isOverflowEnd;
    const scrollPosition = tabTitleContainer.scrollLeft;
    const visibleWidth = tabTitleContainer.clientWidth;
    const totalContentWidth = tabTitleContainer.scrollWidth;
    if (this.effectiveDir === "ltr") {
      isOverflowStart = scrollPosition > 0;
      isOverflowEnd = scrollPosition + visibleWidth < totalContentWidth;
    } else {
      isOverflowStart = scrollPosition < 0;
      isOverflowEnd = scrollPosition !== -(totalContentWidth - visibleWidth);
    }
    this.hasOverflowingStartTabTitle = isOverflowStart;
    this.hasOverflowingEndTabTitle = isOverflowEnd;
  }
  scrollToTabTitles(direction) {
    requestAnimationFrame(() => {
      const tabTitleContainer = this.tabTitleContainerEl;
      if (!tabTitleContainer) {
        return;
      }
      const containerBounds = tabTitleContainer.getBoundingClientRect();
      const tabTitles = Array.from(this.el.querySelectorAll("calcite-tab-title"));
      const { effectiveDir } = this;
      if (direction === "forward") {
        tabTitles.reverse();
      }
      let closestToEdge = null;
      tabTitles.forEach((tabTitle) => {
        const tabTitleBounds = tabTitle.getBoundingClientRect();
        const containerEndX = containerBounds.x + containerBounds.width;
        const tabTitleEndX = tabTitleBounds.x + tabTitleBounds.width;
        if (direction === "forward" && effectiveDir === "ltr" || direction === "backward" && effectiveDir === "rtl") {
          const afterContainerEnd = tabTitleBounds.x > containerEndX;
          if (afterContainerEnd) {
            closestToEdge = tabTitle;
          } else {
            const crossingContainerEnd = tabTitleEndX > containerEndX && tabTitleBounds.x > containerBounds.x;
            if (crossingContainerEnd) {
              closestToEdge = tabTitle;
            }
          }
        } else {
          const beforeContainerStart = tabTitleEndX < containerBounds.x;
          if (beforeContainerStart) {
            closestToEdge = tabTitle;
          } else {
            const crossingContainerStart = tabTitleBounds.x < containerBounds.x && tabTitleEndX > containerBounds.x;
            if (crossingContainerStart) {
              closestToEdge = tabTitle;
            }
          }
        }
      });
      let scrollTo;
      if (closestToEdge) {
        const scrollerButtonContainerWidth = 2 * this.scrollerButtonWidth;
        const offsetAdjustment = direction === "forward" && effectiveDir === "ltr" || direction === "backward" && effectiveDir === "rtl" ? -scrollerButtonContainerWidth : closestToEdge.offsetWidth - (tabTitleContainer.clientWidth + scrollerButtonContainerWidth);
        scrollTo = closestToEdge.offsetLeft + offsetAdjustment;
      } else {
        const scrollPosition = tabTitleContainer.scrollLeft;
        const containerWidth = containerBounds.width;
        const totalContentWidth = tabTitleContainer.scrollWidth;
        const hiddenContentWidth = totalContentWidth - (containerWidth + Math.abs(scrollPosition));
        if (hiddenContentWidth > 0) {
          const directionMultiplier = effectiveDir === "ltr" ? 1 : -1;
          scrollTo = scrollPosition + directionMultiplier * hiddenContentWidth;
        }
      }
      tabTitleContainer.scrollTo({
        left: scrollTo,
        behavior: "smooth"
      });
    });
  }
  scrollToNextTabTitles() {
    this.scrollToTabTitles("forward");
  }
  scrollToPreviousTabTitles() {
    this.scrollToTabTitles("backward");
  }
  handleTabFocus(event, el, destination) {
    const focused = focusElementInGroup(this.enabledTabTitles, el, destination);
    this.scrollTabTitleIntoView(focused, "instant");
    event.stopPropagation();
  }
  getIndexOfTabTitle(el, tabTitles = this.tabTitles) {
    return tabTitles.indexOf(el);
  }
  onTabTitleScroll() {
    this.updateScrollingState();
  }
  async getTabTitleById(id) {
    return Promise.all(this.tabTitles.map((el) => el.getTabIdentifier())).then((ids) => {
      return this.tabTitles[ids.indexOf(id)];
    });
  }
  getVisibleTabTitlesIndices(tabTitles) {
    return tabTitles.reduce((tabTitleIndices, tabTitle, index) => !tabTitle.closed ? [...tabTitleIndices, index] : tabTitleIndices, []);
  }
  handleTabTitleClose(closedTabTitleEl) {
    const { tabTitles } = this;
    const selectionModified = closedTabTitleEl.selected;
    const visibleTabTitlesIndices = this.getVisibleTabTitlesIndices(tabTitles);
    const totalVisibleTabTitles = visibleTabTitlesIndices.length;
    if (totalVisibleTabTitles === 1 && tabTitles[visibleTabTitlesIndices[0]].closable) {
      this.makeFirstVisibleTabClosable = true;
      tabTitles[visibleTabTitlesIndices[0]].closable = false;
      this.selectedTabId = visibleTabTitlesIndices[0];
      if (selectionModified) {
        tabTitles[visibleTabTitlesIndices[0]].activateTab();
      }
    } else if (totalVisibleTabTitles > 1) {
      const closedTabTitleIndex = tabTitles.findIndex((el) => el === closedTabTitleEl);
      const nextTabTitleIndex = visibleTabTitlesIndices.find((value) => value > closedTabTitleIndex);
      if (this.selectedTabId === closedTabTitleIndex) {
        this.selectedTabId = nextTabTitleIndex ? nextTabTitleIndex : totalVisibleTabTitles - 1;
        tabTitles[this.selectedTabId].activateTab();
      }
    }
    requestAnimationFrame(() => {
      focusElement(tabTitles[this.selectedTabId]);
    });
  }
  render() {
    this.el.role = "tablist";
    return html`<div class=${safeClassMap({
      [CSS.container]: true,
      [CSS.scale(this.scale)]: true,
      [CSS.position(this.position)]: true,
      [CSS_UTILITY.rtl]: this.effectiveDir === "rtl"
    })}><div class=${safeClassMap({
      [CSS.tabTitleSlotWrapper]: true
    })} @scroll=${this.onTabTitleScroll} @wheel=${this.onTabTitleWheel} ${ref(this.setTabTitleContainerEl)}><slot @slotchange=${this.onSlotChange}></slot></div><div class=${safeClassMap(CSS.scrollButtonContainer)} .hidden=${!this.hasOverflowingEndTabTitle && !this.hasOverflowingStartTabTitle}>${this.renderScrollButton("start")}${this.renderScrollButton("end")}</div></div>`;
  }
  renderScrollButton(overflowDirection) {
    const { messages, scale, hasOverflowingEndTabTitle, hasOverflowingStartTabTitle } = this;
    const isEnd = overflowDirection === "end";
    return keyed(overflowDirection, html`<div class=${safeClassMap({
      [CSS.scrollButton]: true,
      [CSS.scrollBackwardButton]: !isEnd,
      [CSS.scrollForwardButton]: isEnd
    })}><calcite-button .ariaLabel=${isEnd ? messages.nextTabTitles : messages.previousTabTitles} .disabled=${isEnd ? !hasOverflowingEndTabTitle : !hasOverflowingStartTabTitle} icon-flip-rtl=both .iconStart=${isEnd ? ICON.chevronRight : ICON.chevronLeft} kind=neutral @click=${isEnd ? this.scrollToNextTabTitles : this.scrollToPreviousTabTitles} .scale=${scale} tabindex=-1></calcite-button></div>`);
  }
}
customElement("calcite-tab-nav", TabNav);
export {
  TabNav
};
