UNPKG

@shopify/polaris

Version:

Shopify’s product component library

364 lines (324 loc) • 11.6 kB
import { objectWithoutProperties as _objectWithoutProperties } from '../../_virtual/_rollupPluginBabelHelpers.js'; import React$1, { useContext, Component, createRef } from 'react'; import { useFeatures } from '../../utilities/features/hooks.js'; import { globalIdGeneratorFactory } from '../../utilities/unique-id/unique-id-factory.js'; import { useI18n } from '../../utilities/i18n/hooks.js'; import { classNames, variationName } from '../../utilities/css.js'; import { HorizontalDotsMinor } from '@shopify/polaris-icons'; import { Popover as Popover$1 } from '../Popover/Popover.js'; import { UnstyledLink as UnstyledLink$1 } from '../UnstyledLink/UnstyledLink.js'; import { ActionList as ActionList$1 } from '../ActionList/ActionList.js'; import { Button as Button$1 } from '../Button/Button.js'; import { buttonsFrom } from '../Button/utils.js'; import { ButtonGroup as ButtonGroup$1 } from '../ButtonGroup/ButtonGroup.js'; import isEqual$1 from 'lodash/isEqual'; import { Checkbox as Checkbox$1 } from '../Checkbox/Checkbox.js'; import { ResourceListContext } from '../../utilities/resource-list/context.js'; import { SELECT_ALL_ITEMS } from '../../utilities/resource-list/types.js'; import styles from './ResourceItem.scss.js'; var getUniqueCheckboxID = globalIdGeneratorFactory('ResourceListItemCheckbox'); var getUniqueOverlayID = globalIdGeneratorFactory('ResourceListItemOverlay'); class BaseResourceItem extends Component { constructor(...args) { super(...args); this.state = { actionsMenuVisible: false, focused: false, focusedInner: false, selected: isSelected(this.props.id, this.props.context.selectedItems) }; this.node = null; this.checkboxId = getUniqueCheckboxID(); this.overlayId = getUniqueOverlayID(); this.buttonOverlay = /*#__PURE__*/createRef(); this.setNode = node => { this.node = node; }; this.handleFocus = event => { if (event.target === this.buttonOverlay.current || this.node && event.target === this.node.querySelector("#".concat(this.overlayId))) { this.setState({ focused: true, focusedInner: false }); } else if (this.node && this.node.contains(event.target)) { this.setState({ focused: true, focusedInner: true }); } }; this.handleBlur = ({ relatedTarget }) => { if (this.node && relatedTarget instanceof Element && this.node.contains(relatedTarget)) { return; } this.setState({ focused: false, focusedInner: false }); }; this.handleMouseOut = () => { this.state.focused && this.setState({ focused: false, focusedInner: false }); }; this.handleLargerSelectionArea = event => { stopPropagation(event); this.handleSelection(!this.state.selected, event.nativeEvent.shiftKey); }; this.handleSelection = (value, shiftKey) => { var { id, sortOrder, context: { onSelectionChange } } = this.props; if (id == null || onSelectionChange == null) { return; } this.setState({ focused: value, focusedInner: value }); onSelectionChange(value, id, sortOrder, shiftKey); }; this.handleClick = event => { stopPropagation(event); var { id, onClick, url, context: { selectMode } } = this.props; var { ctrlKey, metaKey } = event.nativeEvent; var anchor = this.node && this.node.querySelector('a'); if (selectMode) { this.handleLargerSelectionArea(event); return; } if (anchor === event.target) { return; } if (onClick) { onClick(id); } if (url && (ctrlKey || metaKey)) { window.open(url, '_blank'); return; } if (url && anchor) { anchor.click(); } }; this.handleKeyUp = event => { var { onClick = noop, context: { selectMode } } = this.props; var { key } = event; if (key === 'Enter' && this.props.url && !selectMode) { onClick(); } }; this.handleActionsClick = () => { this.setState(({ actionsMenuVisible }) => ({ actionsMenuVisible: !actionsMenuVisible })); }; this.handleCloseRequest = () => { this.setState({ actionsMenuVisible: false }); }; } static getDerivedStateFromProps(nextProps, prevState) { var selected = isSelected(nextProps.id, nextProps.context.selectedItems); if (prevState.selected === selected) { return null; } return { selected }; } shouldComponentUpdate(nextProps, nextState) { var restNextContext = _objectWithoutProperties(nextProps.context, ["selectedItems"]), restNextProps = _objectWithoutProperties(nextProps, ["children", "context"]); var _this$props = this.props, restContext = _objectWithoutProperties(_this$props.context, ["selectedItems"]), restProps = _objectWithoutProperties(_this$props, ["children", "context"]); var nextSelectMode = nextProps.context.selectMode; return !isEqual$1(this.state, nextState) || this.props.context.selectMode !== nextSelectMode || !nextProps.context.selectMode && (!isEqual$1(restProps, restNextProps) || !isEqual$1(restContext, restNextContext)); } render() { var { children, url, external, media, shortcutActions, ariaControls, ariaExpanded, persistActions = false, accessibilityLabel, name, context: { selectable, selectMode, loading, resourceName }, i18n, features: { newDesignLanguage }, verticalAlignment } = this.props; var { actionsMenuVisible, focused, focusedInner, selected } = this.state; var ownedMarkup = null; var handleMarkup = null; var mediaMarkup = media ? /*#__PURE__*/React$1.createElement("div", { className: styles.Media }, media) : null; if (selectable) { var checkboxAccessibilityLabel = name || accessibilityLabel || i18n.translate('Polaris.Common.checkbox'); handleMarkup = /*#__PURE__*/React$1.createElement("div", { className: styles.Handle, onClick: this.handleLargerSelectionArea }, /*#__PURE__*/React$1.createElement("div", { onClick: stopPropagation, className: styles.CheckboxWrapper }, /*#__PURE__*/React$1.createElement("div", { onChange: this.handleLargerSelectionArea }, /*#__PURE__*/React$1.createElement(Checkbox$1, { id: this.checkboxId, label: checkboxAccessibilityLabel, labelHidden: true, checked: selected, disabled: loading })))); } if (media || selectable) { ownedMarkup = /*#__PURE__*/React$1.createElement("div", { className: classNames(styles.Owned, !mediaMarkup && styles.OwnedNoMedia) }, handleMarkup, mediaMarkup); } var className = classNames(styles.ResourceItem, newDesignLanguage && styles.newDesignLanguage, focused && styles.focused, selectable && styles.selectable, selected && styles.selected, selectMode && styles.selectMode, persistActions && styles.persistActions, focusedInner && styles.focusedInner); var listItemClassName = classNames(styles.ListItem, focused && !focusedInner && styles.focused, newDesignLanguage && styles.newDesignLanguage); var actionsMarkup = null; var disclosureMarkup = null; if (shortcutActions && !loading) { if (persistActions) { actionsMarkup = /*#__PURE__*/React$1.createElement("div", { className: styles.Actions, onClick: stopPropagation }, /*#__PURE__*/React$1.createElement(ButtonGroup$1, null, buttonsFrom(shortcutActions, { plain: true }))); var disclosureAccessibilityLabel = name ? i18n.translate('Polaris.ResourceList.Item.actionsDropdownLabel', { accessibilityLabel: name }) : i18n.translate('Polaris.ResourceList.Item.actionsDropdown'); disclosureMarkup = /*#__PURE__*/React$1.createElement("div", { className: styles.Disclosure, onClick: stopPropagation }, /*#__PURE__*/React$1.createElement(Popover$1, { activator: /*#__PURE__*/React$1.createElement(Button$1, { accessibilityLabel: disclosureAccessibilityLabel, onClick: this.handleActionsClick, plain: true, icon: HorizontalDotsMinor }), onClose: this.handleCloseRequest, active: actionsMenuVisible }, /*#__PURE__*/React$1.createElement(ActionList$1, { items: shortcutActions }))); } else { actionsMarkup = /*#__PURE__*/React$1.createElement("div", { className: styles.Actions, onClick: stopPropagation }, /*#__PURE__*/React$1.createElement(ButtonGroup$1, { segmented: true }, buttonsFrom(shortcutActions, { size: 'slim' }))); } } var content = children ? /*#__PURE__*/React$1.createElement("div", { className: styles.Content }, children) : null; var containerClassName = classNames(styles.Container, verticalAlignment && styles[variationName('alignment', verticalAlignment)]); var containerMarkup = /*#__PURE__*/React$1.createElement("div", { className: containerClassName, id: this.props.id }, ownedMarkup, content, actionsMarkup, disclosureMarkup); var tabIndex = loading ? -1 : 0; var ariaLabel = accessibilityLabel || i18n.translate('Polaris.ResourceList.Item.viewItem', { itemName: name || resourceName && resourceName.singular || '' }); var accessibleMarkup = url ? /*#__PURE__*/React$1.createElement(UnstyledLink$1, { "aria-describedby": this.props.id, "aria-label": ariaLabel, className: styles.Link, url: url, external: external, tabIndex: tabIndex, id: this.overlayId }) : /*#__PURE__*/React$1.createElement("button", { className: styles.Button, "aria-label": ariaLabel, "aria-controls": ariaControls, "aria-expanded": ariaExpanded, onClick: this.handleClick, tabIndex: tabIndex, ref: this.buttonOverlay }); return /*#__PURE__*/React$1.createElement("li", { className: listItemClassName }, /*#__PURE__*/React$1.createElement("div", { className: styles.ItemWrapper }, /*#__PURE__*/React$1.createElement("div", { ref: this.setNode, className: className, onClick: this.handleClick, onFocus: this.handleFocus, onBlur: this.handleBlur, onKeyUp: this.handleKeyUp, onMouseOut: this.handleMouseOut, "data-href": url }, accessibleMarkup, containerMarkup))); } } function noop() {} function stopPropagation(event) { event.stopPropagation(); } function isSelected(id, selectedItems) { return Boolean(selectedItems && (Array.isArray(selectedItems) && selectedItems.includes(id) || selectedItems === SELECT_ALL_ITEMS)); } function ResourceItem(props) { return /*#__PURE__*/React$1.createElement(BaseResourceItem, Object.assign({}, props, { context: useContext(ResourceListContext), features: useFeatures(), i18n: useI18n() })); } export { ResourceItem };