UNPKG

@carbon/react

Version:

React components for the Carbon Design System

86 lines (84 loc) 2.98 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 useIsomorphicEffect from "../../internal/useIsomorphicEffect.js"; import classNames from "classnames"; import React, { forwardRef, useEffect, useRef, useState } from "react"; import PropTypes from "prop-types"; import { jsx } from "react/jsx-runtime"; //#region src/components/ButtonSet/ButtonSet.tsx /** * Copyright IBM Corp. 2016, 2025 * * 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 buttonOrder = (kind) => ({ ghost: 1, "danger--ghost": 2, tertiary: 3, danger: 5, primary: 6 })[kind] ?? 4; const getButtonKind = (element) => { if (React.isValidElement(element) && element.props && typeof element.props === "object") return element.props.kind ?? "primary"; return "primary"; }; const ButtonSet = forwardRef((props, ref) => { const { children, className, fluid, stacked, ...rest } = props; const prefix = usePrefix(); const fluidInnerRef = useRef(null); const [isStacked, setIsStacked] = useState(false); const [sortedChildren, setSortedChildren] = useState(React.Children.toArray(children)); /** * Used to determine if the buttons are currently stacked */ useIsomorphicEffect(() => { const checkStacking = () => { let newIsStacked = stacked || false; if (fluidInnerRef && fluidInnerRef.current) newIsStacked = window.getComputedStyle(fluidInnerRef.current)?.getPropertyValue?.("--flex-direction") === "column"; return newIsStacked; }; setIsStacked(checkStacking()); if (!fluidInnerRef.current) return; const resizeObserver = new ResizeObserver(() => { setIsStacked(checkStacking()); }); resizeObserver.observe(fluidInnerRef.current); return () => resizeObserver.disconnect(); }, [fluid, stacked]); useEffect(() => { const newSortedChildren = React.Children.toArray(children); newSortedChildren.sort((a, b) => { return (buttonOrder(getButtonKind(a)) - buttonOrder(getButtonKind(b))) * (isStacked ? -1 : 1); }); setSortedChildren(newSortedChildren); }, [children, isStacked]); const buttonSetClasses = classNames(className, `${prefix}--btn-set`, { [`${prefix}--btn-set--stacked`]: isStacked, [`${prefix}--btn-set--fluid`]: fluid }); return /* @__PURE__ */ jsx("div", { ...rest, className: buttonSetClasses, ref, children: fluid ? /* @__PURE__ */ jsx("div", { ref: fluidInnerRef, className: classNames(`${prefix}--btn-set__fluid-inner`, { [`${prefix}--btn-set__fluid-inner--auto-stack`]: true }), children: sortedChildren }) : children }); }); ButtonSet.displayName = "ButtonSet"; ButtonSet.propTypes = { children: PropTypes.node, className: PropTypes.string, fluid: PropTypes.bool, stacked: PropTypes.bool }; //#endregion export { ButtonSet as default };