@trail-ui/react
Version:
76 lines (74 loc) • 2.8 kB
JavaScript
// src/tabs/tabs.tsx
import { useIsMounted } from "@trail-ui/hooks";
import { clsx } from "@trail-ui/shared-utils";
import { filterVariantProps, tabs } from "@trail-ui/theme";
import {
cloneElement,
createContext,
isValidElement,
useContext,
useMemo
} from "react";
import {
Tab as AriaTab,
TabList as AriaTabList,
TabPanel as AriaTabPanel,
Tabs as AriaTabs
} from "react-aria-components";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var InternalTabsContext = createContext(
{}
);
function Tabs(props) {
const { className, classNames, indicator, onSelectionChange, ...otherProps } = props;
const variantProps = filterVariantProps(props, tabs.variantKeys);
const slots = useMemo(() => tabs({ ...variantProps }), [variantProps]);
const baseStyles = clsx(classNames == null ? void 0 : classNames.base, className);
return /* @__PURE__ */ jsx(InternalTabsContext.Provider, { value: { slots, classNames, indicator }, children: /* @__PURE__ */ jsx(
AriaTabs,
{
...otherProps,
onSelectionChange,
className: slots.base({ class: baseStyles })
}
) });
}
function TabList(props) {
const { slots, classNames } = useContext(InternalTabsContext);
return /* @__PURE__ */ jsx(AriaTabList, { ...props, className: slots.tabList({ class: classNames == null ? void 0 : classNames.tabList }) });
}
function Tab(props) {
const { slots, classNames, indicator } = useContext(InternalTabsContext);
const { children } = props;
const [, isMounted] = useIsMounted({
rerender: true
});
const getIndicatoContent = () => {
if (indicator === null) {
return null;
}
if (indicator) {
if (!isValidElement(indicator))
return null;
return cloneElement(indicator, {
className: slots.cursor({ class: classNames == null ? void 0 : classNames.cursor })
});
}
return /* @__PURE__ */ jsx("span", { className: slots.cursor({ class: classNames == null ? void 0 : classNames.cursor }) });
};
return /* @__PURE__ */ jsx(AriaTab, { ...props, className: slots.tab({ class: classNames == null ? void 0 : classNames.tab }), children: (renderProps) => /* @__PURE__ */ jsxs(Fragment, { children: [
renderProps.isSelected && isMounted ? getIndicatoContent() : null,
/* @__PURE__ */ jsx("div", { className: slots.tabContent({ class: classNames == null ? void 0 : classNames.tabContent }), children: typeof children === "function" ? children(renderProps) : children })
] }) });
}
function TabPanel(props) {
const { slots, classNames } = useContext(InternalTabsContext);
return /* @__PURE__ */ jsx(AriaTabPanel, { ...props, className: slots.panel({ class: classNames == null ? void 0 : classNames.panel }) });
}
export {
InternalTabsContext,
Tabs,
TabList,
Tab,
TabPanel
};