UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

186 lines (185 loc) • 6.6 kB
import useIsomorphicLayoutEffect from "../../utils/useIsomorphicLayoutEffect.js"; import { useResizeObserver } from "../../hooks/useResizeObserver.js"; import { useId as useId$1 } from "../../hooks/useId.js"; import { invariant } from "../../utils/invariant.js"; import { isSlot } from "../../utils/is-slot.js"; import { createComponent } from "../../utils/create-component.js"; import { UnderlineItem, UnderlineItemList, UnderlineWrapper } from "../../internal/components/UnderlineTabbedInterface.js"; import UnderlinePanels_module_css_default from "./UnderlinePanels.module.css.js"; import { c } from "react-compiler-runtime"; import { clsx } from "clsx"; import { jsx, jsxs } from "react/jsx-runtime"; import React, { Children, cloneElement, createContext, isValidElement, useContext, useMemo, useRef, useState } from "react"; import { TabContainerElement } from "@github/tab-container-element"; //#region src/experimental/UnderlinePanels/UnderlinePanels.tsx const TabContainerComponent = createComponent(TabContainerElement, "tab-container"); const UnderlinePanelsContext = /*#__PURE__*/ createContext({ iconsVisible: true, loadingCounters: void 0 }); const UnderlinePanels = ({ "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, children, loadingCounters, className, ...props }) => { const [iconsVisible, setIconsVisible] = useState(true); const wrapperRef = useRef(null); const listRef = useRef(null); const parentId = useId$1(props.id); const [tabs_0, tabPanels_0, tabsHaveIcons_0] = useMemo(() => { let tabIndex = 0; let panelIndex = 0; const childrenWithProps = Children.map(children, (child) => { if (/*#__PURE__*/ isValidElement(child) && (child.type === Tab || isSlot(child, Tab))) return /*#__PURE__*/ cloneElement(child, { id: `${parentId}-tab-${tabIndex++}` }); if (/*#__PURE__*/ isValidElement(child) && (child.type === Panel || isSlot(child, Panel))) return /*#__PURE__*/ cloneElement(child, { "aria-labelledby": `${parentId}-tab-${panelIndex++}` }); return child; }); const tabs = []; const tabPanels = []; for (const child_0 of Children.toArray(childrenWithProps)) { if (!/*#__PURE__*/ isValidElement(child_0)) continue; if (child_0.type === Tab || isSlot(child_0, Tab)) tabs.push(child_0); else if (child_0.type === Panel || isSlot(child_0, Panel)) tabPanels.push(child_0); } return [ tabs, tabPanels, tabs.some((tab) => /*#__PURE__*/ React.isValidElement(tab) && tab.props.icon) ]; }, [children, parentId]); const contextValue = useMemo(() => ({ iconsVisible, loadingCounters }), [iconsVisible, loadingCounters]); const iconsVisibleRef = useRef(iconsVisible); useIsomorphicLayoutEffect(() => { iconsVisibleRef.current = iconsVisible; }, [iconsVisible]); const listWidthRef = useRef(0); useResizeObserver((entries) => { if (!tabsHaveIcons_0) return; if (!iconsVisibleRef.current) return; listWidthRef.current = entries[0].contentRect.width; }, listRef, []); useResizeObserver((resizeObserverEntries) => { if (!tabsHaveIcons_0) return; const wrapperWidth = resizeObserverEntries[0].contentRect.width; setIconsVisible(wrapperWidth > listWidthRef.current); }, wrapperRef, []); !(tabs_0.filter((tab_0) => { const ariaSelected = /*#__PURE__*/ React.isValidElement(tab_0) && tab_0.props["aria-selected"]; return ariaSelected === true || ariaSelected === "true"; }).length <= 1) && invariant(false, "Only one tab can be selected at a time."); !(tabs_0.length === tabPanels_0.length) && invariant(false, `The number of tabs and panels must be equal. Counted ${tabs_0.length} tabs and ${tabPanels_0.length} panels.`); return /*#__PURE__*/ jsx(UnderlinePanelsContext.Provider, { value: contextValue, children: /*#__PURE__*/ jsxs(TabContainerComponent, { children: [/*#__PURE__*/ jsx(UnderlineWrapper, { ref: wrapperRef, slot: "tablist-wrapper", "data-icons-visible": iconsVisible, className: clsx(className, UnderlinePanels_module_css_default.StyledUnderlineWrapper), ...props, children: /*#__PURE__*/ jsx(UnderlineItemList, { ref: listRef, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, role: "tablist", children: tabs_0 }) }), tabPanels_0] }) }); }; UnderlinePanels.displayName = "UnderlinePanels"; const TabImpl = (t0) => { const $ = c(15); let ariaSelected; let onSelect; let props; if ($[0] !== t0) { ({"aria-selected": ariaSelected, onSelect, ...props} = t0); $[0] = t0; $[1] = ariaSelected; $[2] = onSelect; $[3] = props; } else { ariaSelected = $[1]; onSelect = $[2]; props = $[3]; } const { loadingCounters } = useContext(UnderlinePanelsContext); let t1; if ($[4] !== onSelect) { t1 = (event) => { if (!event.defaultPrevented && typeof onSelect === "function") onSelect(event); }; $[4] = onSelect; $[5] = t1; } else t1 = $[5]; const clickHandler = t1; let t2; if ($[6] !== onSelect) { t2 = (event_0) => { if ((event_0.key === " " || event_0.key === "Enter") && !event_0.defaultPrevented && typeof onSelect === "function") onSelect(event_0); }; $[6] = onSelect; $[7] = t2; } else t2 = $[7]; const keyDownHandler = t2; const t3 = ariaSelected ? 0 : -1; let t4; if ($[8] !== ariaSelected || $[9] !== clickHandler || $[10] !== keyDownHandler || $[11] !== loadingCounters || $[12] !== props || $[13] !== t3) { t4 = /*#__PURE__*/ jsx(UnderlineItem, { as: "button", role: "tab", tabIndex: t3, "aria-selected": ariaSelected, type: "button", onClick: clickHandler, onKeyDown: keyDownHandler, loadingCounters, ...props }); $[8] = ariaSelected; $[9] = clickHandler; $[10] = keyDownHandler; $[11] = loadingCounters; $[12] = props; $[13] = t3; $[14] = t4; } else t4 = $[14]; return t4; }; TabImpl.displayName = "UnderlinePanels.Tab"; const Tab = /*#__PURE__*/ React.memo(TabImpl); Tab.displayName = "UnderlinePanels.Tab"; const Panel = (t0) => { const $ = c(6); let children; let rest; if ($[0] !== t0) { ({children, ...rest} = t0); $[0] = t0; $[1] = children; $[2] = rest; } else { children = $[1]; rest = $[2]; } let t1; if ($[3] !== children || $[4] !== rest) { t1 = /*#__PURE__*/ jsx("div", { role: "tabpanel", ...rest, children }); $[3] = children; $[4] = rest; $[5] = t1; } else t1 = $[5]; return t1; }; Panel.displayName = "UnderlinePanels.Panel"; var UnderlinePanels_default = Object.assign(UnderlinePanels, { Panel, Tab }); Tab.__SLOT__ = Symbol("UnderlinePanels.Tab"); Panel.__SLOT__ = Symbol("UnderlinePanels.Panel"); //#endregion export { UnderlinePanels_default as default };