UNPKG

@talend/react-components

Version:
310 lines (309 loc) 10.3 kB
import { Component, createElement as _createElement } from 'react'; import ReactDOM from 'react-dom'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; import classNames from 'classnames'; import { Iterable } from 'immutable'; import { DropdownButton, MenuItem } from '@talend/react-bootstrap'; import { withTranslation } from 'react-i18next'; import Inject from '../../Inject'; import OverlayTrigger from '../../OverlayTrigger'; import theme from './ActionDropdown.module.scss'; import Tag from '../../Tag'; import TooltipTrigger from '../../TooltipTrigger'; import Icon from '../../Icon'; import wrapOnClick from '../wrapOnClick'; import CircularProgress from '../../CircularProgress/CircularProgress.component'; import I18N_DOMAIN_COMPONENTS from '../../constants'; import getDefaultT from '../../translate'; import getTabBarBadgeLabel from '../../utils/getTabBarBadgeLabel'; import { get, omit } from "lodash"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; export const DROPDOWN_CONTAINER_CN = 'tc-dropdown-container'; function InjectDropdownMenuItem({ getComponent, component, divider, withMenuItem, liProps, menuItemProps, onSelect, onKeyDown, ...rest }) { const Renderers = Inject.getAll(getComponent, { MenuItem }); if (divider) { return /*#__PURE__*/_jsx(Renderers.MenuItem, { ...menuItemProps, divider: true }); } if (withMenuItem) { return /*#__PURE__*/_jsx(Renderers.MenuItem, { ...menuItemProps, onSelect: onSelect, onKeyDown: onKeyDown, children: /*#__PURE__*/_jsx(Inject, { component: component, getComponent: getComponent, ...rest }) }); } return /*#__PURE__*/_jsx("li", { role: "presentation", ...liProps, children: /*#__PURE__*/_jsx(Inject, { component: component, getComponent: getComponent, onSelect: onSelect, ...rest }) }); } InjectDropdownMenuItem.propTypes = { getComponent: PropTypes.func.isRequired, component: PropTypes.string, divider: PropTypes.bool, withMenuItem: PropTypes.bool, liProps: PropTypes.object, menuItemProps: PropTypes.object, onSelect: PropTypes.func, onKeyDown: PropTypes.func }; InjectDropdownMenuItem.displayname = 'InjectDropdownMenuItem'; function renderMutableMenuItem(item, index, getComponent) { const Renderers = Inject.getAll(getComponent, { MenuItem }); if (item.divider) { return /*#__PURE__*/_jsx(Renderers.MenuItem, { divider: true }, index); } const title = item.title || item.label; const badgeLabel = get(item, 'badge.label', ''); return /*#__PURE__*/_createElement(Renderers.MenuItem, { ...item, key: index, eventKey: item, onClick: wrapOnClick(item), title: badgeLabel ? `${badgeLabel} ${title}` : title, className: classNames(theme['tc-dropdown-item'], 'tc-dropdown-item') }, item.icon && /*#__PURE__*/_jsx(Icon, { name: item.icon }, "icon"), !item.hideLabel && item.label, item.badge && /*#__PURE__*/_jsx(Tag, { className: classNames(theme['tc-dropdown-item-badge'], 'tc-dropdown-item-badge'), bsStyle: item.badge.bsStyle || 'default', children: getTabBarBadgeLabel(item.badge.label) })); } function getMenuItem(item, index, getComponent) { if (Iterable.isIterable(item)) { return renderMutableMenuItem(item.toJS(), index, getComponent); } return renderMutableMenuItem(item, index, getComponent); } function getDropdownContainer(dropdownElement) { let dropdownContainer = dropdownElement; do { dropdownContainer = dropdownContainer.parentElement; } while (dropdownContainer && dropdownContainer.tagName !== 'BODY' && !dropdownContainer.classList.contains(DROPDOWN_CONTAINER_CN)); return dropdownContainer; } /** * @param {object} props react props * @example const props = { label: 'related items', icon: 'fa fa-file-excel-o', items: [ { icon: 'talend-icon', label: 'document 1', onClick: action('document 1 click'), }, { divider: true, }, { label: 'document 2', onClick: action('document 2 click'), }, ], tooltipPlacement: 'right', hideLabel: true, link: true, onSelect: action('item selected'), }; <ActionDropdown {...props} /> */ class ActionDropdown extends Component { constructor(props) { super(props); this.onToggle = this.onToggle.bind(this); this.onItemSelect = this.onItemSelect.bind(this); this.state = {}; } componentDidUpdate(prevProps, prevState) { /* Dropdown/Dropup automatic switch: depending on its position with a defined container, it will switch from down and up mode. By default it checks its position with the <body>. Specific container support with "tc-dropdown-container" classname on the parent container. */ if (!prevState.isOpen && this.state.isOpen) { // eslint-disable-next-line react/no-find-dom-node const dropdown = ReactDOM.findDOMNode(this.ref); const dropdownTrigger = dropdown.querySelector('.dropdown-toggle'); const dropdownMenu = dropdownTrigger.nextSibling; const dropdownContainer = getDropdownContainer(dropdownTrigger); if (dropdownContainer) { const dropdownRect = dropdownMenu.getBoundingClientRect(); const containerRect = dropdownContainer.getBoundingClientRect(); if (!dropdown.classList.contains('dropup') && dropdownRect.bottom > containerRect.bottom && dropdownRect.height < containerRect.top) { dropdown.classList.add('dropup'); } else if (dropdown.classList.contains('dropup') && dropdownRect.top < containerRect.top) { dropdown.classList.remove('dropup'); } } } } onToggle(isOpen) { this.setState({ isOpen }, () => { if (this.props.onToggle) { this.props.onToggle(isOpen); } }); } onItemSelect(object, event) { if (this.props.onSelect) { this.props.onSelect(event, object); } } render() { const { bsStyle = 'default', hideLabel, icon, iconTransform, items = [], badge, label, link, onSelect, tooltipPlacement = 'top', tooltipLabel, getComponent, components, className, loading, children, ellipsis, t = getDefaultT(), ...rest } = this.props; const Renderers = Inject.getAll(getComponent, { MenuItem, DropdownButton }); const injected = Inject.all(getComponent, components, InjectDropdownMenuItem); const title = !ellipsis && [icon && /*#__PURE__*/_jsx(Icon, { name: icon, transform: iconTransform }, "icon"), !hideLabel && /*#__PURE__*/_jsx("span", { className: "tc-dropdown-button-title-label", children: label }, "label"), badge && /*#__PURE__*/_jsx(Tag, { className: classNames(theme['tc-dropdown-item-badge'], 'tc-dropdown-item-badge'), bsStyle: badge.bsStyle || 'default', children: getTabBarBadgeLabel(badge.label) }), /*#__PURE__*/_jsx(Icon, { name: "talend-caret-down", className: classNames(theme['tc-dropdown-caret'], { [theme['tc-dropdown-caret-open']]: this.state.isOpen }) }, "caret")].filter(Boolean); const style = link || ellipsis ? 'link' : bsStyle; const dropdown = /*#__PURE__*/_jsxs(Renderers.DropdownButton, { id: this.props.id, title: title, bsStyle: style, role: "button", onSelect: this.onItemSelect, className: classNames(theme['tc-dropdown-button'], 'tc-dropdown-button', className, { [theme.ellipsis]: ellipsis }), "aria-label": tooltipLabel || label, ...omit(rest, 'tReady'), onToggle: this.onToggle, ref: ref => { this.ref = ref; }, noCaret: true, children: [!children && !items.length && !items.size && !loading && !components && /*#__PURE__*/_jsx(Renderers.MenuItem, { disabled: true, children: t('ACTION_DROPDOWN_EMPTY', { defaultValue: 'No options' }) }, "empty"), injected('beforeItemsDropdown'), items.map((item, key) => getMenuItem(item, key, getComponent)), loading && /*#__PURE__*/_jsx(Renderers.MenuItem, { header: true, className: classNames(theme['tc-dropdown-item'], 'tc-dropdown-item', theme['tc-dropdown-loader'], 'tc-dropdown-loader'), children: /*#__PURE__*/_jsx(CircularProgress, {}) }, items ? items.length + 1 : 0), injected('itemsDropdown'), children, injected('afterItemsDropdown')] }); if (hideLabel || tooltipLabel || ellipsis) { return /*#__PURE__*/_jsx(TooltipTrigger, { label: tooltipLabel || label, tooltipPlacement: tooltipPlacement, children: dropdown }); } return dropdown; } } ActionDropdown.displayName = 'ActionDropdown'; ActionDropdown.propTypes = { id: PropTypes.string, bsStyle: PropTypes.string, className: PropTypes.string, dropup: PropTypes.bool, hideLabel: PropTypes.bool, noCaret: PropTypes.bool, pullRight: PropTypes.bool, icon: PropTypes.string, iconTransform: PropTypes.string, items: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.shape({ icon: PropTypes.string, label: PropTypes.string, ...MenuItem.propTypes })), ImmutablePropTypes.list]), badge: PropTypes.shape({ className: PropTypes.string, label: PropTypes.string, bsStyle: PropTypes.string }), label: PropTypes.string.isRequired, link: PropTypes.bool, loading: PropTypes.bool, ellipsis: PropTypes.bool, onToggle: PropTypes.func, onSelect: PropTypes.func, tooltipPlacement: OverlayTrigger.propTypes.placement, tooltipLabel: PropTypes.string, getComponent: PropTypes.func, components: PropTypes.shape({ beforeItemsDropdown: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), itemsDropdown: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), afterItemsDropdown: PropTypes.oneOfType([PropTypes.object, PropTypes.array]) }), t: PropTypes.func, children: PropTypes.node }; export { getMenuItem, InjectDropdownMenuItem }; export default withTranslation(I18N_DOMAIN_COMPONENTS)(ActionDropdown); //# sourceMappingURL=ActionDropdown.component.js.map