/* side-nav.tsx generated by @compiled/babel-plugin v0.38.1 */
import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import "./side-nav.compiled.css";
import * as React from 'react';
import { ax, ix } from "@compiled/react/runtime";
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { bind } from 'bind-event-listener';
import { flushSync } from 'react-dom';
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
import useStableRef from '@atlaskit/ds-lib/use-stable-ref';
import { OpenLayerObserverNamespaceProvider, useOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
import { fg } from '@atlaskit/platform-feature-flags';
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
import { media } from '@atlaskit/primitives/responsive';
import { useSkipLinkInternal } from '../../../context/skip-links/skip-links-context';
import { TopNavStartElement } from '../../../context/top-nav-start/top-nav-start-context';
import { bannerMountedVar, contentHeightWhenFixed, contentInsetBlockStart, localSlotLayers, sideNavLiveWidthVar, sideNavPanelSplitterId, sideNavVar, topNavMountedVar, UNSAFE_sideNavLayoutVar } from '../constants';
import { DangerouslyHoistSlotSizes } from '../hoist-slot-sizes-context';
import { DangerouslyHoistCssVarToDocumentRoot } from '../hoist-utils';
import { useLayoutId } from '../id-utils';
import { PanelSplitterProvider } from '../panel-splitter/provider';
import { useResizingWidthCssVarOnRootElement } from '../use-resizing-width-css-var-on-root-element';
import { useSafeDefaultWidth } from '../use-safe-default-width';
import { useSideNavRef } from './element-context';
import { sideNavFlyoutCloseDelayMs } from './flyout-close-delay-ms';
import { useIsSideNavShortcutEnabled } from './is-side-nav-shortcut-enabled-context';
import { sideNavToggleTooltipKeyboardShortcut } from './side-nav-toggle-tooltip-keyboard-shortcut';
import { SideNavToggleButtonElement } from './toggle-button-context';
import { useExpandSideNav } from './use-expand-side-nav';
import { useSideNavToggleKeyboardShortcut } from './use-side-nav-toggle-keyboard-shortcut';
import { useSideNavVisibility } from './use-side-nav-visibility';
import { useSideNavVisibilityCallbacks } from './use-side-nav-visibility-callbacks';
import { useToggleSideNav } from './use-toggle-side-nav';
import { SetSideNavVisibilityState, SideNavVisibilityState } from './visibility-context';
var panelSplitterResizingVar = '--n_snvRsz';
var widthResizeBounds = {
  min: '240px',
  max: '50vw'
};
function getResizeBounds() {
  return widthResizeBounds;
}

/**
 * We are using JS to detect Firefox and disable animations, instead of using CSS, as Compiled currently does not merge duplicate
 * CSS at-rules when at-rules are nested: https://github.com/atlassian-labs/compiled/blob/e04a325915e1d13010205089e4915de0e53bc2d4/packages/css/src/plugins/merge-duplicate-at-rules.ts#L5
 * Avoiding nesting the `@supports` at-rule inside of `@media` means Compiled can remove duplicate styles from the generated CSS.
 */
var isFirefox = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
var openLayerObserverSideNavNamespace = 'side-nav';
var styles = {
  root: "_nd5l1b6c _191wglyw _t51zglyw _bfhk1bhr _16qs1cd0 _vchhusvi _4t3ieqxy _152timx3 _kqsw1if8 _1bsb1ego _1pbycs5v _14b5hc79 _qilnk0mc _p5cl7r9e _4ap3vuon _scbpglyw",
  flyoutOpen: "_qiln1gzg _p5clglyw _4ap31bhr _scbp1cd0 _139f8iot _1tpvfnf5 _sylc1a5r _oyeijq3t",
  flyoutAnimateClosed: "_1e0cglyw _qiln1gzg _139f8iot _1tpvfnf5 _sylc1a5r _1uwsjq3t",
  animationRTLSupport: "_15yekb7n _65m41mrw",
  flyoutBaseStylesFullHeightSidebar: "_qiln1gzg _p5clglyw _4ap31bhr _scbp1cd0 _17ly8iot _177m1a5r",
  flyoutOpenFullHeightSidebar: "_hjoifnf5 _vgub1ku9 _s2eg1p9u",
  flyoutAnimateClosedFullHeightSidebar: "_dm25glyw _hjoifnf5 _vgub1mm8 _hh1u1p9u",
  flexContainer: "_4t3i1osq _1e0c1txw _2lx21bp4 _1bah1yb4",
  hiddenMobileAndDesktop: "_1e0cglyw",
  hiddenMobileOnly: "_1e0cglyw _dm2518uv",
  hiddenDesktopOnly: "_dm25glyw",
  animationBaseStyles: "_10t88iot _1vrh1a5r _xrrpfnf5",
  expandAnimationMobile: "_1xq51ku9 _1nu51p9u",
  collapseAnimationMobile: "_1lh81gzg _1xq51mm8 _aadi1p9u",
  expandAnimationDesktop: "_1sg8k0mc _vgub1ku9 _s2eg1p9u",
  collapseAnimationDesktop: "_1sg81gzg _vgub1mm8 _hh1u1p9u",
  fullHeightSidebar: "_165t56xv _180k1wjm _26vxoned _1mt19dtb"
};
var fallbackDefaultWidth = 320;
export var onPeekStartDelayMs = 500;

/**
 * We need an additional component layer so we can wrap the side nav in a `OpenLayerObserver` and have access to the
 * context value.
 */
function SideNavInternal(_ref) {
  var _sideNavState$lastTri;
  var children = _ref.children,
    defaultCollapsed = _ref.defaultCollapsed,
    _ref$defaultWidth = _ref.defaultWidth,
    defaultWidthProp = _ref$defaultWidth === void 0 ? fallbackDefaultWidth : _ref$defaultWidth,
    testId = _ref.testId,
    _ref$label = _ref.label,
    label = _ref$label === void 0 ? 'Sidebar' : _ref$label,
    _ref$skipLinkLabel = _ref.skipLinkLabel,
    skipLinkLabel = _ref$skipLinkLabel === void 0 ? label : _ref$skipLinkLabel,
    onExpand = _ref.onExpand,
    onCollapse = _ref.onCollapse,
    onPeekStart = _ref.onPeekStart,
    onPeekEnd = _ref.onPeekEnd,
    providedId = _ref.id,
    canToggleWithShortcut = _ref.canToggleWithShortcut;
  var id = useLayoutId({
    providedId: providedId
  });
  var expandSideNav = useExpandSideNav({
    trigger: 'skip-link'
  });
  /**
   * Called after clicking on the side nav skip link, and ensures the side nav is expanded so that it is focusable.
   *
   * We need to update the DOM synchronously because `.focus()` is called synchronously after this state update.
   */
  var synchronouslyExpandSideNav = useCallback(function () {
    flushSync(function () {
      /**
       * Calling this unconditionally and relying on it to avoid no-op renders.
       *
       * We _could_ call it conditionally, but we'd be duplicating the screen size checks `expandSideNav` makes.
       */
      expandSideNav();
    });
  }, [expandSideNav]);
  useSkipLinkInternal({
    id: id,
    label: skipLinkLabel,
    onBeforeNavigate: synchronouslyExpandSideNav
  });
  var sideNavState = useContext(SideNavVisibilityState);
  var setSideNavState = useContext(SetSideNavVisibilityState);
  var _useSideNavVisibility = useSideNavVisibility({
      defaultCollapsed: defaultCollapsed
    }),
    isExpandedOnDesktop = _useSideNavVisibility.isExpandedOnDesktop,
    isExpandedOnMobile = _useSideNavVisibility.isExpandedOnMobile;
  // We are placing `defaultCollapsed` into a state container so we can have a stable reference to the initial value.
  // This is so we can use it in an effect _that only runs once_, after the initial render on the client,
  // to sync the side nav context (provided in `<Root>`) with the `defaultCollapsed` prop provided to `<SideNav>`.
  var _useState = useState(defaultCollapsed),
    _useState2 = _slicedToArray(_useState, 1),
    initialDefaultCollapsed = _useState2[0];
  var defaultWidth = useSafeDefaultWidth({
    defaultWidthProp: defaultWidthProp,
    fallbackDefaultWidth: fallbackDefaultWidth,
    slotName: 'SideNav'
  });
  var _useState3 = useState(defaultWidth),
    _useState4 = _slicedToArray(_useState3, 2),
    width = _useState4[0],
    setWidth = _useState4[1];
  var clampedWidth = "clamp(".concat(widthResizeBounds.min, ", ").concat(width, "px, ").concat(widthResizeBounds.max, ")");
  var dangerouslyHoistSlotSizes = useContext(DangerouslyHoistSlotSizes);
  var navRef = useRef(null);
  /**
   * Used to share the side nav element with the `Panel`,
   * which observes the side nav to determine its maximum width.
   */
  var sharedRef = useSideNavRef();
  var mergedRef = mergeRefs([navRef, sharedRef]);
  var toggleButtonElement = useContext(SideNavToggleButtonElement);
  var topNavStartElement = useContext(TopNavStartElement);
  var devTimeOnlyAttributes = {};
  var openLayerObserver = useOpenLayerObserver();
  var flyoutStateRef = useRef({
    type: 'not-active'
  });
  var isFlyoutVisible = (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open';
  var isExpandedOnDesktopRef = useStableRef(isExpandedOnDesktop);
  var hasPeekStartedRef = useRef(false);
  var onPeekStartRef = useStableRef(onPeekStart);
  var onPeekEndRef = useStableRef(onPeekEnd);
  var onPeekStartTimeoutIdRef = useRef(undefined);
  useEffect(function () {
    return function () {
      clearTimeout(onPeekStartTimeoutIdRef.current);
    };
  }, []);
  var updateFlyoutState = useMemo(function () {
    function tryAbortPendingClose() {
      if (flyoutStateRef.current.type === 'waiting-for-close') {
        flyoutStateRef.current.abort();
      }
    }
    function open() {
      var prevFlyoutState = flyoutStateRef.current;
      tryAbortPendingClose();
      flyoutStateRef.current = {
        type: 'open'
      };
      setSideNavState(function (currentState) {
        if ((currentState === null || currentState === void 0 ? void 0 : currentState.desktop) === 'collapsed' && (currentState === null || currentState === void 0 ? void 0 : currentState.flyout) !== 'open') {
          return _objectSpread(_objectSpread({}, currentState), {}, {
            flyout: 'open'
          });
        }
        return currentState;
      });

      // Avoid redundant calls to `onPeekStart()`
      if (prevFlyoutState.type === 'not-active') {
        clearTimeout(onPeekStartTimeoutIdRef.current);
        onPeekStartTimeoutIdRef.current = setTimeout(function () {
          var _onPeekStartRef$curre;
          // If the flyout isn't still open after ~500ms then we won't count the peek
          // As we want to track user intention rather than all hovers
          if (isExpandedOnDesktopRef.current || flyoutStateRef.current.type !== 'open') {
            return;
          }
          hasPeekStartedRef.current = true;
          (_onPeekStartRef$curre = onPeekStartRef.current) === null || _onPeekStartRef$curre === void 0 || _onPeekStartRef$curre.call(onPeekStartRef);
        }, onPeekStartDelayMs);
      }
    }
    function close() {
      var prevFlyoutState = flyoutStateRef.current;
      tryAbortPendingClose();
      flyoutStateRef.current = {
        type: 'not-active'
      };
      setSideNavState(function (currentState) {
        if ((currentState === null || currentState === void 0 ? void 0 : currentState.desktop) === 'collapsed' && (currentState === null || currentState === void 0 ? void 0 : currentState.flyout) === 'open') {
          return _objectSpread(_objectSpread({}, currentState), {}, {
            flyout: 'triggered-animate-close'
          });
        }
        return currentState;
      });

      // Avoid redundant calls to `onPeekEnd()`
      if (prevFlyoutState.type !== 'not-active' && hasPeekStartedRef.current) {
        var _onPeekEndRef$current;
        hasPeekStartedRef.current = false;
        (_onPeekEndRef$current = onPeekEndRef.current) === null || _onPeekEndRef$current === void 0 || _onPeekEndRef$current.call(onPeekEndRef, {
          trigger: isExpandedOnDesktopRef.current ? 'side-nav-expand' : 'mouse-leave'
        });
      }
    }
    return function onAction(action) {
      if (action === 'drag-from-flyout-started') {
        open();
        flyoutStateRef.current = {
          type: 'is-dragging-from-flyout'
        };
        return;
      }
      if (action === 'drag-from-flyout-finished') {
        open();
        return;
      }

      // ignoring all actions until the drag is finished
      if (flyoutStateRef.current.type === 'is-dragging-from-flyout') {
        return;
      }
      if (action === 'open') {
        open();
        return;
      }
      if (action === 'waiting-for-close') {
        if (flyoutStateRef.current.type === 'waiting-for-close') {
          return;
        }

        // A timeout is used to close the flyout after a delay when the user mouses out of the flyout area, and to allow
        // us to cancel the close if the user mouses back in.
        var timeout = setTimeout(function () {
          updateFlyoutState('ready-to-close');
        }, sideNavFlyoutCloseDelayMs);
        flyoutStateRef.current = {
          type: 'waiting-for-close',
          abort: function abort() {
            clearTimeout(timeout);
          }
        };
        return;
      }
      if (action === 'ready-to-close') {
        // If there are no open layers, we can close the flyout.
        if (openLayerObserver.getCount({
          namespace: openLayerObserverSideNavNamespace
        }) === 0) {
          close();
          return;
        }
        flyoutStateRef.current = {
          type: 'ready-to-close'
        };
        return;
      }
      if (action === 'force-close') {
        close();
        return;
      }
    };
  }, [isExpandedOnDesktopRef, onPeekEndRef, onPeekStartRef, openLayerObserver, setSideNavState]);
  var toggleVisibilityByScreenResize = useToggleSideNav({
    trigger: 'screen-resize'
  });
  var toggleVisibilityByClickOutsideOnMobile = useToggleSideNav({
    trigger: 'click-outside-on-mobile'
  });

  // Moving to `useLayoutEffect` so that there's no visual shift in non-SSR environments when using legacy API
  // For SSR the new API is still necessary
  useLayoutEffect(function () {
    if (sideNavState !== null) {
      // Only need to do an initial sync if it hasn't been initialized from Root
      return;
    }

    // Sync the visibility in context (provided in `<Root>`) with the local `defaultCollapsed` prop provided to `SideNav`
    // after SSR hydration. This should only run once, after the initial render on the client.
    setSideNavState({
      desktop: initialDefaultCollapsed ? 'collapsed' : 'expanded',
      mobile: 'collapsed',
      flyout: 'closed',
      lastTrigger: null
    });
  }, [initialDefaultCollapsed, setSideNavState, sideNavState]);
  var handleExpand = useCallback(function (_ref2) {
    var screen = _ref2.screen,
      trigger = _ref2.trigger;
    if (fg('navx-full-height-sidebar')) {
      onExpand === null || onExpand === void 0 || onExpand({
        screen: screen,
        trigger: trigger
      });
    } else {
      onExpand === null || onExpand === void 0 || onExpand({
        screen: screen
      });
    }

    // When the side nav gets expanded, we close the flyout to reset it.
    // This prevents the flyout from staying open and ensures we are respecting the user's intent to expand.
    updateFlyoutState('force-close');
  }, [onExpand, updateFlyoutState]);
  var handleCollapse = useCallback(function (_ref3) {
    var screen = _ref3.screen,
      trigger = _ref3.trigger;
    if (fg('navx-full-height-sidebar')) {
      onCollapse === null || onCollapse === void 0 || onCollapse({
        screen: screen,
        trigger: trigger
      });
    } else {
      onCollapse === null || onCollapse === void 0 || onCollapse({
        screen: screen
      });
    }

    // When the side nav gets collapsed, we close the flyout to reset it.
    // This prevents the flyout from staying open and ensures we are respecting the user's intent to collapse.
    updateFlyoutState('force-close');
  }, [onCollapse, updateFlyoutState]);
  useSideNavVisibilityCallbacks({
    onExpand: handleExpand,
    onCollapse: handleCollapse,
    isExpandedOnDesktop: isExpandedOnDesktop,
    isExpandedOnMobile: isExpandedOnMobile,
    lastTrigger: (_sideNavState$lastTri = sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.lastTrigger) !== null && _sideNavState$lastTri !== void 0 ? _sideNavState$lastTri : null
  });
  useEffect(function () {
    var mediaQueryList = window.matchMedia('(min-width: 64rem)');
    return bind(mediaQueryList, {
      type: 'change',
      listener: function listener() {
        if (mediaQueryList.matches) {
          // We're transitioning from tablet to desktop viewport size.
          // We forcibly show the side nav if it was shown on mobile.
          if (isExpandedOnMobile && !isExpandedOnDesktop) {
            toggleVisibilityByScreenResize();
          }
        }
      }
    });
  }, [toggleVisibilityByScreenResize, isExpandedOnDesktop, isExpandedOnMobile]);

  /**
   * Close the mobile side nav if there is a click outside.
   *
   * Binding/unbinding on changes to `isExpandedOnMobile` instead of window size changes for simplicity.
   * If we listened to window size changes we'd need nested `bind()` calls.
   */
  useEffect(function () {
    if (!isExpandedOnMobile) {
      return;
    }

    /**
     * The expected URL fragment used by the side nav skip link.
     */
    var skipLinkUrlFragment = "#".concat(id);
    return bind(window, {
      type: 'click',
      listener: function listener(event) {
        if (window.matchMedia('(min-width: 64rem)').matches) {
          // Clicks on desktop should do nothing
          return;
        }
        var sideNav = navRef.current;
        if (!sideNav || !(event.target instanceof Node)) {
          // Ignore if our element references are invalid
          return;
        }
        if (!event.target.isConnected) {
          /**
           * If the element that was clicked is no longer in the document, we should not collapse the side nav.
           * This can happen when the user clicks on a dropdown menu item (such as one used in a `...` More menu),
           * as the dropdown menu will close after being clicked. By the time this event listener runs, the clicked
           * element will no longer be in the document, so the check below for `sideNav.contains(event.target)` will fail.
           */
          return;
        }
        if (sideNav.contains(event.target)) {
          // Clicks inside the side nav should not close it
          return;
        }
        if (toggleButtonElement !== null && toggleButtonElement !== void 0 && toggleButtonElement.contains(event.target)) {
          // Clicks on the toggle button will already toggle the side nav,
          // so we need to ignore it or we end up doing a double toggle
          return;
        }
        if (event.target instanceof HTMLAnchorElement &&
        /**
         * Intentionally using `.getAttribute()` for simplicity to match exactly what we expect
         * for skip links.
         *
         * Alternatives considered:
         *
         * - Using `.href` returns a full URL, which would then require extra parsing.
         * - Using `.hash` could incorrectly capture `<a href="/another-page#skip-link-id>` so we'd need extra checks.
         *
         * This approach has an edge case of `<a href="/same-page#skip-link-id>` not being captured,
         * but we are okay with that trade-off.
         */
        event.target.getAttribute('href') === skipLinkUrlFragment) {
          // This was a click on a link to the side nav, so we shouldn't try to collapse the SideNav.
          // It was most likely the skip link, although anyone can render a link with the ID.
          // In either case keeping the SideNav expanded makes sense.
          return;
        }
        toggleVisibilityByClickOutsideOnMobile();
      }
    });
  }, [id, isExpandedOnMobile, toggleButtonElement, toggleVisibilityByClickOutsideOnMobile]);
  useEffect(function () {
    if (!toggleButtonElement) {
      return;
    }
    return bind(toggleButtonElement, {
      type: 'mouseenter',
      listener: function listener() {
        // Only flyout the side nav if the user hovered while the side nav was collapsed
        if (isExpandedOnDesktop) {
          return;
        }

        // Only flyout the side nav on desktop viewports
        var _window$matchMedia = window.matchMedia('(min-width: 64rem)'),
          matches = _window$matchMedia.matches;
        if (matches) {
          updateFlyoutState('open');
        }
      }
    });
  }, [updateFlyoutState, toggleButtonElement, isExpandedOnDesktop]);
  useEffect(function () {
    if (!toggleButtonElement) {
      return;
    }
    return bind(toggleButtonElement, {
      type: 'mouseleave',
      listener: function listener() {
        // If the side nav is not in flyout mode, we don't need to do anything
        if (!isFlyoutVisible) {
          return;
        }
        updateFlyoutState('waiting-for-close');
      }
    });
  }, [isFlyoutVisible, toggleButtonElement, updateFlyoutState]);
  useEffect(function () {
    if (!navRef.current) {
      return;
    }
    return bind(navRef.current, {
      type: 'mouseenter',
      listener: function listener() {
        // If the side nav is not in flyout mode, we don't need to do anything
        if (isExpandedOnDesktop || !isFlyoutVisible) {
          return;
        }

        // The user mouses has moused back over the side nav
        updateFlyoutState('open');
      }
    });
  }, [isFlyoutVisible, updateFlyoutState, isExpandedOnDesktop]);
  useEffect(function () {
    if (!navRef.current) {
      return;
    }
    return bind(navRef.current, {
      type: 'mouseleave',
      listener: function listener() {
        // If the side nav is not in flyout mode, we don't need to do anything
        if (!isFlyoutVisible) {
          return;
        }
        updateFlyoutState('waiting-for-close');
      }
    });
  }, [isFlyoutVisible, updateFlyoutState]);
  useEffect(function () {
    var nav = navRef.current;
    if (!nav) {
      return;
    }
    if (!isFlyoutVisible) {
      return;
    }

    // Using a monitor rather than a drop target. Rationale:
    // - We are not creating a drop target for the users to drop on,
    //   we are just interested in listening to events within an element
    // - We do not want to impact `location.{*}.dropTargets` in events
    return monitorForElements({
      canMonitor: function canMonitor(_ref4) {
        var source = _ref4.source;
        return nav.contains(source.element);
      },
      onGenerateDragPreview: function onGenerateDragPreview() {
        updateFlyoutState('drag-from-flyout-started');
      },
      onDrop: function onDrop(_ref5) {
        var location = _ref5.location;
        // Always marking the drag and done
        updateFlyoutState('drag-from-flyout-finished');

        // If the user dropped outside of the flyout, we will close the flyout
        var underUsersPointer = document.elementFromPoint(location.current.input.clientX, location.current.input.clientY);
        if (!nav.contains(underUsersPointer)) {
          updateFlyoutState('waiting-for-close');
        }
      }
    });
  }, [isFlyoutVisible, updateFlyoutState]);
  useEffect(function () {
    if (!topNavStartElement || !toggleButtonElement) {
      return;
    }
    return bind(topNavStartElement, {
      type: 'mouseover',
      listener: function listener(event) {
        // If the side nav is not in flyout mode, we don't need to do anything
        if (isExpandedOnDesktop || !isFlyoutVisible) {
          return;
        }
        if (event.target === topNavStartElement) {
          // The mouse is directly over the TopNavStart element, so cancel any pending flyout closes.
          updateFlyoutState('open');
          return;
        }
        if (event.target instanceof Element && toggleButtonElement.contains(event.target)) {
          // The mouse is over the toggle button or any of its children, so we don't want to close the flyout.
          // We also don't need to cancel any pending closes, as we have separate event listeners for the toggle button mouse events.
          return;
        }

        // The user has moused over a child element of the TopNavStart element that isn't the toggle button, e.g. the app switcher or nav logo,
        // so we should close the flyout (with a delay).
        updateFlyoutState('waiting-for-close');
      }
    });
  }, [topNavStartElement, isFlyoutVisible, toggleButtonElement, isExpandedOnDesktop, updateFlyoutState]);
  useEffect(function () {
    if (!topNavStartElement) {
      return;
    }
    return bind(topNavStartElement, {
      type: 'mouseleave',
      listener: function listener() {
        // If the side nav is not in flyout mode, we don't need to do anything
        if (!isFlyoutVisible) {
          return;
        }

        // The mouse has left the TopNavStart element, so we should close the flyout with a delay.
        updateFlyoutState('waiting-for-close');
      }
    });
  }, [topNavStartElement, isFlyoutVisible, updateFlyoutState]);
  useEffect(function () {
    // Close the flyout if there are no more layers open and the user is not mousing over the
    // flyout areas (side nav, TopNavStart element)

    return openLayerObserver.onChange(function (_ref6) {
      var count = _ref6.count;
      if (flyoutStateRef.current.type === 'ready-to-close' && count === 0) {
        updateFlyoutState('force-close');
      }
    }, {
      namespace: openLayerObserverSideNavNamespace
    });
  }, [openLayerObserver, updateFlyoutState]);
  useEffect(function () {
    // Clear flyout close timer if being unmounted
    return function cleanupPendingFlyoutClose() {
      if (flyoutStateRef.current.type === 'waiting-for-close') {
        flyoutStateRef.current.abort();
      }
    };
  }, []);
  if (process.env.NODE_ENV !== 'production') {
    var visible = [];
    if (isExpandedOnMobile) {
      visible.push('small');
    }
    if (isExpandedOnDesktop) {
      visible.push('large');
    }
    if (isFlyoutVisible) {
      visible.push('flyout');
    }
    devTimeOnlyAttributes['data-visible'] = visible.length ? visible.join(',') : 'false';
  }
  useSideNavToggleKeyboardShortcut({
    canToggleWithShortcut: canToggleWithShortcut
  });
  // Used to conditionally display the keyboard shortcut in the SideNavPanelSplitter tooltip.
  var isShortcutEnabled = useIsSideNavShortcutEnabled();
  useResizingWidthCssVarOnRootElement({
    isEnabled: true,
    cssVar: panelSplitterResizingVar,
    panelId: sideNavPanelSplitterId
  });
  var isFlyoutClosed = (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'closed' || (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === undefined;

  // Used to prevent sidebar expand animations from running on the initial render.
  // Otherwise, the `@starting-style` rule will cause the sidebar to slide in initially.
  var isFirstRenderRef = useRef(true);
  useEffect(function () {
    if (!fg('navx-full-height-sidebar')) {
      return;
    }
    if (isFirstRenderRef.current) {
      isFirstRenderRef.current = false;
    }
  }, []);

  // This is only used for the regular expand and collapse animations, not the flyout animations.
  var shouldShowSidebarToggleAnimation =
  // We do not apply the animation styles on the initial render, as the `@starting-style` rule will cause the sidebar to
  // slide in initially.
  !isFirstRenderRef.current &&
  // We also do not apply the animation styles if the side nav is in flyout mode to make sure we don't override flyout styles.
  // If we instead try to unset the `transform` property in the flyout styles using `transform: initial`, it results in the entire
  // flyout animation being disabled.
  !isFlyoutVisible &&
  /**
   * Disabling animations for Firefox, as it doesn't support animating the `display` property:
   * https://caniuse.com/mdn-css_properties_display_is_transitionable
   *
   * As of October 2025, Firefox supports the expand animation, but not the collapse animation (it instantly changes to `display: none`).
   * Because of this, we are disabling all sidebar animations for Firefox so it doesn't look like a bug.
   *
   * Unfortunately we cannot use `@supports` to target the support of `transition-behavior: allow-discrete` specifically
   * for the `display` property. And `@supports at-rule(@starting-style)` is also not ready for browser use yet.
   *
   * We are using JS to detect Firefox and disable animations, instead of using CSS, as Compiled currently does not merge duplicate
   * CSS at-rules when at-rules are nested: https://github.com/atlassian-labs/compiled/blob/e04a325915e1d13010205089e4915de0e53bc2d4/packages/css/src/plugins/merge-duplicate-at-rules.ts#L5
   * Avoiding nesting the `@supports` at-rule inside of `@media` means Compiled can remove duplicate styles from the generated CSS.
   */
  !isFirefox;
  return /*#__PURE__*/React.createElement("nav", _extends({
    id: id
  }, devTimeOnlyAttributes, {
    "data-layout-slot": true,
    "aria-label": label,
    style: _defineProperty({}, sideNavVar, clampedWidth),
    ref: mergedRef,
    "data-testid": testId,
    className: ax([styles.root, isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileOnly, !isExpandedOnDesktop && isExpandedOnMobile && !isFlyoutVisible && styles.hiddenDesktopOnly, !isExpandedOnDesktop && !isExpandedOnMobile && !isFlyoutVisible && styles.hiddenMobileAndDesktop, fg('navx-full-height-sidebar') && styles.animationRTLSupport, shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.animationBaseStyles, isExpandedOnMobile && shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.expandAnimationMobile, !isExpandedOnMobile && shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.collapseAnimationMobile, isExpandedOnDesktop && shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.expandAnimationDesktop, !isExpandedOnDesktop && shouldShowSidebarToggleAnimation && fg('navx-full-height-sidebar') && styles.collapseAnimationDesktop, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && !fg('navx-full-height-sidebar') && styles.flyoutOpen, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !fg('navx-full-height-sidebar') && styles.flyoutAnimateClosed, ((sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' || (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close') && !isFirefox && fg('navx-full-height-sidebar') && styles.flyoutBaseStylesFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !isFirefox && fg('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'open' && !isFirefox && fg('navx-full-height-sidebar') && styles.flyoutOpenFullHeightSidebar, (sideNavState === null || sideNavState === void 0 ? void 0 : sideNavState.flyout) === 'triggered-animate-close' && !isFirefox && fg('navx-full-height-sidebar') && styles.flyoutAnimateClosedFullHeightSidebar, isFlyoutClosed && fg('navx-full-height-sidebar') && styles.fullHeightSidebar])
  }), /*#__PURE__*/React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
    variableName: sideNavLiveWidthVar,
    value: "0px",
    mediaQuery: media.above.md,
    responsiveValue: isExpandedOnDesktop ? "var(".concat(panelSplitterResizingVar, ", ").concat(clampedWidth, ")") : 0
  }), dangerouslyHoistSlotSizes &&
  /*#__PURE__*/
  // ------ START UNSAFE STYLES ------
  // These styles are only needed for the UNSAFE legacy use case for Jira + Confluence.
  // When they aren't needed anymore we can delete them wholesale.
  React.createElement(DangerouslyHoistCssVarToDocumentRoot, {
    variableName: UNSAFE_sideNavLayoutVar,
    value: "var(".concat(sideNavLiveWidthVar, ")")
  })
  // ------ END UNSAFE STYLES ------
  , /*#__PURE__*/React.createElement(PanelSplitterProvider, {
    panelId: sideNavPanelSplitterId,
    panelRef: navRef,
    panelWidth: width,
    onCompleteResize: setWidth,
    getResizeBounds: getResizeBounds,
    resizingCssVar: panelSplitterResizingVar,
    isEnabled: isExpandedOnDesktop && !isFlyoutVisible,
    shortcut: isShortcutEnabled ? sideNavToggleTooltipKeyboardShortcut : undefined
  }, /*#__PURE__*/React.createElement("div", {
    className: ax([styles.flexContainer])
  }, children)));
}

/**
 * The side navigation layout area. It will show on the left (inline start) of the screen.
 *
 * Use the side nav area components (`SideNavHeader`, `SideNavContent`, `SideNavFooter`) to position
 * content within areas of the side nav.
 *
 * You can optionally render a `PanelSplitter` as a child to make the side navigation slot resizable.
 */
export function SideNav(_ref8) {
  var children = _ref8.children,
    defaultCollapsed = _ref8.defaultCollapsed,
    _ref8$defaultWidth = _ref8.defaultWidth,
    defaultWidth = _ref8$defaultWidth === void 0 ? 320 : _ref8$defaultWidth,
    testId = _ref8.testId,
    label = _ref8.label,
    _ref8$skipLinkLabel = _ref8.skipLinkLabel,
    skipLinkLabel = _ref8$skipLinkLabel === void 0 ? label : _ref8$skipLinkLabel,
    onExpand = _ref8.onExpand,
    onCollapse = _ref8.onCollapse,
    onPeekStart = _ref8.onPeekStart,
    onPeekEnd = _ref8.onPeekEnd,
    canToggleWithShortcut = _ref8.canToggleWithShortcut,
    id = _ref8.id;
  return /*#__PURE__*/React.createElement(OpenLayerObserverNamespaceProvider, {
    namespace: openLayerObserverSideNavNamespace
  }, /*#__PURE__*/React.createElement(SideNavInternal, {
    defaultCollapsed: defaultCollapsed,
    defaultWidth: defaultWidth,
    testId: testId,
    label: label,
    skipLinkLabel: skipLinkLabel,
    onExpand: onExpand,
    onCollapse: onCollapse,
    onPeekStart: onPeekStart,
    onPeekEnd: onPeekEnd,
    id: id,
    canToggleWithShortcut: canToggleWithShortcut
  }, children));
}