UNPKG

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