@shopify/polaris
Version:
Shopify’s product component library
364 lines (324 loc) • 11.6 kB
JavaScript
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 };