You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
496 lines
19 KiB
496 lines
19 KiB
"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; |