"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable jsx-a11y/no-static-element-interactions */
/** biome-ignore-all lint/a11y/noStaticElementInteractions: We know what we are doing */
const react_1 = __importDefault(require("react"));
const utils_external_1 = require("../../../../utils-external");
const ListboxGroup_1 = require("../group/ListboxGroup");
const ListboxInputSlot_1 = require("../input-slot/ListboxInputSlot");
const ListboxOption_1 = require("../option/ListboxOption");
const ListboxOptions_1 = require("../options/ListboxOptions");
const Listbox_context_1 = require("./Listbox.context");
const domHelpers_1 = require("./domHelpers");
/**
 * Low level component for displaying a list of selectable options with optional grouping.
 * Keyboard navigation is implemented with virtual focus so that real focus can remain on an input field.
 */
function Listbox({ children, setVirtuallyFocusedOptionId }) {
    const id = (0, utils_external_1.useId)();
    const activeId = `aksel-listbox-${id}-active`;
    const virtuallyFocusOption = (element) => {
        setVirtuallyFocusedOptionId((element === null || element === void 0 ? void 0 : element.dataset.id) || "");
        element === null || element === void 0 ? void 0 : element.scrollIntoView({ block: "nearest" });
    };
    return (react_1.default.createElement("div", { onKeyDown: (event) => {
            const listbox = event.currentTarget.querySelector('[role="listbox"]');
            if (!listbox) {
                return;
            }
            // Helper functions
            const getFirstOption = (suffix = "") => listbox.querySelector(`[role="option"]${suffix}`);
            const getLastOption = () => {
                const allOptions = listbox.querySelectorAll('[role="option"]');
                return allOptions[allOptions.length - 1];
            };
            const focusedOptionElm = getFirstOption('[data-virtual-focus="true"]');
            // Doesn't make sense to have real focus on one option and virtual focus on another at the same time.
            // Not sure if it matters, though 🤔
            const optionElmWithRealFocus = getFirstOption(":focus");
            if (optionElmWithRealFocus) {
                listbox.focus();
            }
            const virtuallyFocusWithFallback = (getNextElement, getFallback) => {
                event.preventDefault();
                if (!focusedOptionElm) {
                    virtuallyFocusOption(getFallback());
                    return;
                }
                const nextOption = getNextElement(focusedOptionElm);
                if (!nextOption) {
                    virtuallyFocusOption(getFallback());
                    return;
                }
                virtuallyFocusOption(nextOption);
            };
            switch (event.key) {
                case "ArrowDown":
                    virtuallyFocusWithFallback(domHelpers_1.findNextOption, getFirstOption);
                    break;
                case "ArrowUp":
                    virtuallyFocusWithFallback(domHelpers_1.findPrevOption, getLastOption);
                    break;
                case "Home":
                    event.preventDefault();
                    virtuallyFocusOption(getFirstOption());
                    break;
                case "End":
                    event.preventDefault();
                    virtuallyFocusOption(getLastOption());
                    break;
                case "Enter":
                case "Accept":
                    if (focusedOptionElm) {
                        focusedOptionElm.click();
                    }
                    break;
                // TODO: Consider implementing PageUp/PageDown too
            }
        } },
        react_1.default.createElement(Listbox_context_1.ListboxProvider, { activeId: activeId, setVirtuallyFocusedOptionId: setVirtuallyFocusedOptionId }, children)));
}
Listbox.InputSlot = ListboxInputSlot_1.ListboxInputSlot;
Listbox.Options = ListboxOptions_1.ListboxOptions;
Listbox.Option = ListboxOption_1.ListboxOption;
Listbox.Group = ListboxGroup_1.ListboxGroup;
exports.default = Listbox;
//# sourceMappingURL=ListboxRoot.js.map