"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var React = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _raf = _interopRequireDefault(require("raf")); var _rcResizeObserver = _interopRequireDefault(require("rc-resize-observer")); var _useRaf = _interopRequireWildcard(require("../hooks/useRaf")); var _TabNode = _interopRequireDefault(require("./TabNode")); var _useOffsets = _interopRequireDefault(require("../hooks/useOffsets")); var _useVisibleRange3 = _interopRequireDefault(require("../hooks/useVisibleRange")); var _OperationNode = _interopRequireDefault(require("./OperationNode")); var _TabContext = _interopRequireDefault(require("../TabContext")); var _useTouchMove = _interopRequireDefault(require("../hooks/useTouchMove")); var _useRefs3 = _interopRequireDefault(require("../hooks/useRefs")); var _AddButton = _interopRequireDefault(require("./AddButton")); var _useSyncState5 = _interopRequireDefault(require("../hooks/useSyncState")); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function TabNavList(props, ref) { var _classNames; var _React$useContext = React.useContext(_TabContext.default), prefixCls = _React$useContext.prefixCls, tabs = _React$useContext.tabs; var className = props.className, style = props.style, id = props.id, animated = props.animated, activeKey = props.activeKey, rtl = props.rtl, extra = props.extra, editable = props.editable, locale = props.locale, tabPosition = props.tabPosition, tabBarGutter = props.tabBarGutter, children = props.children, onTabClick = props.onTabClick, onTabScroll = props.onTabScroll; var tabsWrapperRef = (0, React.useRef)(); var tabListRef = (0, React.useRef)(); var operationsRef = (0, React.useRef)(); var innerAddButtonRef = (0, React.useRef)(); var _useRefs = (0, _useRefs3.default)(), _useRefs2 = (0, _slicedToArray2.default)(_useRefs, 2), getBtnRef = _useRefs2[0], removeBtnRef = _useRefs2[1]; var tabPositionTopOrBottom = tabPosition === 'top' || tabPosition === 'bottom'; var _useSyncState = (0, _useSyncState5.default)(0, function (next, prev) { if (tabPositionTopOrBottom && onTabScroll) { onTabScroll({ direction: next > prev ? 'left' : 'right' }); } }), _useSyncState2 = (0, _slicedToArray2.default)(_useSyncState, 2), transformLeft = _useSyncState2[0], setTransformLeft = _useSyncState2[1]; var _useSyncState3 = (0, _useSyncState5.default)(0, function (next, prev) { if (!tabPositionTopOrBottom && onTabScroll) { onTabScroll({ direction: next > prev ? 'top' : 'bottom' }); } }), _useSyncState4 = (0, _slicedToArray2.default)(_useSyncState3, 2), transformTop = _useSyncState4[0], setTransformTop = _useSyncState4[1]; var _useState = (0, React.useState)(0), _useState2 = (0, _slicedToArray2.default)(_useState, 2), wrapperScrollWidth = _useState2[0], setWrapperScrollWidth = _useState2[1]; var _useState3 = (0, React.useState)(0), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), wrapperScrollHeight = _useState4[0], setWrapperScrollHeight = _useState4[1]; var _useState5 = (0, React.useState)(0), _useState6 = (0, _slicedToArray2.default)(_useState5, 2), wrapperContentWidth = _useState6[0], setWrapperContentWidth = _useState6[1]; var _useState7 = (0, React.useState)(0), _useState8 = (0, _slicedToArray2.default)(_useState7, 2), wrapperContentHeight = _useState8[0], setWrapperContentHeight = _useState8[1]; var _useState9 = (0, React.useState)(null), _useState10 = (0, _slicedToArray2.default)(_useState9, 2), wrapperWidth = _useState10[0], setWrapperWidth = _useState10[1]; var _useState11 = (0, React.useState)(null), _useState12 = (0, _slicedToArray2.default)(_useState11, 2), wrapperHeight = _useState12[0], setWrapperHeight = _useState12[1]; var _useState13 = (0, React.useState)(0), _useState14 = (0, _slicedToArray2.default)(_useState13, 2), addWidth = _useState14[0], setAddWidth = _useState14[1]; var _useState15 = (0, React.useState)(0), _useState16 = (0, _slicedToArray2.default)(_useState15, 2), addHeight = _useState16[0], setAddHeight = _useState16[1]; var _useRafState = (0, _useRaf.useRafState)(new Map()), _useRafState2 = (0, _slicedToArray2.default)(_useRafState, 2), tabSizes = _useRafState2[0], setTabSizes = _useRafState2[1]; var tabOffsets = (0, _useOffsets.default)(tabs, tabSizes, wrapperScrollWidth); // ========================== Util ========================= var operationsHiddenClassName = "".concat(prefixCls, "-nav-operations-hidden"); var transformMin = 0; var transformMax = 0; if (!tabPositionTopOrBottom) { transformMin = Math.min(0, wrapperHeight - wrapperScrollHeight); transformMax = 0; } else if (rtl) { transformMin = 0; transformMax = Math.max(0, wrapperScrollWidth - wrapperWidth); } else { transformMin = Math.min(0, wrapperWidth - wrapperScrollWidth); transformMax = 0; } function alignInRange(value) { if (value < transformMin) { return [transformMin, false]; } if (value > transformMax) { return [transformMax, false]; } return [value, true]; } // ========================= Mobile ======================== var touchMovingRef = (0, React.useRef)(); var _useState17 = (0, React.useState)(), _useState18 = (0, _slicedToArray2.default)(_useState17, 2), lockAnimation = _useState18[0], setLockAnimation = _useState18[1]; function doLockAnimation() { setLockAnimation(Date.now()); } function clearTouchMoving() { window.clearTimeout(touchMovingRef.current); } (0, _useTouchMove.default)(tabsWrapperRef, function (offsetX, offsetY) { var preventDefault = false; function doMove(setState, offset) { setState(function (value) { var _alignInRange = alignInRange(value + offset), _alignInRange2 = (0, _slicedToArray2.default)(_alignInRange, 2), newValue = _alignInRange2[0], needPrevent = _alignInRange2[1]; preventDefault = needPrevent; return newValue; }); } if (tabPositionTopOrBottom) { // Skip scroll if place is enough if (wrapperWidth >= wrapperScrollWidth) { return preventDefault; } doMove(setTransformLeft, offsetX); } else { if (wrapperHeight >= wrapperScrollHeight) { return preventDefault; } doMove(setTransformTop, offsetY); } clearTouchMoving(); doLockAnimation(); return preventDefault; }); (0, React.useEffect)(function () { clearTouchMoving(); if (lockAnimation) { touchMovingRef.current = window.setTimeout(function () { setLockAnimation(0); }, 100); } return clearTouchMoving; }, [lockAnimation]); // ========================= Scroll ======================== function scrollToTab() { var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : activeKey; var tabOffset = tabOffsets.get(key); if (!tabOffset) return; if (tabPositionTopOrBottom) { // ============ Align with top & bottom ============ var newTransform = transformLeft; // RTL if (rtl) { if (tabOffset.right < transformLeft) { newTransform = tabOffset.right; } else if (tabOffset.right + tabOffset.width > transformLeft + wrapperWidth) { newTransform = tabOffset.right + tabOffset.width - wrapperWidth; } } // LTR else if (tabOffset.left < -transformLeft) { newTransform = -tabOffset.left; } else if (tabOffset.left + tabOffset.width > -transformLeft + wrapperWidth) { newTransform = -(tabOffset.left + tabOffset.width - wrapperWidth); } setTransformTop(0); setTransformLeft(alignInRange(newTransform)[0]); } else { // ============ Align with left & right ============ var _newTransform = transformTop; if (tabOffset.top < -transformTop) { _newTransform = -tabOffset.top; } else if (tabOffset.top + tabOffset.height > -transformTop + wrapperHeight) { _newTransform = -(tabOffset.top + tabOffset.height - wrapperHeight); } setTransformLeft(0); setTransformTop(alignInRange(_newTransform)[0]); } } // ========================== Tab ========================== // Render tab node & collect tab offset var _useVisibleRange = (0, _useVisibleRange3.default)(tabOffsets, { width: wrapperWidth, height: wrapperHeight, left: transformLeft, top: transformTop }, { width: wrapperContentWidth, height: wrapperContentHeight }, { width: addWidth, height: addHeight }, _objectSpread(_objectSpread({}, props), {}, { tabs: tabs })), _useVisibleRange2 = (0, _slicedToArray2.default)(_useVisibleRange, 2), visibleStart = _useVisibleRange2[0], visibleEnd = _useVisibleRange2[1]; var tabNodes = tabs.map(function (tab) { var key = tab.key; return React.createElement(_TabNode.default, { id: id, prefixCls: prefixCls, key: key, rtl: rtl, tab: tab, closable: tab.closable, editable: editable, active: key === activeKey, tabPosition: tabPosition, tabBarGutter: tabBarGutter, renderWrapper: children, removeAriaLabel: locale === null || locale === void 0 ? void 0 : locale.removeAriaLabel, ref: getBtnRef(key), onClick: function onClick(e) { onTabClick(key, e); }, onRemove: function onRemove() { removeBtnRef(key); }, onFocus: function onFocus() { scrollToTab(key); doLockAnimation(); // Focus element will make scrollLeft change which we should reset back if (!rtl) { tabsWrapperRef.current.scrollLeft = 0; } tabsWrapperRef.current.scrollTop = 0; } }); }); var onListHolderResize = (0, _useRaf.default)(function () { var _tabsWrapperRef$curre, _tabsWrapperRef$curre2, _innerAddButtonRef$cu, _innerAddButtonRef$cu2, _operationsRef$curren, _operationsRef$curren2, _tabListRef$current, _tabListRef$current2, _operationsRef$curren3; // Update wrapper records var offsetWidth = ((_tabsWrapperRef$curre = tabsWrapperRef.current) === null || _tabsWrapperRef$curre === void 0 ? void 0 : _tabsWrapperRef$curre.offsetWidth) || 0; var offsetHeight = ((_tabsWrapperRef$curre2 = tabsWrapperRef.current) === null || _tabsWrapperRef$curre2 === void 0 ? void 0 : _tabsWrapperRef$curre2.offsetHeight) || 0; var newAddWidth = ((_innerAddButtonRef$cu = innerAddButtonRef.current) === null || _innerAddButtonRef$cu === void 0 ? void 0 : _innerAddButtonRef$cu.offsetWidth) || 0; var newAddHeight = ((_innerAddButtonRef$cu2 = innerAddButtonRef.current) === null || _innerAddButtonRef$cu2 === void 0 ? void 0 : _innerAddButtonRef$cu2.offsetHeight) || 0; var newOperationWidth = ((_operationsRef$curren = operationsRef.current) === null || _operationsRef$curren === void 0 ? void 0 : _operationsRef$curren.offsetWidth) || 0; var newOperationHeight = ((_operationsRef$curren2 = operationsRef.current) === null || _operationsRef$curren2 === void 0 ? void 0 : _operationsRef$curren2.offsetHeight) || 0; setWrapperWidth(offsetWidth); setWrapperHeight(offsetHeight); setAddWidth(newAddWidth); setAddHeight(newAddHeight); var newWrapperScrollWidth = (((_tabListRef$current = tabListRef.current) === null || _tabListRef$current === void 0 ? void 0 : _tabListRef$current.offsetWidth) || 0) - newAddWidth; var newWrapperScrollHeight = (((_tabListRef$current2 = tabListRef.current) === null || _tabListRef$current2 === void 0 ? void 0 : _tabListRef$current2.offsetHeight) || 0) - newAddHeight; setWrapperScrollWidth(newWrapperScrollWidth); setWrapperScrollHeight(newWrapperScrollHeight); var isOperationHidden = (_operationsRef$curren3 = operationsRef.current) === null || _operationsRef$curren3 === void 0 ? void 0 : _operationsRef$curren3.className.includes(operationsHiddenClassName); setWrapperContentWidth(newWrapperScrollWidth - (isOperationHidden ? 0 : newOperationWidth)); setWrapperContentHeight(newWrapperScrollHeight - (isOperationHidden ? 0 : newOperationHeight)); // Update buttons records setTabSizes(function () { var newSizes = new Map(); tabs.forEach(function (_ref) { var key = _ref.key; var btnNode = getBtnRef(key).current; if (btnNode) { newSizes.set(key, { width: btnNode.offsetWidth, height: btnNode.offsetHeight, left: btnNode.offsetLeft, top: btnNode.offsetTop }); } }); return newSizes; }); }); // ======================== Dropdown ======================= var startHiddenTabs = tabs.slice(0, visibleStart); var endHiddenTabs = tabs.slice(visibleEnd + 1); var hiddenTabs = [].concat((0, _toConsumableArray2.default)(startHiddenTabs), (0, _toConsumableArray2.default)(endHiddenTabs)); // =================== Link & Operations =================== var _useState19 = (0, React.useState)(), _useState20 = (0, _slicedToArray2.default)(_useState19, 2), inkStyle = _useState20[0], setInkStyle = _useState20[1]; var activeTabOffset = tabOffsets.get(activeKey); // Delay set ink style to avoid remove tab blink var inkBarRafRef = (0, React.useRef)(); function cleanInkBarRaf() { _raf.default.cancel(inkBarRafRef.current); } (0, React.useEffect)(function () { var newInkStyle = {}; if (activeTabOffset) { if (tabPositionTopOrBottom) { if (rtl) { newInkStyle.right = activeTabOffset.right; } else { newInkStyle.left = activeTabOffset.left; } newInkStyle.width = activeTabOffset.width; } else { newInkStyle.top = activeTabOffset.top; newInkStyle.height = activeTabOffset.height; } } cleanInkBarRaf(); inkBarRafRef.current = (0, _raf.default)(function () { setInkStyle(newInkStyle); }); return cleanInkBarRaf; }, [activeTabOffset, tabPositionTopOrBottom, rtl]); // ========================= Effect ======================== (0, React.useEffect)(function () { scrollToTab(); }, [activeKey, activeTabOffset, tabOffsets, tabPositionTopOrBottom]); // Should recalculate when rtl changed (0, React.useEffect)(function () { onListHolderResize(); }, [rtl, tabBarGutter, activeKey, tabs.map(function (tab) { return tab.key; }).join('_')]); // ========================= Render ======================== var hasDropdown = !!hiddenTabs.length; var wrapPrefix = "".concat(prefixCls, "-nav-wrap"); var pingLeft; var pingRight; var pingTop; var pingBottom; if (tabPositionTopOrBottom) { if (rtl) { pingRight = transformLeft > 0; pingLeft = transformLeft + wrapperWidth < wrapperScrollWidth; } else { pingLeft = transformLeft < 0; pingRight = -transformLeft + wrapperWidth < wrapperScrollWidth; } } else { pingTop = transformTop < 0; pingBottom = -transformTop + wrapperHeight < wrapperScrollHeight; } /* eslint-disable jsx-a11y/interactive-supports-focus */ return React.createElement("div", { ref: ref, role: "tablist", className: (0, _classnames.default)("".concat(prefixCls, "-nav"), className), style: style, onKeyDown: function onKeyDown() { // No need animation when use keyboard doLockAnimation(); } }, React.createElement(_rcResizeObserver.default, { onResize: onListHolderResize }, React.createElement("div", { className: (0, _classnames.default)(wrapPrefix, (_classNames = {}, (0, _defineProperty2.default)(_classNames, "".concat(wrapPrefix, "-ping-left"), pingLeft), (0, _defineProperty2.default)(_classNames, "".concat(wrapPrefix, "-ping-right"), pingRight), (0, _defineProperty2.default)(_classNames, "".concat(wrapPrefix, "-ping-top"), pingTop), (0, _defineProperty2.default)(_classNames, "".concat(wrapPrefix, "-ping-bottom"), pingBottom), _classNames)), ref: tabsWrapperRef }, React.createElement(_rcResizeObserver.default, { onResize: onListHolderResize }, React.createElement("div", { ref: tabListRef, className: "".concat(prefixCls, "-nav-list"), style: { transform: "translate(".concat(transformLeft, "px, ").concat(transformTop, "px)"), transition: lockAnimation ? 'none' : undefined } }, tabNodes, React.createElement(_AddButton.default, { ref: innerAddButtonRef, prefixCls: prefixCls, locale: locale, editable: editable, style: { visibility: hasDropdown ? 'hidden' : null } }), React.createElement("div", { className: (0, _classnames.default)("".concat(prefixCls, "-ink-bar"), (0, _defineProperty2.default)({}, "".concat(prefixCls, "-ink-bar-animated"), animated.inkBar)), style: inkStyle }))))), React.createElement(_OperationNode.default, Object.assign({}, props, { ref: operationsRef, prefixCls: prefixCls, tabs: hiddenTabs, className: !hasDropdown && operationsHiddenClassName })), extra && React.createElement("div", { className: "".concat(prefixCls, "-extra-content") }, extra)); /* eslint-enable */ } var _default = React.forwardRef(TabNavList); exports.default = _default;