UNPKG

9.54 kBJavaScriptView Raw
1'use client';
2
3import * as React from 'react';
4import PropTypes from 'prop-types';
5import clsx from 'clsx';
6import composeClasses from '@mui/utils/composeClasses';
7import { alpha } from '@mui/system/colorManipulator';
8import { styled } from "../zero-styled/index.js";
9import memoTheme from "../utils/memoTheme.js";
10import { useDefaultProps } from "../DefaultPropsProvider/index.js";
11import rootShouldForwardProp from "../styles/rootShouldForwardProp.js";
12import ButtonBase from "../ButtonBase/index.js";
13import useEnhancedEffect from "../utils/useEnhancedEffect.js";
14import useForkRef from "../utils/useForkRef.js";
15import ListContext from "../List/ListContext.js";
16import listItemButtonClasses, { getListItemButtonUtilityClass } from "./listItemButtonClasses.js";
17import { jsx as _jsx } from "react/jsx-runtime";
18export const overridesResolver = (props, styles) => {
19 const {
20 ownerState
21 } = props;
22 return [styles.root, ownerState.dense && styles.dense, ownerState.alignItems === 'flex-start' && styles.alignItemsFlexStart, ownerState.divider && styles.divider, !ownerState.disableGutters && styles.gutters];
23};
24const useUtilityClasses = ownerState => {
25 const {
26 alignItems,
27 classes,
28 dense,
29 disabled,
30 disableGutters,
31 divider,
32 selected
33 } = ownerState;
34 const slots = {
35 root: ['root', dense && 'dense', !disableGutters && 'gutters', divider && 'divider', disabled && 'disabled', alignItems === 'flex-start' && 'alignItemsFlexStart', selected && 'selected']
36 };
37 const composedClasses = composeClasses(slots, getListItemButtonUtilityClass, classes);
38 return {
39 ...classes,
40 ...composedClasses
41 };
42};
43const ListItemButtonRoot = styled(ButtonBase, {
44 shouldForwardProp: prop => rootShouldForwardProp(prop) || prop === 'classes',
45 name: 'MuiListItemButton',
46 slot: 'Root',
47 overridesResolver
48})(memoTheme(({
49 theme
50}) => ({
51 display: 'flex',
52 flexGrow: 1,
53 justifyContent: 'flex-start',
54 alignItems: 'center',
55 position: 'relative',
56 textDecoration: 'none',
57 minWidth: 0,
58 boxSizing: 'border-box',
59 textAlign: 'left',
60 paddingTop: 8,
61 paddingBottom: 8,
62 transition: theme.transitions.create('background-color', {
63 duration: theme.transitions.duration.shortest
64 }),
65 '&:hover': {
66 textDecoration: 'none',
67 backgroundColor: (theme.vars || theme).palette.action.hover,
68 // Reset on touch devices, it doesn't add specificity
69 '@media (hover: none)': {
70 backgroundColor: 'transparent'
71 }
72 },
73 [`&.${listItemButtonClasses.selected}`]: {
74 backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.selectedOpacity})` : alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
75 [`&.${listItemButtonClasses.focusVisible}`]: {
76 backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / calc(${theme.vars.palette.action.selectedOpacity} + ${theme.vars.palette.action.focusOpacity}))` : alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity + theme.palette.action.focusOpacity)
77 }
78 },
79 [`&.${listItemButtonClasses.selected}:hover`]: {
80 backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / calc(${theme.vars.palette.action.selectedOpacity} + ${theme.vars.palette.action.hoverOpacity}))` : alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity + theme.palette.action.hoverOpacity),
81 // Reset on touch devices, it doesn't add specificity
82 '@media (hover: none)': {
83 backgroundColor: theme.vars ? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.selectedOpacity})` : alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity)
84 }
85 },
86 [`&.${listItemButtonClasses.focusVisible}`]: {
87 backgroundColor: (theme.vars || theme).palette.action.focus
88 },
89 [`&.${listItemButtonClasses.disabled}`]: {
90 opacity: (theme.vars || theme).palette.action.disabledOpacity
91 },
92 variants: [{
93 props: ({
94 ownerState
95 }) => ownerState.divider,
96 style: {
97 borderBottom: `1px solid ${(theme.vars || theme).palette.divider}`,
98 backgroundClip: 'padding-box'
99 }
100 }, {
101 props: {
102 alignItems: 'flex-start'
103 },
104 style: {
105 alignItems: 'flex-start'
106 }
107 }, {
108 props: ({
109 ownerState
110 }) => !ownerState.disableGutters,
111 style: {
112 paddingLeft: 16,
113 paddingRight: 16
114 }
115 }, {
116 props: ({
117 ownerState
118 }) => ownerState.dense,
119 style: {
120 paddingTop: 4,
121 paddingBottom: 4
122 }
123 }]
124})));
125const ListItemButton = /*#__PURE__*/React.forwardRef(function ListItemButton(inProps, ref) {
126 const props = useDefaultProps({
127 props: inProps,
128 name: 'MuiListItemButton'
129 });
130 const {
131 alignItems = 'center',
132 autoFocus = false,
133 component = 'div',
134 children,
135 dense = false,
136 disableGutters = false,
137 divider = false,
138 focusVisibleClassName,
139 selected = false,
140 className,
141 ...other
142 } = props;
143 const context = React.useContext(ListContext);
144 const childContext = React.useMemo(() => ({
145 dense: dense || context.dense || false,
146 alignItems,
147 disableGutters
148 }), [alignItems, context.dense, dense, disableGutters]);
149 const listItemRef = React.useRef(null);
150 useEnhancedEffect(() => {
151 if (autoFocus) {
152 if (listItemRef.current) {
153 listItemRef.current.focus();
154 } else if (process.env.NODE_ENV !== 'production') {
155 console.error('MUI: Unable to set focus to a ListItemButton whose component has not been rendered.');
156 }
157 }
158 }, [autoFocus]);
159 const ownerState = {
160 ...props,
161 alignItems,
162 dense: childContext.dense,
163 disableGutters,
164 divider,
165 selected
166 };
167 const classes = useUtilityClasses(ownerState);
168 const handleRef = useForkRef(listItemRef, ref);
169 return /*#__PURE__*/_jsx(ListContext.Provider, {
170 value: childContext,
171 children: /*#__PURE__*/_jsx(ListItemButtonRoot, {
172 ref: handleRef,
173 href: other.href || other.to
174 // `ButtonBase` processes `href` or `to` if `component` is set to 'button'
175 ,
176 component: (other.href || other.to) && component === 'div' ? 'button' : component,
177 focusVisibleClassName: clsx(classes.focusVisible, focusVisibleClassName),
178 ownerState: ownerState,
179 className: clsx(classes.root, className),
180 ...other,
181 classes: classes,
182 children: children
183 })
184 });
185});
186process.env.NODE_ENV !== "production" ? ListItemButton.propTypes /* remove-proptypes */ = {
187 // ┌────────────────────────────── Warning ──────────────────────────────┐
188 // │ These PropTypes are generated from the TypeScript type definitions. │
189 // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
190 // └─────────────────────────────────────────────────────────────────────┘
191 /**
192 * Defines the `align-items` style property.
193 * @default 'center'
194 */
195 alignItems: PropTypes.oneOf(['center', 'flex-start']),
196 /**
197 * If `true`, the list item is focused during the first mount.
198 * Focus will also be triggered if the value changes from false to true.
199 * @default false
200 */
201 autoFocus: PropTypes.bool,
202 /**
203 * The content of the component if a `ListItemSecondaryAction` is used it must
204 * be the last child.
205 */
206 children: PropTypes.node,
207 /**
208 * Override or extend the styles applied to the component.
209 */
210 classes: PropTypes.object,
211 /**
212 * @ignore
213 */
214 className: PropTypes.string,
215 /**
216 * The component used for the root node.
217 * Either a string to use a HTML element or a component.
218 */
219 component: PropTypes.elementType,
220 /**
221 * If `true`, compact vertical padding designed for keyboard and mouse input is used.
222 * The prop defaults to the value inherited from the parent List component.
223 * @default false
224 */
225 dense: PropTypes.bool,
226 /**
227 * If `true`, the component is disabled.
228 * @default false
229 */
230 disabled: PropTypes.bool,
231 /**
232 * If `true`, the left and right padding is removed.
233 * @default false
234 */
235 disableGutters: PropTypes.bool,
236 /**
237 * If `true`, a 1px light border is added to the bottom of the list item.
238 * @default false
239 */
240 divider: PropTypes.bool,
241 /**
242 * This prop can help identify which element has keyboard focus.
243 * The class name will be applied when the element gains the focus through keyboard interaction.
244 * It's a polyfill for the [CSS :focus-visible selector](https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo).
245 * The rationale for using this feature [is explained here](https://github.com/WICG/focus-visible/blob/HEAD/explainer.md).
246 * A [polyfill can be used](https://github.com/WICG/focus-visible) to apply a `focus-visible` class to other components
247 * if needed.
248 */
249 focusVisibleClassName: PropTypes.string,
250 /**
251 * @ignore
252 */
253 href: PropTypes.string,
254 /**
255 * Use to apply selected styling.
256 * @default false
257 */
258 selected: PropTypes.bool,
259 /**
260 * The system prop that allows defining system overrides as well as additional CSS styles.
261 */
262 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
263} : void 0;
264export default ListItemButton;
\No newline at end of file