UNPKG

@carbon/react

Version:

React components for the Carbon Design System

79 lines (77 loc) 2.92 kB
/** * Copyright IBM Corp. 2016, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ import { usePrefix } from "../../internal/usePrefix.js"; import { isComponentElement } from "../../internal/utils.js"; import { useMergedRefs } from "../../internal/useMergedRefs.js"; import { AriaLabelPropType } from "../../prop-types/AriaPropTypes.js"; import SwitcherItem from "./SwitcherItem.js"; import SwitcherDivider from "./SwitcherDivider.js"; import classNames from "classnames"; import { Children, cloneElement, forwardRef, useRef } from "react"; import PropTypes from "prop-types"; import { jsx } from "react/jsx-runtime"; //#region src/components/UIShell/Switcher.tsx /** * Copyright IBM Corp. 2016, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ const Switcher = forwardRef((props, forwardRef) => { const switcherRef = useRef(null); const ref = useMergedRefs([switcherRef, forwardRef]); const prefix = usePrefix(); const { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, className: customClassName, children, expanded } = props; const accessibilityLabel = { "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy }; const className = classNames(`${prefix}--switcher`, { [customClassName || ""]: !!customClassName }); const handleSwitcherItemFocus = ({ currentIndex, direction }) => { const enabledIndices = Children.toArray(children).reduce((acc, child, i) => { if (isComponentElement(child, SwitcherItem) && Object.keys(child.props).length) acc.push(i); return acc; }, []); const nextValidIndex = (() => { const nextIndex = enabledIndices.indexOf(currentIndex) + direction; switch (enabledIndices[nextIndex]) { case void 0: if (direction === -1) return enabledIndices[enabledIndices.length - 1]; return enabledIndices[0]; case 0: if (direction === 1) return enabledIndices[1]; default: return enabledIndices[nextIndex]; } })(); const switcherItem = switcherRef.current?.children[nextValidIndex]?.children[0]; if (switcherItem instanceof HTMLElement) switcherItem.focus(); }; const childrenWithProps = Children.toArray(children).map((child, index) => { if (isComponentElement(child, SwitcherItem)) return cloneElement(child, { handleSwitcherItemFocus, index, key: index, expanded }); if (isComponentElement(child, SwitcherDivider)) return cloneElement(child, { key: index }); return child; }); return /* @__PURE__ */ jsx("ul", { ref, className, ...accessibilityLabel, children: childrenWithProps }); }); Switcher.displayName = "Switcher"; Switcher.propTypes = { ...AriaLabelPropType, children: PropTypes.node.isRequired, className: PropTypes.string, expanded: PropTypes.bool }; //#endregion export { Switcher as default };