/**
 * Solid port of Base UI React's
 * `packages/react/src/utils/popups/useTriggerFocusGuards.ts`.
 *
 * Provides focus guard handlers for popup triggers (Popover, Menu).
 *
 * When the popup is open, invisible focus guard elements are placed
 * before and after the trigger. These handlers close the popup and move
 * focus to the appropriate tabbable element when the guards receive
 * focus (i.e. when the user tabs out).
 *
 * Port notes:
 *  - `React.useRef` → plain `{ current: null }` mutable ref literal, the
 *    same `MutableRef<T>` shape the rest of the Solid port uses.
 *  - `useStableCallback` → `createStableCallback`. In Solid the trampoline
 *    keeps identity stable across re-renders (although Solid component
 *    bodies don't re-run, the trampoline still insulates consumers that
 *    capture the callback reference into a long-lived structure).
 *  - `ReactDOM.flushSync` has no direct Solid equivalent — Solid batches
 *    updates synchronously inside event handlers already, so the
 *    `flushSync` wrapper is dropped.
 *  - `React.FocusEvent` → native `FocusEvent`. `event.nativeEvent` is
 *    already `FocusEvent` here, and `event.currentTarget` is the guard
 *    element.
 *  - `TriggerFocusGuardStore` is kept as a minimal structural interface
 *    so it can match both the in-flight `PopoverStore` and `MenuStore`
 *    ports without introducing a hard dependency on the real `PopupStore`
 *    (which is being ported on a parallel track).
 */

import { createChangeEventDetails, REASONS } from "../change-event-details.jsx";
import { contains } from "../dom/contains.jsx";
import { getNextTabbable, getTabbableAfterElement, getTabbableBeforeElement, isOutsideEvent } from "../floating-ui/utils/tabbable.jsx";
import { createStableCallback } from "../stable-callback.jsx";

/**
 * Minimal store interface required by the focus guard hook.
 * Both PopoverStore and MenuStore satisfy this interface.
 *
 * Kept as a structural shape rather than re-importing the real popup
 * store, so this file remains independent of the parallel `PopupStore`
 * port track.
 */

/**
 * Provides focus guard handlers for popup triggers (Popover, Menu).
 *
 * When the popup is open, invisible focus guard elements are placed
 * before and after the trigger. These handlers close the popup and move
 * focus to the appropriate tabbable element when the guards receive
 * focus (i.e. when the user tabs out).
 */
export function useTriggerFocusGuards(store, triggerElementRef) {
  const preFocusGuardRef = {
    current: null
  };
  const handlePreFocusGuardFocus = createStableCallback(() => event => {
    store.setOpen(false, createChangeEventDetails(REASONS.focusOut, event, event.currentTarget));
    const previousTabbable = getTabbableBeforeElement(preFocusGuardRef.current);
    previousTabbable?.focus();
  });
  const handleFocusTargetFocus = createStableCallback(() => event => {
    const positionerElement = store.select("positionerElement");
    if (positionerElement && isOutsideEvent(event, positionerElement)) {
      store.context.beforeContentFocusGuardRef.current?.focus();
    } else {
      store.setOpen(false, createChangeEventDetails(REASONS.focusOut, event, event.currentTarget));
      let nextTabbable = getTabbableAfterElement(store.context.triggerFocusTargetRef.current || triggerElementRef.current);
      while (nextTabbable !== null && contains(positionerElement, nextTabbable)) {
        const prevTabbable = nextTabbable;
        nextTabbable = getNextTabbable(nextTabbable);
        if (nextTabbable === prevTabbable) {
          break;
        }
      }
      nextTabbable?.focus();
    }
  });
  return {
    preFocusGuardRef,
    handlePreFocusGuardFocus,
    handleFocusTargetFocus
  };
}
//# sourceMappingURL=use-trigger-focus-guards.jsx.map
