@clayui/tabs 3.77.0 → 3.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Item.js +1 -1
- package/lib/index.d.ts +21 -0
- package/lib/index.js +79 -4
- package/package.json +3 -3
- package/src/Item.tsx +1 -1
- package/src/__tests__/__snapshots__/index.tsx.snap +1 -0
- package/src/__tests__/index.tsx +9 -24
- package/src/index.tsx +101 -2
package/lib/Item.js
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -2,12 +2,29 @@
|
|
|
2
2
|
* SPDX-FileCopyrightText: © 2019 Liferay, Inc. <https://liferay.com>
|
|
3
3
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
4
4
|
*/
|
|
5
|
+
import { InternalDispatch } from '@clayui/shared';
|
|
5
6
|
import React from 'react';
|
|
6
7
|
import Content from './Content';
|
|
7
8
|
import Item from './Item';
|
|
8
9
|
import TabPane from './TabPane';
|
|
9
10
|
export declare type DisplayType = null | 'basic' | 'underline';
|
|
10
11
|
export interface IProps extends React.HTMLAttributes<HTMLUListElement> {
|
|
12
|
+
/**
|
|
13
|
+
* Flag to indicate the navigation behavior in the tab.
|
|
14
|
+
*
|
|
15
|
+
* - manual - it will just move the focus and tab activation is done just
|
|
16
|
+
* by pressing space or enter.
|
|
17
|
+
* - automatic - moves the focus to the tab and activates the tab.
|
|
18
|
+
*/
|
|
19
|
+
activation?: 'manual' | 'automatic';
|
|
20
|
+
/**
|
|
21
|
+
* The current tab active (controlled).
|
|
22
|
+
*/
|
|
23
|
+
active?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Initial active tab when rendering component (uncontrolled).
|
|
26
|
+
*/
|
|
27
|
+
defaultActive?: number;
|
|
11
28
|
/**
|
|
12
29
|
* Determines how tab is displayed.
|
|
13
30
|
*/
|
|
@@ -20,6 +37,10 @@ export interface IProps extends React.HTMLAttributes<HTMLUListElement> {
|
|
|
20
37
|
* Applies a modern style to the tab.
|
|
21
38
|
*/
|
|
22
39
|
modern?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Callback is called when the active tab changes (controlled).
|
|
42
|
+
*/
|
|
43
|
+
onActiveChange?: InternalDispatch<number>;
|
|
23
44
|
}
|
|
24
45
|
declare function ClayTabs(props: IProps): JSX.Element & {
|
|
25
46
|
Content: typeof Content;
|
package/lib/index.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
4
|
+
|
|
3
5
|
Object.defineProperty(exports, "__esModule", {
|
|
4
6
|
value: true
|
|
5
7
|
});
|
|
6
8
|
exports.default = void 0;
|
|
7
9
|
|
|
10
|
+
var _shared = require("@clayui/shared");
|
|
11
|
+
|
|
8
12
|
var _classnames = _interopRequireDefault(require("classnames"));
|
|
9
13
|
|
|
10
|
-
var _react =
|
|
14
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
11
15
|
|
|
12
16
|
var _Content = _interopRequireDefault(require("./Content"));
|
|
13
17
|
|
|
@@ -15,25 +19,61 @@ var _Item = _interopRequireDefault(require("./Item"));
|
|
|
15
19
|
|
|
16
20
|
var _TabPane = _interopRequireDefault(require("./TabPane"));
|
|
17
21
|
|
|
18
|
-
var _excluded = ["children", "className", "displayType", "justified", "modern"];
|
|
22
|
+
var _excluded = ["activation", "active", "children", "className", "defaultActive", "displayType", "justified", "modern", "onActiveChange"];
|
|
23
|
+
|
|
24
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
25
|
+
|
|
26
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
19
27
|
|
|
20
28
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
29
|
|
|
22
30
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
23
31
|
|
|
32
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
33
|
+
|
|
34
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
35
|
+
|
|
36
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
37
|
+
|
|
38
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
39
|
+
|
|
40
|
+
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
41
|
+
|
|
42
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
43
|
+
|
|
24
44
|
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
25
45
|
|
|
26
46
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
27
47
|
|
|
28
48
|
function ClayTabs(_ref) {
|
|
29
|
-
var
|
|
49
|
+
var _ref$activation = _ref.activation,
|
|
50
|
+
activation = _ref$activation === void 0 ? 'manual' : _ref$activation,
|
|
51
|
+
externalActive = _ref.active,
|
|
52
|
+
children = _ref.children,
|
|
30
53
|
className = _ref.className,
|
|
54
|
+
_ref$defaultActive = _ref.defaultActive,
|
|
55
|
+
defaultActive = _ref$defaultActive === void 0 ? 0 : _ref$defaultActive,
|
|
31
56
|
displayType = _ref.displayType,
|
|
32
57
|
justified = _ref.justified,
|
|
33
58
|
_ref$modern = _ref.modern,
|
|
34
59
|
modern = _ref$modern === void 0 ? true : _ref$modern,
|
|
60
|
+
onActiveChange = _ref.onActiveChange,
|
|
35
61
|
otherProps = _objectWithoutProperties(_ref, _excluded);
|
|
36
62
|
|
|
63
|
+
var tabsRef = (0, _react.useRef)(null);
|
|
64
|
+
|
|
65
|
+
var _useInternalState = (0, _shared.useInternalState)({
|
|
66
|
+
defaultName: 'defaultActive',
|
|
67
|
+
defaultValue: defaultActive,
|
|
68
|
+
handleName: 'onActiveChange',
|
|
69
|
+
name: 'active',
|
|
70
|
+
onChange: onActiveChange,
|
|
71
|
+
value: externalActive
|
|
72
|
+
}),
|
|
73
|
+
_useInternalState2 = _slicedToArray(_useInternalState, 2),
|
|
74
|
+
active = _useInternalState2[0],
|
|
75
|
+
setActive = _useInternalState2[1];
|
|
76
|
+
|
|
37
77
|
return /*#__PURE__*/_react.default.createElement("ul", _extends({}, otherProps, {
|
|
38
78
|
className: (0, _classnames.default)('nav', {
|
|
39
79
|
'nav-justified': justified
|
|
@@ -44,8 +84,43 @@ function ClayTabs(_ref) {
|
|
|
44
84
|
'nav-tabs': displayType === 'basic',
|
|
45
85
|
'nav-underline': displayType === 'underline'
|
|
46
86
|
}, className),
|
|
87
|
+
onKeyDown: function onKeyDown(event) {
|
|
88
|
+
if (!tabsRef.current) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (event.key === _shared.Keys.Left || event.key === _shared.Keys.Right) {
|
|
93
|
+
var tabs = Array.from(tabsRef.current.querySelectorAll(_shared.FOCUSABLE_ELEMENTS.join(',')));
|
|
94
|
+
var activeElement = document.activeElement;
|
|
95
|
+
var position = tabs.indexOf(activeElement);
|
|
96
|
+
var tab = tabs[event.key === _shared.Keys.Left ? position - 1 : position + 1];
|
|
97
|
+
|
|
98
|
+
if (tab) {
|
|
99
|
+
tab.focus();
|
|
100
|
+
|
|
101
|
+
if (activation === 'automatic') {
|
|
102
|
+
var newActive = Array.from(tabsRef.current.querySelectorAll('a, button')).indexOf(tab);
|
|
103
|
+
setActive(newActive);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
ref: tabsRef,
|
|
47
109
|
role: "tablist"
|
|
48
|
-
}), children)
|
|
110
|
+
}), _react.default.Children.map(children, function (child, index) {
|
|
111
|
+
return /*#__PURE__*/_react.default.cloneElement(child, {
|
|
112
|
+
active: child.props.active !== undefined ? child.props.active : active === index,
|
|
113
|
+
onClick: function onClick(event) {
|
|
114
|
+
var onClick = child.props.onClick;
|
|
115
|
+
|
|
116
|
+
if (onClick) {
|
|
117
|
+
onClick(event);
|
|
118
|
+
} else {
|
|
119
|
+
setActive(index);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}));
|
|
49
124
|
}
|
|
50
125
|
|
|
51
126
|
ClayTabs.Content = _Content.default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clayui/tabs",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.78.0",
|
|
4
4
|
"description": "ClayTabs component",
|
|
5
5
|
"license": "BSD-3-Clause",
|
|
6
6
|
"repository": "https://github.com/liferay/clay",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"react"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@clayui/shared": "^3.
|
|
29
|
+
"@clayui/shared": "^3.78.0",
|
|
30
30
|
"classnames": "^2.2.6"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"browserslist": [
|
|
38
38
|
"extends browserslist-config-clay"
|
|
39
39
|
],
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "128788059d168c956b392363054933db34c67cab"
|
|
41
41
|
}
|
package/src/Item.tsx
CHANGED
package/src/__tests__/index.tsx
CHANGED
|
@@ -9,32 +9,16 @@ import {cleanup, fireEvent, render} from '@testing-library/react';
|
|
|
9
9
|
import React from 'react';
|
|
10
10
|
|
|
11
11
|
const ClayTabsWithItems = () => {
|
|
12
|
-
const [
|
|
12
|
+
const [active, setActive] = React.useState<number>(0);
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
15
|
<>
|
|
16
|
-
<ClayTabs>
|
|
17
|
-
<ClayTabs.Item
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
>
|
|
21
|
-
Dummy1
|
|
22
|
-
</ClayTabs.Item>
|
|
23
|
-
<ClayTabs.Item
|
|
24
|
-
active={activeTabKeyValue == 1}
|
|
25
|
-
data-testid="tabItem2"
|
|
26
|
-
onClick={() => setActiveTabKeyValue(1)}
|
|
27
|
-
>
|
|
28
|
-
Dummy2
|
|
29
|
-
</ClayTabs.Item>
|
|
30
|
-
<ClayTabs.Item
|
|
31
|
-
active={activeTabKeyValue == 2}
|
|
32
|
-
onClick={() => setActiveTabKeyValue(2)}
|
|
33
|
-
>
|
|
34
|
-
Dummy3
|
|
35
|
-
</ClayTabs.Item>
|
|
16
|
+
<ClayTabs active={active} onActiveChange={setActive}>
|
|
17
|
+
<ClayTabs.Item>Dummy1</ClayTabs.Item>
|
|
18
|
+
<ClayTabs.Item data-testid="tabItem2">Dummy2</ClayTabs.Item>
|
|
19
|
+
<ClayTabs.Item>Dummy3</ClayTabs.Item>
|
|
36
20
|
</ClayTabs>
|
|
37
|
-
<ClayTabs.Content activeIndex={
|
|
21
|
+
<ClayTabs.Content activeIndex={active}>
|
|
38
22
|
<ClayTabs.TabPane data-testid="tabPane1">
|
|
39
23
|
Tab Content 1
|
|
40
24
|
</ClayTabs.TabPane>
|
|
@@ -96,8 +80,9 @@ describe('ClayTabs', () => {
|
|
|
96
80
|
const {getAllByTestId} = render(
|
|
97
81
|
<>
|
|
98
82
|
<ClayTabs>
|
|
99
|
-
<ClayTabs.Item active href="https://clay.dev/foo"
|
|
100
|
-
|
|
83
|
+
<ClayTabs.Item active href="https://clay.dev/foo">
|
|
84
|
+
One
|
|
85
|
+
</ClayTabs.Item>
|
|
101
86
|
<ClayTabs.Item href="https://clay.dev/bar">
|
|
102
87
|
Two
|
|
103
88
|
</ClayTabs.Item>
|
package/src/index.tsx
CHANGED
|
@@ -3,8 +3,14 @@
|
|
|
3
3
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import {
|
|
7
|
+
FOCUSABLE_ELEMENTS,
|
|
8
|
+
InternalDispatch,
|
|
9
|
+
Keys,
|
|
10
|
+
useInternalState,
|
|
11
|
+
} from '@clayui/shared';
|
|
6
12
|
import classNames from 'classnames';
|
|
7
|
-
import React from 'react';
|
|
13
|
+
import React, {useRef} from 'react';
|
|
8
14
|
|
|
9
15
|
import Content from './Content';
|
|
10
16
|
import Item from './Item';
|
|
@@ -13,6 +19,25 @@ import TabPane from './TabPane';
|
|
|
13
19
|
export type DisplayType = null | 'basic' | 'underline';
|
|
14
20
|
|
|
15
21
|
export interface IProps extends React.HTMLAttributes<HTMLUListElement> {
|
|
22
|
+
/**
|
|
23
|
+
* Flag to indicate the navigation behavior in the tab.
|
|
24
|
+
*
|
|
25
|
+
* - manual - it will just move the focus and tab activation is done just
|
|
26
|
+
* by pressing space or enter.
|
|
27
|
+
* - automatic - moves the focus to the tab and activates the tab.
|
|
28
|
+
*/
|
|
29
|
+
activation?: 'manual' | 'automatic';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The current tab active (controlled).
|
|
33
|
+
*/
|
|
34
|
+
active?: number;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Initial active tab when rendering component (uncontrolled).
|
|
38
|
+
*/
|
|
39
|
+
defaultActive?: number;
|
|
40
|
+
|
|
16
41
|
/**
|
|
17
42
|
* Determines how tab is displayed.
|
|
18
43
|
*/
|
|
@@ -27,6 +52,11 @@ export interface IProps extends React.HTMLAttributes<HTMLUListElement> {
|
|
|
27
52
|
* Applies a modern style to the tab.
|
|
28
53
|
*/
|
|
29
54
|
modern?: boolean;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Callback is called when the active tab changes (controlled).
|
|
58
|
+
*/
|
|
59
|
+
onActiveChange?: InternalDispatch<number>;
|
|
30
60
|
}
|
|
31
61
|
|
|
32
62
|
function ClayTabs(props: IProps): JSX.Element & {
|
|
@@ -37,13 +67,28 @@ function ClayTabs(props: IProps): JSX.Element & {
|
|
|
37
67
|
};
|
|
38
68
|
|
|
39
69
|
function ClayTabs({
|
|
70
|
+
activation = 'manual',
|
|
71
|
+
active: externalActive,
|
|
40
72
|
children,
|
|
41
73
|
className,
|
|
74
|
+
defaultActive = 0,
|
|
42
75
|
displayType,
|
|
43
76
|
justified,
|
|
44
77
|
modern = true,
|
|
78
|
+
onActiveChange,
|
|
45
79
|
...otherProps
|
|
46
80
|
}: IProps) {
|
|
81
|
+
const tabsRef = useRef<HTMLUListElement>(null);
|
|
82
|
+
|
|
83
|
+
const [active, setActive] = useInternalState({
|
|
84
|
+
defaultName: 'defaultActive',
|
|
85
|
+
defaultValue: defaultActive,
|
|
86
|
+
handleName: 'onActiveChange',
|
|
87
|
+
name: 'active',
|
|
88
|
+
onChange: onActiveChange,
|
|
89
|
+
value: externalActive,
|
|
90
|
+
});
|
|
91
|
+
|
|
47
92
|
return (
|
|
48
93
|
<ul
|
|
49
94
|
{...otherProps}
|
|
@@ -62,9 +107,63 @@ function ClayTabs({
|
|
|
62
107
|
|
|
63
108
|
className
|
|
64
109
|
)}
|
|
110
|
+
onKeyDown={(event) => {
|
|
111
|
+
if (!tabsRef.current) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (event.key === Keys.Left || event.key === Keys.Right) {
|
|
116
|
+
const tabs = Array.from<HTMLElement>(
|
|
117
|
+
tabsRef.current.querySelectorAll(
|
|
118
|
+
FOCUSABLE_ELEMENTS.join(',')
|
|
119
|
+
)
|
|
120
|
+
);
|
|
121
|
+
const activeElement = document.activeElement as HTMLElement;
|
|
122
|
+
|
|
123
|
+
const position = tabs.indexOf(activeElement);
|
|
124
|
+
|
|
125
|
+
const tab =
|
|
126
|
+
tabs[
|
|
127
|
+
event.key === Keys.Left
|
|
128
|
+
? position - 1
|
|
129
|
+
: position + 1
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
if (tab) {
|
|
133
|
+
tab.focus();
|
|
134
|
+
|
|
135
|
+
if (activation === 'automatic') {
|
|
136
|
+
const newActive = Array.from(
|
|
137
|
+
tabsRef.current.querySelectorAll('a, button')
|
|
138
|
+
).indexOf(tab);
|
|
139
|
+
|
|
140
|
+
setActive(newActive);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}}
|
|
145
|
+
ref={tabsRef}
|
|
65
146
|
role="tablist"
|
|
66
147
|
>
|
|
67
|
-
{children
|
|
148
|
+
{React.Children.map(children, (child, index) =>
|
|
149
|
+
React.cloneElement(child as React.ReactElement, {
|
|
150
|
+
active:
|
|
151
|
+
(child as React.ReactElement).props.active !== undefined
|
|
152
|
+
? (child as React.ReactElement).props.active
|
|
153
|
+
: active === index,
|
|
154
|
+
onClick: (
|
|
155
|
+
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
|
|
156
|
+
) => {
|
|
157
|
+
const {onClick} = (child as React.ReactElement).props;
|
|
158
|
+
|
|
159
|
+
if (onClick) {
|
|
160
|
+
onClick(event);
|
|
161
|
+
} else {
|
|
162
|
+
setActive(index);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
})
|
|
166
|
+
)}
|
|
68
167
|
</ul>
|
|
69
168
|
);
|
|
70
169
|
}
|