UNPKG

@talend/react-components

Version:
261 lines (259 loc) 6.92 kB
import PropTypes from 'prop-types'; import classNames from 'classnames'; import { Button } from '@talend/react-bootstrap'; import { withTranslation } from 'react-i18next'; import TooltipTrigger from '../../TooltipTrigger'; import CircularProgress from '../../CircularProgress'; import Skeleton from '../../Skeleton'; import Icon from '../../Icon'; import getPropsFrom from '../../utils/getPropsFrom'; import theme from './ActionButton.module.scss'; import I18N_DOMAIN_COMPONENTS from '../../constants'; import getDefaultT from '../../translate'; import OverlayTrigger from '../../OverlayTrigger'; import { SizedIcon } from '@talend/design-system'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const LEFT = 'left'; const RIGHT = 'right'; function getIcon({ icon, iconName, iconTransform, inProgress, loading }) { if (inProgress) { return /*#__PURE__*/_jsx(CircularProgress, { size: "small" }, "icon"); } if (loading) { return /*#__PURE__*/_jsx(Skeleton, { size: "small", type: "circle", className: classNames(theme['tc-action-button-skeleton-circle'], 'tc-action-button-skeleton-circle') }, "icon-skeleton"); } if (iconName) { return /*#__PURE__*/_jsx(SizedIcon, { name: iconName, transform: iconTransform, size: "M" }, "icon"); } if (icon) { return /*#__PURE__*/_jsx(Icon, { name: icon, transform: iconTransform }, "icon"); } return null; } getIcon.propTypes = { icon: PropTypes.string, iconTransform: PropTypes.string, inProgress: PropTypes.bool }; function getLabel({ hideLabel, label, loading }) { if (hideLabel) { return null; } if (loading) { return /*#__PURE__*/_jsx(Skeleton, { type: "text", size: "medium" }, "label-skeleton"); } return /*#__PURE__*/_jsx("span", { children: label }, "label"); } getLabel.propTypes = { label: PropTypes.string, loading: PropTypes.bool, hideLabel: PropTypes.bool }; function adjustContentPlacement(icon, label, iconPosition) { if (iconPosition === RIGHT) { return [label, icon]; } return [icon, label]; } function getContent(props) { return adjustContentPlacement(getIcon(props), getLabel(props), props.iconPosition); } function getHandler(func, model, label, rest) { return func && (event => func(event, { action: { label, ...rest }, model })); } function noOp() {} /** * @param {object} props react props * @example const props = { label: 'edit', icon: 'fa fa-edit', onClick: action('onEdit'), tooltipPlacement: 'right', hideLabel: true, link: true, }; <Action {...props} /> */ function ActionButton(props) { const { bsStyle, buttonRef, children, inProgress, disabled, hideLabel, label, loading, download, link, model, onMouseDown = noOp, onClick = noOp, onMouseEnter, onMouseLeave, overlayId, overlayComponent, overlayPlacement, overlayRef, tooltipPlacement, tooltipClassName, tooltip, tooltipLabel, available, t, ...rest } = props; if (!available) { return null; } if (loading && !link) { return /*#__PURE__*/_jsx(Skeleton, { type: "button" }); } const buttonProps = getPropsFrom(Button, rest); const buttonContent = getContent(props); const btnIsDisabled = inProgress || disabled; const style = link ? 'link' : bsStyle; const rClick = getHandler(onClick, model, label, rest); const rMouseDown = getHandler(onMouseDown, model, label, rest); const rMouseEnter = getHandler(onMouseEnter, model, label, rest); const rMouseLeave = getHandler(onMouseLeave, model, label, rest); buttonProps.className = classNames(buttonProps.className, { 'btn-icon-only': hideLabel || !label, [theme['btn-disabled']]: btnIsDisabled }); let ariaLabel = tooltipLabel || label; if (inProgress) { ariaLabel = t('ACTION_IN_PROGRESS', { defaultValue: '{{label}} (in progress)', label: ariaLabel }); } if (loading) { ariaLabel = t('SKELETON_LOADING', { defaultValue: '{{type}} Loading...', type: ariaLabel }); } const hasPopup = !inProgress && overlayComponent; if (hasPopup) { buttonProps['aria-haspopup'] = true; } // enforce security on target="_blank" if (buttonProps.target === '_blank') { buttonProps.rel = 'noopener noreferrer'; } let btn = /*#__PURE__*/_jsxs(Button, { onMouseDown: !overlayComponent ? rMouseDown : null, onClick: !overlayComponent ? rClick : null, onMouseEnter: !overlayComponent ? rMouseEnter : null, onMouseLeave: !overlayComponent ? rMouseLeave : null, bsStyle: style, disabled: btnIsDisabled, role: link ? 'link' : null, "aria-label": ariaLabel, ref: buttonRef, download: download, ...buttonProps, children: [buttonContent, children] }); if (hasPopup) { btn = /*#__PURE__*/_jsx(OverlayTrigger, { onClick: rClick, onMouseEnter: rMouseEnter, onMouseLeave: rMouseLeave, overlayRef: overlayRef, overlayId: overlayId, overlayPlacement: overlayPlacement, overlayComponent: props.overlayComponent, getComponent: props.getComponent, preventScrolling: props.preventScrolling, children: btn }); } // 2 ways to display the tooltip via props: `hideLabel` and `tooltip`. // warning: when `tooltip` is set to false, then no tooltip even if `hideLabel` is set const shouldDisplayTooltip = (hideLabel || tooltip || tooltipLabel) && tooltip !== false; if (ariaLabel && shouldDisplayTooltip) { btn = /*#__PURE__*/_jsx(TooltipTrigger, { label: ariaLabel, tooltipPlacement: tooltipPlacement, className: tooltipClassName, children: btn }); } return btn; } ActionButton.propTypes = { ...getIcon.propTypes, available: PropTypes.bool, inProgress: PropTypes.bool, id: PropTypes.string, bsStyle: PropTypes.string, buttonRef: PropTypes.func, disabled: PropTypes.bool, download: PropTypes.string, hideLabel: PropTypes.bool, iconPosition: PropTypes.oneOf([LEFT, RIGHT]), label: PropTypes.string.isRequired, loading: PropTypes.bool, link: PropTypes.bool, model: PropTypes.object, // eslint-disable-line react/forbid-prop-types name: PropTypes.string, onClick: PropTypes.func, iconName: PropTypes.string, tooltipPlacement: OverlayTrigger.propTypes.placement, t: PropTypes.func, tooltip: PropTypes.bool, tooltipLabel: PropTypes.string, tooltipClassName: PropTypes.string }; ActionButton.defaultProps = { available: true, bsStyle: 'default', tooltipPlacement: 'top', inProgress: false, loading: false, disabled: false, t: getDefaultT() }; ActionButton.displayName = 'ActionButton'; export default withTranslation(I18N_DOMAIN_COMPONENTS)(ActionButton); //# sourceMappingURL=ActionButton.component.js.map