import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/*
 * Copyright (c) 2023-2025 Datalayer, Inc.
 * Distributed under the terms of the Modified BSD License.
 */
import React, { useState, useCallback, useRef, forwardRef, useMemo, useEffect, } from 'react';
import clsx from 'clsx';
import { SearchIcon, XIcon, LinkExternalIcon } from '@primer/octicons-react';
import { Button, FormControl, Text, TextInput, Label, } from '@primer/react-brand';
import { CircleYellowIcon } from '@datalayer/icons-react';
import { NavigationVisbilityObserver } from './NavigationVisbilityObserver.js';
import { useCoreStore } from '../../state/index.js';
import { useOnClickOutside, useFocusTrap, useKeyboardEscape, useWindowSize, useNavigate, } from '../../hooks/index.js';
import { useRunStore } from '../../state/index.js';
import { useId } from '../../hooks/index.js';
/**
 * Design tokens
 */
import '@primer/brand-primitives/lib/design-tokens/css/tokens/functional/components/subdomain-nav-bar/colors-with-modes.css';
/** * Main Stylesheet (as a CSS Module) */
import styles from './SubdomainNavBar.module.css';
const testIds = {
    root: 'SubdomainNavBar',
    get innerContainer() {
        return `${this.root}-inner-container`;
    },
    get menuButton() {
        return `${this.root}-menuButton`;
    },
    get menuLinks() {
        return `${this.root}-menuLinks`;
    },
    get liveRegion() {
        return `${this.root}-search-live-region`;
    },
};
function Root({ children, className, fixed = true, fullWidth = false, logoHref = 'https://datalayer.ai', title, titleHref = '/', ...rest }) {
    const navigate = useNavigate();
    const runStore = useRunStore();
    const { configuration } = useCoreStore();
    const { isMedium } = useWindowSize();
    const isDev = runStore.isDev;
    const [menuHidden, setMenuHidden] = useState(true);
    const [searchVisible, setSearchVisible] = useState(false);
    const [startOfContentButtonFocused, setStartOfContentButtonFocused] = useState(false);
    const mainElRef = useRef(null);
    const startOfContentID = useId('dla-start-of-content');
    const handleMobileMenuClick = () => setMenuHidden(!menuHidden);
    const handleSearchVisibility = () => setSearchVisible(!searchVisible);
    const focusTrapRef = useRef(null);
    useEffect(() => {
        const mainEl = document.querySelector('main');
        if (mainEl) {
            mainEl.id = mainEl.id || startOfContentID;
            mainElRef.current = mainEl;
        }
    }, [startOfContentID]);
    useFocusTrap({
        containerRef: focusTrapRef,
        restoreFocusOnCleanUp: true,
        disabled: menuHidden,
    });
    useKeyboardEscape(() => {
        setMenuHidden(true);
    });
    useEffect(() => {
        if (isMedium) {
            setMenuHidden(true);
        }
    }, [isMedium, menuHidden]);
    useEffect(() => {
        const newOverflowState = menuHidden ? 'auto' : 'hidden';
        document.body.style.overflow = newOverflowState;
    }, [menuHidden]);
    const setStartOfContentButtonFocusedTrue = useCallback(() => setStartOfContentButtonFocused(true), []);
    const setStartOfContentButtonFocusedFalse = useCallback(() => setStartOfContentButtonFocused(false), []);
    const hasLinks = useMemo(() => React.Children.toArray(children).filter(child => React.isValidElement(child) &&
        typeof child.type !== 'string' &&
        child.type === Link), 
    // eslint-disable-next-line react-hooks/exhaustive-deps
    []).length > 0;
    const menuItems = useMemo(() => React.Children.toArray(children)
        .map((child, index) => {
        if (React.isValidElement(child) && typeof child.type !== 'string') {
            if (child.type === Link) {
                return React.cloneElement(child, {
                    'data-navitemid': child.props.children,
                    href: child.props.href,
                    children: child.props.children,
                    style: {
                        [`--animation-order`]: index,
                    },
                });
            }
            return null;
        }
    })
        .filter(Boolean), [children]);
    return (_jsxs(_Fragment, { children: [_jsxs("div", { className: clsx(styles['SubdomainNavBar-outer-container'], fixed && styles['SubdomainNavBar-outer-container--fixed']), children: [_jsx(Button, { as: "a", href: `#${mainElRef.current?.id || startOfContentID}`, variant: "primary", className: clsx(styles['SubdomainNavBar-skip-to-content'], !startOfContentButtonFocused && 'visually-hidden'), onFocus: setStartOfContentButtonFocusedTrue, onBlur: setStartOfContentButtonFocusedFalse, children: "Skip to content" }), _jsx("header", { className: clsx(styles['SubdomainNavBar'], className), "data-testid": testIds.root, ...rest, children: _jsxs("div", { ref: focusTrapRef, className: clsx(styles['SubdomainNavBar-inner-container'], searchVisible &&
                                styles['SubdomainNavBar-inner-container--search-open'], !fullWidth && styles['SubdomainNavBar-inner-container--centered']), "data-testid": testIds.innerContainer, children: [_jsx("nav", { "aria-label": "global breadcrumb", children: _jsxs("ol", { className: styles['SubdomainNavBar-title-area'], children: [_jsx("li", { children: _jsx("a", { href: "javascript: return false;", "aria-label": "Datalayer Home", className: styles['SubdomainNavBar-logo-mark'], onClick: e => navigate('/', e), children: _jsx("img", { src: configuration.brand.logoUrl, style: { height: 25 } }) }) }), isDev && (_jsx("li", { children: _jsx(Label, { leadingVisual: _jsx(CircleYellowIcon, {}), color: "green-blue", children: "DEV" }) }))] }) }), hasLinks && (_jsx("nav", { id: "menu-navigation", "aria-label": title, className: styles['SubdomainNavBar-primary-nav'], "data-testid": testIds.menuLinks, children: _jsx(NavigationVisbilityObserver, { className: clsx(styles['SubdomainNavBar-primary-nav-list--invisible']), children: menuItems }) })), _jsxs("div", { className: clsx(styles['SubdomainNavBar-secondary-nav']), children: [React.Children.toArray(children)
                                            .map(child => {
                                            if (React.isValidElement(child) &&
                                                typeof child.type !== 'string') {
                                                if (child.type === Search) {
                                                    return React.cloneElement(child, {
                                                        active: searchVisible,
                                                        handlerFn: handleSearchVisibility,
                                                        title,
                                                    });
                                                }
                                                return null;
                                            }
                                        })
                                            .filter(Boolean), hasLinks && (_jsxs("button", { "aria-expanded": !menuHidden, "aria-label": "Menu", "aria-controls": "menu-navigation", "aria-haspopup": "true", className: clsx(styles['SubdomainNavBar-menu-button'], styles['SubdomainNavBar-mobile-menu-button'], !menuHidden && styles['SubdomainNavBar-menu-button--close']), "data-testid": testIds.menuButton, onClick: handleMobileMenuClick, children: [_jsx("div", { className: clsx(styles['SubdomainNavBar-menu-button-bar']) }), _jsx("div", { className: clsx(styles['SubdomainNavBar-menu-button-bar']) }), _jsx("div", { className: clsx(styles['SubdomainNavBar-menu-button-bar']) })] })), isMedium && (_jsx("div", { className: clsx(styles['SubdomainNavBar-button-area'], styles['SubdomainNavBar-button-area--visible']), children: _jsxs("div", { className: styles['SubdomainNavBar-button-area-inner'], children: [React.Children.toArray(children)
                                                        .map(child => {
                                                        if (React.isValidElement(child) &&
                                                            typeof child.type !== 'string') {
                                                            if (child.type === PrimaryAction) {
                                                                return child;
                                                            }
                                                            return null;
                                                        }
                                                    })
                                                        .filter(Boolean), React.Children.toArray(children)
                                                        .map(child => {
                                                        if (React.isValidElement(child) &&
                                                            typeof child.type !== 'string') {
                                                            if (child.type === SecondaryAction) {
                                                                return child;
                                                            }
                                                            return null;
                                                        }
                                                    })
                                                        .filter(Boolean)] }) })), !isMedium && (_jsxs("div", { className: clsx(styles['SubdomainNavBar-menu-wrapper'], menuHidden && styles['SubdomainNavBar-menu-wrapper--close']), children: [_jsxs("div", { children: [title && titleHref && (_jsx(Text, { as: "p", children: _jsx("a", { href: titleHref, "aria-label": `${title} home`, className: clsx(styles['SubdomainNavBar-link'], styles['SubdomainNavBar-link--title']), children: title }) })), hasLinks && !menuHidden && (_jsx(NavigationVisbilityObserver, { showOnlyOnNarrow: true, className: clsx(styles['SubdomainNavBar-primary-nav-list--visible']), children: menuItems }))] }), _jsx("div", { className: clsx(styles['SubdomainNavBar-button-area'], styles['SubdomainNavBar-button-area--visible']), children: _jsxs("div", { className: styles['SubdomainNavBar-button-area-inner'], children: [React.Children.toArray(children)
                                                                .map(child => {
                                                                if (React.isValidElement(child) &&
                                                                    typeof child.type !== 'string') {
                                                                    if (child.type === PrimaryAction) {
                                                                        return child;
                                                                    }
                                                                    return null;
                                                                }
                                                            })
                                                                .filter(Boolean), React.Children.toArray(children)
                                                                .map(child => {
                                                                if (React.isValidElement(child) &&
                                                                    typeof child.type !== 'string') {
                                                                    if (child.type === SecondaryAction) {
                                                                        return child;
                                                                    }
                                                                    return null;
                                                                }
                                                            })
                                                                .filter(Boolean)] }) })] }))] })] }) })] }), !mainElRef.current && _jsx("div", { id: `${startOfContentID}`, tabIndex: -1 })] }));
}
function Link({ href, className, children, isExternal, target, ...rest }) {
    return (_jsx("li", { className: clsx(styles['SubdomainNavBar-primary-nav-list-item'], className), ...rest, children: _jsxs("a", { href: href, target: target ?? '_self', className: clsx(styles['SubdomainNavBar-link']), children: [_jsx("span", { className: clsx(styles['SubdomainNavBar-link-text']), children: children }), isExternal && (_jsx(LinkExternalIcon, { size: 16, "aria-label": "External link" }))] }) }));
}
const SearchInternal = ({ active, title, searchResults, searchTerm, handlerFn, onSubmit, onChange, }, ref) => {
    const dialogRef = useRef(null);
    useFocusTrap({
        containerRef: dialogRef,
        restoreFocusOnCleanUp: true,
        disabled: !active,
    });
    useOnClickOutside(dialogRef, handlerFn);
    const [activeDescendant, setActiveDescendant] = useState(-1);
    const [listboxActive, setListboxActive] = useState();
    const [liveRegion, setLiveRegion] = useState(false);
    const handleClose = useCallback((event = null) => {
        if (handlerFn)
            handlerFn(event);
        setActiveDescendant(-1);
    }, [handlerFn]);
    useOnClickOutside(dialogRef, handleClose);
    useKeyboardEscape(() => {
        // Close the dialog if combobox is already collapsed
        if (!listboxActive && active) {
            handleClose();
            return false;
        }
        setListboxActive(false);
        setActiveDescendant(-1);
    });
    const handleAriaFocus = useCallback(event => {
        const supportedKeys = ['ArrowDown', 'ArrowUp', 'Escape', 'Enter'];
        const currentCount = activeDescendant;
        const searchResultsLength = searchResults ? searchResults.length : 0;
        const dialog = dialogRef.current;
        let count;
        // Prevent any other keys outside of supported from being prevented.
        // Only prevent "Enter" if activeDescendant is greater than -1.
        if (!supportedKeys.includes(event.key) ||
            (event.key === 'Enter' && activeDescendant === -1) ||
            !dialog) {
            return false;
        }
        event.preventDefault();
        if (event.key === 'ArrowDown') {
            // If count reaches last search result item, reset to -1
            count = currentCount < searchResultsLength - 1 ? currentCount + 1 : -1;
            setActiveDescendant(count);
        }
        else if (event.key === 'ArrowUp') {
            // Reset to last search result item if
            count =
                currentCount === -1 ? searchResultsLength - 1 : currentCount - 1;
            setActiveDescendant(count);
        }
        if (['ArrowDown', 'ArrowUp'].includes(event.key)) {
            dialog
                .querySelector(`#subdomainnavbar-search-result-${count}`)
                ?.scrollIntoView();
        }
        if (event.key === 'Enter') {
            const link = dialog.querySelector(`#subdomainnavbar-search-result-${activeDescendant} a`);
            link.click();
        }
    }, [searchResults, activeDescendant]);
    const searchLiveRegion = useCallback(() => {
        // Adding a non-breaking space and then removing it will force screen readers to announce the text,
        // as it thinks that there was a change within the live region.
        setLiveRegion(true);
        setTimeout(() => {
            if (active)
                setLiveRegion(false);
        }, 200);
    }, [active]);
    useEffect(() => {
        // We want to set "listboxActive" when search results are present,
        // or the user pressed "Escape". We watch for "searchTerm", as we -
        // want the listbox to become active if they pressed "Escape", and -
        // adjusted their existing value.
        const search = searchResults && searchResults.length ? true : false;
        setListboxActive(search);
        searchLiveRegion();
    }, [searchResults, searchTerm, searchLiveRegion]);
    return (_jsxs(_Fragment, { children: [_jsx("div", { className: clsx(styles['SubdomainNavBar-search-trigger']), children: _jsx("button", { "aria-label": "search", className: styles['SubdomainNavBar-search-button'], onClick: handlerFn, "data-testid": "toggle-search", children: _jsx(SearchIcon, {}) }) }), active && (_jsxs("div", { ref: dialogRef, role: "dialog", "aria-label": `Search ${title}`, "aria-modal": "true", tabIndex: -1, className: clsx(styles['SubdomainNavBar-search-dialog']), children: [_jsxs("div", { className: clsx(styles['SubdomainNavBar-search-dialog-control-area']), children: [_jsx("form", { className: clsx(styles['SubdomainNavBar-search-form']), onSubmit: onSubmit, role: "search", children: _jsxs(FormControl, { fullWidth: true, size: "medium", children: [_jsx(FormControl.Label, { visuallyHidden: true, children: "Search" }), _jsx(TextInput, { ref: ref, className: clsx(styles['SubdomainNavBar-search-text-input']), name: "search", role: "combobox", "aria-expanded": listboxActive, "aria-controls": "listbox-search-results", placeholder: `Search ${title}`, onChange: onChange, defaultValue: searchTerm, invisible: true, leadingVisual: _jsx(SearchIcon, { size: 16 }), "aria-activedescendant": activeDescendant === -1
                                                ? undefined
                                                : `subdomainnavbar-search-result-${activeDescendant}`, onKeyDown: handleAriaFocus })] }) }), _jsx("button", { "aria-label": "Close", className: clsx(styles['SubdomainNavBar-menu-button'], styles['SubdomainNavBar-menu-button--close']), onClick: handleClose, children: _jsx(XIcon, { size: 24 }) })] }), _jsxs("div", { id: "listbox-search-results", children: [listboxActive && (_jsxs("div", { className: clsx(styles['SubdomainNavBar-search-results-container']), children: [_jsxs(Text, { id: "subdomainnavbar-search-results-heading", className: styles['SubdomainNavBar-search-results-heading'], children: ["Results for \u201C", searchTerm, "\u201D"] }), _jsx("ul", { role: "listbox", tabIndex: 0, "aria-labelledby": "subdomainnavbar-search-results-heading", className: clsx(styles['SubdomainNavBar-search-results']), children: searchResults?.map((result, index) => (_jsxs("li", { id: `subdomainnavbar-search-result-${index}`, className: styles['SubdomainNavBar-search-result-item'], role: "option", "aria-selected": index === activeDescendant, children: [_jsx("div", { className: styles['SubdomainNavBar-search-result-item-container'], children: _jsx("a", { href: result.url, children: result.title }) }), _jsx(Text, { as: "p", size: "200", id: `subdomainnavbar-search-result-item-desc${index}`, className: styles['SubdomainNavBar-search-result-item-desc'], children: result.description }), _jsxs("div", { children: [_jsx(Text, { size: "100", className: styles['SubdomainNavBar-search-result-item-desc'], children: result.date }), result.category && (_jsxs(_Fragment, { children: [_jsxs(Text, { size: "100", className: styles['SubdomainNavBar-search-result-item-desc'], children: [' ', "\u2022", ' '] }), _jsx(Text, { size: "100", className: styles['SubdomainNavBar-search-result-item-desc'], children: result.category })] }))] })] }, `${result.title}-${index}`))) })] })), _jsxs("div", { "aria-live": "polite", "aria-atomic": "true", "data-testid": testIds.liveRegion, className: "visually-hidden", children: [`${searchResults?.length} suggestions.`, liveRegion && _jsx("span", { children: "\u00A0" })] })] })] }))] }));
};
const Search = forwardRef(SearchInternal);
function PrimaryAction({ children, ...rest }) {
    const { hasArrow = false, size = 'small' } = rest;
    return (_jsx(Button, { as: "a", href: "javascript: return false;", className: clsx(styles['SubdomainNavBar-cta-button']), variant: "primary", size: size, hasArrow: hasArrow, ...rest, children: children }));
}
function SecondaryAction({ children, ...rest }) {
    const { hasArrow = false, size = 'small' } = rest;
    return (_jsx(Button, { as: "a", href: "javascript: return false;", className: clsx(styles['SubdomainNavBar-cta-button'], styles['SubdomainNavBar-cta-button--secondary']), size: size, hasArrow: hasArrow, ...rest, children: children }));
}
export const SubdomainNavBar = Object.assign(Root, {
    Link,
    Search,
    PrimaryAction,
    SecondaryAction,
    testIds,
});
