chromium/third_party/material_web_components/components-chromium/node_modules/@material/web/chips/internal/chip-set.js

/**
 * @license
 * Copyright 2023 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { __decorate } from "tslib";
import { html, isServer, LitElement } from 'lit';
import { queryAssignedElements } from 'lit/decorators.js';
import { Chip } from './chip.js';
/**
 * A chip set component.
 */
export class ChipSet extends LitElement {
    get chips() {
        return this.childElements.filter((child) => child instanceof Chip);
    }
    constructor() {
        super();
        this.internals = 
        // Cast needed for closure
        this.attachInternals();
        if (!isServer) {
            this.addEventListener('focusin', this.updateTabIndices.bind(this));
            this.addEventListener('update-focus', this.updateTabIndices.bind(this));
            this.addEventListener('keydown', this.handleKeyDown.bind(this));
            this.internals.role = 'toolbar';
        }
    }
    render() {
        return html `<slot @slotchange=${this.updateTabIndices}></slot>`;
    }
    handleKeyDown(event) {
        const isLeft = event.key === 'ArrowLeft';
        const isRight = event.key === 'ArrowRight';
        const isHome = event.key === 'Home';
        const isEnd = event.key === 'End';
        // Ignore non-navigation keys
        if (!isLeft && !isRight && !isHome && !isEnd) {
            return;
        }
        const { chips } = this;
        // Don't try to select another chip if there aren't any.
        if (chips.length < 2) {
            return;
        }
        // Prevent default interactions, such as scrolling.
        event.preventDefault();
        if (isHome || isEnd) {
            const index = isHome ? 0 : chips.length - 1;
            chips[index].focus({ trailing: isEnd });
            this.updateTabIndices();
            return;
        }
        // Check if moving forwards or backwards
        const isRtl = getComputedStyle(this).direction === 'rtl';
        const forwards = isRtl ? isLeft : isRight;
        const focusedChip = chips.find((chip) => chip.matches(':focus-within'));
        if (!focusedChip) {
            // If there is not already a chip focused, select the first or last chip
            // based on the direction we're traveling.
            const nextChip = forwards ? chips[0] : chips[chips.length - 1];
            nextChip.focus({ trailing: !forwards });
            this.updateTabIndices();
            return;
        }
        const currentIndex = chips.indexOf(focusedChip);
        let nextIndex = forwards ? currentIndex + 1 : currentIndex - 1;
        // Search for the next sibling that is not disabled to select.
        // If we return to the host index, there is nothing to select.
        while (nextIndex !== currentIndex) {
            if (nextIndex >= chips.length) {
                // Return to start if moving past the last item.
                nextIndex = 0;
            }
            else if (nextIndex < 0) {
                // Go to end if moving before the first item.
                nextIndex = chips.length - 1;
            }
            // Check if the next sibling is disabled. If so,
            // move the index and continue searching.
            //
            // Some toolbar items may be focusable when disabled for increased
            // visibility.
            const nextChip = chips[nextIndex];
            if (nextChip.disabled && !nextChip.alwaysFocusable) {
                if (forwards) {
                    nextIndex++;
                }
                else {
                    nextIndex--;
                }
                continue;
            }
            nextChip.focus({ trailing: !forwards });
            this.updateTabIndices();
            break;
        }
    }
    updateTabIndices() {
        // The chip that should be focusable is either the chip that currently has
        // focus or the first chip that can be focused.
        const { chips } = this;
        let chipToFocus;
        for (const chip of chips) {
            const isChipFocusable = chip.alwaysFocusable || !chip.disabled;
            const chipIsFocused = chip.matches(':focus-within');
            if (chipIsFocused && isChipFocusable) {
                // Found the first chip that is actively focused. This overrides the
                // first focusable chip found.
                chipToFocus = chip;
                continue;
            }
            if (isChipFocusable && !chipToFocus) {
                chipToFocus = chip;
            }
            // Disable non-focused chips. If we disable all of them, we'll grant focus
            // to the first focusable child that was found.
            chip.tabIndex = -1;
        }
        if (chipToFocus) {
            chipToFocus.tabIndex = 0;
        }
    }
}
__decorate([
    queryAssignedElements()
], ChipSet.prototype, "childElements", void 0);
//# sourceMappingURL=chip-set.js.map