@material-ui/core
Version:
React components that implement Google's Material Design.
330 lines (266 loc) • 11.4 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.styles = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _react = _interopRequireDefault(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _clsx = _interopRequireDefault(require("clsx"));
var _utils = require("@material-ui/utils");
var _withStyles = _interopRequireDefault(require("../styles/withStyles"));
var _ButtonBase = _interopRequireDefault(require("../ButtonBase"));
var _reactHelpers = require("../utils/reactHelpers");
var _ListContext = _interopRequireDefault(require("../List/ListContext"));
var _reactDom = _interopRequireDefault(require("react-dom"));
var _warning = _interopRequireDefault(require("warning"));
var styles = function styles(theme) {
return {
/* Styles applied to the (normally root) `component` element. May be wrapped by a `container`. */
root: {
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'center',
position: 'relative',
textDecoration: 'none',
width: '100%',
boxSizing: 'border-box',
textAlign: 'left',
paddingTop: 8,
paddingBottom: 8,
'&$focusVisible': {
backgroundColor: theme.palette.action.selected
},
'&$selected, &$selected:hover': {
backgroundColor: theme.palette.action.selected
},
'&$disabled': {
opacity: 0.5
}
},
/* Styles applied to the `container` element if `children` includes `ListItemSecondaryAction`. */
container: {
position: 'relative'
},
/* Pseudo-class applied to the `component`'s `focusVisibleClassName` prop if `button={true}`. */
focusVisible: {},
/* Styles applied to the `component` element if dense. */
dense: {
paddingTop: 4,
paddingBottom: 4
},
/* Styles applied to the `component` element if `alignItems="flex-start"`. */
alignItemsFlexStart: {
alignItems: 'flex-start'
},
/* Pseudo-class applied to the inner `component` element if `disabled={true}`. */
disabled: {},
/* Styles applied to the inner `component` element if `divider={true}`. */
divider: {
borderBottom: "1px solid ".concat(theme.palette.divider),
backgroundClip: 'padding-box'
},
/* Styles applied to the inner `component` element if `disableGutters={false}`. */
gutters: {
paddingLeft: 16,
paddingRight: 16
},
/* Styles applied to the inner `component` element if `button={true}`. */
button: {
transition: theme.transitions.create('background-color', {
duration: theme.transitions.duration.shortest
}),
'&:hover': {
textDecoration: 'none',
backgroundColor: theme.palette.action.hover,
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {
backgroundColor: 'transparent'
}
}
},
/* Styles applied to the `component` element if `children` includes `ListItemSecondaryAction`. */
secondaryAction: {
// Add some space to avoid collision as `ListItemSecondaryAction`
// is absolutely positioned.
paddingRight: 48
},
/* Pseudo-class applied to the root element if `selected={true}`. */
selected: {}
};
};
exports.styles = styles;
var useEnhancedEffect = typeof window === 'undefined' ? _react.default.useEffect : _react.default.useLayoutEffect;
/**
* Uses an additional container component if `ListItemSecondaryAction` is the last child.
*/
var ListItem = _react.default.forwardRef(function ListItem(props, ref) {
var _props$alignItems = props.alignItems,
alignItems = _props$alignItems === void 0 ? 'center' : _props$alignItems,
_props$autoFocus = props.autoFocus,
autoFocus = _props$autoFocus === void 0 ? false : _props$autoFocus,
_props$button = props.button,
button = _props$button === void 0 ? false : _props$button,
childrenProp = props.children,
classes = props.classes,
className = props.className,
componentProp = props.component,
_props$ContainerCompo = props.ContainerComponent,
ContainerComponent = _props$ContainerCompo === void 0 ? 'li' : _props$ContainerCompo,
_props$ContainerProps = props.ContainerProps;
_props$ContainerProps = _props$ContainerProps === void 0 ? {} : _props$ContainerProps;
var ContainerClassName = _props$ContainerProps.className,
ContainerProps = (0, _objectWithoutProperties2.default)(_props$ContainerProps, ["className"]),
dense = props.dense,
_props$disabled = props.disabled,
disabled = _props$disabled === void 0 ? false : _props$disabled,
_props$disableGutters = props.disableGutters,
disableGutters = _props$disableGutters === void 0 ? false : _props$disableGutters,
_props$divider = props.divider,
divider = _props$divider === void 0 ? false : _props$divider,
focusVisibleClassName = props.focusVisibleClassName,
_props$selected = props.selected,
selected = _props$selected === void 0 ? false : _props$selected,
other = (0, _objectWithoutProperties2.default)(props, ["alignItems", "autoFocus", "button", "children", "classes", "className", "component", "ContainerComponent", "ContainerProps", "dense", "disabled", "disableGutters", "divider", "focusVisibleClassName", "selected"]);
var context = _react.default.useContext(_ListContext.default);
var childContext = {
dense: dense || context.dense || false,
alignItems: alignItems
};
var listItemRef = _react.default.useRef(null);
useEnhancedEffect(function () {
if (autoFocus) {
if (listItemRef.current) {
listItemRef.current.focus();
} else {
process.env.NODE_ENV !== "production" ? (0, _warning.default)(false, 'Material-UI: unable to set focus to a ListItem whose component has not been rendered.') : void 0;
}
}
}, [autoFocus]);
var children = _react.default.Children.toArray(childrenProp);
var hasSecondaryAction = children.length && (0, _reactHelpers.isMuiElement)(children[children.length - 1], ['ListItemSecondaryAction']);
var handleOwnRef = _react.default.useCallback(function (instance) {
// #StrictMode ready
listItemRef.current = _reactDom.default.findDOMNode(instance);
}, []);
var handleRef = (0, _reactHelpers.useForkRef)(handleOwnRef, ref);
var componentProps = (0, _extends2.default)({
className: (0, _clsx.default)(classes.root, className, childContext.dense && classes.dense, !disableGutters && classes.gutters, divider && classes.divider, disabled && classes.disabled, button && classes.button, alignItems !== "center" && classes.alignItemsFlexStart, hasSecondaryAction && classes.secondaryAction, selected && classes.selected),
disabled: disabled
}, other);
var Component = componentProp || 'li';
if (button) {
componentProps.component = componentProp || 'div';
componentProps.focusVisibleClassName = (0, _clsx.default)(classes.focusVisible, focusVisibleClassName);
Component = _ButtonBase.default;
}
if (hasSecondaryAction) {
// Use div by default.
Component = !componentProps.component && !componentProp ? 'div' : Component; // Avoid nesting of li > li.
if (ContainerComponent === 'li') {
if (Component === 'li') {
Component = 'div';
} else if (componentProps.component === 'li') {
componentProps.component = 'div';
}
}
return _react.default.createElement(_ListContext.default.Provider, {
value: childContext
}, _react.default.createElement(ContainerComponent, (0, _extends2.default)({
className: (0, _clsx.default)(classes.container, ContainerClassName),
ref: handleRef
}, ContainerProps), _react.default.createElement(Component, componentProps, children), children.pop()));
}
return _react.default.createElement(_ListContext.default.Provider, {
value: childContext
}, _react.default.createElement(Component, (0, _extends2.default)({
ref: handleRef
}, componentProps), children));
});
process.env.NODE_ENV !== "production" ? ListItem.propTypes = {
/**
* Defines the `align-items` style property.
*/
alignItems: _propTypes.default.oneOf(['flex-start', 'center']),
/**
* If `true`, the list item will be focused during the first mount.
* Focus will also be triggered if the value changes from false to true.
*/
autoFocus: _propTypes.default.bool,
/**
* If `true`, the list item will be a button (using `ButtonBase`).
*/
button: _propTypes.default.bool,
/**
* The content of the component. If a `ListItemSecondaryAction` is used it must
* be the last child.
*/
children: (0, _utils.chainPropTypes)(_propTypes.default.node, function (props) {
var children = _react.default.Children.toArray(props.children); // React.Children.toArray(props.children).findLastIndex(isListItemSecondaryAction)
var secondaryActionIndex = -1;
for (var i = children.length - 1; i >= 0; i -= 1) {
var child = children[i];
if ((0, _reactHelpers.isMuiElement)(child, ['ListItemSecondaryAction'])) {
secondaryActionIndex = i;
break;
}
} // is ListItemSecondaryAction the last child of ListItem
if (secondaryActionIndex !== -1 && secondaryActionIndex !== children.length - 1) {
return new Error('Material-UI: you used an element after ListItemSecondaryAction. ' + 'For ListItem to detect that it has a secondary action ' + 'you must pass it as the last child to ListItem.');
}
return null;
}),
/**
* Override or extend the styles applied to the component.
* See [CSS API](#css) below for more details.
*/
classes: _propTypes.default.object.isRequired,
/**
* @ignore
*/
className: _propTypes.default.string,
/**
* The component used for the root node.
* Either a string to use a DOM element or a component.
* By default, it's a `li` when `button` is `false` and a `div` when `button` is `true`.
*/
component: _propTypes.default.elementType,
/**
* The container component used when a `ListItemSecondaryAction` is the last child.
*/
ContainerComponent: _propTypes.default.elementType,
/**
* Props applied to the container component if used.
*/
ContainerProps: _propTypes.default.object,
/**
* If `true`, compact vertical padding designed for keyboard and mouse input will be used.
*/
dense: _propTypes.default.bool,
/**
* If `true`, the list item will be disabled.
*/
disabled: _propTypes.default.bool,
/**
* If `true`, the left and right padding is removed.
*/
disableGutters: _propTypes.default.bool,
/**
* If `true`, a 1px light border is added to the bottom of the list item.
*/
divider: _propTypes.default.bool,
/**
* @ignore
*/
focusVisibleClassName: _propTypes.default.string,
/**
* Use to apply selected styling.
*/
selected: _propTypes.default.bool
} : void 0;
var _default = (0, _withStyles.default)(styles, {
name: 'MuiListItem'
})(ListItem);
exports.default = _default;