// #region Imports
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Listen } from '../../../../Events/Decorators/ListenDecorator';
import { Appearanceable } from '../../../Behaviors/Appearanceable';
import { Disableable } from '../../../Behaviors/Disableable';
import { Slottable } from '../../../Behaviors/Slottable';
import { Variantable } from '../../../Behaviors/Variantable';
import { KeyboardController } from '../../../Controllers/KeyboardController';
import { ResizeController } from '../../../Controllers/ResizeController';
import { Attribute } from '../../../Decorators/AttributeDecorator';
import { Component } from '../../../Decorators/ComponentDecorator';
import { Watch } from '../../../Decorators/WatchDecorator';
import { FlowDirection } from '../../../Types/FlowDirection';
import { Orientation } from '../../../Types/Orientation';
import { TabStripPlacement } from '../../../Types/TabStripPlacement';
import { Variant } from '../../../Types/Variant';
import { CustomElement } from '../../Abstracts/CustomElement';
import { InkBarElement } from '../../Primitives/InkBar/InkBarElement';
import { tabStripElementTemplate } from './TabStripElementTemplate';
import { TabStripItemElement } from './TabStripItemElement';
import { tabStripElementJoyStyle } from './Themes/TabStripElement.Joy';
import { tabStripElementMemphisStyle } from './Themes/TabStripElement.Memphis';
import { tabStripElementCosmopolitanStyle } from './Themes/TabStripElement.Cosmopolitan';
import { Themeable } from '../../../Behaviors/Themeable';
// #endregion
/**
 * TabStrip - A navigation container for organizing and switching between related content panels.
 *
 * Provides tab-based navigation with keyboard support, visual indicators, and flexible placement options.
 * Manages tab selection states and coordinates with tab panel content. Essential for organizing
 * complex interfaces with multiple related views or data sets.
 *
 * @name TabStripElement
 * @element mosaik-tab-strip
 * @category Selectors
 *
 * @csspart tab-strip - The main tab strip container
 * @csspart tab-list - Container for the tab buttons
 * @csspart indicator - Active tab indicator element
 * @csspart overflow - Overflow controls for scrollable tabs
 *
 * @cssprop --tab-strip-background-color - Background color of the tab strip
 * @cssprop --tab-strip-border-color - Border color for tab strip edges
 * @cssprop --tab-strip-gap - Spacing between individual tabs
 * @cssprop --tab-strip-padding - Internal padding of the tab strip
 * @cssprop --tab-indicator-color - Color of the active tab indicator
 * @cssprop --tab-indicator-height - Height of the tab indicator bar
 * @cssprop --tab-selected-background - Background color of selected tabs
 * @cssprop --tab-hover-background - Background color on tab hover
 *
 * @dependency InkBarElement - Provides the active tab indicator animation
 *
 * @example
 * ```html
 * <!-- Basic horizontal tab strip -->
 * <mosaik-tab-strip>
 *   <mosaik-tab-strip-item selected>Overview</mosaik-tab-strip-item>
 *   <mosaik-tab-strip-item>Details</mosaik-tab-strip-item>
 *   <mosaik-tab-strip-item>Settings</mosaik-tab-strip-item>
 * </mosaik-tab-strip>
 *
 * <!-- Tab strip with indicator -->
 * <mosaik-tab-strip has-indicator placement="top">
 *   <mosaik-tab-strip-item>Dashboard</mosaik-tab-strip-item>
 *   <mosaik-tab-strip-item>Analytics</mosaik-tab-strip-item>
 *   <mosaik-tab-strip-item>Reports</mosaik-tab-strip-item>
 *   <mosaik-tab-strip-item disabled>Admin</mosaik-tab-strip-item>
 * </mosaik-tab-strip>
 *
 * <!-- Vertical tab navigation -->
 * <div class="app-layout">
 *   <mosaik-tab-strip placement="left" has-indicator>
 *     <mosaik-tab-strip-item selected>
 *       <mosaik-icon slot="icon" data="home"></mosaik-icon>
 *       Home
 *     </mosaik-tab-strip-item>
 *     <mosaik-tab-strip-item>
 *       <mosaik-icon slot="icon" data="user"></mosaik-icon>
 *       Profile
 *     </mosaik-tab-strip-item>
 *     <mosaik-tab-strip-item>
 *       <mosaik-icon slot="icon" data="settings"></mosaik-icon>
 *       Settings
 *     </mosaik-tab-strip-item>
 *   </mosaik-tab-strip>
 *   <div class="content-area">
 *     <!-- Tab panel content -->
 *   </div>
 * </div>
 *
 * <!-- Scrollable tab strip for many tabs -->
 * <mosaik-tab-strip variant="scrollable">
 *   <mosaik-tab-strip-item>Tab 1</mosaik-tab-strip-item>
 *   <mosaik-tab-strip-item>Tab 2</mosaik-tab-strip-item>
 *   <mosaik-tab-strip-item>Tab 3</mosaik-tab-strip-item>
 *   <!-- More tabs... -->
 * </mosaik-tab-strip>
 * ```
 *
 * @public
 */
let TabStripElement = class TabStripElement extends Themeable(Slottable(Disableable(Variantable(Appearanceable(CustomElement))))) {
    // #region Fields
    _resizeController;
    _keyboardController;
    _indicatorElement;
    _placement;
    _hasIndicator;
    // #endregion
    // #region Ctor
    /**
     * @public
     */
    constructor() {
        super();
        this._placement = TabStripPlacement.Top;
        this._hasIndicator = true;
        this._indicatorElement = null;
        this._keyboardController = new KeyboardController(this, { capture: true });
        this._resizeController = new ResizeController(this, {
            callback: () => {
                const current = this.getCurrent();
                if (current) {
                    this.alignIndicatorTo(current);
                }
            }
        });
    }
    // #endregion
    // #region Properties
    /**
     * Returns the `{@link is}` property.
     * The `{@link is}` property represents natural name of this element.
     *
     * @public
     * @static
     * @readonly
     */
    static get is() {
        return 'mosaik-tab-strip';
    }
    /**
     * Gets or sets the `placement` property.
     *
     * @public
     * @attr
     */
    get placement() {
        return this._placement;
    }
    set placement(value) {
        if (this._placement !== value) {
            this._placement = value;
            this.requestUpdate('placement');
        }
    }
    /**
     * Gets or sets the `hasIndicator` property.
     *
     * @public
     * @attr
     */
    get hasIndicator() {
        return this._hasIndicator;
    }
    set hasIndicator(value) {
        if (this._hasIndicator !== value) {
            this._hasIndicator = value;
            this.requestUpdate('hasIndicator');
        }
    }
    /**
     * Returns the items of the tab strip.
     *
     * @public
     * @readonly
     */
    get items() {
        return this.getSlotAssignmentsOf('', TabStripItemElement);
    }
    /**
     * Returns the selected tab item.
     *
     * @public
     * @readonly
     */
    get selectedItem() {
        return this.items.find((x) => x.isSelected) ?? null;
    }
    /**
     * Returns the selected index.
     *
     * @public
     * @readonly
     */
    get selectedIndex() {
        return this.items.findIndex((x) => x.isSelected);
    }
    // #endregion
    // #region Methods
    /**
     * Selects the specified tab item.
     *
     * @public
     * @param tabStripItem - The tab item to select.
     */
    select(tabStripItem) {
        if (tabStripItem.disabled) {
            return;
        }
        for (const item of this.items) {
            const isCurrent = item === tabStripItem;
            item.isSelected = isCurrent;
            if (item.isSelected) {
                this.alignIndicatorTo(item);
            }
        }
        this.requestUpdate();
    }
    /**
     * Selects the specified tab item by its index.
     *
     * @public
     * @param index - The index of the tab item to select.
     */
    selectByIndex(index) {
        this.select(this.items[index]);
    }
    /**
     * Selects the specified tab item by its value.
     *
     * @public
     * @param value - The value of the tab item to select.
     */
    selectByValue(value) {
        const item = this.items.find((x) => x.value === value);
        if (item) {
            this.select(item);
        }
    }
    /**
     * @public
     * @override
     */
    onSlotChanges(slotName) {
        super.onSlotChanges(slotName);
        const elements = this.items;
        for (const [i, e] of elements.entries()) {
            // if the tab item already disabled, we don't want to enable it.
            if (!e.disabled) {
                e.disabled = this.disabled;
            }
            e.variant = this.variant;
            e.dir = this.dir;
            e.classList.toggle('first', i === 0);
            e.classList.toggle('inner', i > 0 && i < elements.length - 1);
            e.classList.toggle('last', i === elements.length - 1);
            if (e.isSelected) {
                this.alignIndicatorTo(e);
            }
        }
    }
    /**
     * @protected
     * @override
     */
    onApplyTemplate() {
        super.onApplyTemplate();
        this._indicatorElement = this.getTemplatePart('indicator');
    }
    /**
     * @protected
     */
    onClick(event) {
        // we want only tab strip items
        if (!(event.target instanceof TabStripItemElement)) {
            return;
        }
        const current = event.target;
        // keep in min that the initial previous could be null when no item from the beginning is selected.
        const previous = this.getCurrent();
        const others = this.items
            .filter((x) => x !== current && x !== previous)
            .filter((x) => !x.isSelected);
        // this.value = current.value;
        others.forEach((x) => x.isSelected = false);
        if (current !== previous) {
            if (previous) {
                previous.isSelected = false;
            }
        }
        current.isSelected = true;
        this.alignIndicatorTo(current);
    }
    /**
     * @protected
     */
    onTabStripItemSelectionChanged(event) {
        if (event.target instanceof TabStripItemElement) {
            if (event.target.isSelected) {
                // this.alignIndicatorTo(event.target);
                this.select(event.target);
            }
        }
    }
    /**
     * @protected
     */
    onDisabledPropertyChange(_prev, next) {
        if (next !== undefined) {
            this.items.forEach((x) => {
                // if the tab item already disabled, we don't want to enable it.
                if (!x.disabled) {
                    x.disabled = next;
                }
            });
            const current = this.getCurrent();
            if (current) {
                this.alignIndicatorTo(current);
            }
        }
    }
    /**
     * @protected
     */
    onVariantPropertyChange(_prev, next) {
        if (next) {
            this.items.forEach((x) => x.variant = next);
            const current = this.getCurrent();
            if (current) {
                this.alignIndicatorTo(current);
            }
        }
    }
    /**
     * @protected
     */
    onDirPropertyChange(_prev, next) {
        if (next) {
            this.items.forEach((x) => x.dir = next);
            const current = this.getCurrent();
            if (current) {
                this.alignIndicatorTo(current);
            }
        }
    }
    /**
     * @protected
     */
    onOrientationPropertyChanged(_prev, next) {
        if (next) {
            const current = this.getCurrent();
            if (current) {
                this.alignIndicatorTo(current);
            }
        }
    }
    /**
     * @protected
     */
    onHasIndicatorPropertyChanged(_prev, next) {
        if (next) {
            this._indicatorElement = this.getTemplatePart('indicator');
            const current = this.getCurrent();
            if (current) {
                this.alignIndicatorTo(current);
            }
        }
        else {
            this._indicatorElement = null;
        }
    }
    /**
     * @private
     */
    alignIndicatorTo(element) {
        if (!this._hasIndicator) {
            return;
        }
        if (this._indicatorElement) {
            this._indicatorElement.target = element;
            this._indicatorElement.align();
        }
    }
    /**
     * @private
     */
    getCurrent() {
        return this.items.find((x) => x.isSelected) ?? null;
    }
};
__decorate([
    Attribute({ type: TabStripPlacement }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], TabStripElement.prototype, "placement", null);
__decorate([
    Attribute({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], TabStripElement.prototype, "hasIndicator", null);
__decorate([
    Listen('click'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Event]),
    __metadata("design:returntype", void 0)
], TabStripElement.prototype, "onClick", null);
__decorate([
    Listen('selectionChanged'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [CustomEvent]),
    __metadata("design:returntype", void 0)
], TabStripElement.prototype, "onTabStripItemSelectionChanged", null);
__decorate([
    Watch('disabled'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Boolean, Boolean]),
    __metadata("design:returntype", void 0)
], TabStripElement.prototype, "onDisabledPropertyChange", null);
__decorate([
    Watch('variant'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", void 0)
], TabStripElement.prototype, "onVariantPropertyChange", null);
__decorate([
    Watch('dir'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", void 0)
], TabStripElement.prototype, "onDirPropertyChange", null);
__decorate([
    Watch('orientation'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String]),
    __metadata("design:returntype", void 0)
], TabStripElement.prototype, "onOrientationPropertyChanged", null);
__decorate([
    Watch('hasIndicator'),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Boolean, Boolean]),
    __metadata("design:returntype", void 0)
], TabStripElement.prototype, "onHasIndicatorPropertyChanged", null);
TabStripElement = __decorate([
    Component({
        selector: 'mosaik-tab-strip',
        template: tabStripElementTemplate,
        themes: {
            joy: tabStripElementJoyStyle,
            memphis: tabStripElementMemphisStyle,
            cosmopolitan: tabStripElementCosmopolitanStyle
        },
        host: {
            role: 'tablist'
        },
        imports: [
            InkBarElement
        ]
    }),
    __metadata("design:paramtypes", [])
], TabStripElement);
export { TabStripElement };
//# sourceMappingURL=TabStripElement.js.map