/**
 * External dependencies
 */
import * as Ariakit from '@ariakit/react';
import clsx from 'clsx';

/**
 * WordPress dependencies
 */
import warning from '@wordpress/warning';
import { forwardRef, useLayoutEffect, useState } from '@wordpress/element';
import { useMergeRefs } from '@wordpress/compose';

/**
 * Internal dependencies
 */

import { useTabsContext } from './context';
import { StyledTabList } from './styles';
import { useTrackElementOffsetRect } from '../utils/element-rect';
import { useTrackOverflow } from './use-track-overflow';
import { useAnimatedOffsetRect } from '../utils/hooks/use-animated-offset-rect';
import { jsx as _jsx } from "react/jsx-runtime";
const DEFAULT_SCROLL_MARGIN = 24;

/**
 * Scrolls a given parent element so that a given rect is visible.
 *
 * The scroll is updated initially and whenever the rect changes.
 */
function useScrollRectIntoView(parent, rect, {
  margin = DEFAULT_SCROLL_MARGIN
} = {}) {
  useLayoutEffect(() => {
    if (!parent || !rect) {
      return;
    }
    const {
      scrollLeft: parentScroll
    } = parent;
    const parentWidth = parent.getBoundingClientRect().width;
    const {
      left: childLeft,
      width: childWidth
    } = rect;
    const parentRightEdge = parentScroll + parentWidth;
    const childRightEdge = childLeft + childWidth;
    const rightOverflow = childRightEdge + margin - parentRightEdge;
    const leftOverflow = parentScroll - (childLeft - margin);
    let scrollLeft = null;
    if (leftOverflow > 0) {
      scrollLeft = parentScroll - leftOverflow;
    } else if (rightOverflow > 0) {
      scrollLeft = parentScroll + rightOverflow;
    }
    if (scrollLeft !== null) {
      /**
       * The optional chaining is used here to avoid unit test failures.
       * It can be removed when JSDOM supports `Element` scroll methods.
       * See: https://github.com/WordPress/gutenberg/pull/66498#issuecomment-2441146096
       */
      parent.scroll?.({
        left: scrollLeft
      });
    }
  }, [margin, parent, rect]);
}
export const TabList = forwardRef(function TabList({
  children,
  ...otherProps
}, ref) {
  var _useTabsContext;
  const {
    store
  } = (_useTabsContext = useTabsContext()) !== null && _useTabsContext !== void 0 ? _useTabsContext : {};
  const selectedId = Ariakit.useStoreState(store, 'selectedId');
  const activeId = Ariakit.useStoreState(store, 'activeId');
  const selectOnMove = Ariakit.useStoreState(store, 'selectOnMove');
  const items = Ariakit.useStoreState(store, 'items');
  const [parent, setParent] = useState();
  const refs = useMergeRefs([ref, setParent]);
  const selectedItem = store?.item(selectedId);
  const renderedItems = Ariakit.useStoreState(store, 'renderedItems');
  const selectedItemIndex = renderedItems && selectedItem ? renderedItems.indexOf(selectedItem) : -1;
  // Use selectedItemIndex as a dependency to force recalculation when the
  // selected item index changes (elements are swapped / added / removed).
  const selectedRect = useTrackElementOffsetRect(selectedItem?.element, [selectedItemIndex]);

  // Track overflow to show scroll hints.
  const overflow = useTrackOverflow(parent, {
    first: items?.at(0)?.element,
    last: items?.at(-1)?.element
  });

  // Size, position, and animate the indicator.
  useAnimatedOffsetRect(parent, selectedRect, {
    prefix: 'selected',
    dataAttribute: 'indicator-animated',
    transitionEndFilter: event => event.pseudoElement === '::before',
    roundRect: true
  });

  // Make sure selected tab is scrolled into view.
  useScrollRectIntoView(parent, selectedRect);
  const onBlur = () => {
    if (!selectOnMove) {
      return;
    }

    // When automatic tab selection is on, make sure that the active tab is up
    // to date with the selected tab when leaving the tablist. This makes sure
    // that the selected tab will receive keyboard focus when tabbing back into
    // the tablist.
    if (selectedId !== activeId) {
      store?.setActiveId(selectedId);
    }
  };
  if (!store) {
    globalThis.SCRIPT_DEBUG === true ? warning('`Tabs.TabList` must be wrapped in a `Tabs` component.') : void 0;
    return null;
  }
  return /*#__PURE__*/_jsx(StyledTabList, {
    ref: refs,
    store: store,
    render: props => {
      var _props$tabIndex;
      return /*#__PURE__*/_jsx("div", {
        ...props,
        // Fallback to -1 to prevent browsers from making the tablist
        // tabbable when it is a scrolling container.
        tabIndex: (_props$tabIndex = props.tabIndex) !== null && _props$tabIndex !== void 0 ? _props$tabIndex : -1
      });
    },
    onBlur: onBlur,
    "data-select-on-move": selectOnMove ? 'true' : 'false',
    ...otherProps,
    className: clsx(overflow.first && 'is-overflowing-first', overflow.last && 'is-overflowing-last', otherProps.className),
    children: children
  });
});
//# sourceMappingURL=tablist.js.map