"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AutoSuggest = void 0;
const react_1 = __importStar(require("react"));
const search_1 = require("../../form/search");
const stack_1 = require("../../primitives/stack");
const typography_1 = require("../../typography");
const ListboxRoot_1 = __importDefault(require("../../utils/components/Listbox/root/ListboxRoot"));
const DismissableLayer_1 = require("../../utils/components/dismissablelayer/DismissableLayer");
const Floating_1 = require("../../utils/components/floating/Floating");
const hooks_1 = require("../../utils/hooks");
const AutoSuggest = (0, react_1.forwardRef)(({ options, onSelect, value, onChange, open, setOpen }, ref) => {
    const [virtuallyFocusedOptionId, setVirtuallyFocusedOptionId] = (0, react_1.useState)("");
    const [inputRef, setInputRef] = (0, react_1.useState)(null);
    /* Unsure why N version works, but not regular here */
    const mergedRef = (0, hooks_1.useMergeRefsN)([setInputRef, ref]);
    const handleClose = () => {
        setOpen(false);
    };
    const handleChange = (newValue) => {
        onChange(newValue);
        setOpen(true);
    };
    const handleSelectOption = (0, react_1.useCallback)((option) => {
        const createdNewToken = onSelect(option);
        if (createdNewToken) {
            inputRef === null || inputRef === void 0 ? void 0 : inputRef.focus();
            setOpen(false);
        }
    }, [onSelect, inputRef, setOpen]);
    return (react_1.default.createElement(Floating_1.Floating, null,
        react_1.default.createElement(ListboxRoot_1.default, { setVirtuallyFocusedOptionId: setVirtuallyFocusedOptionId },
            react_1.default.createElement(Floating_1.Floating.Anchor, null,
                react_1.default.createElement(ListboxRoot_1.default.InputSlot, null,
                    react_1.default.createElement(search_1.Search, { label: "Tabells\u00F8k", variant: "simple", className: "aksel-property-filter__input", placeholder: "Type to filter...", ref: mergedRef, value: value, onChange: handleChange, onClick: () => {
                            setOpen(true);
                        }, onFocus: () => setOpen(true), size: "small", autoComplete: "off" }))),
            open && (react_1.default.createElement(AutoSuggestPopup, { options: options, onSelect: handleSelectOption, focusedValue: virtuallyFocusedOptionId, onClose: handleClose, safeZoneAnchor: inputRef, autoSuggestValue: value })))));
});
exports.AutoSuggest = AutoSuggest;
const AutoSuggestPopup = (0, react_1.forwardRef)(({ options, onSelect, focusedValue, onClose, safeZoneAnchor, autoSuggestValue, }, ref) => {
    return (react_1.default.createElement(DismissableLayer_1.DismissableLayer, { asChild: true, onDismiss: onClose, safeZone: { anchor: safeZoneAnchor } },
        react_1.default.createElement(Floating_1.Floating.Content, { ref: ref, align: "start", side: "bottom", fallbackPlacements: [], sideOffset: 8, className: "aksel-property-filter__popup" },
            react_1.default.createElement("div", { className: "aksel-property-filter__popup-inner" },
                react_1.default.createElement(ListboxRoot_1.default.Options, null, options.map((group) => (react_1.default.createElement(ListboxRoot_1.default.Group, { key: group.label, label: group.label }, group.options.map((item) => (react_1.default.createElement(AutoSuggestOption, { key: item.value, item: item, onSelect: onSelect, hasVirtualFocus: focusedValue === item.value, autoSuggestValue: autoSuggestValue })))))))))));
});
const AutoSuggestOption = react_1.default.memo(({ item, onSelect, hasVirtualFocus, autoSuggestValue, }) => (react_1.default.createElement(ListboxRoot_1.default.Option, { id: item.value, onClick: () => onSelect(item), hasVirtualFocus: hasVirtualFocus, "aria-selected": false },
    react_1.default.createElement(stack_1.VStack, { gap: "space-0" },
        react_1.default.createElement(typography_1.BodyShort, { as: "div", size: "small" },
            react_1.default.createElement(HighlightText, { text: item.label, highlightText: autoSuggestValue })),
        item.description && react_1.default.createElement(typography_1.Detail, { as: "div" }, item.description)))));
function HighlightText({ text, highlightText, }) {
    if (!text || !highlightText) {
        return react_1.default.createElement("span", null, text);
    }
    if (text === highlightText) {
        return react_1.default.createElement(Highlight, { text: text });
    }
    const { noMatches, matches } = highlightSplit(text, highlightText);
    const highlighted = [];
    noMatches.forEach((noMatch, idx) => {
        highlighted.push(react_1.default.createElement("span", { key: `noMatch-${idx}` }, noMatch));
        if (matches && idx < matches.length) {
            highlighted.push(react_1.default.createElement(Highlight, { key: `match-${idx}`, text: matches[idx] }));
        }
    });
    return react_1.default.createElement("span", null, highlighted);
}
function Highlight({ text }) {
    return react_1.default.createElement("mark", { className: "aksel-listbox__highlight" }, text);
}
function highlightSplit(text, highlightText) {
    /* Skip loooong texts */
    if (highlightText.length > 1000) {
        return { noMatches: [text], matches: null };
    }
    /* Case insensitive filtering */
    const filteringPattern = highlightText.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&");
    const regexp = new RegExp(filteringPattern, "gi");
    const noMatches = text.split(regexp);
    const matches = text.match(regexp);
    return { noMatches, matches };
}
//# sourceMappingURL=AutoSuggest.js.map