/**
 * 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 { forEach } 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 HostListener from "../../globals/decorators/host-listener.js";
import HostListenerMixin from "../../globals/mixins/host-listener.js";
import { NAVIGATION_DIRECTION } from "../content-switcher/defs.js";
import content_switcher_default from "../content-switcher/content-switcher.js";
import { TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_TYPE } from "./defs.js";
import tabs_default$1 from "./tabs.scss.js";
import { html } from "lit";
import { property, query, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import ChevronRight16 from "@carbon/icons/es/chevron--right/16.js";
import ChevronLeft16 from "@carbon/icons/es/chevron--left/16.js";
//#region src/components/tabs/tabs.ts
/**
* Copyright IBM Corp. 2019, 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.
*/
let CDSTabs = class CDSTabs extends HostListenerMixin(content_switcher_default) {
	constructor(..._args) {
		super(..._args);
		this._currentIndex = 0;
		this._totalTabs = 0;
		this._isScrollable = false;
		this.tablist = null;
		this.BUTTON_WIDTH = 44;
		this._currentScrollPosition = 0;
		this.selectingItemsAssistiveText = "Selecting items. Use up and down arrow keys to navigate.";
		this.selectedItemAssistiveText = "Selected an item.";
		this.triggerContent = "";
		this.type = "";
		this._isIntersectionLeftTrackerInContent = true;
		this._isIntersectionRightTrackerInContent = true;
		this._observerIntersection = null;
		this._observeIntersectionContainer = (records) => {
			const { _intersectionLeftSentinelNode: intersectionLeftSentinelNode, _intersectionRightSentinelNode: intersectionRightSentinelNode } = this;
			records.forEach(({ isIntersecting, target }) => {
				if (target === intersectionLeftSentinelNode) this._isIntersectionLeftTrackerInContent = isIntersecting;
				if (target === intersectionRightSentinelNode) this._isIntersectionRightTrackerInContent = isIntersecting;
			});
		};
	}
	/**
	* Navigates through tabs.
	*
	* @param direction `-1` to navigate backward, `1` to navigate forward.
	* @param [options] The options.
	* @param [options.immediate]
	*   Defaults to `true`
	*   `true` to make it "immediate selection change" mode, which does:
	*
	*   Starts with the selected item
	*   Going prev/next item immediately changes the selection
	*/
	_navigate(direction) {
		const immediate = this.selectionMode === "automatic";
		const { selectorItemHighlighted, selectorItemSelected } = this.constructor;
		const nextItem = this._getNextItem(this.querySelector(immediate ? selectorItemSelected : selectorItemHighlighted), direction);
		if (!nextItem) return;
		this._handleUserInitiatedSelectItem(nextItem, "keyboard");
		if (!immediate) this.resetHighlighted(nextItem);
		nextItem.scrollIntoView({
			block: "nearest",
			inline: "nearest"
		});
		const nextItemText = nextItem.textContent;
		if (nextItemText) this._assistiveStatusText = nextItemText;
		this._currentIndex += direction;
		this.requestUpdate();
	}
	/**
	* Resets the highlighted state of all tabs, setting only the specified tab as highlighted.
	*
	* @param nextItem The tab item to be highlighted. If provided, only this item will be highlighted.
	*   If null or undefined, all tabs will have their highlighted state set to false.
	*/
	resetHighlighted(nextItem) {
		const { selectorItem } = this.constructor;
		forEach(this.querySelectorAll(selectorItem), (item) => {
			item["highlighted"] = nextItem === item;
		});
	}
	_handleClick(event) {
		super._handleClick(event);
		const currentItem = this._getCurrentItem(event.target);
		if (currentItem) this.resetHighlighted(currentItem);
	}
	_handleKeydown(event) {
		const { key } = event;
		const action = this.constructor.getAction(key);
		const enabledTabs = this.querySelectorAll(`cds-tab:not([disabled])`);
		switch (action) {
			case "home":
				{
					const [firstEnabledTab] = enabledTabs;
					firstEnabledTab.scrollIntoView({
						block: "nearest",
						inline: "nearest"
					});
					if (this.selectionMode === "manual") this.resetHighlighted(firstEnabledTab);
					this._handleUserInitiatedSelectItem(firstEnabledTab, this.selectionMode !== "manual" ? "activation" : "keyboard");
					this.requestUpdate();
				}
				break;
			case "end":
				{
					const lastEnabledTab = enabledTabs[enabledTabs.length - 1];
					lastEnabledTab.scrollIntoView({
						block: "nearest",
						inline: "nearest"
					});
					if (this.selectionMode === "manual") this.resetHighlighted(lastEnabledTab);
					this._handleUserInitiatedSelectItem(lastEnabledTab, this.selectionMode !== "manual" ? "activation" : "keyboard");
					this.requestUpdate();
				}
				break;
			case "navigating":
				{
					const direction = NAVIGATION_DIRECTION[key];
					if (direction) this._navigate(direction);
				}
				break;
			case "activating":
				{
					const focusedTab = this.querySelector(`cds-tab[highlighted]`);
					if (focusedTab) {
						this._handleUserInitiatedSelectItem(focusedTab, "activation");
						this.requestUpdate();
					}
				}
				break;
			default: break;
		}
	}
	_handleTabClosed(event) {
		const { selectorItem, selectorItemEnabled, selectorItemSelected } = this.constructor;
		const { index } = event.detail;
		const allTabs = this.querySelectorAll(selectorItem);
		const enabledTabsBeforeRemoval = this.querySelectorAll(selectorItemEnabled);
		const activeItem = this.querySelector(selectorItemSelected);
		const indexInEnabledTabs = Array.from(enabledTabsBeforeRemoval).indexOf(allTabs[index]);
		const activeTabClosed = activeItem === allTabs[index];
		requestAnimationFrame(() => {
			const enabledTabs = this.querySelectorAll(selectorItemEnabled);
			if (enabledTabs.length > 0) {
				if (activeTabClosed) {
					enabledTabs[0].selected = true;
					this.value = enabledTabs[0].value;
				}
				const nextHighlightedItem = indexInEnabledTabs < enabledTabs.length ? enabledTabs[indexInEnabledTabs] : enabledTabs[indexInEnabledTabs - 1];
				nextHighlightedItem.highlighted = true;
				nextHighlightedItem.shadowRoot?.querySelector(`.cds--tabs__nav-link--dismissable`)?.focus();
				nextHighlightedItem.scrollIntoView({
					block: "nearest",
					inline: "nearest"
				});
			} else {
				this.value = "";
				return;
			}
		});
	}
	/**
	* Handles click on overflow scroll buttons.
	*
	* @param _ Event object
	* @param [options] The options.
	* @param [options.direction] `-1` to scroll forward, `1` to scroll backward.
	*/
	_handleScrollButtonClick(_, { direction }) {
		if (!this.tablist) return;
		const { scrollLeft, clientWidth, scrollWidth } = this._contentContainerNode;
		switch (direction) {
			case -1:
				this._contentContainerNode.scrollLeft = Math.max(scrollLeft - scrollWidth / this._totalTabs * 1.5, 0);
				break;
			case 1:
				this._contentContainerNode.scrollLeft = Math.min(scrollLeft + scrollWidth / this._totalTabs * 1.5, scrollWidth - clientWidth) + 1;
				break;
			default: break;
		}
	}
	_handleSlotchange() {
		super._handleSlotchange?.();
		const { selectorItemSelected } = this.constructor;
		const selectedItem = this.querySelector(selectorItemSelected);
		const nextItem = this._getNextItem(selectedItem, 1);
		if (nextItem) nextItem.hideDivider = true;
		this._updateTabsState();
	}
	_selectionDidChange(itemToSelect, interactionType) {
		super._selectionDidChange(itemToSelect, interactionType);
		this._assistiveStatusText = this.selectedItemAssistiveText;
	}
	/**
	* Cleans-up and creates the intersection observer for the scrolling container.
	*
	* @param [options] The options.
	* @param [options.create] `true` to create the new intersection observer.
	*/
	_cleanAndCreateIntersectionObserverContainer({ create } = {}) {
		const { _intersectionLeftSentinelNode: intersectionLeftSentinelNode, _intersectionRightSentinelNode: intersectionRightSentinelNode } = this;
		if (this._observerIntersection) {
			this._observerIntersection.disconnect();
			this._observerIntersection = null;
		}
		if (create) {
			this._observerIntersection = new IntersectionObserver(this._observeIntersectionContainer, {
				root: this,
				threshold: 0
			});
			if (intersectionLeftSentinelNode) this._observerIntersection.observe(intersectionLeftSentinelNode);
			if (intersectionRightSentinelNode) this._observerIntersection.observe(intersectionRightSentinelNode);
		}
	}
	disconnectedCallback() {
		this._cleanAndCreateIntersectionObserverContainer();
		super.disconnectedCallback();
	}
	shouldUpdate(changedProperties) {
		super.shouldUpdate(changedProperties);
		if (this.tablist) {
			const { clientWidth, scrollWidth } = this.tablist;
			this._isScrollable = scrollWidth > clientWidth;
		}
		const { selectorItem } = this.constructor;
		if (changedProperties.has("type") || changedProperties.has("iconSize")) {
			this._totalTabs = 0;
			forEach(this.querySelectorAll(selectorItem), (elem) => {
				this._totalTabs++;
				elem.type = this.type;
				elem.iconSize = this.iconSize;
			});
		}
		return true;
	}
	firstUpdated() {
		super.firstUpdated();
		this._tabInitialLoad();
		this._cleanAndCreateIntersectionObserverContainer({ create: true });
	}
	updated(changedProperties) {
		super.updated?.(changedProperties);
		if (changedProperties.has("value")) {
			const tab = this.querySelector(`cds-tab[value="${this.value}"]`);
			if (tab) {
				const { width: tabWidth } = tab?.getBoundingClientRect() ?? {};
				const start = tab.offsetLeft ?? 0;
				const end = tab.offsetLeft + tabWidth;
				const visibleStart = this.tablist.scrollLeft + this.BUTTON_WIDTH;
				const visibleEnd = this.tablist.scrollLeft + this.tablist.clientWidth - this.BUTTON_WIDTH;
				if (start < visibleStart) this.tablist.scrollLeft = start - this.BUTTON_WIDTH;
				if (end > visibleEnd) this.tablist.scrollLeft = end + this.BUTTON_WIDTH - this.tablist.clientWidth;
			}
		}
		if (changedProperties.has("_currentScrollPosition")) {
			if (this._contentNode) this._contentNode.style.insetInlineStart = `-${this._currentScrollPosition}px`;
		}
		if (changedProperties.has("dismissable")) this._updateTabsState();
	}
	/**
	* Render the previous button if tablist is wider than container.
	*/
	renderPreviousButton() {
		const { _isIntersectionLeftTrackerInContent: isIntersectionLeftTrackerInContent } = this;
		return html`
      <button
        part="prev-button"
        tabindex="-1"
        aria-hidden="true"
        class="${classMap({
			[`cds--tab--overflow-nav-button`]: true,
			[`cds--tabs__nav-caret-left`]: true,
			[`cds--tab--overflow-nav-button--previous`]: true,
			[`cds--tab--overflow-nav-button--hidden`]: isIntersectionLeftTrackerInContent
		})}"
        @click=${(_) => this._handleScrollButtonClick(_, { direction: NAVIGATION_DIRECTION.Left })}>
        ${iconLoader(ChevronLeft16)}
      </button>
    `;
	}
	/**
	* Render the next button if tablist is wider than container.
	*/
	renderNextButton() {
		const { _isIntersectionRightTrackerInContent: isIntersectionRightTrackerInContent } = this;
		return html`
      <button
        part="next-button"
        tabindex="-1"
        aria-hidden="true"
        class="${classMap({
			[`cds--tab--overflow-nav-button`]: true,
			[`cds--tabs__nav-caret-right`]: true,
			[`cds--tab--overflow-nav-button--next`]: true,
			[`cds--tab--overflow-nav-button--hidden`]: isIntersectionRightTrackerInContent
		})}"
        @click=${(_) => this._handleScrollButtonClick(_, { direction: NAVIGATION_DIRECTION.Right })}>
        ${iconLoader(ChevronRight16)}
      </button>
    `;
	}
	render() {
		const { _assistiveStatusText: assistiveStatusText, _handleSlotchange: handleSlotchange } = this;
		return html`
      ${this.renderPreviousButton()}
      <div class="${"cds"}--tabs-nav-content-container">
        <div class="${"cds"}--tabs-nav-content">
          <div class="${"cds"}--tabs-nav">
            <div id="tablist" role="tablist" class="${"cds"}--tab--list">
              <div class="${"cds"}--sub-content-left"></div>
              <slot @slotchange=${handleSlotchange}></slot>
              <div class="${"cds"}--sub-content-right"></div>
            </div>
          </div>
        </div>
      </div>
      ${this.renderNextButton()}
      <div
        class="${"cds"}--assistive-text"
        role="status"
        aria-live="assertive"
        aria-relevant="additions text">
        ${assistiveStatusText}
      </div>
    `;
	}
	_updateTabsState() {
		const { selectorItem } = this.constructor;
		this.querySelectorAll(selectorItem).forEach((tab, index) => {
			tab._dismissable = this.dismissable;
			tab._index = index;
		});
	}
	_tabInitialLoad() {
		const { selectorTablist, selectorItemEnabled } = this.constructor;
		const { selectionMode, selectedIndex } = this;
		const tablist = this.shadowRoot.querySelector(selectorTablist);
		this.tablist = tablist;
		const firstItem = this.querySelectorAll(selectorItemEnabled)[selectedIndex];
		if (firstItem) {
			if (selectionMode === "manual") firstItem.highlighted = true;
			firstItem.selected = true;
			this.value = firstItem.value;
		}
	}
	static {
		this.TRIGGER_KEYS = new Set([" ", "Enter"]);
	}
	/**
	* A selector that will return tabs.
	*/
	static get selectorItem() {
		return `cds-tab`;
	}
	/**
	* A selector that will return enabled tabs.
	*/
	static get selectorItemEnabled() {
		return `cds-tab:not([disabled])`;
	}
	/**
	* A selector that will return highlighted tabs.
	*/
	static get selectorItemHighlighted() {
		return `cds-tab[highlighted]`;
	}
	/**
	* A selector that will return selected tabs.
	*/
	static get selectorItemSelected() {
		return `cds-tab[selected]`;
	}
	/**
	* A selector that returns the tablist
	*/
	static get selectorTablist() {
		return `.cds--tab--list`;
	}
	/**
	* The name of the custom event fired before a tab is selected upon a user gesture.
	* Cancellation of this event stops changing the user-initiated selection.
	*/
	static get eventBeforeSelect() {
		return `cds-tabs-beingselected`;
	}
	/**
	* The name of the custom event fired after a a tab is selected upon a user gesture.
	*/
	static get eventSelect() {
		return `cds-tabs-selected`;
	}
	static {
		this.styles = tabs_default$1;
	}
	/**
	* @param key The key symbol.
	* @returns A action for dropdown for the given key symbol.
	*/
	static getAction(key) {
		if (key === "Home") return "home";
		if (key === "End") return "end";
		if (key in NAVIGATION_DIRECTION) return "navigating";
		if (key === "Enter" || key === " ") return "activating";
		return "none";
	}
};
__decorate([HostListener("click")], CDSTabs.prototype, "_handleClick", null);
__decorate([HostListener("keydown")], CDSTabs.prototype, "_handleKeydown", null);
__decorate([HostListener("cds-tab-closed")], CDSTabs.prototype, "_handleTabClosed", null);
__decorate([query(`.cds--tabs-nav-content-container`)], CDSTabs.prototype, "_contentContainerNode", void 0);
__decorate([query(`.cds--tabs-nav-content`)], CDSTabs.prototype, "_contentNode", void 0);
__decorate([state()], CDSTabs.prototype, "_currentScrollPosition", void 0);
__decorate([query(`.cds--sub-content-left`)], CDSTabs.prototype, "_intersectionLeftSentinelNode", void 0);
__decorate([query(`.cds--sub-content-right`)], CDSTabs.prototype, "_intersectionRightSentinelNode", void 0);
__decorate([property({ attribute: "selecting-items-assistive-text" })], CDSTabs.prototype, "selectingItemsAssistiveText", void 0);
__decorate([property({ attribute: "selected-item-assistive-text" })], CDSTabs.prototype, "selectedItemAssistiveText", void 0);
__decorate([property({ attribute: "trigger-content" })], CDSTabs.prototype, "triggerContent", void 0);
__decorate([property({ reflect: true })], CDSTabs.prototype, "type", void 0);
__decorate([property({
	type: Boolean,
	reflect: true
})], CDSTabs.prototype, "dismissable", void 0);
__decorate([property({
	attribute: "icon-size",
	reflect: true
})], CDSTabs.prototype, "iconSize", void 0);
__decorate([state()], CDSTabs.prototype, "_isIntersectionLeftTrackerInContent", void 0);
__decorate([state()], CDSTabs.prototype, "_isIntersectionRightTrackerInContent", void 0);
CDSTabs = __decorate([carbonElement(`cds-tabs`)], CDSTabs);
var tabs_default = CDSTabs;
//#endregion
export { NAVIGATION_DIRECTION, TABS_ICON_SIZE, TABS_KEYBOARD_ACTION, TABS_TYPE, tabs_default as default };

//# sourceMappingURL=tabs.js.map