UNPKG

@shopify/polaris

Version:

Shopify’s admin product component library

458 lines (399 loc) • 16.7 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var debounce = require('lodash/debounce'); var polarisTokens = require('@shopify/polaris-tokens'); var reactTransitionGroup = require('react-transition-group'); var css = require('../../utilities/css.js'); var clamp = require('../../utilities/clamp.js'); var BulkActions$1 = require('./BulkActions.scss.js'); var BulkActionMenu = require('./components/BulkActionMenu/BulkActionMenu.js'); var CheckableButton = require('../CheckableButton/CheckableButton.js'); var hooks = require('../../utilities/i18n/hooks.js'); var Button = require('../Button/Button.js'); var Popover = require('../Popover/Popover.js'); var BulkActionButton = require('./components/BulkActionButton/BulkActionButton.js'); var ActionList = require('../ActionList/ActionList.js'); var ButtonGroup = require('../ButtonGroup/ButtonGroup.js'); var EventListener = require('../EventListener/EventListener.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce); const MAX_PROMOTED_ACTIONS = 2; const slideClasses = { appear: css.classNames(BulkActions$1['default'].Slide, BulkActions$1['default']['Slide-appear']), appearActive: css.classNames(BulkActions$1['default'].Slide, BulkActions$1['default']['Slide-appearing']), enter: css.classNames(BulkActions$1['default'].Slide, BulkActions$1['default']['Slide-enter']), enterActive: css.classNames(BulkActions$1['default'].Slide, BulkActions$1['default']['Slide-entering']), exit: css.classNames(BulkActions$1['default'].Slide, BulkActions$1['default']['Slide-exit']) }; class BulkActionsInner extends React.PureComponent { constructor(...args) { super(...args); this.state = { smallScreenPopoverVisible: false, largeScreenPopoverVisible: false, containerWidth: 0, measuring: true }; this.containerNode = null; this.largeScreenButtonsNode = null; this.moreActionsNode = null; this.checkableWrapperNode = /*#__PURE__*/React.createRef(); this.largeScreenGroupNode = /*#__PURE__*/React.createRef(); this.smallScreenGroupNode = /*#__PURE__*/React.createRef(); this.promotedActionsWidths = []; this.bulkActionsWidth = 0; this.addedMoreActionsWidthForMeasuring = 0; this.handleResize = debounce__default['default'](() => { const { smallScreenPopoverVisible, largeScreenPopoverVisible } = this.state; if (this.containerNode) { const containerWidth = this.containerNode.getBoundingClientRect().width; if (containerWidth > 0) { this.setState({ containerWidth }); } } if (smallScreenPopoverVisible || largeScreenPopoverVisible) { this.setState({ smallScreenPopoverVisible: false, largeScreenPopoverVisible: false }); } }, 50, { trailing: true }); this.setLargeScreenButtonsNode = node => { this.largeScreenButtonsNode = node; }; this.setContainerNode = node => { this.containerNode = node; }; this.setMoreActionsNode = node => { this.moreActionsNode = node; }; this.setSelectMode = val => { const { onSelectModeToggle } = this.props; if (onSelectModeToggle) { onSelectModeToggle(val); } }; this.toggleSmallScreenPopover = () => { if (this.props.onMoreActionPopoverToggle) { this.props.onMoreActionPopoverToggle(this.state.smallScreenPopoverVisible); } this.setState(({ smallScreenPopoverVisible }) => ({ smallScreenPopoverVisible: !smallScreenPopoverVisible })); }; this.toggleLargeScreenPopover = () => { if (this.props.onMoreActionPopoverToggle) { this.props.onMoreActionPopoverToggle(this.state.largeScreenPopoverVisible); } this.setState(({ largeScreenPopoverVisible }) => ({ largeScreenPopoverVisible: !largeScreenPopoverVisible })); }; this.handleMeasurement = width => { const { measuring } = this.state; if (measuring) { this.promotedActionsWidths.push(width); } }; } numberOfPromotedActionsToRender() { const { promotedActions } = this.props; const { containerWidth, measuring } = this.state; if (!promotedActions) { return 0; } if (containerWidth >= this.bulkActionsWidth || measuring) { return promotedActions.length; } let sufficientSpace = false; let counter = promotedActions.length - 1; let totalWidth = 0; while (!sufficientSpace && counter >= 0) { totalWidth += this.promotedActionsWidths[counter]; const widthWithRemovedAction = this.bulkActionsWidth - totalWidth + this.addedMoreActionsWidthForMeasuring; if (containerWidth >= widthWithRemovedAction) { sufficientSpace = true; } else { counter--; } } return clamp.clamp(counter, 0, promotedActions.length); } hasActions() { const { promotedActions, actions } = this.props; return Boolean(promotedActions && promotedActions.length > 0 || actions && actions.length > 0); } actionSections() { const { actions } = this.props; if (!actions || actions.length === 0) { return; } if (instanceOfBulkActionListSectionArray(actions)) { return actions; } if (instanceOfBulkActionArray(actions)) { return [{ items: actions }]; } } rolledInPromotedActions() { const { promotedActions } = this.props; const numberOfPromotedActionsToRender = this.numberOfPromotedActionsToRender(); if (!promotedActions || promotedActions.length === 0 || numberOfPromotedActionsToRender >= promotedActions.length) { return []; } const rolledInPromotedActions = promotedActions.map(action => { if (instanceOfMenuGroupDescriptor(action)) { return { items: [...action.actions] }; } return { items: [action] }; }); return rolledInPromotedActions.slice(numberOfPromotedActionsToRender); } // eslint-disable-next-line @typescript-eslint/member-ordering componentDidMount() { const { actions, promotedActions } = this.props; if (promotedActions && !actions && this.moreActionsNode) { this.addedMoreActionsWidthForMeasuring = this.moreActionsNode.getBoundingClientRect().width; } this.bulkActionsWidth = this.largeScreenButtonsNode ? this.largeScreenButtonsNode.getBoundingClientRect().width - this.addedMoreActionsWidthForMeasuring : 0; if (this.containerNode) { this.setState({ containerWidth: this.containerNode.getBoundingClientRect().width, measuring: false }); } } // eslint-disable-next-line @typescript-eslint/member-ordering render() { const { selectMode, accessibilityLabel, label = '', onToggleAll, selected, smallScreen, disabled, promotedActions, paginatedSelectAllText = null, paginatedSelectAllAction, i18n } = this.props; const actionSections = this.actionSections(); if (promotedActions && promotedActions.length > MAX_PROMOTED_ACTIONS) { // eslint-disable-next-line no-console console.warn(i18n.translate('Polaris.ResourceList.BulkActions.warningMessage', { maxPromotedActions: MAX_PROMOTED_ACTIONS })); } const { smallScreenPopoverVisible, largeScreenPopoverVisible, measuring } = this.state; const paginatedSelectAllActionMarkup = paginatedSelectAllAction ? /*#__PURE__*/React__default['default'].createElement(Button.Button, { onClick: paginatedSelectAllAction.onAction, plain: true, disabled: disabled }, paginatedSelectAllAction.content) : null; const paginatedSelectAllTextMarkup = paginatedSelectAllText && paginatedSelectAllAction ? /*#__PURE__*/React__default['default'].createElement("span", { "aria-live": "polite" }, paginatedSelectAllText) : paginatedSelectAllText; const paginatedSelectAllMarkup = paginatedSelectAllActionMarkup || paginatedSelectAllTextMarkup ? /*#__PURE__*/React__default['default'].createElement("div", { className: BulkActions$1['default'].PaginatedSelectAll }, paginatedSelectAllTextMarkup, " ", paginatedSelectAllActionMarkup) : null; const cancelButton = /*#__PURE__*/React__default['default'].createElement(Button.Button, { onClick: this.setSelectMode.bind(this, false), disabled: disabled }, i18n.translate('Polaris.Common.cancel')); const numberOfPromotedActionsToRender = this.numberOfPromotedActionsToRender(); const allActionsPopover = this.hasActions() ? /*#__PURE__*/React__default['default'].createElement("div", { className: BulkActions$1['default'].Popover, ref: this.setMoreActionsNode }, /*#__PURE__*/React__default['default'].createElement(Popover.Popover, { active: smallScreenPopoverVisible, activator: /*#__PURE__*/React__default['default'].createElement(BulkActionButton.BulkActionButton, { disclosure: true, onAction: this.toggleSmallScreenPopover, content: i18n.translate('Polaris.ResourceList.BulkActions.actionsActivatorLabel'), disabled: disabled, indicator: this.isNewBadgeInBadgeActions() }), onClose: this.toggleSmallScreenPopover }, /*#__PURE__*/React__default['default'].createElement(ActionList.ActionList, { items: promotedActions, sections: actionSections, onActionAnyItem: this.toggleSmallScreenPopover }))) : null; const promotedActionsMarkup = promotedActions && numberOfPromotedActionsToRender > 0 ? [...promotedActions].slice(0, numberOfPromotedActionsToRender).map((action, index) => { if (instanceOfMenuGroupDescriptor(action)) { return /*#__PURE__*/React__default['default'].createElement(BulkActionMenu.BulkActionMenu, Object.assign({ key: index }, action, { isNewBadgeInBadgeActions: this.isNewBadgeInBadgeActions() })); } return /*#__PURE__*/React__default['default'].createElement(BulkActionButton.BulkActionButton, Object.assign({ disabled: disabled }, action, { key: index, handleMeasurement: this.handleMeasurement })); }) : null; const rolledInPromotedActions = this.rolledInPromotedActions(); const activatorLabel = !promotedActions || promotedActions && numberOfPromotedActionsToRender === 0 && !measuring ? i18n.translate('Polaris.ResourceList.BulkActions.actionsActivatorLabel') : i18n.translate('Polaris.ResourceList.BulkActions.moreActionsActivatorLabel'); let combinedActions = []; if (actionSections && rolledInPromotedActions.length > 0) { combinedActions = [...rolledInPromotedActions, ...actionSections]; } else if (actionSections) { combinedActions = actionSections; } else if (rolledInPromotedActions.length > 0) { combinedActions = [...rolledInPromotedActions]; } const actionsPopover = actionSections || rolledInPromotedActions.length > 0 || measuring ? /*#__PURE__*/React__default['default'].createElement("div", { className: BulkActions$1['default'].Popover, ref: this.setMoreActionsNode }, /*#__PURE__*/React__default['default'].createElement(Popover.Popover, { active: largeScreenPopoverVisible, activator: /*#__PURE__*/React__default['default'].createElement(BulkActionButton.BulkActionButton, { disclosure: true, onAction: this.toggleLargeScreenPopover, content: activatorLabel, disabled: disabled, indicator: this.isNewBadgeInBadgeActions() }), onClose: this.toggleLargeScreenPopover }, /*#__PURE__*/React__default['default'].createElement(ActionList.ActionList, { sections: combinedActions, onActionAnyItem: this.toggleLargeScreenPopover }))) : null; const checkableButtonProps = { accessibilityLabel, label, selected, selectMode, onToggleAll, measuring, disabled }; const smallScreenGroup = smallScreen ? /*#__PURE__*/React__default['default'].createElement(reactTransitionGroup.Transition, { timeout: 0, in: selectMode, key: "smallGroup", nodeRef: this.smallScreenGroupNode }, status => { const smallScreenGroupClassName = css.classNames(BulkActions$1['default'].Group, BulkActions$1['default']['Group-smallScreen'], BulkActions$1['default'][`Group-${status}`]); return /*#__PURE__*/React__default['default'].createElement("div", { className: smallScreenGroupClassName, ref: this.smallScreenGroupNode }, /*#__PURE__*/React__default['default'].createElement("div", { className: BulkActions$1['default'].ButtonGroupWrapper }, /*#__PURE__*/React__default['default'].createElement(ButtonGroup.ButtonGroup, { segmented: true }, /*#__PURE__*/React__default['default'].createElement(reactTransitionGroup.CSSTransition, { nodeRef: this.checkableWrapperNode, in: selectMode, timeout: polarisTokens.durationBase, classNames: slideClasses, appear: !selectMode }, /*#__PURE__*/React__default['default'].createElement("div", { className: BulkActions$1['default'].CheckableContainer, ref: this.checkableWrapperNode }, /*#__PURE__*/React__default['default'].createElement(CheckableButton.CheckableButton, Object.assign({}, checkableButtonProps, { smallScreen: true })))), allActionsPopover, cancelButton)), paginatedSelectAllMarkup); }) : null; const largeGroupContent = promotedActionsMarkup || actionsPopover ? /*#__PURE__*/React__default['default'].createElement(ButtonGroup.ButtonGroup, { segmented: true }, /*#__PURE__*/React__default['default'].createElement(CheckableButton.CheckableButton, checkableButtonProps), promotedActionsMarkup, actionsPopover) : /*#__PURE__*/React__default['default'].createElement(CheckableButton.CheckableButton, checkableButtonProps); const largeScreenGroup = smallScreen ? null : /*#__PURE__*/React__default['default'].createElement(reactTransitionGroup.Transition, { timeout: 0, in: selectMode, key: "largeGroup", nodeRef: this.largeScreenGroupNode }, status => { const largeScreenGroupClassName = css.classNames(BulkActions$1['default'].Group, BulkActions$1['default']['Group-largeScreen'], !measuring && BulkActions$1['default'][`Group-${status}`], measuring && BulkActions$1['default']['Group-measuring']); return /*#__PURE__*/React__default['default'].createElement("div", { className: largeScreenGroupClassName, ref: this.largeScreenGroupNode }, /*#__PURE__*/React__default['default'].createElement(EventListener.EventListener, { event: "resize", handler: this.handleResize }), /*#__PURE__*/React__default['default'].createElement("div", { className: BulkActions$1['default'].ButtonGroupWrapper, ref: this.setLargeScreenButtonsNode }, largeGroupContent), paginatedSelectAllMarkup); }); return /*#__PURE__*/React__default['default'].createElement("div", { ref: this.setContainerNode }, smallScreenGroup, largeScreenGroup); } isNewBadgeInBadgeActions() { const actions = this.actionSections(); if (!actions) return false; for (const action of actions) { for (const item of action.items) { var _item$badge; if (((_item$badge = item.badge) === null || _item$badge === void 0 ? void 0 : _item$badge.status) === 'new') return true; } } return false; } } function instanceOfBulkActionListSectionArray(actions) { const validList = actions.filter(action => { return action.items; }); return actions.length === validList.length; } function instanceOfBulkActionArray(actions) { const validList = actions.filter(action => { return !action.items; }); return actions.length === validList.length; } function instanceOfMenuGroupDescriptor(action) { return 'title' in action; } function BulkActions(props) { const i18n = hooks.useI18n(); return /*#__PURE__*/React__default['default'].createElement(BulkActionsInner, Object.assign({}, props, { i18n: i18n })); } exports.BulkActions = BulkActions;