@mskcc/carbon-react
Version:
Carbon react components for the MSKCC DSM
180 lines (169 loc) • 6.29 kB
JavaScript
/**
* MSKCC 2021, 2024
*/
;
Object.defineProperty(exports, '__esModule', { value: true });
var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
var iconsReact = require('@carbon/icons-react');
var cx = require('classnames');
var PropTypes = require('prop-types');
var React = require('react');
require('../Text/index.js');
var useId = require('../../internal/useId.js');
var usePrefix = require('../../internal/usePrefix.js');
var AccordionProvider = require('./AccordionProvider.js');
var Text = require('../Text/Text.js');
var match = require('../../internal/keyboard/match.js');
var keys = require('../../internal/keyboard/keys.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx);
var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
function AccordionItem(_ref) {
let {
children,
className: customClassName = '',
open = false,
onHeadingClick,
renderToggle,
title = 'title',
disabled: controlledDisabled,
handleAnimationEnd,
openIcon,
closeIcon,
iconOnlyToggle = false,
headingClassName,
titleClassName,
contentClassName,
...rest
} = _ref;
const [isOpen, setIsOpen] = React.useState(open);
const [prevIsOpen, setPrevIsOpen] = React.useState(open);
const [animation, setAnimation] = React.useState('');
const accordionState = React.useContext(AccordionProvider.AccordionContext);
const disabledIsControlled = typeof controlledDisabled === 'boolean';
const disabled = disabledIsControlled ? controlledDisabled : accordionState.disabled;
const id = useId.useId('accordion-item');
const prefix = usePrefix.usePrefix();
const className = cx__default["default"]({
[`${prefix}--accordion__item`]: true,
[`${prefix}--accordion__item--active`]: isOpen,
[`${prefix}--accordion__item--${animation}`]: animation,
[`${prefix}--accordion__item--disabled`]: disabled,
'msk-accordion-item--toggle-icon-only': iconOnlyToggle,
[customClassName]: !!customClassName
});
const defaultRenderToggle = props => !iconOnlyToggle ? /*#__PURE__*/React__default["default"].createElement("button", _rollupPluginBabelHelpers["extends"]({
type: "button"
}, props)) : /*#__PURE__*/React__default["default"].createElement("div", props);
const Toggle = renderToggle || defaultRenderToggle;
if (open !== prevIsOpen) {
setAnimation(isOpen ? 'collapsing' : 'expanding');
setIsOpen(open);
setPrevIsOpen(open);
}
// When the AccordionItem heading is clicked, toggle the open state of the
// panel
function onClick(event) {
const nextValue = !isOpen;
setAnimation(isOpen ? 'collapsing' : 'expanding');
setIsOpen(nextValue);
if (onHeadingClick) {
// TODO: normalize signature, potentially:
// onHeadingClick :: (event: Event, state: { isOpen: Boolean }) => any
onHeadingClick({
isOpen: nextValue,
event
});
}
}
// If the AccordionItem is open, and the user hits the ESC key, then close it
function onKeyDown(event) {
if (isOpen && match.match(event, keys.Escape)) {
setIsOpen(false);
}
}
function onAnimationEnd(event) {
if (handleAnimationEnd) {
handleAnimationEnd(event);
}
setAnimation('');
}
function onIconClick(event) {
if (iconOnlyToggle) {
onClick(event);
}
}
// Determine which icon to use
let IconComponent;
if (openIcon && closeIcon) {
IconComponent = /*#__PURE__*/React__default["default"].createElement("button", {
className: "msk-accordion-item--expand-icon",
onClick: iconOnlyToggle ? onIconClick : undefined // Attach onClick if iconOnlyToggle is true
}, isOpen ? closeIcon : openIcon);
} else {
IconComponent = /*#__PURE__*/React__default["default"].createElement(iconsReact.ChevronRight, {
onClick: iconOnlyToggle ? onIconClick : undefined,
className: `${prefix}--accordion__arrow`
});
}
return /*#__PURE__*/React__default["default"].createElement("li", _rollupPluginBabelHelpers["extends"]({
className: className
}, rest, {
onAnimationEnd: onAnimationEnd
}), /*#__PURE__*/React__default["default"].createElement(Toggle, {
disabled: disabled,
"aria-controls": id,
"aria-expanded": isOpen,
className: cx__default["default"](headingClassName, `${prefix}--accordion__heading`),
onClick: !iconOnlyToggle ? onClick : undefined // Attach onClick if iconOnlyToggle is false
,
onKeyDown: onKeyDown,
type: !iconOnlyToggle ? 'button' : undefined
}, IconComponent, /*#__PURE__*/React__default["default"].createElement(Text.Text, {
as: "div",
className: cx__default["default"](titleClassName, `${prefix}--accordion__title`)
}, title)), /*#__PURE__*/React__default["default"].createElement("div", {
id: id,
className: cx__default["default"](contentClassName, `${prefix}--accordion__content`)
}, children));
}
AccordionItem.propTypes = {
/**
* Provide the contents of your AccordionItem
*/
children: PropTypes__default["default"].node,
headingClassName: PropTypes__default["default"].node,
titleClassName: PropTypes__default["default"].node,
contentClassName: PropTypes__default["default"].node,
/**
* Specify an optional className to be applied to the container node
*/
className: PropTypes__default["default"].string,
/**
* Specify whether an individual AccordionItem should be disabled
*/
disabled: PropTypes__default["default"].bool,
/**
* The handler of the massaged `click` event.
*/
onClick: PropTypes__default["default"].func,
/**
* The handler of the massaged `click` event on the heading.
*/
onHeadingClick: PropTypes__default["default"].func,
/**
* `true` to open the expand.
*/
open: PropTypes__default["default"].bool,
/**
* The callback function to render the expand button.
* Can be a React component class.
*/
renderToggle: PropTypes__default["default"].func,
/**
* The accordion title.
*/
title: PropTypes__default["default"].node
};
exports["default"] = AccordionItem;