// packages/block-editor/src/components/navigable-toolbar/index.js
import { NavigableMenu, Toolbar } from "@wordpress/components";
import {
  useState,
  useRef,
  useLayoutEffect,
  useEffect,
  useCallback
} from "@wordpress/element";
import { useSelect } from "@wordpress/data";
import deprecated from "@wordpress/deprecated";
import { focus } from "@wordpress/dom";
import { useShortcut } from "@wordpress/keyboard-shortcuts";
import { ESCAPE } from "@wordpress/keycodes";
import { store as blockEditorStore } from "../../store";
import { unlock } from "../../lock-unlock";
import { jsx } from "react/jsx-runtime";
function hasOnlyToolbarItem(elements) {
  const dataProp = "toolbarItem";
  return !elements.some((element) => !(dataProp in element.dataset));
}
function getAllFocusableToolbarItemsIn(container) {
  return Array.from(
    container.querySelectorAll("[data-toolbar-item]:not([disabled])")
  );
}
function hasFocusWithin(container) {
  return container.contains(container.ownerDocument.activeElement);
}
function focusFirstTabbableIn(container) {
  const [firstTabbable] = focus.tabbable.find(container);
  if (firstTabbable) {
    firstTabbable.focus({
      // When focusing newly mounted toolbars,
      // the position of the popover is often not right on the first render
      // This prevents the layout shifts when focusing the dialogs.
      preventScroll: true
    });
  }
}
function useIsAccessibleToolbar(toolbarRef) {
  const initialAccessibleToolbarState = true;
  const [isAccessibleToolbar, setIsAccessibleToolbar] = useState(
    initialAccessibleToolbarState
  );
  const determineIsAccessibleToolbar = useCallback(() => {
    const tabbables = focus.tabbable.find(toolbarRef.current);
    const onlyToolbarItem = hasOnlyToolbarItem(tabbables);
    if (!onlyToolbarItem) {
      deprecated("Using custom components as toolbar controls", {
        since: "5.6",
        alternative: "ToolbarItem, ToolbarButton or ToolbarDropdownMenu components",
        link: "https://developer.wordpress.org/block-editor/components/toolbar-button/#inside-blockcontrols"
      });
    }
    setIsAccessibleToolbar(onlyToolbarItem);
  }, [toolbarRef]);
  useLayoutEffect(() => {
    const observer = new window.MutationObserver(
      determineIsAccessibleToolbar
    );
    observer.observe(toolbarRef.current, {
      childList: true,
      subtree: true
    });
    return () => observer.disconnect();
  }, [determineIsAccessibleToolbar, isAccessibleToolbar, toolbarRef]);
  return isAccessibleToolbar;
}
function useToolbarFocus({
  toolbarRef,
  focusOnMount,
  isAccessibleToolbar,
  defaultIndex,
  onIndexChange,
  shouldUseKeyboardFocusShortcut,
  focusEditorOnEscape
}) {
  const [initialFocusOnMount] = useState(focusOnMount);
  const [initialIndex] = useState(defaultIndex);
  const focusToolbar = useCallback(() => {
    focusFirstTabbableIn(toolbarRef.current);
  }, [toolbarRef]);
  const focusToolbarViaShortcut = () => {
    if (shouldUseKeyboardFocusShortcut) {
      focusToolbar();
    }
  };
  useShortcut("core/block-editor/focus-toolbar", focusToolbarViaShortcut);
  useEffect(() => {
    if (initialFocusOnMount) {
      focusToolbar();
    }
  }, [isAccessibleToolbar, initialFocusOnMount, focusToolbar]);
  useEffect(() => {
    const navigableToolbarRef = toolbarRef.current;
    let raf = 0;
    if (!initialFocusOnMount && !hasFocusWithin(navigableToolbarRef)) {
      raf = window.requestAnimationFrame(() => {
        const items = getAllFocusableToolbarItemsIn(navigableToolbarRef);
        const index = initialIndex || 0;
        if (items[index] && hasFocusWithin(navigableToolbarRef)) {
          items[index].focus({
            // When focusing newly mounted toolbars,
            // the position of the popover is often not right on the first render
            // This prevents the layout shifts when focusing the dialogs.
            preventScroll: true
          });
        }
      });
    }
    return () => {
      window.cancelAnimationFrame(raf);
      if (!onIndexChange || !navigableToolbarRef) {
        return;
      }
      const items = getAllFocusableToolbarItemsIn(navigableToolbarRef);
      const index = items.findIndex((item) => item.tabIndex === 0);
      onIndexChange(index);
    };
  }, [initialIndex, initialFocusOnMount, onIndexChange, toolbarRef]);
  const { getLastFocus } = unlock(useSelect(blockEditorStore));
  useEffect(() => {
    const navigableToolbarRef = toolbarRef.current;
    if (focusEditorOnEscape) {
      const handleKeyDown = (event) => {
        const lastFocus = getLastFocus();
        if (event.keyCode === ESCAPE && lastFocus?.current) {
          event.preventDefault();
          lastFocus.current.focus();
        }
      };
      navigableToolbarRef.addEventListener("keydown", handleKeyDown);
      return () => {
        navigableToolbarRef.removeEventListener(
          "keydown",
          handleKeyDown
        );
      };
    }
  }, [focusEditorOnEscape, getLastFocus, toolbarRef]);
}
function NavigableToolbar({
  children,
  focusOnMount,
  focusEditorOnEscape = false,
  shouldUseKeyboardFocusShortcut = true,
  __experimentalInitialIndex: initialIndex,
  __experimentalOnIndexChange: onIndexChange,
  orientation = "horizontal",
  ...props
}) {
  const toolbarRef = useRef();
  const isAccessibleToolbar = useIsAccessibleToolbar(toolbarRef);
  useToolbarFocus({
    toolbarRef,
    focusOnMount,
    defaultIndex: initialIndex,
    onIndexChange,
    isAccessibleToolbar,
    shouldUseKeyboardFocusShortcut,
    focusEditorOnEscape
  });
  if (isAccessibleToolbar) {
    return /* @__PURE__ */ jsx(
      Toolbar,
      {
        label: props["aria-label"],
        ref: toolbarRef,
        orientation,
        ...props,
        children
      }
    );
  }
  return /* @__PURE__ */ jsx(
    NavigableMenu,
    {
      orientation,
      role: "toolbar",
      ref: toolbarRef,
      ...props,
      children
    }
  );
}
export {
  NavigableToolbar as default
};
//# sourceMappingURL=index.js.map
