import React__default, { useState, useRef, useCallback, useEffect } from 'react';
import classnames from 'classnames';
import { g as getDefaultExportFromCjs } from './_commonjsHelpers-es.js';
import { a as debounce_1 } from './debounce-es.js';
import { a as isObject_1 } from './isObjectLike-es.js';
import { T as Typography } from './Typography-es.js';

var styles = {"tabs":"cHJe2HsBNic-","overflow":"eQt1Jis30lo-","overflowRight":"_6Vf7pQfyKKk-","overflowLeft":"jyevrJK7Bcg-","tabRow":"LfIIg9bwrhQ-","tab":"DEdzikxlAkw-","selected":"VDB94VYoyB0-","tabContent":"htdKg6As4bY-","spinning":"XFrAkUebMjI-"};

var debounce = debounce_1,
    isObject = isObject_1;

/** Error message constants. */
var FUNC_ERROR_TEXT = 'Expected a function';

/**
 * Creates a throttled function that only invokes `func` at most once per
 * every `wait` milliseconds. The throttled function comes with a `cancel`
 * method to cancel delayed `func` invocations and a `flush` method to
 * immediately invoke them. Provide `options` to indicate whether `func`
 * should be invoked on the leading and/or trailing edge of the `wait`
 * timeout. The `func` is invoked with the last arguments provided to the
 * throttled function. Subsequent calls to the throttled function return the
 * result of the last `func` invocation.
 *
 * **Note:** If `leading` and `trailing` options are `true`, `func` is
 * invoked on the trailing edge of the timeout only if the throttled function
 * is invoked more than once during the `wait` timeout.
 *
 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
 * until to the next tick, similar to `setTimeout` with a timeout of `0`.
 *
 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
 * for details over the differences between `_.throttle` and `_.debounce`.
 *
 * @static
 * @memberOf _
 * @since 0.1.0
 * @category Function
 * @param {Function} func The function to throttle.
 * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
 * @param {Object} [options={}] The options object.
 * @param {boolean} [options.leading=true]
 *  Specify invoking on the leading edge of the timeout.
 * @param {boolean} [options.trailing=true]
 *  Specify invoking on the trailing edge of the timeout.
 * @returns {Function} Returns the new throttled function.
 * @example
 *
 * // Avoid excessively updating the position while scrolling.
 * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
 *
 * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
 * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
 * jQuery(element).on('click', throttled);
 *
 * // Cancel the trailing throttled invocation.
 * jQuery(window).on('popstate', throttled.cancel);
 */
function throttle(func, wait, options) {
  var leading = true,
      trailing = true;

  if (typeof func != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  if (isObject(options)) {
    leading = 'leading' in options ? !!options.leading : leading;
    trailing = 'trailing' in options ? !!options.trailing : trailing;
  }
  return debounce(func, wait, {
    'leading': leading,
    'maxWait': wait,
    'trailing': trailing
  });
}

var throttle_1 = throttle;

var throttle$1 = /*@__PURE__*/getDefaultExportFromCjs(throttle_1);

function useTabsOverflow() {
    const [overflowRight, setOverflowRight] = useState(false);
    const [overflowLeft, setOverflowLeft] = useState(false);
    const tabRow = useRef(null);
    const handleOverflowing = () => {
        if (tabRow.current) {
            const scrollWidth = tabRow.current.scrollWidth;
            const clientWidth = tabRow.current.clientWidth;
            const maxScroll = scrollWidth - clientWidth;
            const scrollPos = tabRow.current.scrollLeft;
            setOverflowRight(scrollPos >= 0 && scrollPos != maxScroll);
            setOverflowLeft(scrollPos > 0 && scrollPos < scrollWidth);
        }
    };
    const throttledHandleOverflowing = useCallback(throttle$1(handleOverflowing, 100), []);
    useEffect(() => {
        var _a;
        handleOverflowing();
        (_a = tabRow === null || tabRow === void 0 ? void 0 : tabRow.current) === null || _a === void 0 ? void 0 : _a.addEventListener("scroll", throttledHandleOverflowing);
        return () => {
            var _a;
            (_a = tabRow === null || tabRow === void 0 ? void 0 : tabRow.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("scroll", throttledHandleOverflowing);
        };
    });
    return {
        overflowRight,
        overflowLeft,
        tabRow,
    };
}

const useArrowKeyNavigation = ({ elementsRef, onActivate, }) => {
    const handleKeyDown = useCallback((event) => {
        const elements = elementsRef.current;
        if (!elements)
            return;
        const currentIndex = getActiveTabIndex(elements);
        if (currentIndex === -1)
            return;
        const focusAndActivateTab = (index) => {
            const element = elements.get(index);
            if (element) {
                element.focus();
                onActivate(index);
            }
        };
        if (event.key === "ArrowRight") {
            event.preventDefault();
            const nextIndex = (currentIndex + 1) % elements.size;
            focusAndActivateTab(nextIndex);
        }
        else if (event.key === "ArrowLeft") {
            event.preventDefault();
            const prevIndex = (currentIndex - 1 + elements.size) % elements.size;
            focusAndActivateTab(prevIndex);
        }
    }, [elementsRef, onActivate]);
    return handleKeyDown;
};
function getActiveTabIndex(elements) {
    const currentTab = Array.from(elements).find(([, element]) => element === document.activeElement);
    if (!currentTab) {
        return -1;
    }
    const [currentIndex] = currentTab;
    return currentIndex;
}

function Tabs({ children, defaultTab = 0, activeTab: controlledActiveTab, onTabChange, }) {
    var _a;
    const tabChildren = getActiveTabs(children);
    const activeTabInitialValue = defaultTab < tabChildren.length ? defaultTab : 0;
    const [internalActiveTab, setInternalActiveTab] = useState(activeTabInitialValue);
    const activeTab = controlledActiveTab !== undefined ? controlledActiveTab : internalActiveTab;
    const { overflowRight, overflowLeft, tabRow } = useTabsOverflow();
    const overflowClassNames = classnames(styles.overflow, {
        [styles.overflowRight]: overflowRight,
        [styles.overflowLeft]: overflowLeft,
    });
    const tabRefs = useRef(new Map());
    const activateTab = (index) => {
        return () => {
            if (controlledActiveTab === undefined) {
                setInternalActiveTab(index);
            }
            if (onTabChange) {
                onTabChange(index);
            }
        };
    };
    const handleKeyDown = useArrowKeyNavigation({
        elementsRef: tabRefs,
        onActivate: index => activateTab(index)(),
    });
    const activeTabProps = (_a = tabChildren[activeTab]) === null || _a === void 0 ? void 0 : _a.props;
    useEffect(() => {
        if (activeTab > tabChildren.length - 1) {
            setInternalActiveTab(activeTabInitialValue);
        }
    }, [tabChildren.length]);
    return (React__default.createElement("div", { className: styles.tabs },
        React__default.createElement("div", { className: overflowClassNames },
            React__default.createElement("ul", { role: "tablist", className: styles.tabRow, ref: tabRow, onKeyDown: handleKeyDown }, React__default.Children.map(children, child => {
                if (!isChildTab(child)) {
                    return child;
                }
                const index = tabChildren.findIndex(tab => tab.props.label === child.props.label);
                return (React__default.createElement(InternalTab, { label: child.props.label, selected: activeTab === index, activateTab: activateTab(index), onClick: child.props.onClick, ref: el => {
                        if (el) {
                            tabRefs.current.set(index, el);
                        }
                        else {
                            tabRefs.current.delete(index);
                        }
                    }, tabIndex: activeTab === index ? 0 : -1 }));
            }))),
        React__default.createElement("section", { role: "tabpanel", className: styles.tabContent, "aria-label": typeof (activeTabProps === null || activeTabProps === void 0 ? void 0 : activeTabProps.label) === "string"
                ? activeTabProps.label
                : undefined }, activeTabProps === null || activeTabProps === void 0 ? void 0 : activeTabProps.children)));
}
function Tab({ label }) {
    return React__default.createElement(React__default.Fragment, null, label);
}
const InternalTab = React__default.forwardRef(({ label, selected, activateTab, onClick, tabIndex }, ref) => {
    const className = classnames(styles.tab, { [styles.selected]: selected });
    return (React__default.createElement("li", { role: "presentation" },
        React__default.createElement("button", { type: "button", role: "tab", className: className, onClick: event => {
                activateTab();
                onClick === null || onClick === void 0 ? void 0 : onClick(event);
            }, ref: ref, tabIndex: tabIndex }, typeof label === "string" ? (React__default.createElement(Typography, { element: "span", size: "large", fontWeight: "semiBold" }, label)) : (label))));
});
InternalTab.displayName = "InternalTab";
function getActiveTabs(children) {
    const activeTabChildren = [];
    React__default.Children.toArray(children).forEach(child => {
        if (isChildTab(child)) {
            activeTabChildren.push(child);
        }
    });
    return activeTabChildren;
}
function isChildTab(child) {
    return React__default.isValidElement(child) && child.type === Tab;
}

export { Tabs as T, Tab as a };
