1 | "use strict";
|
2 |
|
3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
4 |
|
5 | Object.defineProperty(exports, "__esModule", {
|
6 | value: true
|
7 | });
|
8 | exports.default = exports.styles = void 0;
|
9 |
|
10 | var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
11 |
|
12 | var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
13 |
|
14 | var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
15 |
|
16 | var _react = _interopRequireDefault(require("react"));
|
17 |
|
18 | var _reactIs = require("react-is");
|
19 |
|
20 | var _propTypes = _interopRequireDefault(require("prop-types"));
|
21 |
|
22 | var _clsx = _interopRequireDefault(require("clsx"));
|
23 |
|
24 | var _utils = require("@material-ui/utils");
|
25 |
|
26 | var _debounce = _interopRequireDefault(require("../utils/debounce"));
|
27 |
|
28 | var _ownerWindow = _interopRequireDefault(require("../utils/ownerWindow"));
|
29 |
|
30 | var _normalizeScrollLeft = require("normalize-scroll-left");
|
31 |
|
32 | var _animate = _interopRequireDefault(require("../internal/animate"));
|
33 |
|
34 | var _ScrollbarSize = _interopRequireDefault(require("./ScrollbarSize"));
|
35 |
|
36 | var _withStyles = _interopRequireDefault(require("../styles/withStyles"));
|
37 |
|
38 | var _TabIndicator = _interopRequireDefault(require("./TabIndicator"));
|
39 |
|
40 | var _TabScrollButton = _interopRequireDefault(require("./TabScrollButton"));
|
41 |
|
42 | var _useEventCallback = _interopRequireDefault(require("../utils/useEventCallback"));
|
43 |
|
44 | var _useTheme = _interopRequireDefault(require("../styles/useTheme"));
|
45 |
|
46 | var styles = function styles(theme) {
|
47 | return {
|
48 |
|
49 | root: {
|
50 | overflow: 'hidden',
|
51 | minHeight: 48,
|
52 | WebkitOverflowScrolling: 'touch',
|
53 |
|
54 | display: 'flex'
|
55 | },
|
56 |
|
57 |
|
58 | vertical: {
|
59 | flexDirection: 'column'
|
60 | },
|
61 |
|
62 |
|
63 | flexContainer: {
|
64 | display: 'flex'
|
65 | },
|
66 |
|
67 |
|
68 | flexContainerVertical: {
|
69 | flexDirection: 'column'
|
70 | },
|
71 |
|
72 |
|
73 | centered: {
|
74 | justifyContent: 'center'
|
75 | },
|
76 |
|
77 |
|
78 | scroller: {
|
79 | position: 'relative',
|
80 | display: 'inline-block',
|
81 | flex: '1 1 auto',
|
82 | whiteSpace: 'nowrap'
|
83 | },
|
84 |
|
85 |
|
86 | fixed: {
|
87 | overflowX: 'hidden',
|
88 | width: '100%'
|
89 | },
|
90 |
|
91 |
|
92 | scrollable: {
|
93 | overflowX: 'scroll',
|
94 |
|
95 | scrollbarWidth: 'none',
|
96 |
|
97 | '&::-webkit-scrollbar': {
|
98 | display: 'none'
|
99 |
|
100 | }
|
101 | },
|
102 |
|
103 |
|
104 | scrollButtons: {},
|
105 |
|
106 |
|
107 | scrollButtonsDesktop: (0, _defineProperty2.default)({}, theme.breakpoints.down('xs'), {
|
108 | display: 'none'
|
109 | }),
|
110 |
|
111 |
|
112 | indicator: {}
|
113 | };
|
114 | };
|
115 |
|
116 | exports.styles = styles;
|
117 |
|
118 | var Tabs = _react.default.forwardRef(function Tabs(props, ref) {
|
119 | var action = props.action,
|
120 | _props$centered = props.centered,
|
121 | centered = _props$centered === void 0 ? false : _props$centered,
|
122 | childrenProp = props.children,
|
123 | classes = props.classes,
|
124 | className = props.className,
|
125 | _props$component = props.component,
|
126 | Component = _props$component === void 0 ? 'div' : _props$component,
|
127 | _props$indicatorColor = props.indicatorColor,
|
128 | indicatorColor = _props$indicatorColor === void 0 ? 'secondary' : _props$indicatorColor,
|
129 | onChange = props.onChange,
|
130 | _props$orientation = props.orientation,
|
131 | orientation = _props$orientation === void 0 ? 'horizontal' : _props$orientation,
|
132 | _props$ScrollButtonCo = props.ScrollButtonComponent,
|
133 | ScrollButtonComponent = _props$ScrollButtonCo === void 0 ? _TabScrollButton.default : _props$ScrollButtonCo,
|
134 | _props$scrollButtons = props.scrollButtons,
|
135 | scrollButtons = _props$scrollButtons === void 0 ? 'auto' : _props$scrollButtons,
|
136 | _props$TabIndicatorPr = props.TabIndicatorProps,
|
137 | TabIndicatorProps = _props$TabIndicatorPr === void 0 ? {} : _props$TabIndicatorPr,
|
138 | _props$textColor = props.textColor,
|
139 | textColor = _props$textColor === void 0 ? 'inherit' : _props$textColor,
|
140 | value = props.value,
|
141 | _props$variant = props.variant,
|
142 | variant = _props$variant === void 0 ? 'standard' : _props$variant,
|
143 | other = (0, _objectWithoutProperties2.default)(props, ["action", "centered", "children", "classes", "className", "component", "indicatorColor", "onChange", "orientation", "ScrollButtonComponent", "scrollButtons", "TabIndicatorProps", "textColor", "value", "variant"]);
|
144 | var theme = (0, _useTheme.default)();
|
145 | var scrollable = variant === 'scrollable';
|
146 | var isRtl = theme.direction === 'rtl';
|
147 | var vertical = orientation === 'vertical';
|
148 | var scrollStart = vertical ? 'scrollTop' : 'scrollLeft';
|
149 | var start = vertical ? 'top' : 'left';
|
150 | var end = vertical ? 'bottom' : 'right';
|
151 | var clientSize = vertical ? 'clientHeight' : 'clientWidth';
|
152 | var size = vertical ? 'height' : 'width';
|
153 |
|
154 | if (process.env.NODE_ENV !== 'production') {
|
155 | if (centered && scrollable) {
|
156 | console.error('Material-UI: you can not use the `centered={true}` and `variant="scrollable"` properties ' + 'at the same time on a `Tabs` component.');
|
157 | }
|
158 | }
|
159 |
|
160 | var _React$useState = _react.default.useState(false),
|
161 | mounted = _React$useState[0],
|
162 | setMounted = _React$useState[1];
|
163 |
|
164 | var _React$useState2 = _react.default.useState({}),
|
165 | indicatorStyle = _React$useState2[0],
|
166 | setIndicatorStyle = _React$useState2[1];
|
167 |
|
168 | var _React$useState3 = _react.default.useState({
|
169 | start: false,
|
170 | end: false
|
171 | }),
|
172 | displayScroll = _React$useState3[0],
|
173 | setDisplayScroll = _React$useState3[1];
|
174 |
|
175 | var _React$useState4 = _react.default.useState({
|
176 | overflow: 'hidden',
|
177 | marginBottom: null
|
178 | }),
|
179 | scrollerStyle = _React$useState4[0],
|
180 | setScrollerStyle = _React$useState4[1];
|
181 |
|
182 | var valueToIndex = new Map();
|
183 |
|
184 | var tabsRef = _react.default.useRef(null);
|
185 |
|
186 | var childrenWrapperRef = _react.default.useRef(null);
|
187 |
|
188 | var getTabsMeta = function getTabsMeta() {
|
189 | var tabsNode = tabsRef.current;
|
190 | var tabsMeta;
|
191 |
|
192 | if (tabsNode) {
|
193 | var rect = tabsNode.getBoundingClientRect();
|
194 |
|
195 | tabsMeta = {
|
196 | clientWidth: tabsNode.clientWidth,
|
197 | scrollLeft: tabsNode.scrollLeft,
|
198 | scrollTop: tabsNode.scrollTop,
|
199 | scrollLeftNormalized: (0, _normalizeScrollLeft.getNormalizedScrollLeft)(tabsNode, theme.direction),
|
200 | scrollWidth: tabsNode.scrollWidth,
|
201 | top: rect.top,
|
202 | bottom: rect.bottom,
|
203 | left: rect.left,
|
204 | right: rect.right
|
205 | };
|
206 | }
|
207 |
|
208 | var tabMeta;
|
209 |
|
210 | if (tabsNode && value !== false) {
|
211 | var _children = childrenWrapperRef.current.children;
|
212 |
|
213 | if (_children.length > 0) {
|
214 | var tab = _children[valueToIndex.get(value)];
|
215 |
|
216 | if (process.env.NODE_ENV !== 'production') {
|
217 | if (!tab) {
|
218 | console.error(["Material-UI: the value provided `".concat(value, "` to the Tabs component is invalid."), 'None of the Tabs children have this value.', valueToIndex.keys ? "You can provide one of the following values: ".concat(Array.from(valueToIndex.keys()).join(', '), ".") : null].join('\n'));
|
219 | }
|
220 | }
|
221 |
|
222 | tabMeta = tab ? tab.getBoundingClientRect() : null;
|
223 | }
|
224 | }
|
225 |
|
226 | return {
|
227 | tabsMeta: tabsMeta,
|
228 | tabMeta: tabMeta
|
229 | };
|
230 | };
|
231 |
|
232 | var updateIndicatorState = (0, _useEventCallback.default)(function () {
|
233 | var _newIndicatorStyle;
|
234 |
|
235 | var _getTabsMeta = getTabsMeta(),
|
236 | tabsMeta = _getTabsMeta.tabsMeta,
|
237 | tabMeta = _getTabsMeta.tabMeta;
|
238 |
|
239 | var startValue = 0;
|
240 |
|
241 | if (tabMeta && tabsMeta) {
|
242 | if (vertical) {
|
243 | startValue = tabMeta.top - tabsMeta.top + tabsMeta.scrollTop;
|
244 | } else {
|
245 | var correction = isRtl ? tabsMeta.scrollLeftNormalized + tabsMeta.clientWidth - tabsMeta.scrollWidth : tabsMeta.scrollLeft;
|
246 | startValue = tabMeta.left - tabsMeta.left + correction;
|
247 | }
|
248 | }
|
249 |
|
250 | var newIndicatorStyle = (_newIndicatorStyle = {}, (0, _defineProperty2.default)(_newIndicatorStyle, start, startValue), (0, _defineProperty2.default)(_newIndicatorStyle, size, tabMeta ? tabMeta[size] : 0), _newIndicatorStyle);
|
251 |
|
252 | if (isNaN(indicatorStyle[start]) || isNaN(indicatorStyle[size])) {
|
253 | setIndicatorStyle(newIndicatorStyle);
|
254 | } else {
|
255 | var dStart = Math.abs(indicatorStyle[start] - newIndicatorStyle[start]);
|
256 | var dSize = Math.abs(indicatorStyle[size] - newIndicatorStyle[size]);
|
257 |
|
258 | if (dStart >= 1 || dSize >= 1) {
|
259 | setIndicatorStyle(newIndicatorStyle);
|
260 | }
|
261 | }
|
262 | });
|
263 |
|
264 | var scroll = function scroll(scrollValue) {
|
265 | (0, _animate.default)(scrollStart, tabsRef.current, scrollValue);
|
266 | };
|
267 |
|
268 | var moveTabsScroll = function moveTabsScroll(delta) {
|
269 | var scrollValue = tabsRef.current[scrollStart];
|
270 |
|
271 | if (vertical) {
|
272 | scrollValue += delta;
|
273 | } else {
|
274 | scrollValue += delta * (isRtl ? -1 : 1);
|
275 |
|
276 | scrollValue *= isRtl && (0, _normalizeScrollLeft.detectScrollType)() === 'reverse' ? -1 : 1;
|
277 | }
|
278 |
|
279 | scroll(scrollValue);
|
280 | };
|
281 |
|
282 | var handleStartScrollClick = function handleStartScrollClick() {
|
283 | moveTabsScroll(-tabsRef.current[clientSize]);
|
284 | };
|
285 |
|
286 | var handleEndScrollClick = function handleEndScrollClick() {
|
287 | moveTabsScroll(tabsRef.current[clientSize]);
|
288 | };
|
289 |
|
290 | var handleScrollbarSizeChange = _react.default.useCallback(function (scrollbarHeight) {
|
291 | setScrollerStyle({
|
292 | overflow: null,
|
293 | marginBottom: -scrollbarHeight
|
294 | });
|
295 | }, []);
|
296 |
|
297 | var getConditionalElements = function getConditionalElements() {
|
298 | var conditionalElements = {};
|
299 | conditionalElements.scrollbarSizeListener = scrollable ? _react.default.createElement(_ScrollbarSize.default, {
|
300 | className: classes.scrollable,
|
301 | onChange: handleScrollbarSizeChange
|
302 | }) : null;
|
303 | var scrollButtonsActive = displayScroll.start || displayScroll.end;
|
304 | var showScrollButtons = scrollable && (scrollButtons === 'auto' && scrollButtonsActive || scrollButtons === 'desktop' || scrollButtons === 'on');
|
305 | conditionalElements.scrollButtonStart = showScrollButtons ? _react.default.createElement(ScrollButtonComponent, {
|
306 | orientation: orientation,
|
307 | direction: isRtl ? 'right' : 'left',
|
308 | onClick: handleStartScrollClick,
|
309 | visible: displayScroll.start,
|
310 | className: (0, _clsx.default)(classes.scrollButtons, scrollButtons !== 'on' && classes.scrollButtonsDesktop)
|
311 | }) : null;
|
312 | conditionalElements.scrollButtonEnd = showScrollButtons ? _react.default.createElement(ScrollButtonComponent, {
|
313 | orientation: orientation,
|
314 | direction: isRtl ? 'left' : 'right',
|
315 | onClick: handleEndScrollClick,
|
316 | visible: displayScroll.end,
|
317 | className: (0, _clsx.default)(classes.scrollButtons, scrollButtons !== 'on' && classes.scrollButtonsDesktop)
|
318 | }) : null;
|
319 | return conditionalElements;
|
320 | };
|
321 |
|
322 | var scrollSelectedIntoView = (0, _useEventCallback.default)(function () {
|
323 | var _getTabsMeta2 = getTabsMeta(),
|
324 | tabsMeta = _getTabsMeta2.tabsMeta,
|
325 | tabMeta = _getTabsMeta2.tabMeta;
|
326 |
|
327 | if (!tabMeta || !tabsMeta) {
|
328 | return;
|
329 | }
|
330 |
|
331 | if (tabMeta[start] < tabsMeta[start]) {
|
332 |
|
333 | var nextScrollStart = tabsMeta[scrollStart] + (tabMeta[start] - tabsMeta[start]);
|
334 | scroll(nextScrollStart);
|
335 | } else if (tabMeta[end] > tabsMeta[end]) {
|
336 |
|
337 | var _nextScrollStart = tabsMeta[scrollStart] + (tabMeta[end] - tabsMeta[end]);
|
338 |
|
339 | scroll(_nextScrollStart);
|
340 | }
|
341 | });
|
342 | var updateScrollButtonState = (0, _useEventCallback.default)(function () {
|
343 | if (scrollable && scrollButtons !== 'off') {
|
344 | var _tabsRef$current = tabsRef.current,
|
345 | scrollTop = _tabsRef$current.scrollTop,
|
346 | scrollHeight = _tabsRef$current.scrollHeight,
|
347 | clientHeight = _tabsRef$current.clientHeight,
|
348 | scrollWidth = _tabsRef$current.scrollWidth,
|
349 | clientWidth = _tabsRef$current.clientWidth;
|
350 | var showStartScroll;
|
351 | var showEndScroll;
|
352 |
|
353 | if (vertical) {
|
354 | showStartScroll = scrollTop > 1;
|
355 | showEndScroll = scrollTop < scrollHeight - clientHeight - 1;
|
356 | } else {
|
357 | var scrollLeft = (0, _normalizeScrollLeft.getNormalizedScrollLeft)(tabsRef.current, theme.direction);
|
358 |
|
359 | showStartScroll = isRtl ? scrollLeft < scrollWidth - clientWidth - 1 : scrollLeft > 1;
|
360 | showEndScroll = !isRtl ? scrollLeft < scrollWidth - clientWidth - 1 : scrollLeft > 1;
|
361 | }
|
362 |
|
363 | if (showStartScroll !== displayScroll.start || showEndScroll !== displayScroll.end) {
|
364 | setDisplayScroll({
|
365 | start: showStartScroll,
|
366 | end: showEndScroll
|
367 | });
|
368 | }
|
369 | }
|
370 | });
|
371 |
|
372 | _react.default.useEffect(function () {
|
373 | var handleResize = (0, _debounce.default)(function () {
|
374 | updateIndicatorState();
|
375 | updateScrollButtonState();
|
376 | });
|
377 | var win = (0, _ownerWindow.default)(tabsRef.current);
|
378 | win.addEventListener('resize', handleResize);
|
379 | return function () {
|
380 | handleResize.clear();
|
381 | win.removeEventListener('resize', handleResize);
|
382 | };
|
383 | }, [updateIndicatorState, updateScrollButtonState]);
|
384 |
|
385 | var handleTabsScroll = _react.default.useCallback((0, _debounce.default)(function () {
|
386 | updateScrollButtonState();
|
387 | }));
|
388 |
|
389 | _react.default.useEffect(function () {
|
390 | return function () {
|
391 | handleTabsScroll.clear();
|
392 | };
|
393 | }, [handleTabsScroll]);
|
394 |
|
395 | _react.default.useEffect(function () {
|
396 | setMounted(true);
|
397 | }, []);
|
398 |
|
399 | _react.default.useEffect(function () {
|
400 | updateIndicatorState();
|
401 | updateScrollButtonState();
|
402 | });
|
403 |
|
404 | _react.default.useEffect(function () {
|
405 | scrollSelectedIntoView();
|
406 | }, [scrollSelectedIntoView, indicatorStyle]);
|
407 |
|
408 | _react.default.useImperativeHandle(action, function () {
|
409 | return {
|
410 | updateIndicator: updateIndicatorState,
|
411 | updateScrollButtons: updateScrollButtonState
|
412 | };
|
413 | }, [updateIndicatorState, updateScrollButtonState]);
|
414 |
|
415 | var indicator = _react.default.createElement(_TabIndicator.default, (0, _extends2.default)({
|
416 | className: classes.indicator,
|
417 | orientation: orientation,
|
418 | color: indicatorColor
|
419 | }, TabIndicatorProps, {
|
420 | style: (0, _extends2.default)({}, indicatorStyle, {}, TabIndicatorProps.style)
|
421 | }));
|
422 |
|
423 | var childIndex = 0;
|
424 |
|
425 | var children = _react.default.Children.map(childrenProp, function (child) {
|
426 | if (!_react.default.isValidElement(child)) {
|
427 | return null;
|
428 | }
|
429 |
|
430 | if (process.env.NODE_ENV !== 'production') {
|
431 | if ((0, _reactIs.isFragment)(child)) {
|
432 | console.error(["Material-UI: the Tabs component doesn't accept a Fragment as a child.", 'Consider providing an array instead.'].join('\n'));
|
433 | }
|
434 | }
|
435 |
|
436 | var childValue = child.props.value === undefined ? childIndex : child.props.value;
|
437 | valueToIndex.set(childValue, childIndex);
|
438 | var selected = childValue === value;
|
439 | childIndex += 1;
|
440 | return _react.default.cloneElement(child, {
|
441 | fullWidth: variant === 'fullWidth',
|
442 | indicator: selected && !mounted && indicator,
|
443 | selected: selected,
|
444 | onChange: onChange,
|
445 | textColor: textColor,
|
446 | value: childValue
|
447 | });
|
448 | });
|
449 |
|
450 | var conditionalElements = getConditionalElements();
|
451 | return _react.default.createElement(Component, (0, _extends2.default)({
|
452 | className: (0, _clsx.default)(classes.root, className, vertical && classes.vertical),
|
453 | ref: ref
|
454 | }, other), conditionalElements.scrollButtonStart, conditionalElements.scrollbarSizeListener, _react.default.createElement("div", {
|
455 | className: (0, _clsx.default)(classes.scroller, scrollable ? classes.scrollable : classes.fixed),
|
456 | style: scrollerStyle,
|
457 | ref: tabsRef,
|
458 | onScroll: handleTabsScroll
|
459 | }, _react.default.createElement("div", {
|
460 | className: (0, _clsx.default)(classes.flexContainer, vertical && classes.flexContainerVertical, centered && !scrollable && classes.centered),
|
461 | ref: childrenWrapperRef,
|
462 | role: "tablist"
|
463 | }, children), mounted && indicator), conditionalElements.scrollButtonEnd);
|
464 | });
|
465 |
|
466 | process.env.NODE_ENV !== "production" ? Tabs.propTypes = {
|
467 | |
468 |
|
469 |
|
470 |
|
471 |
|
472 |
|
473 |
|
474 |
|
475 | action: _utils.refType,
|
476 |
|
477 | |
478 |
|
479 |
|
480 |
|
481 | centered: _propTypes.default.bool,
|
482 |
|
483 | |
484 |
|
485 |
|
486 | children: _propTypes.default.node,
|
487 |
|
488 | |
489 |
|
490 |
|
491 |
|
492 | classes: _propTypes.default.object.isRequired,
|
493 |
|
494 | |
495 |
|
496 |
|
497 | className: _propTypes.default.string,
|
498 |
|
499 | |
500 |
|
501 |
|
502 |
|
503 | component: _propTypes.default.elementType,
|
504 |
|
505 | |
506 |
|
507 |
|
508 | indicatorColor: _propTypes.default.oneOf(['secondary', 'primary']),
|
509 |
|
510 | |
511 |
|
512 |
|
513 |
|
514 |
|
515 |
|
516 | onChange: _propTypes.default.func,
|
517 |
|
518 | |
519 |
|
520 |
|
521 | orientation: _propTypes.default.oneOf(['horizontal', 'vertical']),
|
522 |
|
523 | |
524 |
|
525 |
|
526 | ScrollButtonComponent: _propTypes.default.elementType,
|
527 |
|
528 | |
529 |
|
530 |
|
531 |
|
532 |
|
533 |
|
534 |
|
535 |
|
536 | scrollButtons: _propTypes.default.oneOf(['auto', 'desktop', 'on', 'off']),
|
537 |
|
538 | |
539 |
|
540 |
|
541 | TabIndicatorProps: _propTypes.default.object,
|
542 |
|
543 | |
544 |
|
545 |
|
546 | textColor: _propTypes.default.oneOf(['secondary', 'primary', 'inherit']),
|
547 |
|
548 | |
549 |
|
550 |
|
551 |
|
552 | value: _propTypes.default.any,
|
553 |
|
554 | |
555 |
|
556 |
|
557 |
|
558 |
|
559 |
|
560 |
|
561 |
|
562 |
|
563 | variant: _propTypes.default.oneOf(['standard', 'scrollable', 'fullWidth'])
|
564 | } : void 0;
|
565 |
|
566 | var _default = (0, _withStyles.default)(styles, {
|
567 | name: 'MuiTabs'
|
568 | })(Tabs);
|
569 |
|
570 | exports.default = _default; |
\ | No newline at end of file |