@mskcc/carbon-react
Version:
Carbon react components for the MSKCC DSM
243 lines (238 loc) • 7.41 kB
JavaScript
/**
* MSKCC 2021, 2024
*/
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
import cx from 'classnames';
import PropTypes from 'prop-types';
import React__default, { useState } from 'react';
import { Warning, Incomplete, CheckmarkOutline, CircleDash } from '@carbon/icons-react';
import { usePrefix } from '../../internal/usePrefix.js';
import { matches } from '../../internal/keyboard/match.js';
import { Enter, Space } from '../../internal/keyboard/keys.js';
function ProgressIndicator(_ref) {
let {
children,
className: customClassName,
currentIndex: controlledIndex = 0,
onChange,
spaceEqually,
vertical,
...rest
} = _ref;
const prefix = usePrefix();
const [currentIndex, setCurrentIndex] = useState(controlledIndex);
const [prevControlledIndex, setPrevControlledIndex] = useState(controlledIndex);
const className = cx({
[`${prefix}--progress`]: true,
[`${prefix}--progress--vertical`]: vertical,
[`${prefix}--progress--space-equal`]: spaceEqually && !vertical,
[customClassName]: customClassName
});
if (controlledIndex !== prevControlledIndex) {
setCurrentIndex(controlledIndex);
setPrevControlledIndex(controlledIndex);
}
return /*#__PURE__*/React__default.createElement("ul", _extends({
className: className
}, rest), React__default.Children.map(children, (child, index) => {
// only setup click handlers if onChange event is passed
const onClick = onChange ? () => onChange(index) : undefined;
if (index === currentIndex) {
return /*#__PURE__*/React__default.cloneElement(child, {
complete: child.props.complete,
current: child.props.complete ? false : true,
index,
onClick
});
}
if (index < currentIndex) {
return /*#__PURE__*/React__default.cloneElement(child, {
complete: true,
index,
onClick
});
}
if (index > currentIndex) {
return /*#__PURE__*/React__default.cloneElement(child, {
complete: child.props.complete || false,
index,
onClick
});
}
return null;
}));
}
ProgressIndicator.propTypes = {
/**
* Provide `<ProgressStep>` components to be rendered in the
* `<ProgressIndicator>`
*/
children: PropTypes.node,
/**
* Provide an optional className to be applied to the containing node
*/
className: PropTypes.string,
/**
* Optionally specify the current step array index
*/
currentIndex: PropTypes.number,
/**
* Optional callback called if a ProgressStep is clicked on. Returns the index of the step.
*/
onChange: PropTypes.func,
/**
* Specify whether the progress steps should be split equally in size in the div
*/
spaceEqually: PropTypes.bool,
/**
* Determines whether or not the ProgressIndicator should be rendered vertically.
*/
vertical: PropTypes.bool
};
function ProgressStep(_ref2) {
let {
label,
description,
className,
current,
complete,
invalid,
secondaryLabel,
disabled,
onClick,
translateWithId: t,
...rest
} = _ref2;
const prefix = usePrefix();
const classes = cx({
[`${prefix}--progress-step`]: true,
[`${prefix}--progress-step--current`]: current,
[`${prefix}--progress-step--complete`]: complete,
[`${prefix}--progress-step--incomplete`]: !complete && !current,
[`${prefix}--progress-step--disabled`]: disabled,
[className]: className
});
const handleKeyDown = e => {
if (matches(e, [Enter, Space])) {
onClick();
}
};
// eslint-disable-next-line react/prop-types
const SVGIcon = _ref3 => {
let {
complete,
current,
description,
invalid,
prefix
} = _ref3;
if (invalid) {
return /*#__PURE__*/React__default.createElement(Warning, {
className: `${prefix}--progress__warning`
}, /*#__PURE__*/React__default.createElement("title", null, description));
}
if (current) {
return /*#__PURE__*/React__default.createElement(Incomplete, null, /*#__PURE__*/React__default.createElement("title", null, description));
}
if (complete) {
return /*#__PURE__*/React__default.createElement(CheckmarkOutline, null, /*#__PURE__*/React__default.createElement("title", null, description));
}
return /*#__PURE__*/React__default.createElement(CircleDash, null, /*#__PURE__*/React__default.createElement("title", null, description));
};
let message = t('carbon.progress-step.incomplete');
if (current) {
message = t('carbon.progress-step.current');
}
if (complete) {
message = t('carbon.progress-step.complete');
}
if (invalid) {
message = t('carbon.progress-step.invalid');
}
return /*#__PURE__*/React__default.createElement("li", {
className: classes
}, /*#__PURE__*/React__default.createElement("button", _extends({
type: "button",
className: cx(`${prefix}--progress-step-button`, {
[`${prefix}--progress-step-button--unclickable`]: !onClick || current
}),
disabled: disabled,
"aria-disabled": disabled,
tabIndex: !current && onClick && !disabled ? 0 : -1,
onClick: !current ? onClick : undefined,
onKeyDown: handleKeyDown,
title: label
}, rest), /*#__PURE__*/React__default.createElement(SVGIcon, {
complete: complete,
current: current,
description: description,
invalid: invalid,
prefix: prefix
}), /*#__PURE__*/React__default.createElement("div", {
className: `${prefix}--progress-text`
}, /*#__PURE__*/React__default.createElement("p", {
className: `${prefix}--progress-label`
}, label), secondaryLabel !== null && secondaryLabel !== undefined ? /*#__PURE__*/React__default.createElement("p", {
className: `${prefix}--progress-optional`
}, secondaryLabel) : null), /*#__PURE__*/React__default.createElement("span", {
className: `${prefix}--assistive-text`
}, message), /*#__PURE__*/React__default.createElement("span", {
className: `${prefix}--progress-line`
})));
}
ProgressStep.propTypes = {
/**
* Provide an optional className to be applied to the containing `<li>` node
*/
className: PropTypes.string,
/**
* Specify whether the step has been completed
*/
complete: PropTypes.bool,
/**
* Specify whether the step is the current step
*/
current: PropTypes.bool,
/**
* Provide a description for the `<ProgressStep>`
*/
description: PropTypes.string,
/**
* Specify whether the step is disabled
*/
disabled: PropTypes.bool,
/**
* Index of the current step within the ProgressIndicator
*/
index: PropTypes.number,
/**
* Specify whether the step is invalid
*/
invalid: PropTypes.bool,
/**
* Provide the label for the `<ProgressStep>`
*/
label: PropTypes.node.isRequired,
/**
* A callback called if the step is clicked or the enter key is pressed
*/
onClick: PropTypes.func,
/**
* Provide the props that describe a progress step tooltip
*/
overflowTooltipProps: PropTypes.object,
/**
* Provide an optional secondary label
*/
secondaryLabel: PropTypes.string,
/**
* The ID of the tooltip content.
*/
tooltipId: PropTypes.string,
/**
* Optional method that takes in a message id and returns an
* internationalized string.
*/
translateWithId: PropTypes.func
};
export { ProgressIndicator, ProgressStep };