/* flyout-menu-item-content.tsx generated by @compiled/babel-plugin v0.38.1 */
"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.FlyoutMenuItemContent = void 0;
require("./flyout-menu-item-content.compiled.css");
var _runtime = require("@compiled/react/runtime");
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = _interopRequireWildcard(require("react"));
var _analyticsNext = require("@atlaskit/analytics-next");
var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
var _experimental = require("@atlaskit/popup/experimental");
var _flyoutMenuItemContext = require("./flyout-menu-item-context");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
/**
 * The vertical offset in px to ensure the flyout container does not exceed the bounds of
 * the window. This matches the padding of the content container, and it's position within
 * the viewport.
 * 
 * - FlyoutMenuItemContent: paddingBlock: token('space.100'); – 8px top, 8px bottom
 * - Position: 5px top, 5px bottom
 * 
 * Total vertical padding:
 * 		(8px [content top] + 8px [content bottom]) +
 * 		(5px [position top] + 5px [position bottom]) = 26px
 */
var FLYOUT_MENU_VERTICAL_OFFSET_PX = 26;
var flyoutMenuItemContentStyles = {
  root: "_1q51u2gc _85i5u2gc _bozgu2gc _y4tiu2gc _14b51kdj"
};
var flyoutMenuItemContentContainerStyles = {
  container: "_1e0c1txw _4t3i1osq _c71l2gk1 _2lx21bp4"
};
/**
 * __FlyoutMenuItemContent__
 *
 * The content that appears when the flyout menu is open.
 */
var FlyoutMenuItemContent = exports.FlyoutMenuItemContent = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, forwardedRef) {
  var children = _ref.children,
    containerTestId = _ref.containerTestId,
    onClose = _ref.onClose,
    autoFocus = _ref.autoFocus;
  var setIsOpen = (0, _react.useContext)(_flyoutMenuItemContext.SetIsOpenContext);
  var onCloseRef = (0, _react.useContext)(_flyoutMenuItemContext.OnCloseContext);
  var _useAnalyticsEvents = (0, _analyticsNext.useAnalyticsEvents)(),
    createAnalyticsEvent = _useAnalyticsEvents.createAnalyticsEvent;

  // The source of the close is not accessible to the consumer, it is determined within the
  // handleClose function, or passed in as a parameter in FlyoutMenuItemTrigger (outside-click),
  // or FlyoutHeader (close-button).
  var handleClose = (0, _react.useCallback)(function (event, source) {
    if ((0, _platformFeatureFlags.fg)("platform_dst_nav4_flyout_menu_slots_close_button")) {
      // Use the passed source if provided, otherwise determine from event
      var determinedSource = source || 'other';
      if (!source) {
        if (event instanceof KeyboardEvent) {
          var keyboardEvent = event;
          if (keyboardEvent.key === 'Escape' || keyboardEvent.key === 'Esc') {
            determinedSource = 'escape-key';
          }
        } else if (event instanceof MouseEvent) {
          if (event && 'type' in event && event.type === 'click') {
            determinedSource = 'outside-click';
          }
        }
      }

      // When flyout menu is closed, fire analytics event
      var navigationAnalyticsEvent = createAnalyticsEvent({
        source: 'sideNav',
        actionSubject: 'flyoutMenu',
        action: 'closed',
        attributes: {
          closeSource: determinedSource
        }
      });
      navigationAnalyticsEvent.fire('navigation');
    }
    onClose === null || onClose === void 0 || onClose();
    setIsOpen(false);
  }, [setIsOpen, onClose, createAnalyticsEvent]);

  // Register handleClose in the ref to allow the FlyoutMenuItemTrigger to access it
  (0, _react.useEffect)(function () {
    onCloseRef.current = handleClose;
  }, [handleClose, onCloseRef]);
  var titleId = (0, _react.useId)();
  return /*#__PURE__*/_react.default.createElement(_experimental.PopupContent, {
    appearance: "UNSAFE_modal-below-sm",
    onClose: handleClose,
    placement: "right-start"
    // Using a capture event listener so that we are more resilient against
    // code that stops events. We _really_ want to close the flyout whenever
    // user user clicks outside the flyout content
    ,
    shouldUseCaptureOnOutsideClick: true,
    shouldFitViewport: true,
    testId: containerTestId,
    xcss: flyoutMenuItemContentStyles.root,
    autoFocus: autoFocus,
    role: (0, _platformFeatureFlags.fg)("platform_dst_nav4_flyout_menu_slots_close_button") ? "dialog" : undefined,
    titleId: (0, _platformFeatureFlags.fg)("platform_dst_nav4_flyout_menu_slots_close_button") ? titleId : undefined
    /**
     * Disabling GPU acceleration removes the use of `transform` by popper.js for this popup.
     *
     * This allows makers to use popups with `shouldRenderToParent` inside the flyout.
     *
     * Without this, the `transform` makes the flyout the containing element for fixed positioning.
     * Because the flyout is also a scroll container then any nested, layered element is unable to
     * escape the flyout.
     *
     * Disabling the `transform` is the simplest way to resolve this layering issue,
     * and should have negligible performance impacts, because the flyout menus should rarely
     * need to be repositioned.
     */,
    shouldDisableGpuAcceleration: true,
    shouldRenderToParent: (0, _platformFeatureFlags.fg)('platform_dst_nav4_flyoutmenuitem_render_to_parent')
  }, function (_ref2) {
    var update = _ref2.update;
    return /*#__PURE__*/_react.default.createElement(UpdatePopperOnContentResize, {
      ref: forwardedRef,
      update: update
    }, (0, _platformFeatureFlags.fg)("platform_dst_nav4_flyout_menu_slots_close_button") ? /*#__PURE__*/_react.default.createElement(_flyoutMenuItemContext.TitleIdContextProvider, {
      value: titleId
    }, /*#__PURE__*/_react.default.createElement("div", {
      className: (0, _runtime.ax)([flyoutMenuItemContentContainerStyles.container])
    }, children)) : children);
  });
});
function createResizeObserver(update) {
  return new ResizeObserver(update);
}

/**
 * Will call the Popper.js `update()` method to recalculate positioning, when the flyout menu changes size.
 * This is the size of the scroll container, NOT the scroll content.
 *
 * We could potentially bake this into `@atlaskit/popup` or `@atlaskit/popper` but there are a few
 * reasons to keep it scoped to flyout menus for now:
 *
 * 1. It's easier to unwind
 * 2. We've only had bug reports for flyout menus
 * 3. Popup exposes the `update` function so consumers can already do this themselves if necessary
 * 4. Flyout menus are a lot more restricted to other popups, it might not make sense more generally
 */
var UpdatePopperOnContentResize = /*#__PURE__*/(0, _react.forwardRef)(function (_ref3, forwardedRef) {
  var update = _ref3.update,
    children = _ref3.children;
  /**
   * Storing our `update` function in a ref so that we have a stable reference to it.
   * We need this because our `ResizeObserver` callback cannot be changed after creating it.
   */
  var updateRef = (0, _react.useRef)(update);
  (0, _react.useEffect)(function () {
    updateRef.current = update;
  }, [update]);

  /**
   * Stable function that calls the latest `update` function by calling it through the stable ref.
   */
  var triggerUpdate = (0, _react.useCallback)(function () {
    var _updateRef$current;
    (_updateRef$current = updateRef.current) === null || _updateRef$current === void 0 || _updateRef$current.call(updateRef);
  }, []);
  var _useState = (0, _react.useState)(function () {
      return createResizeObserver(triggerUpdate);
    }),
    _useState2 = (0, _slicedToArray2.default)(_useState, 1),
    resizeObserver = _useState2[0];

  /**
   * This is a callback ref that will update which `HTMLElement` we are observing,
   * if or when the underlying `HTMLElement` changes or unmounts.
   */
  var observeCallbackRef = (0, _react.useCallback)(function (element) {
    /**
     * Unobserves all observed elements.
     * Allows us to cleanup without needing to store a reference to the previous element.
     */
    resizeObserver.disconnect();
    if (!element) {
      return;
    }
    resizeObserver.observe(element);
  }, [resizeObserver]);

  /**
   * We need to memoize the ref otherwise `triggerUpdate` is repeatedly called.
   *
   * This stems from ResizeObserver firing once after calling `.observe()` even if there
   * was no resize.
   *
   * Without memoizing the ref, the update causes a rerender, which causes the ref to
   * get recreated, which triggers an update and so on in a loop.
   */
  var ref = (0, _react.useMemo)(function () {
    return (0, _mergeRefs.default)([forwardedRef, observeCallbackRef]);
  }, [forwardedRef, observeCallbackRef]);
  return /*#__PURE__*/_react.default.createElement("div", {
    ref: ref
  }, children);
});