UNPKG

@ariakit/react-core

Version:

Ariakit React core

195 lines (193 loc) 5.95 kB
"use client"; import { TabScopedContextProvider, useTabProviderContext } from "../__chunks/QGC5LOGZ.js"; import { useDisclosureContent } from "../__chunks/K4R5DNTX.js"; import { useDisclosureStore } from "../__chunks/T22PY7TE.js"; import { useCollectionItem } from "../__chunks/Y62RTBST.js"; import "../__chunks/T2AZQXQU.js"; import "../__chunks/ABN76PSX.js"; import "../__chunks/APTFW6PT.js"; import { useFocusable } from "../__chunks/OE2EFRVA.js"; import "../__chunks/SWN3JYXT.js"; import { useStoreState } from "../__chunks/RTNCFSKZ.js"; import "../__chunks/5CPL3B7G.js"; import { createElement, createHook, forwardRef } from "../__chunks/VOQWLFSQ.js"; import { useEvent, useId, useMergeRefs, useWrapElement } from "../__chunks/5GGHRIN3.js"; import "../__chunks/SK3NAZA3.js"; import { __objRest, __spreadProps, __spreadValues } from "../__chunks/3YLGPPWQ.js"; // src/tab/tab-panel.tsx import { getAllTabbableIn } from "@ariakit/core/utils/focus"; import { invariant } from "@ariakit/core/utils/misc"; import { useCallback, useEffect, useRef, useState } from "react"; import { jsx } from "react/jsx-runtime"; var TagName = "div"; var useTabPanel = createHook( function useTabPanel2(_a) { var _b = _a, { store, unmountOnHide, tabId: tabIdProp, getItem: getItemProp, scrollRestoration, scrollElement } = _b, props = __objRest(_b, [ "store", "unmountOnHide", "tabId", "getItem", "scrollRestoration", "scrollElement" ]); const context = useTabProviderContext(); store = store || context; invariant( store, process.env.NODE_ENV !== "production" && "TabPanel must receive a `store` prop or be wrapped in a TabProvider component." ); const ref = useRef(null); const id = useId(props.id); const tabId = useStoreState( store.panels, () => { var _a2; return tabIdProp || ((_a2 = store == null ? void 0 : store.panels.item(id)) == null ? void 0 : _a2.tabId); } ); const open = useStoreState( store, (state) => !!tabId && state.selectedId === tabId ); const disclosure = useDisclosureStore({ open }); const mounted = useStoreState(disclosure, "mounted"); const scrollPositionRef = useRef( /* @__PURE__ */ new Map() ); const getScrollElement = useEvent(() => { const panelElement = ref.current; if (!panelElement) return null; if (!scrollElement) return panelElement; if (typeof scrollElement === "function") { return scrollElement(panelElement); } if ("current" in scrollElement) { return scrollElement.current; } return scrollElement; }); useEffect(() => { var _a2, _b2; if (!scrollRestoration) return; if (!mounted) return; const element = getScrollElement(); if (!element) return; if (scrollRestoration === "reset") { element.scroll(0, 0); return; } if (!tabId) return; const position = scrollPositionRef.current.get(tabId); element.scroll((_a2 = position == null ? void 0 : position.x) != null ? _a2 : 0, (_b2 = position == null ? void 0 : position.y) != null ? _b2 : 0); const onScroll = () => { scrollPositionRef.current.set(tabId, { x: element.scrollLeft, y: element.scrollTop }); }; element.addEventListener("scroll", onScroll); return () => { element.removeEventListener("scroll", onScroll); }; }, [scrollRestoration, mounted, tabId, getScrollElement, store]); const [hasTabbableChildren, setHasTabbableChildren] = useState(false); useEffect(() => { const element = ref.current; if (!element) return; const tabbable = getAllTabbableIn(element); setHasTabbableChildren(!!tabbable.length); }, []); const getItem = useCallback( (item) => { const nextItem = __spreadProps(__spreadValues({}, item), { id: id || item.id, tabId: tabIdProp }); if (getItemProp) { return getItemProp(nextItem); } return nextItem; }, [id, tabIdProp, getItemProp] ); const onKeyDownProp = props.onKeyDown; const onKeyDown = useEvent((event) => { onKeyDownProp == null ? void 0 : onKeyDownProp(event); if (event.defaultPrevented) return; if (!(store == null ? void 0 : store.composite)) return; const keyMap = { ArrowLeft: store.previous, ArrowRight: store.next, Home: store.first, End: store.last }; const action = keyMap[event.key]; if (!action) return; const { selectedId } = store.getState(); const nextId = action({ activeId: selectedId }); if (!nextId) return; event.preventDefault(); store.move(nextId); }); props = useWrapElement( props, (element) => /* @__PURE__ */ jsx(TabScopedContextProvider, { value: store, children: element }), [store] ); props = __spreadProps(__spreadValues({ id, role: "tabpanel", "aria-labelledby": tabId || void 0 }, props), { children: unmountOnHide && !mounted ? null : props.children, ref: useMergeRefs(ref, props.ref), onKeyDown }); props = useFocusable(__spreadValues({ // If the tab panel is rendered as part of another composite widget such // as combobox, it should not be focusable. focusable: !store.composite && !hasTabbableChildren }, props)); props = useDisclosureContent(__spreadValues({ store: disclosure }, props)); props = useCollectionItem(__spreadProps(__spreadValues({ store: store.panels }, props), { getItem })); return props; } ); var TabPanel = forwardRef(function TabPanel2(props) { const htmlProps = useTabPanel(props); return createElement(TagName, htmlProps); }); export { TabPanel, useTabPanel };