UNPKG

9.29 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 ButtonBase from "../ButtonBase/index.js";
8import capitalize from "../utils/capitalize.js";
9import { styled } from "../zero-styled/index.js";
10import memoTheme from "../utils/memoTheme.js";
11import { useDefaultProps } from "../DefaultPropsProvider/index.js";
12import unsupportedProp from "../utils/unsupportedProp.js";
13import tabClasses, { getTabUtilityClass } from "./tabClasses.js";
14import { jsxs as _jsxs } from "react/jsx-runtime";
15const useUtilityClasses = ownerState => {
16 const {
17 classes,
18 textColor,
19 fullWidth,
20 wrapped,
21 icon,
22 label,
23 selected,
24 disabled
25 } = ownerState;
26 const slots = {
27 root: ['root', icon && label && 'labelIcon', `textColor${capitalize(textColor)}`, fullWidth && 'fullWidth', wrapped && 'wrapped', selected && 'selected', disabled && 'disabled'],
28 icon: ['iconWrapper', 'icon']
29 };
30 return composeClasses(slots, getTabUtilityClass, classes);
31};
32const TabRoot = styled(ButtonBase, {
33 name: 'MuiTab',
34 slot: 'Root',
35 overridesResolver: (props, styles) => {
36 const {
37 ownerState
38 } = props;
39 return [styles.root, ownerState.label && ownerState.icon && styles.labelIcon, styles[`textColor${capitalize(ownerState.textColor)}`], ownerState.fullWidth && styles.fullWidth, ownerState.wrapped && styles.wrapped, {
40 [`& .${tabClasses.iconWrapper}`]: styles.iconWrapper
41 }, {
42 [`& .${tabClasses.icon}`]: styles.icon
43 }];
44 }
45})(memoTheme(({
46 theme
47}) => ({
48 ...theme.typography.button,
49 maxWidth: 360,
50 minWidth: 90,
51 position: 'relative',
52 minHeight: 48,
53 flexShrink: 0,
54 padding: '12px 16px',
55 overflow: 'hidden',
56 whiteSpace: 'normal',
57 textAlign: 'center',
58 lineHeight: 1.25,
59 variants: [{
60 props: ({
61 ownerState
62 }) => ownerState.label && (ownerState.iconPosition === 'top' || ownerState.iconPosition === 'bottom'),
63 style: {
64 flexDirection: 'column'
65 }
66 }, {
67 props: ({
68 ownerState
69 }) => ownerState.label && ownerState.iconPosition !== 'top' && ownerState.iconPosition !== 'bottom',
70 style: {
71 flexDirection: 'row'
72 }
73 }, {
74 props: ({
75 ownerState
76 }) => ownerState.icon && ownerState.label,
77 style: {
78 minHeight: 72,
79 paddingTop: 9,
80 paddingBottom: 9
81 }
82 }, {
83 props: ({
84 ownerState,
85 iconPosition
86 }) => ownerState.icon && ownerState.label && iconPosition === 'top',
87 style: {
88 [`& > .${tabClasses.icon}`]: {
89 marginBottom: 6
90 }
91 }
92 }, {
93 props: ({
94 ownerState,
95 iconPosition
96 }) => ownerState.icon && ownerState.label && iconPosition === 'bottom',
97 style: {
98 [`& > .${tabClasses.icon}`]: {
99 marginTop: 6
100 }
101 }
102 }, {
103 props: ({
104 ownerState,
105 iconPosition
106 }) => ownerState.icon && ownerState.label && iconPosition === 'start',
107 style: {
108 [`& > .${tabClasses.icon}`]: {
109 marginRight: theme.spacing(1)
110 }
111 }
112 }, {
113 props: ({
114 ownerState,
115 iconPosition
116 }) => ownerState.icon && ownerState.label && iconPosition === 'end',
117 style: {
118 [`& > .${tabClasses.icon}`]: {
119 marginLeft: theme.spacing(1)
120 }
121 }
122 }, {
123 props: {
124 textColor: 'inherit'
125 },
126 style: {
127 color: 'inherit',
128 opacity: 0.6,
129 // same opacity as theme.palette.text.secondary
130 [`&.${tabClasses.selected}`]: {
131 opacity: 1
132 },
133 [`&.${tabClasses.disabled}`]: {
134 opacity: (theme.vars || theme).palette.action.disabledOpacity
135 }
136 }
137 }, {
138 props: {
139 textColor: 'primary'
140 },
141 style: {
142 color: (theme.vars || theme).palette.text.secondary,
143 [`&.${tabClasses.selected}`]: {
144 color: (theme.vars || theme).palette.primary.main
145 },
146 [`&.${tabClasses.disabled}`]: {
147 color: (theme.vars || theme).palette.text.disabled
148 }
149 }
150 }, {
151 props: {
152 textColor: 'secondary'
153 },
154 style: {
155 color: (theme.vars || theme).palette.text.secondary,
156 [`&.${tabClasses.selected}`]: {
157 color: (theme.vars || theme).palette.secondary.main
158 },
159 [`&.${tabClasses.disabled}`]: {
160 color: (theme.vars || theme).palette.text.disabled
161 }
162 }
163 }, {
164 props: ({
165 ownerState
166 }) => ownerState.fullWidth,
167 style: {
168 flexShrink: 1,
169 flexGrow: 1,
170 flexBasis: 0,
171 maxWidth: 'none'
172 }
173 }, {
174 props: ({
175 ownerState
176 }) => ownerState.wrapped,
177 style: {
178 fontSize: theme.typography.pxToRem(12)
179 }
180 }]
181})));
182const Tab = /*#__PURE__*/React.forwardRef(function Tab(inProps, ref) {
183 const props = useDefaultProps({
184 props: inProps,
185 name: 'MuiTab'
186 });
187 const {
188 className,
189 disabled = false,
190 disableFocusRipple = false,
191 // eslint-disable-next-line react/prop-types
192 fullWidth,
193 icon: iconProp,
194 iconPosition = 'top',
195 // eslint-disable-next-line react/prop-types
196 indicator,
197 label,
198 onChange,
199 onClick,
200 onFocus,
201 // eslint-disable-next-line react/prop-types
202 selected,
203 // eslint-disable-next-line react/prop-types
204 selectionFollowsFocus,
205 // eslint-disable-next-line react/prop-types
206 textColor = 'inherit',
207 value,
208 wrapped = false,
209 ...other
210 } = props;
211 const ownerState = {
212 ...props,
213 disabled,
214 disableFocusRipple,
215 selected,
216 icon: !!iconProp,
217 iconPosition,
218 label: !!label,
219 fullWidth,
220 textColor,
221 wrapped
222 };
223 const classes = useUtilityClasses(ownerState);
224 const icon = iconProp && label && /*#__PURE__*/React.isValidElement(iconProp) ? /*#__PURE__*/React.cloneElement(iconProp, {
225 className: clsx(classes.icon, iconProp.props.className)
226 }) : iconProp;
227 const handleClick = event => {
228 if (!selected && onChange) {
229 onChange(event, value);
230 }
231 if (onClick) {
232 onClick(event);
233 }
234 };
235 const handleFocus = event => {
236 if (selectionFollowsFocus && !selected && onChange) {
237 onChange(event, value);
238 }
239 if (onFocus) {
240 onFocus(event);
241 }
242 };
243 return /*#__PURE__*/_jsxs(TabRoot, {
244 focusRipple: !disableFocusRipple,
245 className: clsx(classes.root, className),
246 ref: ref,
247 role: "tab",
248 "aria-selected": selected,
249 disabled: disabled,
250 onClick: handleClick,
251 onFocus: handleFocus,
252 ownerState: ownerState,
253 tabIndex: selected ? 0 : -1,
254 ...other,
255 children: [iconPosition === 'top' || iconPosition === 'start' ? /*#__PURE__*/_jsxs(React.Fragment, {
256 children: [icon, label]
257 }) : /*#__PURE__*/_jsxs(React.Fragment, {
258 children: [label, icon]
259 }), indicator]
260 });
261});
262process.env.NODE_ENV !== "production" ? Tab.propTypes /* remove-proptypes */ = {
263 // ┌────────────────────────────── Warning ──────────────────────────────┐
264 // │ These PropTypes are generated from the TypeScript type definitions. │
265 // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
266 // └─────────────────────────────────────────────────────────────────────┘
267 /**
268 * This prop isn't supported.
269 * Use the `component` prop if you need to change the children structure.
270 */
271 children: unsupportedProp,
272 /**
273 * Override or extend the styles applied to the component.
274 */
275 classes: PropTypes.object,
276 /**
277 * @ignore
278 */
279 className: PropTypes.string,
280 /**
281 * If `true`, the component is disabled.
282 * @default false
283 */
284 disabled: PropTypes.bool,
285 /**
286 * If `true`, the keyboard focus ripple is disabled.
287 * @default false
288 */
289 disableFocusRipple: PropTypes.bool,
290 /**
291 * If `true`, the ripple effect is disabled.
292 *
293 * ⚠️ Without a ripple there is no styling for :focus-visible by default. Be sure
294 * to highlight the element by applying separate styles with the `.Mui-focusVisible` class.
295 * @default false
296 */
297 disableRipple: PropTypes.bool,
298 /**
299 * The icon to display.
300 */
301 icon: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
302 /**
303 * The position of the icon relative to the label.
304 * @default 'top'
305 */
306 iconPosition: PropTypes.oneOf(['bottom', 'end', 'start', 'top']),
307 /**
308 * The label element.
309 */
310 label: PropTypes.node,
311 /**
312 * @ignore
313 */
314 onChange: PropTypes.func,
315 /**
316 * @ignore
317 */
318 onClick: PropTypes.func,
319 /**
320 * @ignore
321 */
322 onFocus: PropTypes.func,
323 /**
324 * The system prop that allows defining system overrides as well as additional CSS styles.
325 */
326 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
327 /**
328 * You can provide your own value. Otherwise, we fallback to the child position index.
329 */
330 value: PropTypes.any,
331 /**
332 * Tab labels appear in a single row.
333 * They can use a second line if needed.
334 * @default false
335 */
336 wrapped: PropTypes.bool
337} : void 0;
338export default Tab;
\No newline at end of file