@wordpress/components
Version:
UI components for WordPress.
109 lines (108 loc) • 3.84 kB
JavaScript
import * as Ariakit from "@ariakit/react";
import clsx from "clsx";
import warning from "@wordpress/warning";
import { forwardRef, useLayoutEffect, useState } from "@wordpress/element";
import { useMergeRefs } from "@wordpress/compose";
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;
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) {
parent.scroll?.({
left: scrollLeft
});
}
}, [margin, parent, rect]);
}
const TabList = forwardRef(function TabList2({
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;
const selectedRect = useTrackElementOffsetRect(selectedItem?.element, [selectedItemIndex]);
const overflow = useTrackOverflow(parent, {
first: items?.at(0)?.element,
last: items?.at(-1)?.element
});
useAnimatedOffsetRect(parent, selectedRect, {
prefix: "selected",
dataAttribute: "indicator-animated",
transitionEndFilter: (event) => event.pseudoElement === "::before",
roundRect: true
});
useScrollRectIntoView(parent, selectedRect);
const onBlur = () => {
if (!selectOnMove) {
return;
}
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,
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,
"data-select-on-move": selectOnMove ? "true" : "false",
...otherProps,
className: clsx(overflow.first && "is-overflowing-first", overflow.last && "is-overflowing-last", otherProps.className),
children
});
});
export {
TabList
};
//# sourceMappingURL=tablist.js.map