UNPKG

11.6 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
4
5var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
6
7Object.defineProperty(exports, "__esModule", {
8 value: true
9});
10exports.default = exports.styles = void 0;
11
12var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
13
14var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
15
16var React = _interopRequireWildcard(require("react"));
17
18var _propTypes = _interopRequireDefault(require("prop-types"));
19
20var _clsx = _interopRequireDefault(require("clsx"));
21
22var _utils = require("@material-ui/utils");
23
24var _withStyles = _interopRequireDefault(require("../styles/withStyles"));
25
26var _ButtonBase = _interopRequireDefault(require("../ButtonBase"));
27
28var _isMuiElement = _interopRequireDefault(require("../utils/isMuiElement"));
29
30var _useForkRef = _interopRequireDefault(require("../utils/useForkRef"));
31
32var _ListContext = _interopRequireDefault(require("../List/ListContext"));
33
34var ReactDOM = _interopRequireWildcard(require("react-dom"));
35
36var styles = function styles(theme) {
37 return {
38 /* Styles applied to the (normally root) `component` element. May be wrapped by a `container`. */
39 root: {
40 display: 'flex',
41 justifyContent: 'flex-start',
42 alignItems: 'center',
43 position: 'relative',
44 textDecoration: 'none',
45 width: '100%',
46 boxSizing: 'border-box',
47 textAlign: 'left',
48 paddingTop: 8,
49 paddingBottom: 8,
50 '&$focusVisible': {
51 backgroundColor: theme.palette.action.selected
52 },
53 '&$selected, &$selected:hover': {
54 backgroundColor: theme.palette.action.selected
55 },
56 '&$disabled': {
57 opacity: 0.5
58 }
59 },
60
61 /* Styles applied to the `container` element if `children` includes `ListItemSecondaryAction`. */
62 container: {
63 position: 'relative'
64 },
65
66 /* Pseudo-class applied to the `component`'s `focusVisibleClassName` prop if `button={true}`. */
67 focusVisible: {},
68
69 /* Styles applied to the `component` element if dense. */
70 dense: {
71 paddingTop: 4,
72 paddingBottom: 4
73 },
74
75 /* Styles applied to the `component` element if `alignItems="flex-start"`. */
76 alignItemsFlexStart: {
77 alignItems: 'flex-start'
78 },
79
80 /* Pseudo-class applied to the inner `component` element if `disabled={true}`. */
81 disabled: {},
82
83 /* Styles applied to the inner `component` element if `divider={true}`. */
84 divider: {
85 borderBottom: "1px solid ".concat(theme.palette.divider),
86 backgroundClip: 'padding-box'
87 },
88
89 /* Styles applied to the inner `component` element if `disableGutters={false}`. */
90 gutters: {
91 paddingLeft: 16,
92 paddingRight: 16
93 },
94
95 /* Styles applied to the inner `component` element if `button={true}`. */
96 button: {
97 transition: theme.transitions.create('background-color', {
98 duration: theme.transitions.duration.shortest
99 }),
100 '&:hover': {
101 textDecoration: 'none',
102 backgroundColor: theme.palette.action.hover,
103 // Reset on touch devices, it doesn't add specificity
104 '@media (hover: none)': {
105 backgroundColor: 'transparent'
106 }
107 }
108 },
109
110 /* Styles applied to the `component` element if `children` includes `ListItemSecondaryAction`. */
111 secondaryAction: {
112 // Add some space to avoid collision as `ListItemSecondaryAction`
113 // is absolutely positioned.
114 paddingRight: 48
115 },
116
117 /* Pseudo-class applied to the root element if `selected={true}`. */
118 selected: {}
119 };
120};
121
122exports.styles = styles;
123var useEnhancedEffect = typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect;
124/**
125 * Uses an additional container component if `ListItemSecondaryAction` is the last child.
126 */
127
128var ListItem = /*#__PURE__*/React.forwardRef(function ListItem(props, ref) {
129 var _props$alignItems = props.alignItems,
130 alignItems = _props$alignItems === void 0 ? 'center' : _props$alignItems,
131 _props$autoFocus = props.autoFocus,
132 autoFocus = _props$autoFocus === void 0 ? false : _props$autoFocus,
133 _props$button = props.button,
134 button = _props$button === void 0 ? false : _props$button,
135 childrenProp = props.children,
136 classes = props.classes,
137 className = props.className,
138 componentProp = props.component,
139 _props$ContainerCompo = props.ContainerComponent,
140 ContainerComponent = _props$ContainerCompo === void 0 ? 'li' : _props$ContainerCompo,
141 _props$ContainerProps = props.ContainerProps;
142 _props$ContainerProps = _props$ContainerProps === void 0 ? {} : _props$ContainerProps;
143 var ContainerClassName = _props$ContainerProps.className,
144 ContainerProps = (0, _objectWithoutProperties2.default)(_props$ContainerProps, ["className"]),
145 _props$dense = props.dense,
146 dense = _props$dense === void 0 ? false : _props$dense,
147 _props$disabled = props.disabled,
148 disabled = _props$disabled === void 0 ? false : _props$disabled,
149 _props$disableGutters = props.disableGutters,
150 disableGutters = _props$disableGutters === void 0 ? false : _props$disableGutters,
151 _props$divider = props.divider,
152 divider = _props$divider === void 0 ? false : _props$divider,
153 focusVisibleClassName = props.focusVisibleClassName,
154 _props$selected = props.selected,
155 selected = _props$selected === void 0 ? false : _props$selected,
156 other = (0, _objectWithoutProperties2.default)(props, ["alignItems", "autoFocus", "button", "children", "classes", "className", "component", "ContainerComponent", "ContainerProps", "dense", "disabled", "disableGutters", "divider", "focusVisibleClassName", "selected"]);
157 var context = React.useContext(_ListContext.default);
158 var childContext = {
159 dense: dense || context.dense || false,
160 alignItems: alignItems
161 };
162 var listItemRef = React.useRef(null);
163 useEnhancedEffect(function () {
164 if (autoFocus) {
165 if (listItemRef.current) {
166 listItemRef.current.focus();
167 } else if (process.env.NODE_ENV !== 'production') {
168 console.error('Material-UI: Unable to set focus to a ListItem whose component has not been rendered.');
169 }
170 }
171 }, [autoFocus]);
172 var children = React.Children.toArray(childrenProp);
173 var hasSecondaryAction = children.length && (0, _isMuiElement.default)(children[children.length - 1], ['ListItemSecondaryAction']);
174 var handleOwnRef = React.useCallback(function (instance) {
175 // #StrictMode ready
176 listItemRef.current = ReactDOM.findDOMNode(instance);
177 }, []);
178 var handleRef = (0, _useForkRef.default)(handleOwnRef, ref);
179 var componentProps = (0, _extends2.default)({
180 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),
181 disabled: disabled
182 }, other);
183 var Component = componentProp || 'li';
184
185 if (button) {
186 componentProps.component = componentProp || 'div';
187 componentProps.focusVisibleClassName = (0, _clsx.default)(classes.focusVisible, focusVisibleClassName);
188 Component = _ButtonBase.default;
189 }
190
191 if (hasSecondaryAction) {
192 // Use div by default.
193 Component = !componentProps.component && !componentProp ? 'div' : Component; // Avoid nesting of li > li.
194
195 if (ContainerComponent === 'li') {
196 if (Component === 'li') {
197 Component = 'div';
198 } else if (componentProps.component === 'li') {
199 componentProps.component = 'div';
200 }
201 }
202
203 return /*#__PURE__*/React.createElement(_ListContext.default.Provider, {
204 value: childContext
205 }, /*#__PURE__*/React.createElement(ContainerComponent, (0, _extends2.default)({
206 className: (0, _clsx.default)(classes.container, ContainerClassName),
207 ref: handleRef
208 }, ContainerProps), /*#__PURE__*/React.createElement(Component, componentProps, children), children.pop()));
209 }
210
211 return /*#__PURE__*/React.createElement(_ListContext.default.Provider, {
212 value: childContext
213 }, /*#__PURE__*/React.createElement(Component, (0, _extends2.default)({
214 ref: handleRef
215 }, componentProps), children));
216});
217process.env.NODE_ENV !== "production" ? ListItem.propTypes = {
218 /**
219 * Defines the `align-items` style property.
220 */
221 alignItems: _propTypes.default.oneOf(['flex-start', 'center']),
222
223 /**
224 * If `true`, the list item will be focused during the first mount.
225 * Focus will also be triggered if the value changes from false to true.
226 */
227 autoFocus: _propTypes.default.bool,
228
229 /**
230 * If `true`, the list item will be a button (using `ButtonBase`). Props intended
231 * for `ButtonBase` can then be applied to `ListItem`.
232 */
233 button: _propTypes.default.bool,
234
235 /**
236 * The content of the component. If a `ListItemSecondaryAction` is used it must
237 * be the last child.
238 */
239 children: (0, _utils.chainPropTypes)(_propTypes.default.node, function (props) {
240 var children = React.Children.toArray(props.children); // React.Children.toArray(props.children).findLastIndex(isListItemSecondaryAction)
241
242 var secondaryActionIndex = -1;
243
244 for (var i = children.length - 1; i >= 0; i -= 1) {
245 var child = children[i];
246
247 if ((0, _isMuiElement.default)(child, ['ListItemSecondaryAction'])) {
248 secondaryActionIndex = i;
249 break;
250 }
251 } // is ListItemSecondaryAction the last child of ListItem
252
253
254 if (secondaryActionIndex !== -1 && secondaryActionIndex !== children.length - 1) {
255 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.');
256 }
257
258 return null;
259 }),
260
261 /**
262 * Override or extend the styles applied to the component.
263 * See [CSS API](#css) below for more details.
264 */
265 classes: _propTypes.default.object.isRequired,
266
267 /**
268 * @ignore
269 */
270 className: _propTypes.default.string,
271
272 /**
273 * The component used for the root node.
274 * Either a string to use a HTML element or a component.
275 * By default, it's a `li` when `button` is `false` and a `div` when `button` is `true`.
276 */
277 component: _propTypes.default
278 /* @typescript-to-proptypes-ignore */
279 .elementType,
280
281 /**
282 * The container component used when a `ListItemSecondaryAction` is the last child.
283 */
284 ContainerComponent: _propTypes.default.elementType,
285
286 /**
287 * Props applied to the container component if used.
288 */
289 ContainerProps: _propTypes.default.object,
290
291 /**
292 * If `true`, compact vertical padding designed for keyboard and mouse input will be used.
293 */
294 dense: _propTypes.default.bool,
295
296 /**
297 * If `true`, the list item will be disabled.
298 */
299 disabled: _propTypes.default.bool,
300
301 /**
302 * If `true`, the left and right padding is removed.
303 */
304 disableGutters: _propTypes.default.bool,
305
306 /**
307 * If `true`, a 1px light border is added to the bottom of the list item.
308 */
309 divider: _propTypes.default.bool,
310
311 /**
312 * @ignore
313 */
314 focusVisibleClassName: _propTypes.default.string,
315
316 /**
317 * Use to apply selected styling.
318 */
319 selected: _propTypes.default.bool
320} : void 0;
321
322var _default = (0, _withStyles.default)(styles, {
323 name: 'MuiListItem'
324})(ListItem);
325
326exports.default = _default;
\No newline at end of file