import { jsx, jsxs } from 'react/jsx-runtime';
import { createContext, useContext, forwardRef, useRef, useEffect, useCallback, useState, useId, useMemo, Children, useLayoutEffect } from 'react';
import { c as cx } from './index-De1g9FRV.js';
import { S as SvgKeyboardArrowDown } from './keyboard_arrow_down-C8WQ38p1.js';
import { I as Icon } from './Icon-B4uCvMU9.js';
import { t as textStyles } from './Text.module-BcVew1AQ.js';
import { u as useLayoutPropsUtil } from './useLayoutPropsUtil-DjqeAJZ9.js';
import { u as useMergeRefs } from './useMergeRefs-Dfmtq9cI.js';

import './SideNav.css';const sidenav = "_sidenav_mozz8_1";
const root = "_root_mozz8_2";
const group = "_group_mozz8_6";
const hidden = "_hidden_mozz8_38";
const arrow = "_arrow_mozz8_60";
const styles = {
	sidenav: sidenav,
	root: root,
	"sidenav-group": "_sidenav-group_mozz8_3",
	"sidenav-link": "_sidenav-link_mozz8_4",
	"sidenav-collapsible": "_sidenav-collapsible_mozz8_5",
	group: group,
	hidden: hidden,
	"group-label": "_group-label_mozz8_52",
	arrow: arrow,
	"has-indicator": "_has-indicator_mozz8_134"
};

const sideNavKeyboardNavigation = (e, links, current) => {
  const currentIndex = Array.prototype.indexOf.call(links, current.current);
  switch (e.key) {
    case "ArrowDown":
      if (!links) return;
      e.preventDefault();
      links[currentIndex].setAttribute("tabindex", "-1");
      if (currentIndex === links.length - 1) {
        links[0].setAttribute("tabindex", "0");
        links[0].focus();
        break;
      }
      links[currentIndex + 1].setAttribute("tabindex", "0");
      links[currentIndex + 1].focus();
      break;
    case "ArrowUp":
      e.preventDefault();
      if (!links) return;
      links[currentIndex].setAttribute("tabindex", "-1");
      if (currentIndex === 0) {
        links[links.length - 1].setAttribute("tabindex", "0");
        links[links.length - 1].focus();
        break;
      }
      links[currentIndex - 1].setAttribute("tabindex", "0");
      links[currentIndex - 1].focus();
      break;
  }
};

const SideNavContext$1 = createContext(null);

const useSideNav = () => {
  const context = useContext(SideNavContext$1);
  if (context == null) {
    throw new Error("useSideNav must be wrapped in <SideNav />");
  }
  return context;
};

const SideNavLink$1 = forwardRef(
  (props, ref) => {
    const {
      className,
      children,
      href,
      id,
      active,
      onClick,
      onKeyDown,
      onKeyUp,
      style,
      disabled,
      ...rest
    } = props;
    const { links } = useSideNav();
    const linkRef = useRef(null);
    const { activeIds, addActiveId, removeActiveId } = useSideNav();
    useEffect(() => {
      if (!activeIds.has(id) && active) {
        addActiveId(id);
        return;
      }
      if (activeIds.has(id) && !active) {
        removeActiveId(id);
      }
    }, [active, activeIds, addActiveId, removeActiveId, id]);
    function onKeyDownHandler(e) {
      sideNavKeyboardNavigation(e, links, linkRef);
      onKeyDown?.(e, id);
    }
    function onKeyUpHandler(e) {
      if (disabled) return;
      if (e.code === "Space" || e.code === "Enter") {
        e.preventDefault();
        if (onClick) {
          e.currentTarget.click();
        }
      }
      onKeyUp?.(e, id);
    }
    function onClickHandler(e) {
      if (disabled) {
        e.preventDefault();
        return;
      }
      const current = Array.prototype.slice.call(links).filter((child) => child.tabIndex === 0)[0];
      if (current) current.setAttribute("tabindex", "-1");
      linkRef.current?.setAttribute("tabindex", "0");
      linkRef.current?.focus();
      onClick?.(e, id);
    }
    return /* @__PURE__ */ jsx("li", { className, "data-anv": "sidenav-link", style, ref, children: /* @__PURE__ */ jsx(
      "a",
      {
        className: styles["sidenav-link"],
        "aria-current": active ? "page" : void 0,
        href,
        ref: linkRef,
        onClick: onClickHandler,
        onKeyDown: onKeyDownHandler,
        onKeyUp: onKeyUpHandler,
        id,
        "aria-disabled": disabled,
        tabIndex: active ? 0 : -1,
        ...rest,
        children
      }
    ) });
  }
);
SideNavLink$1.displayName = "SideNavLink";

const defaultContext = {
  location: "",
  setLocation: (_location) => {
  }
};
const SideNavContext = createContext(defaultContext);
const useSideNavContext = () => useContext(SideNavContext);

const SideNavLinkWithRouting = forwardRef(
  ({ href, pathname, search, onClick, ...rest }, ref) => {
    const { location, setLocation } = useSideNavContext();
    const to = pathname + (search ?? "");
    const handleClick = useCallback(
      (...args) => {
        args[0].preventDefault();
        history.pushState(null, "", to);
        setLocation(to);
        return onClick?.(...args);
      },
      [onClick, to, setLocation]
    );
    return /* @__PURE__ */ jsx(
      SideNavLink$1,
      {
        href: pathname != null ? to : href,
        active: pathname === location,
        onClick: pathname != null ? handleClick : onClick,
        ref,
        ...rest
      }
    );
  }
);
SideNavLinkWithRouting.displayName = SideNavLink$1.displayName;
const SideNavLink = forwardRef(
  (rest, ref) => {
    if ("pathname" in rest) {
      return /* @__PURE__ */ jsx(SideNavLinkWithRouting, { ref, ...rest });
    } else {
      return /* @__PURE__ */ jsx(SideNavLink$1, { ref, ...rest });
    }
  }
);
SideNavLink.displayName = SideNavLink$1.displayName;

const SideNavCollapsible = forwardRef((props, ref) => {
  const {
    className,
    children,
    label,
    onClick,
    onKeyDown,
    defaultExpanded = false,
    expanded: expandedControlled,
    ...rest
  } = props;
  const [expanded, setExpanded] = useState(defaultExpanded);
  const [hasSelected, setHasSelected] = useState(false);
  const sideNavGroupLabelRef = useRef(null);
  const groupRef = useRef(null);
  const sideNavGroupClassNames = cx(styles["sidenav-collapsible"], className);
  const { links, reCalculateLinks } = useSideNav();
  const groupId = useId();
  const setExpandedUncontrolled = (newState) => {
    if (expandedControlled === void 0)
      setExpanded((prev) => {
        if (newState !== void 0) return newState;
        return !prev;
      });
  };
  useEffect(() => {
    if (expandedControlled !== void 0) {
      setExpanded(expandedControlled);
    }
  }, [expandedControlled]);
  const { activeIds } = useSideNav();
  const childIds = useMemo(
    () => Children.map(children, (child) => child.props)?.map(
      (item) => item.id
    ) || [],
    [children]
  );
  function handleOnClick(e) {
    setExpandedUncontrolled();
    setTimeout(() => reCalculateLinks(), 0);
    const current = Array.prototype.slice.call(links).filter((child) => child.tabIndex === 0)[0];
    if (current) current.setAttribute("tabindex", "-1");
    sideNavGroupLabelRef.current?.setAttribute("tabindex", "0");
    sideNavGroupLabelRef.current?.focus();
    onClick?.(e);
  }
  function handleKeyDown(e) {
    sideNavKeyboardNavigation(e, links, sideNavGroupLabelRef);
    switch (e.key) {
      case "ArrowRight":
        setExpanded(true);
        setTimeout(() => reCalculateLinks(), 0);
        break;
      case "ArrowLeft":
        setExpanded(false);
        setTimeout(() => reCalculateLinks(), 0);
        break;
    }
    onKeyDown?.(e);
  }
  useLayoutEffect(() => {
    const hasActiveChildren = childIds.some((id) => activeIds.has(id));
    if (hasActiveChildren) {
      setExpandedUncontrolled(true);
      setHasSelected(true);
      setTimeout(() => {
        const selectedChild = groupRef.current?.querySelector(`[active='true']`);
        selectedChild?.setAttribute("tabindex", "0");
        reCalculateLinks();
      }, 0);
    }
  }, []);
  useEffect(() => {
    if (!activeIds.size || !childIds.some((id) => activeIds.has(id))) {
      setHasSelected(false);
      return;
    }
    setHasSelected(true);
  }, [activeIds, childIds]);
  return /* @__PURE__ */ jsxs(
    "li",
    {
      ref,
      "data-anv": "sidenav-collapsible",
      ...rest,
      className: sideNavGroupClassNames,
      children: [
        /* @__PURE__ */ jsxs(
          "button",
          {
            "aria-expanded": expanded,
            "aria-controls": groupId,
            type: "button",
            tabIndex: -1,
            onClick: handleOnClick,
            ref: sideNavGroupLabelRef,
            className: cx(styles["sidenav-link"], {
              [styles["has-indicator"]]: hasSelected && !expanded
            }),
            onKeyDown: handleKeyDown,
            children: [
              label,
              /* @__PURE__ */ jsx(Icon, { className: styles["arrow"], inherit: true, svg: SvgKeyboardArrowDown, "aria-hidden": true })
            ]
          }
        ),
        /* @__PURE__ */ jsx(
          "ul",
          {
            id: groupId,
            ref: groupRef,
            className: cx(styles["group"], !expanded && styles.hidden),
            children
          }
        )
      ]
    }
  );
});
SideNavCollapsible.displayName = "SideNavCollapsible";

const SideNavGroup = forwardRef(
  (props, ref) => {
    const { children, label, ...rest } = props;
    const sideNavGroupClassNames = cx(styles["sidenav-group"]);
    const groupLabelClassNames = cx(
      textStyles["eyebrow"],
      styles["group-label"]
    );
    const groupLabelId = useId();
    return /* @__PURE__ */ jsxs("li", { ref, "data-anv": "sidenav-group", ...rest, children: [
      /* @__PURE__ */ jsx("label", { id: groupLabelId, className: groupLabelClassNames, children: label }),
      /* @__PURE__ */ jsx("ul", { "aria-labelledby": groupLabelId, className: sideNavGroupClassNames, children })
    ] });
  }
);
SideNavGroup.displayName = "SideNavGroup";

const SideNavProvider = ({ children }) => {
  const [location, setLocation] = useState("");
  useEffect(() => {
    setLocation(window.location.pathname);
  }, []);
  const sideNavContext = {
    location,
    setLocation
  };
  return /* @__PURE__ */ jsx(SideNavContext.Provider, { value: sideNavContext, children });
};

const SideNav = Object.assign(
  forwardRef(function SideNavInner(props, ref) {
    const { layoutStyles, componentProps } = useLayoutPropsUtil(props);
    const [activeIds, setActiveIds] = useState(/* @__PURE__ */ new Set());
    const { className, children, style, ...rest } = componentProps;
    const addActiveId = useCallback(
      (id) => {
        if (activeIds.has(id)) return;
        const newIds = new Set(activeIds);
        newIds.add(id);
        setActiveIds(newIds);
      },
      [activeIds]
    );
    const removeActiveId = useCallback(
      (id) => {
        if (!activeIds.has(id)) return;
        const newIds = new Set(activeIds);
        newIds.delete(id);
        setActiveIds(newIds);
      },
      [activeIds]
    );
    const sideNavRef = useRef(null);
    const [links, setLinks] = useState();
    const styleCombined = {
      ...style,
      ...layoutStyles
    };
    const reCalculateLinks = useCallback(() => {
      if (sideNavRef.current) {
        const items = sideNavRef.current.querySelectorAll(
          "li[data-anv='sidenav-link'] a:not([aria-disabled='true']), li[data-anv='sidenav-collapsible'] button[aria-expanded]:not([aria-disabled='true'])"
        );
        setLinks(items);
      }
    }, [sideNavRef]);
    useEffect(() => {
      reCalculateLinks();
    }, [reCalculateLinks]);
    const sidenavClassNames = cx([styles["sidenav"]], className);
    const value = useMemo(
      () => ({
        links,
        reCalculateLinks,
        activeIds,
        addActiveId,
        removeActiveId
      }),
      [links, activeIds, addActiveId, removeActiveId, reCalculateLinks]
    );
    return /* @__PURE__ */ jsx(SideNavProvider, { children: /* @__PURE__ */ jsx(SideNavContext$1.Provider, { value, children: /* @__PURE__ */ jsx(
      "nav",
      {
        ref: useMergeRefs([sideNavRef, ref]),
        className: sidenavClassNames,
        style: styleCombined,
        "data-anv": "sidenav",
        ...rest,
        children: /* @__PURE__ */ jsx("ul", { className: styles["root"], children })
      }
    ) }) });
  }),
  {
    /**
     * SideNavLink component for individual navigation links.
     *
     * Features:
     * - Individual navigation links with active state support
     * - Keyboard navigation integration with arrow keys
     * - Focus management and tabindex handling
     * - Accessible with proper ARIA attributes
     * - Click and keyboard event handling
     * - Disabled state support
     *
     * @example
     * <SideNav.Link id="intro" href="/intro" active>
     *   Introduction
     * </SideNav.Link>
     */
    Link: SideNavLink,
    /**
     * SideNavCollapsible component for expandable navigation sections.
     *
     * Features:
     * - Expandable/collapsible navigation sections
     * - Controlled and uncontrolled expansion states
     * - Keyboard navigation with arrow keys for expansion
     * - Automatic expansion when child links are active
     * - Accessible with proper ARIA expanded states
     * - Visual indicators for active children
     *
     * @example
     * <SideNav.Collapsible label="Components">
     *   <SideNav.Link id="button" href="/components/button">
     *     Button
     *   </SideNav.Link>
     *   <SideNav.Link id="input" href="/components/input">
     *     Input
     *   </SideNav.Link>
     * </SideNav.Collapsible>
     */
    Collapsible: SideNavCollapsible,
    /**
     * SideNavGroup component for grouping related navigation links.
     *
     * Features:
     * - Groups related navigation links with labels
     * - Accessible with proper ARIA labeling
     * - Semantic grouping for screen readers
     * - Consistent styling and spacing
     *
     * @example
     * <SideNav.Group label="Getting Started">
     *   <SideNav.Link id="intro" href="/intro">
     *     Introduction
     *   </SideNav.Link>
     *   <SideNav.Link id="installation" href="/installation">
     *     Installation
     *   </SideNav.Link>
     * </SideNav.Group>
     */
    Group: SideNavGroup
  }
);
SideNav.displayName = "SideNav";

export { SideNav as S };
//# sourceMappingURL=SideNav-DoxX8Vi-.js.map
