import { LitElement } from 'lit';
/**
 * @mixin
 * Mixin that provides roving tabindex navigation primitives for toolbar
 * and menu components following WAI-ARIA keyboard patterns.
 *
 * Subclasses override `_getRovingTargets()` to return the focusable HTMLElements
 * in DOM order. The mixin manages tabindex across those targets (one `0`, rest `-1`)
 * and provides wrapping next/prev/first/last navigation.
 *
 * Does NOT install a keydown handler — each component defines its own
 * (horizontal vs vertical, RTL, extra keys like Enter/Escape).
 *
 * @example
 * ```typescript
 * import { RovingTabindexMixin } from './RovingTabindexMixin'
 *
 * class MyToolbar extends RovingTabindexMixin(LitElement) {
 *   _getRovingTargets(): HTMLElement[] {
 *     return Array.from(this.querySelectorAll('button'))
 *   }
 * }
 * ```
 */
export const RovingTabindexMixin = (superClass) => {
    class RovingTabindexClass extends superClass {
        constructor() {
            super(...arguments);
            /** @internal Index of the last focused target */
            this._rovingIndex = 0;
        }
        /** @internal Override: return focusable HTMLElements in navigation order */
        _getRovingTargets() {
            return [];
        }
        /** @internal Set tabindex 0 on target at index, -1 on all others. Optionally focus. */
        _rovingFocus(index, shouldFocus = true) {
            const targets = this._getRovingTargets();
            if (targets.length === 0)
                return;
            const clamped = Math.max(0, Math.min(index, targets.length - 1));
            targets.forEach((t, i) => t.setAttribute('tabindex', i === clamped ? '0' : '-1'));
            if (shouldFocus)
                targets[clamped]?.focus();
            this._rovingIndex = clamped;
        }
        /** @internal Move to next target (wraps to first) */
        _rovingNext() {
            const targets = this._getRovingTargets();
            if (targets.length === 0)
                return;
            const current = this._rovingCurrentIndex();
            const next = current < targets.length - 1 ? current + 1 : 0;
            this._rovingFocus(next);
        }
        /** @internal Move to previous target (wraps to last) */
        _rovingPrev() {
            const targets = this._getRovingTargets();
            if (targets.length === 0)
                return;
            const current = this._rovingCurrentIndex();
            const prev = current > 0 ? current - 1 : targets.length - 1;
            this._rovingFocus(prev);
        }
        /** @internal Focus first target */
        _rovingFirst() {
            this._rovingFocus(0);
        }
        /** @internal Focus last target */
        _rovingLast() {
            const targets = this._getRovingTargets();
            if (targets.length > 0)
                this._rovingFocus(targets.length - 1);
        }
        /** @internal Find index of currently focused target */
        _rovingCurrentIndex() {
            const active = document.activeElement;
            return this._getRovingTargets().findIndex(t => t === active || t.contains(active));
        }
    }
    return RovingTabindexClass;
};
//# sourceMappingURL=RovingTabindexMixin.js.map