UNPKG

@carbon/react

Version:

React components for the Carbon Design System

183 lines (181 loc) 5.83 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 { useId } from "../../internal/useId.js"; import { deprecateValuesWithin } from "../../prop-types/deprecateValuesWithin.js"; import { mapPopoverAlign } from "../../tools/mapPopoverAlign.js"; import { useFeatureFlag } from "../FeatureFlags/index.js"; import { IconButton } from "../IconButton/index.js"; import Button_default from "../Button/index.js"; import { mergeRefs } from "../../tools/mergeRefs.js"; import { Menu as Menu$1 } from "../Menu/Menu.js"; import { useAttachedMenu } from "../../internal/useAttachedMenu.js"; import classNames from "classnames"; import React, { useRef } from "react"; import PropTypes from "prop-types"; import { jsx, jsxs } from "react/jsx-runtime"; import { ChevronDown } from "@carbon/icons-react"; import { autoUpdate, flip, hide, size, useFloating } from "@floating-ui/react"; //#region src/components/ComboButton/index.tsx /** * Copyright IBM Corp. 2023, 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 defaultTranslations = { [{ "carbon.combo-button.additional-actions": "carbon.combo-button.additional-actions" }["carbon.combo-button.additional-actions"]]: "Additional actions" }; const defaultTranslateWithId = (messageId) => { return defaultTranslations[messageId]; }; const ComboButton = React.forwardRef(function ComboButton({ children, className, disabled, label, onClick, size: size$1 = "lg", menuAlignment = "bottom", tooltipAlignment, translateWithId: t = defaultTranslateWithId, ...rest }, forwardRef) { const enableOnlyFloatingStyles = useFeatureFlag("enable-v12-dynamic-floating-styles"); const id = useId("combobutton"); const prefix = usePrefix(); const containerRef = useRef(null); let middlewares = []; if (!enableOnlyFloatingStyles) middlewares = [flip({ crossAxis: false }), hide()]; if (menuAlignment === "bottom" || menuAlignment === "top") middlewares.push(size({ apply({ rects, elements }) { Object.assign(elements.floating.style, { width: `${rects.reference.width}px` }); } })); const { refs, floatingStyles, placement, middlewareData } = useFloating({ placement: menuAlignment, strategy: "fixed", middleware: middlewares, whileElementsMounted: autoUpdate }); const ref = mergeRefs(forwardRef, containerRef, refs.setReference); const { open, handleClick: hookOnClick, handleMousedown: handleTriggerMousedown, handleClose } = useAttachedMenu(containerRef); useIsomorphicEffect(() => { const updatedFloatingStyles = { ...floatingStyles, visibility: middlewareData.hide?.referenceHidden ? "hidden" : "visible" }; Object.keys(updatedFloatingStyles).forEach((style) => { if (refs.floating.current) refs.floating.current.style[style] = updatedFloatingStyles[style]; }); }, [ floatingStyles, refs.floating, middlewareData, placement, open ]); function handleTriggerClick() { if (containerRef.current) hookOnClick(); } function handlePrimaryActionClick(e) { if (onClick) onClick(e); } const containerClasses = classNames(`${prefix}--combo-button__container`, `${prefix}--combo-button__container--${size$1}`, { [`${prefix}--combo-button__container--open`]: open }, className); const menuClasses = classNames(`${prefix}--combo-button__${menuAlignment}`); const primaryActionClasses = classNames(`${prefix}--combo-button__primary-action`); const triggerClasses = classNames(`${prefix}--combo-button__trigger`); return /* @__PURE__ */ jsxs("div", { ...rest, className: containerClasses, ref, "aria-owns": open ? id : void 0, children: [ /* @__PURE__ */ jsx("div", { className: primaryActionClasses, children: /* @__PURE__ */ jsx(Button_default, { title: label, size: size$1, disabled, onClick: handlePrimaryActionClick, children: label }) }), /* @__PURE__ */ jsx(IconButton, { ref: refs.setReference, className: triggerClasses, label: t("carbon.combo-button.additional-actions"), size: size$1, disabled, align: tooltipAlignment, "aria-haspopup": true, "aria-expanded": open, onClick: handleTriggerClick, onMouseDown: handleTriggerMousedown, "aria-controls": open ? id : void 0, children: /* @__PURE__ */ jsx(ChevronDown, {}) }), /* @__PURE__ */ jsx(Menu$1, { containerRef, menuAlignment, className: menuClasses, ref: refs.setFloating, id, label: t("carbon.combo-button.additional-actions"), size: size$1, open, onClose: handleClose, children }) ] }); }); ComboButton.propTypes = { children: PropTypes.node.isRequired, className: PropTypes.string, disabled: PropTypes.bool, label: PropTypes.string.isRequired, menuAlignment: PropTypes.oneOf([ "top", "top-start", "top-end", "bottom", "bottom-start", "bottom-end" ]), onClick: PropTypes.func, size: PropTypes.oneOf([ "xs", "sm", "md", "lg" ]), tooltipAlignment: deprecateValuesWithin(PropTypes.oneOf([ "top", "top-left", "top-right", "bottom", "bottom-left", "bottom-right", "left", "left-bottom", "left-top", "right", "right-bottom", "right-top", "top-start", "top-end", "bottom-start", "bottom-end", "left-end", "left-start", "right-end", "right-start" ]), [ "top", "top-start", "top-end", "bottom", "bottom-start", "bottom-end", "left", "left-start", "left-end", "right", "right-start", "right-end" ], mapPopoverAlign), translateWithId: PropTypes.func }; //#endregion export { ComboButton };