Comparing version 15.4.0 to 15.5.0
@@ -20,3 +20,3 @@ import _extends from "@babel/runtime/helpers/esm/extends"; | ||
import useVisibleRange from "../hooks/useVisibleRange"; | ||
import { genDataNodeKey, stringify } from "../util"; | ||
import { genDataNodeKey, getRemovable, stringify } from "../util"; | ||
import AddButton from "./AddButton"; | ||
@@ -277,5 +277,122 @@ import ExtraContent from "./ExtraContent"; | ||
// ========================= Focus ========================= | ||
var _useState11 = useState(), | ||
_useState12 = _slicedToArray(_useState11, 2), | ||
focusKey = _useState12[0], | ||
setFocusKey = _useState12[1]; | ||
var _useState13 = useState(false), | ||
_useState14 = _slicedToArray(_useState13, 2), | ||
isMouse = _useState14[0], | ||
setIsMouse = _useState14[1]; | ||
var enabledTabs = tabs.filter(function (tab) { | ||
return !tab.disabled; | ||
}).map(function (tab) { | ||
return tab.key; | ||
}); | ||
var onOffset = function onOffset(offset) { | ||
var currentIndex = enabledTabs.indexOf(focusKey || activeKey); | ||
var len = enabledTabs.length; | ||
var nextIndex = (currentIndex + offset + len) % len; | ||
var newKey = enabledTabs[nextIndex]; | ||
setFocusKey(newKey); | ||
}; | ||
var handleKeyDown = function handleKeyDown(e) { | ||
var code = e.code; | ||
var isRTL = rtl && tabPositionTopOrBottom; | ||
var firstEnabledTab = enabledTabs[0]; | ||
var lastEnabledTab = enabledTabs[enabledTabs.length - 1]; | ||
switch (code) { | ||
// LEFT | ||
case 'ArrowLeft': | ||
{ | ||
if (tabPositionTopOrBottom) { | ||
onOffset(isRTL ? 1 : -1); | ||
} | ||
break; | ||
} | ||
// RIGHT | ||
case 'ArrowRight': | ||
{ | ||
if (tabPositionTopOrBottom) { | ||
onOffset(isRTL ? -1 : 1); | ||
} | ||
break; | ||
} | ||
// UP | ||
case 'ArrowUp': | ||
{ | ||
e.preventDefault(); | ||
if (!tabPositionTopOrBottom) { | ||
onOffset(-1); | ||
} | ||
break; | ||
} | ||
// DOWN | ||
case 'ArrowDown': | ||
{ | ||
e.preventDefault(); | ||
if (!tabPositionTopOrBottom) { | ||
onOffset(1); | ||
} | ||
break; | ||
} | ||
// HOME | ||
case 'Home': | ||
{ | ||
e.preventDefault(); | ||
setFocusKey(firstEnabledTab); | ||
break; | ||
} | ||
// END | ||
case 'End': | ||
{ | ||
e.preventDefault(); | ||
setFocusKey(lastEnabledTab); | ||
break; | ||
} | ||
// Enter & Space | ||
case 'Enter': | ||
case 'Space': | ||
{ | ||
e.preventDefault(); | ||
onTabClick(focusKey, e); | ||
break; | ||
} | ||
// Backspace | ||
case 'Backspace': | ||
case 'Delete': | ||
{ | ||
var removeIndex = enabledTabs.indexOf(focusKey); | ||
var removeTab = tabs.find(function (tab) { | ||
return tab.key === focusKey; | ||
}); | ||
var removable = getRemovable(removeTab === null || removeTab === void 0 ? void 0 : removeTab.closable, removeTab === null || removeTab === void 0 ? void 0 : removeTab.closeIcon, editable, removeTab === null || removeTab === void 0 ? void 0 : removeTab.disabled); | ||
if (removable) { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
editable.onEdit('remove', { | ||
key: focusKey, | ||
event: e | ||
}); | ||
// when remove last tab, focus previous tab | ||
if (removeIndex === enabledTabs.length - 1) { | ||
onOffset(-1); | ||
} else { | ||
onOffset(1); | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
}; | ||
// ========================== Tab ========================== | ||
var tabNodeStyle = {}; | ||
if (tabPosition === 'top' || tabPosition === 'bottom') { | ||
if (tabPositionTopOrBottom) { | ||
tabNodeStyle[rtl ? 'marginRight' : 'marginLeft'] = tabBarGutter; | ||
@@ -297,8 +414,15 @@ } else { | ||
active: key === activeKey, | ||
focus: key === focusKey, | ||
renderWrapper: children, | ||
removeAriaLabel: locale === null || locale === void 0 ? void 0 : locale.removeAriaLabel, | ||
tabCount: enabledTabs.length, | ||
currentPosition: i + 1, | ||
onClick: function onClick(e) { | ||
onTabClick(key, e); | ||
}, | ||
onKeyDown: handleKeyDown, | ||
onFocus: function onFocus() { | ||
if (!isMouse) { | ||
setFocusKey(key); | ||
} | ||
scrollToTab(key); | ||
@@ -314,2 +438,11 @@ doLockAnimation(); | ||
tabsWrapperRef.current.scrollTop = 0; | ||
}, | ||
onBlur: function onBlur() { | ||
setFocusKey(undefined); | ||
}, | ||
onMouseDown: function onMouseDown() { | ||
setIsMouse(true); | ||
}, | ||
onMouseUp: function onMouseUp() { | ||
setIsMouse(false); | ||
} | ||
@@ -421,2 +554,3 @@ }); | ||
role: "tablist", | ||
"aria-orientation": tabPositionTopOrBottom ? 'horizontal' : 'vertical', | ||
className: classNames("".concat(prefixCls, "-nav"), className), | ||
@@ -423,0 +557,0 @@ style: style, |
@@ -8,2 +8,3 @@ import * as React from 'react'; | ||
active: boolean; | ||
focus: boolean; | ||
closable?: boolean; | ||
@@ -15,4 +16,10 @@ editable?: EditableConfig; | ||
removeAriaLabel?: string; | ||
tabCount: number; | ||
currentPosition: number; | ||
removeIcon?: React.ReactNode; | ||
onKeyDown: React.KeyboardEventHandler; | ||
onMouseDown: React.MouseEventHandler; | ||
onMouseUp: React.MouseEventHandler; | ||
onFocus: React.FocusEventHandler; | ||
onBlur: React.FocusEventHandler; | ||
style?: React.CSSProperties; | ||
@@ -19,0 +26,0 @@ } |
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; | ||
import classNames from 'classnames'; | ||
import KeyCode from "rc-util/es/KeyCode"; | ||
import * as React from 'react'; | ||
@@ -10,2 +9,3 @@ import { genDataNodeKey, getRemovable } from "../util"; | ||
active = props.active, | ||
focus = props.focus, | ||
_props$tab = props.tab, | ||
@@ -23,3 +23,9 @@ key = _props$tab.key, | ||
onFocus = props.onFocus, | ||
style = props.style; | ||
onBlur = props.onBlur, | ||
onKeyDown = props.onKeyDown, | ||
onMouseDown = props.onMouseDown, | ||
onMouseUp = props.onMouseUp, | ||
style = props.style, | ||
tabCount = props.tabCount, | ||
currentPosition = props.currentPosition; | ||
var tabPrefix = "".concat(prefixCls, "-tab"); | ||
@@ -44,11 +50,16 @@ var removable = getRemovable(closable, closeIcon, editable, disabled); | ||
}, [label, icon]); | ||
var btnRef = React.useRef(null); | ||
React.useEffect(function () { | ||
if (focus && btnRef.current) { | ||
btnRef.current.focus(); | ||
} | ||
}, [focus]); | ||
var node = /*#__PURE__*/React.createElement("div", { | ||
key: key | ||
// ref={ref} | ||
, | ||
key: key, | ||
"data-node-key": genDataNodeKey(key), | ||
className: classNames(tabPrefix, _defineProperty(_defineProperty(_defineProperty({}, "".concat(tabPrefix, "-with-remove"), removable), "".concat(tabPrefix, "-active"), active), "".concat(tabPrefix, "-disabled"), disabled)), | ||
className: classNames(tabPrefix, _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, "".concat(tabPrefix, "-with-remove"), removable), "".concat(tabPrefix, "-active"), active), "".concat(tabPrefix, "-disabled"), disabled), "".concat(tabPrefix, "-focus"), focus)), | ||
style: style, | ||
onClick: onInternalClick | ||
}, /*#__PURE__*/React.createElement("div", { | ||
ref: btnRef, | ||
role: "tab", | ||
@@ -60,3 +71,3 @@ "aria-selected": active, | ||
"aria-disabled": disabled, | ||
tabIndex: disabled ? null : 0, | ||
tabIndex: disabled ? null : active ? 0 : -1, | ||
onClick: function onClick(e) { | ||
@@ -66,10 +77,17 @@ e.stopPropagation(); | ||
}, | ||
onKeyDown: function onKeyDown(e) { | ||
if ([KeyCode.SPACE, KeyCode.ENTER].includes(e.which)) { | ||
e.preventDefault(); | ||
onInternalClick(e); | ||
} | ||
}, | ||
onFocus: onFocus | ||
}, icon && /*#__PURE__*/React.createElement("span", { | ||
onKeyDown: onKeyDown, | ||
onMouseDown: onMouseDown, | ||
onMouseUp: onMouseUp, | ||
onFocus: onFocus, | ||
onBlur: onBlur | ||
}, focus && /*#__PURE__*/React.createElement("div", { | ||
"aria-live": "polite", | ||
style: { | ||
width: 0, | ||
height: 0, | ||
position: 'absolute', | ||
overflow: 'hidden', | ||
opacity: 0 | ||
} | ||
}, "Tab ".concat(currentPosition, " of ").concat(tabCount)), icon && /*#__PURE__*/React.createElement("span", { | ||
className: "".concat(tabPrefix, "-icon") | ||
@@ -79,3 +97,3 @@ }, icon), label && labelNode), removable && /*#__PURE__*/React.createElement("button", { | ||
"aria-label": removeAriaLabel || 'remove', | ||
tabIndex: 0, | ||
tabIndex: active ? 0 : -1, | ||
className: "".concat(tabPrefix, "-remove"), | ||
@@ -82,0 +100,0 @@ onClick: function onClick(e) { |
@@ -287,5 +287,122 @@ "use strict"; | ||
// ========================= Focus ========================= | ||
var _useState11 = (0, _react.useState)(), | ||
_useState12 = (0, _slicedToArray2.default)(_useState11, 2), | ||
focusKey = _useState12[0], | ||
setFocusKey = _useState12[1]; | ||
var _useState13 = (0, _react.useState)(false), | ||
_useState14 = (0, _slicedToArray2.default)(_useState13, 2), | ||
isMouse = _useState14[0], | ||
setIsMouse = _useState14[1]; | ||
var enabledTabs = tabs.filter(function (tab) { | ||
return !tab.disabled; | ||
}).map(function (tab) { | ||
return tab.key; | ||
}); | ||
var onOffset = function onOffset(offset) { | ||
var currentIndex = enabledTabs.indexOf(focusKey || activeKey); | ||
var len = enabledTabs.length; | ||
var nextIndex = (currentIndex + offset + len) % len; | ||
var newKey = enabledTabs[nextIndex]; | ||
setFocusKey(newKey); | ||
}; | ||
var handleKeyDown = function handleKeyDown(e) { | ||
var code = e.code; | ||
var isRTL = rtl && tabPositionTopOrBottom; | ||
var firstEnabledTab = enabledTabs[0]; | ||
var lastEnabledTab = enabledTabs[enabledTabs.length - 1]; | ||
switch (code) { | ||
// LEFT | ||
case 'ArrowLeft': | ||
{ | ||
if (tabPositionTopOrBottom) { | ||
onOffset(isRTL ? 1 : -1); | ||
} | ||
break; | ||
} | ||
// RIGHT | ||
case 'ArrowRight': | ||
{ | ||
if (tabPositionTopOrBottom) { | ||
onOffset(isRTL ? -1 : 1); | ||
} | ||
break; | ||
} | ||
// UP | ||
case 'ArrowUp': | ||
{ | ||
e.preventDefault(); | ||
if (!tabPositionTopOrBottom) { | ||
onOffset(-1); | ||
} | ||
break; | ||
} | ||
// DOWN | ||
case 'ArrowDown': | ||
{ | ||
e.preventDefault(); | ||
if (!tabPositionTopOrBottom) { | ||
onOffset(1); | ||
} | ||
break; | ||
} | ||
// HOME | ||
case 'Home': | ||
{ | ||
e.preventDefault(); | ||
setFocusKey(firstEnabledTab); | ||
break; | ||
} | ||
// END | ||
case 'End': | ||
{ | ||
e.preventDefault(); | ||
setFocusKey(lastEnabledTab); | ||
break; | ||
} | ||
// Enter & Space | ||
case 'Enter': | ||
case 'Space': | ||
{ | ||
e.preventDefault(); | ||
onTabClick(focusKey, e); | ||
break; | ||
} | ||
// Backspace | ||
case 'Backspace': | ||
case 'Delete': | ||
{ | ||
var removeIndex = enabledTabs.indexOf(focusKey); | ||
var removeTab = tabs.find(function (tab) { | ||
return tab.key === focusKey; | ||
}); | ||
var removable = (0, _util.getRemovable)(removeTab === null || removeTab === void 0 ? void 0 : removeTab.closable, removeTab === null || removeTab === void 0 ? void 0 : removeTab.closeIcon, editable, removeTab === null || removeTab === void 0 ? void 0 : removeTab.disabled); | ||
if (removable) { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
editable.onEdit('remove', { | ||
key: focusKey, | ||
event: e | ||
}); | ||
// when remove last tab, focus previous tab | ||
if (removeIndex === enabledTabs.length - 1) { | ||
onOffset(-1); | ||
} else { | ||
onOffset(1); | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
}; | ||
// ========================== Tab ========================== | ||
var tabNodeStyle = {}; | ||
if (tabPosition === 'top' || tabPosition === 'bottom') { | ||
if (tabPositionTopOrBottom) { | ||
tabNodeStyle[rtl ? 'marginRight' : 'marginLeft'] = tabBarGutter; | ||
@@ -307,8 +424,15 @@ } else { | ||
active: key === activeKey, | ||
focus: key === focusKey, | ||
renderWrapper: children, | ||
removeAriaLabel: locale === null || locale === void 0 ? void 0 : locale.removeAriaLabel, | ||
tabCount: enabledTabs.length, | ||
currentPosition: i + 1, | ||
onClick: function onClick(e) { | ||
onTabClick(key, e); | ||
}, | ||
onKeyDown: handleKeyDown, | ||
onFocus: function onFocus() { | ||
if (!isMouse) { | ||
setFocusKey(key); | ||
} | ||
scrollToTab(key); | ||
@@ -324,2 +448,11 @@ doLockAnimation(); | ||
tabsWrapperRef.current.scrollTop = 0; | ||
}, | ||
onBlur: function onBlur() { | ||
setFocusKey(undefined); | ||
}, | ||
onMouseDown: function onMouseDown() { | ||
setIsMouse(true); | ||
}, | ||
onMouseUp: function onMouseUp() { | ||
setIsMouse(false); | ||
} | ||
@@ -431,2 +564,3 @@ }); | ||
role: "tablist", | ||
"aria-orientation": tabPositionTopOrBottom ? 'horizontal' : 'vertical', | ||
className: (0, _classnames.default)("".concat(prefixCls, "-nav"), className), | ||
@@ -433,0 +567,0 @@ style: style, |
@@ -8,2 +8,3 @@ import * as React from 'react'; | ||
active: boolean; | ||
focus: boolean; | ||
closable?: boolean; | ||
@@ -15,4 +16,10 @@ editable?: EditableConfig; | ||
removeAriaLabel?: string; | ||
tabCount: number; | ||
currentPosition: number; | ||
removeIcon?: React.ReactNode; | ||
onKeyDown: React.KeyboardEventHandler; | ||
onMouseDown: React.MouseEventHandler; | ||
onMouseUp: React.MouseEventHandler; | ||
onFocus: React.FocusEventHandler; | ||
onBlur: React.FocusEventHandler; | ||
style?: React.CSSProperties; | ||
@@ -19,0 +26,0 @@ } |
@@ -11,3 +11,2 @@ "use strict"; | ||
var _classnames = _interopRequireDefault(require("classnames")); | ||
var _KeyCode = _interopRequireDefault(require("rc-util/lib/KeyCode")); | ||
var React = _interopRequireWildcard(require("react")); | ||
@@ -21,2 +20,3 @@ var _util = require("../util"); | ||
active = props.active, | ||
focus = props.focus, | ||
_props$tab = props.tab, | ||
@@ -34,3 +34,9 @@ key = _props$tab.key, | ||
onFocus = props.onFocus, | ||
style = props.style; | ||
onBlur = props.onBlur, | ||
onKeyDown = props.onKeyDown, | ||
onMouseDown = props.onMouseDown, | ||
onMouseUp = props.onMouseUp, | ||
style = props.style, | ||
tabCount = props.tabCount, | ||
currentPosition = props.currentPosition; | ||
var tabPrefix = "".concat(prefixCls, "-tab"); | ||
@@ -55,11 +61,16 @@ var removable = (0, _util.getRemovable)(closable, closeIcon, editable, disabled); | ||
}, [label, icon]); | ||
var btnRef = React.useRef(null); | ||
React.useEffect(function () { | ||
if (focus && btnRef.current) { | ||
btnRef.current.focus(); | ||
} | ||
}, [focus]); | ||
var node = /*#__PURE__*/React.createElement("div", { | ||
key: key | ||
// ref={ref} | ||
, | ||
key: key, | ||
"data-node-key": (0, _util.genDataNodeKey)(key), | ||
className: (0, _classnames.default)(tabPrefix, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, "".concat(tabPrefix, "-with-remove"), removable), "".concat(tabPrefix, "-active"), active), "".concat(tabPrefix, "-disabled"), disabled)), | ||
className: (0, _classnames.default)(tabPrefix, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, "".concat(tabPrefix, "-with-remove"), removable), "".concat(tabPrefix, "-active"), active), "".concat(tabPrefix, "-disabled"), disabled), "".concat(tabPrefix, "-focus"), focus)), | ||
style: style, | ||
onClick: onInternalClick | ||
}, /*#__PURE__*/React.createElement("div", { | ||
ref: btnRef, | ||
role: "tab", | ||
@@ -71,3 +82,3 @@ "aria-selected": active, | ||
"aria-disabled": disabled, | ||
tabIndex: disabled ? null : 0, | ||
tabIndex: disabled ? null : active ? 0 : -1, | ||
onClick: function onClick(e) { | ||
@@ -77,10 +88,17 @@ e.stopPropagation(); | ||
}, | ||
onKeyDown: function onKeyDown(e) { | ||
if ([_KeyCode.default.SPACE, _KeyCode.default.ENTER].includes(e.which)) { | ||
e.preventDefault(); | ||
onInternalClick(e); | ||
} | ||
}, | ||
onFocus: onFocus | ||
}, icon && /*#__PURE__*/React.createElement("span", { | ||
onKeyDown: onKeyDown, | ||
onMouseDown: onMouseDown, | ||
onMouseUp: onMouseUp, | ||
onFocus: onFocus, | ||
onBlur: onBlur | ||
}, focus && /*#__PURE__*/React.createElement("div", { | ||
"aria-live": "polite", | ||
style: { | ||
width: 0, | ||
height: 0, | ||
position: 'absolute', | ||
overflow: 'hidden', | ||
opacity: 0 | ||
} | ||
}, "Tab ".concat(currentPosition, " of ").concat(tabCount)), icon && /*#__PURE__*/React.createElement("span", { | ||
className: "".concat(tabPrefix, "-icon") | ||
@@ -90,3 +108,3 @@ }, icon), label && labelNode), removable && /*#__PURE__*/React.createElement("button", { | ||
"aria-label": removeAriaLabel || 'remove', | ||
tabIndex: 0, | ||
tabIndex: active ? 0 : -1, | ||
className: "".concat(tabPrefix, "-remove"), | ||
@@ -93,0 +111,0 @@ onClick: function onClick(e) { |
{ | ||
"name": "rc-tabs", | ||
"version": "15.4.0", | ||
"version": "15.5.0", | ||
"description": "tabs ui component for react", | ||
@@ -35,3 +35,3 @@ "keywords": [ | ||
"now-build": "npm run build", | ||
"prepublishOnly": "npm run lint && npm run test && npm run compile", | ||
"prepublishOnly": "npm run lint && npm run test && npm run compile && np --yolo --no-publish", | ||
"start": "dumi dev", | ||
@@ -53,3 +53,4 @@ "test": "rc-test" | ||
"@testing-library/jest-dom": "^6.1.4", | ||
"@testing-library/react": "^15.0.2", | ||
"@testing-library/react": "^16.0.1", | ||
"@testing-library/user-event": "^14.5.2", | ||
"@types/classnames": "^2.2.10", | ||
@@ -66,4 +67,4 @@ "@types/enzyme": "^3.10.5", | ||
"eslint": "^8.54.0", | ||
"eslint-plugin-jest": "^27.2.1", | ||
"eslint-plugin-unicorn": "^53.0.0", | ||
"eslint-plugin-jest": "^28.9.0", | ||
"eslint-plugin-unicorn": "^56.0.1", | ||
"fastclick": "~1.0.6", | ||
@@ -70,0 +71,0 @@ "father": "^4.0.0", |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
174802
4286
34