@mskcc/carbon-react
Version:
Carbon react components for the MSKCC DSM
145 lines (141 loc) • 4.61 kB
JavaScript
/**
* MSKCC 2021, 2024
*/
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
import React__default, { useRef, useState } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import { ChevronDown } from '@carbon/icons-react';
import Button from '../Button/Button.js';
import '../Button/Button.Skeleton.js';
import { IconButton } from '../IconButton/IconButton.js';
import { Menu } from '../Menu/Menu.js';
import { useAttachedMenu } from '../../internal/useAttachedMenu.js';
import { useId } from '../../internal/useId.js';
import { useMergedRefs } from '../../internal/useMergedRefs.js';
import { usePrefix } from '../../internal/usePrefix.js';
var _ChevronDown;
const spacing = 4; // top and bottom spacing between the button and the menu. in px
const defaultTranslations = {
'carbon.combo-button.additional-actions': 'Additional actions'
};
function defaultTranslateWithId(messageId) {
return defaultTranslations[messageId];
}
const ComboButton = /*#__PURE__*/React__default.forwardRef(function ComboButton(_ref, forwardRef) {
let {
children,
className,
disabled,
label,
onClick,
size = 'lg',
tooltipAlignment,
translateWithId: t = defaultTranslateWithId,
...rest
} = _ref;
const id = useId('combobutton');
const prefix = usePrefix();
const containerRef = useRef(null);
const menuRef = useRef(null);
const ref = useMergedRefs([forwardRef, containerRef]);
const [width, setWidth] = useState(0);
const {
open,
x,
y,
handleClick: hookOnClick,
handleMousedown: handleTriggerMousedown,
handleClose
} = useAttachedMenu(containerRef);
function handleTriggerClick() {
if (containerRef.current) {
const {
width: w
} = containerRef.current.getBoundingClientRect();
setWidth(w);
hookOnClick();
}
}
function handlePrimaryActionClick(e) {
if (onClick) {
onClick(e);
}
}
function handleOpen() {
menuRef.current.style.width = `${width}px`;
}
const containerClasses = cx(`${prefix}--combo-button__container`, `${prefix}--combo-button__container--${size}`, {
[`${prefix}--combo-button__container--open`]: open
}, className);
const primaryActionClasses = cx(`${prefix}--combo-button__primary-action`);
const triggerClasses = cx(`${prefix}--combo-button__trigger`);
return /*#__PURE__*/React__default.createElement("div", _extends({}, rest, {
className: containerClasses,
ref: ref,
"aria-owns": open ? id : null
}), /*#__PURE__*/React__default.createElement("div", {
className: primaryActionClasses
}, /*#__PURE__*/React__default.createElement(Button, {
size: size,
disabled: disabled,
onClick: handlePrimaryActionClick
}, label)), /*#__PURE__*/React__default.createElement(IconButton, {
className: triggerClasses,
label: t('carbon.combo-button.additional-actions'),
size: size,
disabled: disabled,
align: tooltipAlignment,
"aria-haspopup": true,
"aria-expanded": open,
onClick: handleTriggerClick,
onMouseDown: handleTriggerMousedown,
"aria-controls": open ? id : null
}, _ChevronDown || (_ChevronDown = /*#__PURE__*/React__default.createElement(ChevronDown, null))), /*#__PURE__*/React__default.createElement(Menu, {
ref: menuRef,
id: id,
label: t('carbon.combo-button.additional-actions'),
size: size,
open: open,
onClose: handleClose,
onOpen: handleOpen,
x: x,
y: [y[0] - spacing, y[1] + spacing]
}, children));
});
ComboButton.propTypes = {
/**
* A collection of MenuItems to be rendered as additional actions for this ComboButton.
*/
children: PropTypes.node.isRequired,
/**
* Additional CSS class names.
*/
className: PropTypes.string,
/**
* Specify whether the ComboButton should be disabled, or not.
*/
disabled: PropTypes.bool,
/**
* Provide the label to be renderd on the primary action button.
*/
label: PropTypes.string.isRequired,
/**
* Provide an optional function to be called when the primary action element is clicked.
*/
onClick: PropTypes.func,
/**
* Specify the size of the buttons and menu.
*/
size: PropTypes.oneOf(['sm', 'md', 'lg']),
/**
* Specify how the trigger tooltip should be aligned.
*/
tooltipAlignment: PropTypes.oneOf(['top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'left', 'right']),
/**
* Optional method that takes in a message id and returns an
* internationalized string.
*/
translateWithId: PropTypes.func
};
export { ComboButton };