UNPKG

@carbon/react

Version:

React components for the Carbon Design System

112 lines (110 loc) 3.85 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 { AccordionContext } from "./AccordionProvider.js"; import { Text } from "../Text/Text.js"; import { Escape } from "../../internal/keyboard/keys.js"; import { match } from "../../internal/keyboard/match.js"; import { useId } from "../../internal/useId.js"; import { deprecate } from "../../prop-types/deprecate.js"; import classNames from "classnames"; import React, { useContext, useEffect, useRef, useState } from "react"; import PropTypes from "prop-types"; import { jsx, jsxs } from "react/jsx-runtime"; import { ChevronRight } from "@carbon/icons-react"; //#region src/components/Accordion/AccordionItem.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 defaultRenderToggle = (props) => /* @__PURE__ */ jsx("button", { type: "button", ...props }); function AccordionItem({ children, className: customClassName = "", open = false, onHeadingClick, renderExpando = defaultRenderToggle, renderToggle, title = "title", disabled: controlledDisabled, handleAnimationEnd, "aria-label": ariaLabel, ...rest }) { const [isOpen, setIsOpen] = useState(open); const prevOpenRef = useRef(open); const accordionState = useContext(AccordionContext); const disabled = typeof controlledDisabled === "boolean" ? controlledDisabled : accordionState.disabled; const id = useId("accordion-item"); const prefix = usePrefix(); const className = classNames({ [`${prefix}--accordion__item`]: true, [`${prefix}--accordion__item--active`]: isOpen && !disabled, [`${prefix}--accordion__item--disabled`]: disabled, [customClassName]: !!customClassName }); const Toggle = renderToggle || renderExpando; const content = React.useCallback((node) => { if (!node) return; if (isOpen) node.style.maxBlockSize = ""; }, [isOpen]); useEffect(() => { if (open !== prevOpenRef.current) { setIsOpen(open); prevOpenRef.current = open; } }, [open]); function onClick(event) { const nextValue = !isOpen; setIsOpen(nextValue); if (onHeadingClick) onHeadingClick({ isOpen: nextValue, event }); } function onKeyDown(event) { if (isOpen && match(event, Escape)) setIsOpen(false); } function onAnimationEnd(event) { if (handleAnimationEnd) handleAnimationEnd(event); } return /* @__PURE__ */ jsxs("li", { className, ...rest, children: [/* @__PURE__ */ jsxs(Toggle, { disabled, "aria-controls": id, "aria-expanded": isOpen, "aria-label": ariaLabel, className: `${prefix}--accordion__heading`, onClick, onKeyDown, type: "button", children: [/* @__PURE__ */ jsx(ChevronRight, { className: `${prefix}--accordion__arrow` }), /* @__PURE__ */ jsx(Text, { as: "div", className: `${prefix}--accordion__title`, children: title })] }), /* @__PURE__ */ jsx("div", { ref: content, className: `${prefix}--accordion__wrapper`, onTransitionEnd: onAnimationEnd, children: /* @__PURE__ */ jsx("div", { id, className: `${prefix}--accordion__content`, children }) })] }); } AccordionItem.propTypes = { children: PropTypes.node, className: PropTypes.string, disabled: PropTypes.bool, "aria-label": PropTypes.string, onClick: PropTypes.func, onHeadingClick: PropTypes.func, open: PropTypes.bool, renderExpando: deprecate(PropTypes.func, "The `renderExpando` prop has been deprecated and will be removed in the next major release of Carbon. Use the `renderToggle` prop instead."), renderToggle: PropTypes.func, title: PropTypes.node }; //#endregion export { AccordionItem as default };