1 | "use strict";
|
2 | 'use client';
|
3 |
|
4 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
5 | var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
6 | Object.defineProperty(exports, "__esModule", {
|
7 | value: true
|
8 | });
|
9 | exports.default = void 0;
|
10 | var React = _interopRequireWildcard(require("react"));
|
11 | var _reactIs = require("react-is");
|
12 | var _propTypes = _interopRequireDefault(require("prop-types"));
|
13 | var _clsx = _interopRequireDefault(require("clsx"));
|
14 | var _refType = _interopRequireDefault(require("@mui/utils/refType"));
|
15 | var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"));
|
16 | var _RtlProvider = require("@mui/system/RtlProvider");
|
17 | var _useSlotProps = _interopRequireDefault(require("@mui/utils/useSlotProps"));
|
18 | var _zeroStyled = require("../zero-styled");
|
19 | var _memoTheme = _interopRequireDefault(require("../utils/memoTheme"));
|
20 | var _DefaultPropsProvider = require("../DefaultPropsProvider");
|
21 | var _debounce = _interopRequireDefault(require("../utils/debounce"));
|
22 | var _animate = _interopRequireDefault(require("../internal/animate"));
|
23 | var _ScrollbarSize = _interopRequireDefault(require("./ScrollbarSize"));
|
24 | var _TabScrollButton = _interopRequireDefault(require("../TabScrollButton"));
|
25 | var _useEventCallback = _interopRequireDefault(require("../utils/useEventCallback"));
|
26 | var _tabsClasses = _interopRequireWildcard(require("./tabsClasses"));
|
27 | var _ownerDocument = _interopRequireDefault(require("../utils/ownerDocument"));
|
28 | var _ownerWindow = _interopRequireDefault(require("../utils/ownerWindow"));
|
29 | var _jsxRuntime = require("react/jsx-runtime");
|
30 | const nextItem = (list, item) => {
|
31 | if (list === item) {
|
32 | return list.firstChild;
|
33 | }
|
34 | if (item && item.nextElementSibling) {
|
35 | return item.nextElementSibling;
|
36 | }
|
37 | return list.firstChild;
|
38 | };
|
39 | const previousItem = (list, item) => {
|
40 | if (list === item) {
|
41 | return list.lastChild;
|
42 | }
|
43 | if (item && item.previousElementSibling) {
|
44 | return item.previousElementSibling;
|
45 | }
|
46 | return list.lastChild;
|
47 | };
|
48 | const moveFocus = (list, currentFocus, traversalFunction) => {
|
49 | let wrappedOnce = false;
|
50 | let nextFocus = traversalFunction(list, currentFocus);
|
51 | while (nextFocus) {
|
52 |
|
53 | if (nextFocus === list.firstChild) {
|
54 | if (wrappedOnce) {
|
55 | return;
|
56 | }
|
57 | wrappedOnce = true;
|
58 | }
|
59 |
|
60 |
|
61 | const nextFocusDisabled = nextFocus.disabled || nextFocus.getAttribute('aria-disabled') === 'true';
|
62 | if (!nextFocus.hasAttribute('tabindex') || nextFocusDisabled) {
|
63 |
|
64 | nextFocus = traversalFunction(list, nextFocus);
|
65 | } else {
|
66 | nextFocus.focus();
|
67 | return;
|
68 | }
|
69 | }
|
70 | };
|
71 | const useUtilityClasses = ownerState => {
|
72 | const {
|
73 | vertical,
|
74 | fixed,
|
75 | hideScrollbar,
|
76 | scrollableX,
|
77 | scrollableY,
|
78 | centered,
|
79 | scrollButtonsHideMobile,
|
80 | classes
|
81 | } = ownerState;
|
82 | const slots = {
|
83 | root: ['root', vertical && 'vertical'],
|
84 | scroller: ['scroller', fixed && 'fixed', hideScrollbar && 'hideScrollbar', scrollableX && 'scrollableX', scrollableY && 'scrollableY'],
|
85 | flexContainer: ['flexContainer', vertical && 'flexContainerVertical', centered && 'centered'],
|
86 | indicator: ['indicator'],
|
87 | scrollButtons: ['scrollButtons', scrollButtonsHideMobile && 'scrollButtonsHideMobile'],
|
88 | scrollableX: [scrollableX && 'scrollableX'],
|
89 | hideScrollbar: [hideScrollbar && 'hideScrollbar']
|
90 | };
|
91 | return (0, _composeClasses.default)(slots, _tabsClasses.getTabsUtilityClass, classes);
|
92 | };
|
93 | const TabsRoot = (0, _zeroStyled.styled)('div', {
|
94 | name: 'MuiTabs',
|
95 | slot: 'Root',
|
96 | overridesResolver: (props, styles) => {
|
97 | const {
|
98 | ownerState
|
99 | } = props;
|
100 | return [{
|
101 | [`& .${_tabsClasses.default.scrollButtons}`]: styles.scrollButtons
|
102 | }, {
|
103 | [`& .${_tabsClasses.default.scrollButtons}`]: ownerState.scrollButtonsHideMobile && styles.scrollButtonsHideMobile
|
104 | }, styles.root, ownerState.vertical && styles.vertical];
|
105 | }
|
106 | })((0, _memoTheme.default)(({
|
107 | theme
|
108 | }) => ({
|
109 | overflow: 'hidden',
|
110 | minHeight: 48,
|
111 |
|
112 | WebkitOverflowScrolling: 'touch',
|
113 | display: 'flex',
|
114 | variants: [{
|
115 | props: ({
|
116 | ownerState
|
117 | }) => ownerState.vertical,
|
118 | style: {
|
119 | flexDirection: 'column'
|
120 | }
|
121 | }, {
|
122 | props: ({
|
123 | ownerState
|
124 | }) => ownerState.scrollButtonsHideMobile,
|
125 | style: {
|
126 | [`& .${_tabsClasses.default.scrollButtons}`]: {
|
127 | [theme.breakpoints.down('sm')]: {
|
128 | display: 'none'
|
129 | }
|
130 | }
|
131 | }
|
132 | }]
|
133 | })));
|
134 | const TabsScroller = (0, _zeroStyled.styled)('div', {
|
135 | name: 'MuiTabs',
|
136 | slot: 'Scroller',
|
137 | overridesResolver: (props, styles) => {
|
138 | const {
|
139 | ownerState
|
140 | } = props;
|
141 | return [styles.scroller, ownerState.fixed && styles.fixed, ownerState.hideScrollbar && styles.hideScrollbar, ownerState.scrollableX && styles.scrollableX, ownerState.scrollableY && styles.scrollableY];
|
142 | }
|
143 | })({
|
144 | position: 'relative',
|
145 | display: 'inline-block',
|
146 | flex: '1 1 auto',
|
147 | whiteSpace: 'nowrap',
|
148 | variants: [{
|
149 | props: ({
|
150 | ownerState
|
151 | }) => ownerState.fixed,
|
152 | style: {
|
153 | overflowX: 'hidden',
|
154 | width: '100%'
|
155 | }
|
156 | }, {
|
157 | props: ({
|
158 | ownerState
|
159 | }) => ownerState.hideScrollbar,
|
160 | style: {
|
161 |
|
162 | scrollbarWidth: 'none',
|
163 |
|
164 | '&::-webkit-scrollbar': {
|
165 | display: 'none'
|
166 | }
|
167 | }
|
168 | }, {
|
169 | props: ({
|
170 | ownerState
|
171 | }) => ownerState.scrollableX,
|
172 | style: {
|
173 | overflowX: 'auto',
|
174 | overflowY: 'hidden'
|
175 | }
|
176 | }, {
|
177 | props: ({
|
178 | ownerState
|
179 | }) => ownerState.scrollableY,
|
180 | style: {
|
181 | overflowY: 'auto',
|
182 | overflowX: 'hidden'
|
183 | }
|
184 | }]
|
185 | });
|
186 | const FlexContainer = (0, _zeroStyled.styled)('div', {
|
187 | name: 'MuiTabs',
|
188 | slot: 'FlexContainer',
|
189 | overridesResolver: (props, styles) => {
|
190 | const {
|
191 | ownerState
|
192 | } = props;
|
193 | return [styles.flexContainer, ownerState.vertical && styles.flexContainerVertical, ownerState.centered && styles.centered];
|
194 | }
|
195 | })({
|
196 | display: 'flex',
|
197 | variants: [{
|
198 | props: ({
|
199 | ownerState
|
200 | }) => ownerState.vertical,
|
201 | style: {
|
202 | flexDirection: 'column'
|
203 | }
|
204 | }, {
|
205 | props: ({
|
206 | ownerState
|
207 | }) => ownerState.centered,
|
208 | style: {
|
209 | justifyContent: 'center'
|
210 | }
|
211 | }]
|
212 | });
|
213 | const TabsIndicator = (0, _zeroStyled.styled)('span', {
|
214 | name: 'MuiTabs',
|
215 | slot: 'Indicator',
|
216 | overridesResolver: (props, styles) => styles.indicator
|
217 | })((0, _memoTheme.default)(({
|
218 | theme
|
219 | }) => ({
|
220 | position: 'absolute',
|
221 | height: 2,
|
222 | bottom: 0,
|
223 | width: '100%',
|
224 | transition: theme.transitions.create(),
|
225 | variants: [{
|
226 | props: {
|
227 | indicatorColor: 'primary'
|
228 | },
|
229 | style: {
|
230 | backgroundColor: (theme.vars || theme).palette.primary.main
|
231 | }
|
232 | }, {
|
233 | props: {
|
234 | indicatorColor: 'secondary'
|
235 | },
|
236 | style: {
|
237 | backgroundColor: (theme.vars || theme).palette.secondary.main
|
238 | }
|
239 | }, {
|
240 | props: ({
|
241 | ownerState
|
242 | }) => ownerState.vertical,
|
243 | style: {
|
244 | height: '100%',
|
245 | width: 2,
|
246 | right: 0
|
247 | }
|
248 | }]
|
249 | })));
|
250 | const TabsScrollbarSize = (0, _zeroStyled.styled)(_ScrollbarSize.default)({
|
251 | overflowX: 'auto',
|
252 | overflowY: 'hidden',
|
253 |
|
254 | scrollbarWidth: 'none',
|
255 |
|
256 | '&::-webkit-scrollbar': {
|
257 | display: 'none'
|
258 | }
|
259 | });
|
260 | const defaultIndicatorStyle = {};
|
261 | let warnedOnceTabPresent = false;
|
262 | const Tabs = React.forwardRef(function Tabs(inProps, ref) {
|
263 | const props = (0, _DefaultPropsProvider.useDefaultProps)({
|
264 | props: inProps,
|
265 | name: 'MuiTabs'
|
266 | });
|
267 | const theme = (0, _zeroStyled.useTheme)();
|
268 | const isRtl = (0, _RtlProvider.useRtl)();
|
269 | const {
|
270 | 'aria-label': ariaLabel,
|
271 | 'aria-labelledby': ariaLabelledBy,
|
272 | action,
|
273 | centered = false,
|
274 | children: childrenProp,
|
275 | className,
|
276 | component = 'div',
|
277 | allowScrollButtonsMobile = false,
|
278 | indicatorColor = 'primary',
|
279 | onChange,
|
280 | orientation = 'horizontal',
|
281 | ScrollButtonComponent = _TabScrollButton.default,
|
282 | scrollButtons = 'auto',
|
283 | selectionFollowsFocus,
|
284 | slots = {},
|
285 | slotProps = {},
|
286 | TabIndicatorProps = {},
|
287 | TabScrollButtonProps = {},
|
288 | textColor = 'primary',
|
289 | value,
|
290 | variant = 'standard',
|
291 | visibleScrollbar = false,
|
292 | ...other
|
293 | } = props;
|
294 | const scrollable = variant === 'scrollable';
|
295 | const vertical = orientation === 'vertical';
|
296 | const scrollStart = vertical ? 'scrollTop' : 'scrollLeft';
|
297 | const start = vertical ? 'top' : 'left';
|
298 | const end = vertical ? 'bottom' : 'right';
|
299 | const clientSize = vertical ? 'clientHeight' : 'clientWidth';
|
300 | const size = vertical ? 'height' : 'width';
|
301 | const ownerState = {
|
302 | ...props,
|
303 | component,
|
304 | allowScrollButtonsMobile,
|
305 | indicatorColor,
|
306 | orientation,
|
307 | vertical,
|
308 | scrollButtons,
|
309 | textColor,
|
310 | variant,
|
311 | visibleScrollbar,
|
312 | fixed: !scrollable,
|
313 | hideScrollbar: scrollable && !visibleScrollbar,
|
314 | scrollableX: scrollable && !vertical,
|
315 | scrollableY: scrollable && vertical,
|
316 | centered: centered && !scrollable,
|
317 | scrollButtonsHideMobile: !allowScrollButtonsMobile
|
318 | };
|
319 | const classes = useUtilityClasses(ownerState);
|
320 | const startScrollButtonIconProps = (0, _useSlotProps.default)({
|
321 | elementType: slots.StartScrollButtonIcon,
|
322 | externalSlotProps: slotProps.startScrollButtonIcon,
|
323 | ownerState
|
324 | });
|
325 | const endScrollButtonIconProps = (0, _useSlotProps.default)({
|
326 | elementType: slots.EndScrollButtonIcon,
|
327 | externalSlotProps: slotProps.endScrollButtonIcon,
|
328 | ownerState
|
329 | });
|
330 | if (process.env.NODE_ENV !== 'production') {
|
331 | if (centered && scrollable) {
|
332 | console.error('MUI: You can not use the `centered={true}` and `variant="scrollable"` properties ' + 'at the same time on a `Tabs` component.');
|
333 | }
|
334 | }
|
335 | const [mounted, setMounted] = React.useState(false);
|
336 | const [indicatorStyle, setIndicatorStyle] = React.useState(defaultIndicatorStyle);
|
337 | const [displayStartScroll, setDisplayStartScroll] = React.useState(false);
|
338 | const [displayEndScroll, setDisplayEndScroll] = React.useState(false);
|
339 | const [updateScrollObserver, setUpdateScrollObserver] = React.useState(false);
|
340 | const [scrollerStyle, setScrollerStyle] = React.useState({
|
341 | overflow: 'hidden',
|
342 | scrollbarWidth: 0
|
343 | });
|
344 | const valueToIndex = new Map();
|
345 | const tabsRef = React.useRef(null);
|
346 | const tabListRef = React.useRef(null);
|
347 | const getTabsMeta = () => {
|
348 | const tabsNode = tabsRef.current;
|
349 | let tabsMeta;
|
350 | if (tabsNode) {
|
351 | const rect = tabsNode.getBoundingClientRect();
|
352 |
|
353 | tabsMeta = {
|
354 | clientWidth: tabsNode.clientWidth,
|
355 | scrollLeft: tabsNode.scrollLeft,
|
356 | scrollTop: tabsNode.scrollTop,
|
357 | scrollWidth: tabsNode.scrollWidth,
|
358 | top: rect.top,
|
359 | bottom: rect.bottom,
|
360 | left: rect.left,
|
361 | right: rect.right
|
362 | };
|
363 | }
|
364 | let tabMeta;
|
365 | if (tabsNode && value !== false) {
|
366 | const children = tabListRef.current.children;
|
367 | if (children.length > 0) {
|
368 | const tab = children[valueToIndex.get(value)];
|
369 | if (process.env.NODE_ENV !== 'production') {
|
370 | if (!tab) {
|
371 | console.error([`MUI: The \`value\` provided to the Tabs component is invalid.`, `None of the Tabs' children match with "${value}".`, valueToIndex.keys ? `You can provide one of the following values: ${Array.from(valueToIndex.keys()).join(', ')}.` : null].join('\n'));
|
372 | }
|
373 | }
|
374 | tabMeta = tab ? tab.getBoundingClientRect() : null;
|
375 | if (process.env.NODE_ENV !== 'production') {
|
376 | if (process.env.NODE_ENV !== 'test' && !warnedOnceTabPresent && tabMeta && tabMeta.width === 0 && tabMeta.height === 0 &&
|
377 |
|
378 | tabsMeta.clientWidth !== 0) {
|
379 | tabsMeta = null;
|
380 | console.error(['MUI: The `value` provided to the Tabs component is invalid.', `The Tab with this \`value\` ("${value}") is not part of the document layout.`, "Make sure the tab item is present in the document or that it's not `display: none`."].join('\n'));
|
381 | warnedOnceTabPresent = true;
|
382 | }
|
383 | }
|
384 | }
|
385 | }
|
386 | return {
|
387 | tabsMeta,
|
388 | tabMeta
|
389 | };
|
390 | };
|
391 | const updateIndicatorState = (0, _useEventCallback.default)(() => {
|
392 | const {
|
393 | tabsMeta,
|
394 | tabMeta
|
395 | } = getTabsMeta();
|
396 | let startValue = 0;
|
397 | let startIndicator;
|
398 | if (vertical) {
|
399 | startIndicator = 'top';
|
400 | if (tabMeta && tabsMeta) {
|
401 | startValue = tabMeta.top - tabsMeta.top + tabsMeta.scrollTop;
|
402 | }
|
403 | } else {
|
404 | startIndicator = isRtl ? 'right' : 'left';
|
405 | if (tabMeta && tabsMeta) {
|
406 | startValue = (isRtl ? -1 : 1) * (tabMeta[startIndicator] - tabsMeta[startIndicator] + tabsMeta.scrollLeft);
|
407 | }
|
408 | }
|
409 | const newIndicatorStyle = {
|
410 | [startIndicator]: startValue,
|
411 |
|
412 | [size]: tabMeta ? tabMeta[size] : 0
|
413 | };
|
414 | if (typeof indicatorStyle[startIndicator] !== 'number' || typeof indicatorStyle[size] !== 'number') {
|
415 | setIndicatorStyle(newIndicatorStyle);
|
416 | } else {
|
417 | const dStart = Math.abs(indicatorStyle[startIndicator] - newIndicatorStyle[startIndicator]);
|
418 | const dSize = Math.abs(indicatorStyle[size] - newIndicatorStyle[size]);
|
419 | if (dStart >= 1 || dSize >= 1) {
|
420 | setIndicatorStyle(newIndicatorStyle);
|
421 | }
|
422 | }
|
423 | });
|
424 | const scroll = (scrollValue, {
|
425 | animation = true
|
426 | } = {}) => {
|
427 | if (animation) {
|
428 | (0, _animate.default)(scrollStart, tabsRef.current, scrollValue, {
|
429 | duration: theme.transitions.duration.standard
|
430 | });
|
431 | } else {
|
432 | tabsRef.current[scrollStart] = scrollValue;
|
433 | }
|
434 | };
|
435 | const moveTabsScroll = delta => {
|
436 | let scrollValue = tabsRef.current[scrollStart];
|
437 | if (vertical) {
|
438 | scrollValue += delta;
|
439 | } else {
|
440 | scrollValue += delta * (isRtl ? -1 : 1);
|
441 | }
|
442 | scroll(scrollValue);
|
443 | };
|
444 | const getScrollSize = () => {
|
445 | const containerSize = tabsRef.current[clientSize];
|
446 | let totalSize = 0;
|
447 | const children = Array.from(tabListRef.current.children);
|
448 | for (let i = 0; i < children.length; i += 1) {
|
449 | const tab = children[i];
|
450 | if (totalSize + tab[clientSize] > containerSize) {
|
451 |
|
452 |
|
453 | if (i === 0) {
|
454 | totalSize = containerSize;
|
455 | }
|
456 | break;
|
457 | }
|
458 | totalSize += tab[clientSize];
|
459 | }
|
460 | return totalSize;
|
461 | };
|
462 | const handleStartScrollClick = () => {
|
463 | moveTabsScroll(-1 * getScrollSize());
|
464 | };
|
465 | const handleEndScrollClick = () => {
|
466 | moveTabsScroll(getScrollSize());
|
467 | };
|
468 |
|
469 |
|
470 |
|
471 | const handleScrollbarSizeChange = React.useCallback(scrollbarWidth => {
|
472 | setScrollerStyle({
|
473 | overflow: null,
|
474 | scrollbarWidth
|
475 | });
|
476 | }, []);
|
477 | const getConditionalElements = () => {
|
478 | const conditionalElements = {};
|
479 | conditionalElements.scrollbarSizeListener = scrollable ? (0, _jsxRuntime.jsx)(TabsScrollbarSize, {
|
480 | onChange: handleScrollbarSizeChange,
|
481 | className: (0, _clsx.default)(classes.scrollableX, classes.hideScrollbar)
|
482 | }) : null;
|
483 | const scrollButtonsActive = displayStartScroll || displayEndScroll;
|
484 | const showScrollButtons = scrollable && (scrollButtons === 'auto' && scrollButtonsActive || scrollButtons === true);
|
485 | conditionalElements.scrollButtonStart = showScrollButtons ? (0, _jsxRuntime.jsx)(ScrollButtonComponent, {
|
486 | slots: {
|
487 | StartScrollButtonIcon: slots.StartScrollButtonIcon
|
488 | },
|
489 | slotProps: {
|
490 | startScrollButtonIcon: startScrollButtonIconProps
|
491 | },
|
492 | orientation: orientation,
|
493 | direction: isRtl ? 'right' : 'left',
|
494 | onClick: handleStartScrollClick,
|
495 | disabled: !displayStartScroll,
|
496 | ...TabScrollButtonProps,
|
497 | className: (0, _clsx.default)(classes.scrollButtons, TabScrollButtonProps.className)
|
498 | }) : null;
|
499 | conditionalElements.scrollButtonEnd = showScrollButtons ? (0, _jsxRuntime.jsx)(ScrollButtonComponent, {
|
500 | slots: {
|
501 | EndScrollButtonIcon: slots.EndScrollButtonIcon
|
502 | },
|
503 | slotProps: {
|
504 | endScrollButtonIcon: endScrollButtonIconProps
|
505 | },
|
506 | orientation: orientation,
|
507 | direction: isRtl ? 'left' : 'right',
|
508 | onClick: handleEndScrollClick,
|
509 | disabled: !displayEndScroll,
|
510 | ...TabScrollButtonProps,
|
511 | className: (0, _clsx.default)(classes.scrollButtons, TabScrollButtonProps.className)
|
512 | }) : null;
|
513 | return conditionalElements;
|
514 | };
|
515 | const scrollSelectedIntoView = (0, _useEventCallback.default)(animation => {
|
516 | const {
|
517 | tabsMeta,
|
518 | tabMeta
|
519 | } = getTabsMeta();
|
520 | if (!tabMeta || !tabsMeta) {
|
521 | return;
|
522 | }
|
523 | if (tabMeta[start] < tabsMeta[start]) {
|
524 |
|
525 | const nextScrollStart = tabsMeta[scrollStart] + (tabMeta[start] - tabsMeta[start]);
|
526 | scroll(nextScrollStart, {
|
527 | animation
|
528 | });
|
529 | } else if (tabMeta[end] > tabsMeta[end]) {
|
530 |
|
531 | const nextScrollStart = tabsMeta[scrollStart] + (tabMeta[end] - tabsMeta[end]);
|
532 | scroll(nextScrollStart, {
|
533 | animation
|
534 | });
|
535 | }
|
536 | });
|
537 | const updateScrollButtonState = (0, _useEventCallback.default)(() => {
|
538 | if (scrollable && scrollButtons !== false) {
|
539 | setUpdateScrollObserver(!updateScrollObserver);
|
540 | }
|
541 | });
|
542 | React.useEffect(() => {
|
543 | const handleResize = (0, _debounce.default)(() => {
|
544 |
|
545 |
|
546 |
|
547 |
|
548 |
|
549 |
|
550 | if (tabsRef.current) {
|
551 | updateIndicatorState();
|
552 | }
|
553 | });
|
554 | let resizeObserver;
|
555 |
|
556 | |
557 |
|
558 |
|
559 | const handleMutation = records => {
|
560 | records.forEach(record => {
|
561 | record.removedNodes.forEach(item => {
|
562 | resizeObserver?.unobserve(item);
|
563 | });
|
564 | record.addedNodes.forEach(item => {
|
565 | resizeObserver?.observe(item);
|
566 | });
|
567 | });
|
568 | handleResize();
|
569 | updateScrollButtonState();
|
570 | };
|
571 | const win = (0, _ownerWindow.default)(tabsRef.current);
|
572 | win.addEventListener('resize', handleResize);
|
573 | let mutationObserver;
|
574 | if (typeof ResizeObserver !== 'undefined') {
|
575 | resizeObserver = new ResizeObserver(handleResize);
|
576 | Array.from(tabListRef.current.children).forEach(child => {
|
577 | resizeObserver.observe(child);
|
578 | });
|
579 | }
|
580 | if (typeof MutationObserver !== 'undefined') {
|
581 | mutationObserver = new MutationObserver(handleMutation);
|
582 | mutationObserver.observe(tabListRef.current, {
|
583 | childList: true
|
584 | });
|
585 | }
|
586 | return () => {
|
587 | handleResize.clear();
|
588 | win.removeEventListener('resize', handleResize);
|
589 | mutationObserver?.disconnect();
|
590 | resizeObserver?.disconnect();
|
591 | };
|
592 | }, [updateIndicatorState, updateScrollButtonState]);
|
593 |
|
594 | |
595 |
|
596 |
|
597 |
|
598 | React.useEffect(() => {
|
599 | const tabListChildren = Array.from(tabListRef.current.children);
|
600 | const length = tabListChildren.length;
|
601 | if (typeof IntersectionObserver !== 'undefined' && length > 0 && scrollable && scrollButtons !== false) {
|
602 | const firstTab = tabListChildren[0];
|
603 | const lastTab = tabListChildren[length - 1];
|
604 | const observerOptions = {
|
605 | root: tabsRef.current,
|
606 | threshold: 0.99
|
607 | };
|
608 | const handleScrollButtonStart = entries => {
|
609 | setDisplayStartScroll(!entries[0].isIntersecting);
|
610 | };
|
611 | const firstObserver = new IntersectionObserver(handleScrollButtonStart, observerOptions);
|
612 | firstObserver.observe(firstTab);
|
613 | const handleScrollButtonEnd = entries => {
|
614 | setDisplayEndScroll(!entries[0].isIntersecting);
|
615 | };
|
616 | const lastObserver = new IntersectionObserver(handleScrollButtonEnd, observerOptions);
|
617 | lastObserver.observe(lastTab);
|
618 | return () => {
|
619 | firstObserver.disconnect();
|
620 | lastObserver.disconnect();
|
621 | };
|
622 | }
|
623 | return undefined;
|
624 | }, [scrollable, scrollButtons, updateScrollObserver, childrenProp?.length]);
|
625 | React.useEffect(() => {
|
626 | setMounted(true);
|
627 | }, []);
|
628 | React.useEffect(() => {
|
629 | updateIndicatorState();
|
630 | });
|
631 | React.useEffect(() => {
|
632 |
|
633 | scrollSelectedIntoView(defaultIndicatorStyle !== indicatorStyle);
|
634 | }, [scrollSelectedIntoView, indicatorStyle]);
|
635 | React.useImperativeHandle(action, () => ({
|
636 | updateIndicator: updateIndicatorState,
|
637 | updateScrollButtons: updateScrollButtonState
|
638 | }), [updateIndicatorState, updateScrollButtonState]);
|
639 | const indicator = (0, _jsxRuntime.jsx)(TabsIndicator, {
|
640 | ...TabIndicatorProps,
|
641 | className: (0, _clsx.default)(classes.indicator, TabIndicatorProps.className),
|
642 | ownerState: ownerState,
|
643 | style: {
|
644 | ...indicatorStyle,
|
645 | ...TabIndicatorProps.style
|
646 | }
|
647 | });
|
648 | let childIndex = 0;
|
649 | const children = React.Children.map(childrenProp, child => {
|
650 | if (! React.isValidElement(child)) {
|
651 | return null;
|
652 | }
|
653 | if (process.env.NODE_ENV !== 'production') {
|
654 | if ((0, _reactIs.isFragment)(child)) {
|
655 | console.error(["MUI: The Tabs component doesn't accept a Fragment as a child.", 'Consider providing an array instead.'].join('\n'));
|
656 | }
|
657 | }
|
658 | const childValue = child.props.value === undefined ? childIndex : child.props.value;
|
659 | valueToIndex.set(childValue, childIndex);
|
660 | const selected = childValue === value;
|
661 | childIndex += 1;
|
662 | return React.cloneElement(child, {
|
663 | fullWidth: variant === 'fullWidth',
|
664 | indicator: selected && !mounted && indicator,
|
665 | selected,
|
666 | selectionFollowsFocus,
|
667 | onChange,
|
668 | textColor,
|
669 | value: childValue,
|
670 | ...(childIndex === 1 && value === false && !child.props.tabIndex ? {
|
671 | tabIndex: 0
|
672 | } : {})
|
673 | });
|
674 | });
|
675 | const handleKeyDown = event => {
|
676 | const list = tabListRef.current;
|
677 | const currentFocus = (0, _ownerDocument.default)(list).activeElement;
|
678 |
|
679 |
|
680 |
|
681 | const role = currentFocus.getAttribute('role');
|
682 | if (role !== 'tab') {
|
683 | return;
|
684 | }
|
685 | let previousItemKey = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';
|
686 | let nextItemKey = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown';
|
687 | if (orientation === 'horizontal' && isRtl) {
|
688 |
|
689 | previousItemKey = 'ArrowRight';
|
690 | nextItemKey = 'ArrowLeft';
|
691 | }
|
692 | switch (event.key) {
|
693 | case previousItemKey:
|
694 | event.preventDefault();
|
695 | moveFocus(list, currentFocus, previousItem);
|
696 | break;
|
697 | case nextItemKey:
|
698 | event.preventDefault();
|
699 | moveFocus(list, currentFocus, nextItem);
|
700 | break;
|
701 | case 'Home':
|
702 | event.preventDefault();
|
703 | moveFocus(list, null, nextItem);
|
704 | break;
|
705 | case 'End':
|
706 | event.preventDefault();
|
707 | moveFocus(list, null, previousItem);
|
708 | break;
|
709 | default:
|
710 | break;
|
711 | }
|
712 | };
|
713 | const conditionalElements = getConditionalElements();
|
714 | return (0, _jsxRuntime.jsxs)(TabsRoot, {
|
715 | className: (0, _clsx.default)(classes.root, className),
|
716 | ownerState: ownerState,
|
717 | ref: ref,
|
718 | as: component,
|
719 | ...other,
|
720 | children: [conditionalElements.scrollButtonStart, conditionalElements.scrollbarSizeListener, (0, _jsxRuntime.jsxs)(TabsScroller, {
|
721 | className: classes.scroller,
|
722 | ownerState: ownerState,
|
723 | style: {
|
724 | overflow: scrollerStyle.overflow,
|
725 | [vertical ? `margin${isRtl ? 'Left' : 'Right'}` : 'marginBottom']: visibleScrollbar ? undefined : -scrollerStyle.scrollbarWidth
|
726 | },
|
727 | ref: tabsRef,
|
728 | children: [(0, _jsxRuntime.jsx)(FlexContainer, {
|
729 | "aria-label": ariaLabel,
|
730 | "aria-labelledby": ariaLabelledBy,
|
731 | "aria-orientation": orientation === 'vertical' ? 'vertical' : null,
|
732 | className: classes.flexContainer,
|
733 | ownerState: ownerState,
|
734 | onKeyDown: handleKeyDown,
|
735 | ref: tabListRef,
|
736 | role: "tablist",
|
737 | children: children
|
738 | }), mounted && indicator]
|
739 | }), conditionalElements.scrollButtonEnd]
|
740 | });
|
741 | });
|
742 | process.env.NODE_ENV !== "production" ? Tabs.propTypes = {
|
743 |
|
744 |
|
745 |
|
746 |
|
747 | |
748 |
|
749 |
|
750 |
|
751 |
|
752 |
|
753 |
|
754 |
|
755 | action: _refType.default,
|
756 | |
757 |
|
758 |
|
759 |
|
760 |
|
761 | allowScrollButtonsMobile: _propTypes.default.bool,
|
762 | |
763 |
|
764 |
|
765 | 'aria-label': _propTypes.default.string,
|
766 | |
767 |
|
768 |
|
769 | 'aria-labelledby': _propTypes.default.string,
|
770 | |
771 |
|
772 |
|
773 |
|
774 |
|
775 | centered: _propTypes.default.bool,
|
776 | |
777 |
|
778 |
|
779 | children: _propTypes.default.node,
|
780 | |
781 |
|
782 |
|
783 | classes: _propTypes.default.object,
|
784 | |
785 |
|
786 |
|
787 | className: _propTypes.default.string,
|
788 | |
789 |
|
790 |
|
791 |
|
792 | component: _propTypes.default.elementType,
|
793 | |
794 |
|
795 |
|
796 |
|
797 | indicatorColor: _propTypes.default .oneOfType([_propTypes.default.oneOf(['primary', 'secondary']), _propTypes.default.string]),
|
798 | |
799 |
|
800 |
|
801 |
|
802 |
|
803 |
|
804 | onChange: _propTypes.default.func,
|
805 | |
806 |
|
807 |
|
808 |
|
809 | orientation: _propTypes.default.oneOf(['horizontal', 'vertical']),
|
810 | |
811 |
|
812 |
|
813 |
|
814 | ScrollButtonComponent: _propTypes.default.elementType,
|
815 | |
816 |
|
817 |
|
818 |
|
819 |
|
820 |
|
821 |
|
822 |
|
823 |
|
824 |
|
825 |
|
826 | scrollButtons: _propTypes.default .oneOf(['auto', false, true]),
|
827 | |
828 |
|
829 |
|
830 |
|
831 | selectionFollowsFocus: _propTypes.default.bool,
|
832 | |
833 |
|
834 |
|
835 |
|
836 |
|
837 | slotProps: _propTypes.default.shape({
|
838 | endScrollButtonIcon: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object]),
|
839 | startScrollButtonIcon: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object])
|
840 | }),
|
841 | |
842 |
|
843 |
|
844 |
|
845 | slots: _propTypes.default.shape({
|
846 | EndScrollButtonIcon: _propTypes.default.elementType,
|
847 | StartScrollButtonIcon: _propTypes.default.elementType
|
848 | }),
|
849 | |
850 |
|
851 |
|
852 | sx: _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.object, _propTypes.default.bool])), _propTypes.default.func, _propTypes.default.object]),
|
853 | |
854 |
|
855 |
|
856 |
|
857 | TabIndicatorProps: _propTypes.default.object,
|
858 | |
859 |
|
860 |
|
861 |
|
862 | TabScrollButtonProps: _propTypes.default.object,
|
863 | |
864 |
|
865 |
|
866 |
|
867 | textColor: _propTypes.default.oneOf(['inherit', 'primary', 'secondary']),
|
868 | |
869 |
|
870 |
|
871 |
|
872 | value: _propTypes.default.any,
|
873 | |
874 |
|
875 |
|
876 |
|
877 |
|
878 |
|
879 |
|
880 |
|
881 |
|
882 |
|
883 | variant: _propTypes.default.oneOf(['fullWidth', 'scrollable', 'standard']),
|
884 | |
885 |
|
886 |
|
887 |
|
888 |
|
889 | visibleScrollbar: _propTypes.default.bool
|
890 | } : void 0;
|
891 | var _default = exports.default = Tabs; |
\ | No newline at end of file |