@patternfly/react-core 6.3.0-prerelease.13 → 6.3.0-prerelease.15
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/CHANGELOG.md +12 -0
- package/components/package.json +1 -1
- package/deprecated/package.json +1 -1
- package/dist/dynamic/components/AboutModal/package.json +1 -1
- package/dist/dynamic/components/Accordion/package.json +1 -1
- package/dist/dynamic/components/ActionList/package.json +1 -1
- package/dist/dynamic/components/Alert/package.json +1 -1
- package/dist/dynamic/components/Avatar/package.json +1 -1
- package/dist/dynamic/components/BackToTop/package.json +1 -1
- package/dist/dynamic/components/Backdrop/package.json +1 -1
- package/dist/dynamic/components/BackgroundImage/package.json +1 -1
- package/dist/dynamic/components/Badge/package.json +1 -1
- package/dist/dynamic/components/Banner/package.json +1 -1
- package/dist/dynamic/components/Brand/package.json +1 -1
- package/dist/dynamic/components/Breadcrumb/package.json +1 -1
- package/dist/dynamic/components/Button/package.json +1 -1
- package/dist/dynamic/components/CalendarMonth/package.json +1 -1
- package/dist/dynamic/components/Card/package.json +1 -1
- package/dist/dynamic/components/Checkbox/package.json +1 -1
- package/dist/dynamic/components/ClipboardCopy/package.json +1 -1
- package/dist/dynamic/components/CodeBlock/package.json +1 -1
- package/dist/dynamic/components/Content/package.json +1 -1
- package/dist/dynamic/components/DataList/package.json +1 -1
- package/dist/dynamic/components/DatePicker/package.json +1 -1
- package/dist/dynamic/components/DescriptionList/package.json +1 -1
- package/dist/dynamic/components/Divider/package.json +1 -1
- package/dist/dynamic/components/Drawer/package.json +1 -1
- package/dist/dynamic/components/Dropdown/package.json +1 -1
- package/dist/dynamic/components/DualListSelector/package.json +1 -1
- package/dist/dynamic/components/EmptyState/package.json +1 -1
- package/dist/dynamic/components/ExpandableSection/package.json +1 -1
- package/dist/dynamic/components/FileUpload/package.json +1 -1
- package/dist/dynamic/components/Form/package.json +1 -1
- package/dist/dynamic/components/FormSelect/package.json +1 -1
- package/dist/dynamic/components/HelperText/package.json +1 -1
- package/dist/dynamic/components/Hint/package.json +1 -1
- package/dist/dynamic/components/Icon/package.json +1 -1
- package/dist/dynamic/components/InputGroup/package.json +1 -1
- package/dist/dynamic/components/JumpLinks/package.json +1 -1
- package/dist/dynamic/components/Label/package.json +1 -1
- package/dist/dynamic/components/List/package.json +1 -1
- package/dist/dynamic/components/LoginPage/package.json +1 -1
- package/dist/dynamic/components/Masthead/package.json +1 -1
- package/dist/dynamic/components/Menu/package.json +1 -1
- package/dist/dynamic/components/MenuToggle/package.json +1 -1
- package/dist/dynamic/components/Modal/package.json +1 -1
- package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
- package/dist/dynamic/components/Nav/package.json +1 -1
- package/dist/dynamic/components/NotificationBadge/package.json +1 -1
- package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
- package/dist/dynamic/components/NumberInput/package.json +1 -1
- package/dist/dynamic/components/OverflowMenu/package.json +1 -1
- package/dist/dynamic/components/Page/package.json +1 -1
- package/dist/dynamic/components/Pagination/package.json +1 -1
- package/dist/dynamic/components/Panel/package.json +1 -1
- package/dist/dynamic/components/Popover/package.json +1 -1
- package/dist/dynamic/components/Progress/package.json +1 -1
- package/dist/dynamic/components/ProgressStepper/package.json +1 -1
- package/dist/dynamic/components/Radio/package.json +1 -1
- package/dist/dynamic/components/SearchInput/package.json +1 -1
- package/dist/dynamic/components/Select/package.json +1 -1
- package/dist/dynamic/components/Sidebar/package.json +1 -1
- package/dist/dynamic/components/SimpleList/package.json +1 -1
- package/dist/dynamic/components/Skeleton/package.json +1 -1
- package/dist/dynamic/components/SkipToContent/package.json +1 -1
- package/dist/dynamic/components/Slider/package.json +1 -1
- package/dist/dynamic/components/Spinner/package.json +1 -1
- package/dist/dynamic/components/Switch/package.json +1 -1
- package/dist/dynamic/components/Tabs/package.json +1 -1
- package/dist/dynamic/components/TextArea/package.json +1 -1
- package/dist/dynamic/components/TextInput/package.json +1 -1
- package/dist/dynamic/components/TextInputGroup/package.json +1 -1
- package/dist/dynamic/components/TimePicker/package.json +1 -1
- package/dist/dynamic/components/Timestamp/package.json +1 -1
- package/dist/dynamic/components/Title/package.json +1 -1
- package/dist/dynamic/components/ToggleGroup/package.json +1 -1
- package/dist/dynamic/components/Toolbar/package.json +1 -1
- package/dist/dynamic/components/Tooltip/package.json +1 -1
- package/dist/dynamic/components/TreeView/package.json +1 -1
- package/dist/dynamic/components/Truncate/package.json +1 -1
- package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
- package/dist/dynamic/components/Wizard/package.json +1 -1
- package/dist/dynamic/deprecated/components/Chip/package.json +1 -1
- package/dist/dynamic/deprecated/components/DragDrop/package.json +1 -1
- package/dist/dynamic/deprecated/components/DualListSelector/package.json +1 -1
- package/dist/dynamic/deprecated/components/Modal/package.json +1 -1
- package/dist/dynamic/deprecated/components/Tile/package.json +1 -1
- package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
- package/dist/dynamic/deprecated/components/package.json +1 -1
- package/dist/dynamic/helpers/FocusTrap/FocusTrap/package.json +1 -1
- package/dist/dynamic/helpers/GenerateId/GenerateId/package.json +1 -1
- package/dist/dynamic/helpers/KeyboardHandler/package.json +1 -1
- package/dist/dynamic/helpers/OUIA/ouia/package.json +1 -1
- package/dist/dynamic/helpers/Popper/Popper/package.json +1 -1
- package/dist/dynamic/helpers/constants/package.json +1 -1
- package/dist/dynamic/helpers/datetimeUtils/package.json +1 -1
- package/dist/dynamic/helpers/fileUtils/package.json +1 -1
- package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
- package/dist/dynamic/helpers/package.json +1 -1
- package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
- package/dist/dynamic/helpers/typeUtils/package.json +1 -1
- package/dist/dynamic/helpers/useInterval/package.json +1 -1
- package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
- package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
- package/dist/dynamic/helpers/util/package.json +1 -1
- package/dist/dynamic/layouts/Bullseye/package.json +1 -1
- package/dist/dynamic/layouts/Flex/package.json +1 -1
- package/dist/dynamic/layouts/Gallery/package.json +1 -1
- package/dist/dynamic/layouts/Grid/package.json +1 -1
- package/dist/dynamic/layouts/Level/package.json +1 -1
- package/dist/dynamic/layouts/Split/package.json +1 -1
- package/dist/dynamic/layouts/Stack/package.json +1 -1
- package/dist/dynamic/styles/package.json +1 -1
- package/dist/dynamic-modules.json +1 -0
- package/dist/esm/components/DualListSelector/DualListSelector.d.ts +5 -0
- package/dist/esm/components/DualListSelector/DualListSelector.d.ts.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelector.js +4 -3
- package/dist/esm/components/DualListSelector/DualListSelector.js.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorContext.d.ts +1 -0
- package/dist/esm/components/DualListSelector/DualListSelectorContext.d.ts.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorContext.js +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorContext.js.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorListWrapper.d.ts.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorListWrapper.js +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorListWrapper.js.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorTree.d.ts.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorTree.js +4 -1
- package/dist/esm/components/DualListSelector/DualListSelectorTree.js.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorTreeItem.d.ts +5 -0
- package/dist/esm/components/DualListSelector/DualListSelectorTreeItem.d.ts.map +1 -1
- package/dist/esm/components/DualListSelector/DualListSelectorTreeItem.js +8 -4
- package/dist/esm/components/DualListSelector/DualListSelectorTreeItem.js.map +1 -1
- package/dist/esm/components/Tabs/OverflowTab.d.ts +26 -0
- package/dist/esm/components/Tabs/OverflowTab.d.ts.map +1 -1
- package/dist/esm/components/Tabs/OverflowTab.js +2 -2
- package/dist/esm/components/Tabs/OverflowTab.js.map +1 -1
- package/dist/esm/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/esm/components/Tabs/Tab.js +5 -2
- package/dist/esm/components/Tabs/Tab.js.map +1 -1
- package/dist/esm/components/Tabs/Tabs.d.ts +8 -0
- package/dist/esm/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/esm/components/Tabs/Tabs.js +41 -9
- package/dist/esm/components/Tabs/Tabs.js.map +1 -1
- package/dist/esm/components/Tabs/TabsContext.d.ts +1 -0
- package/dist/esm/components/Tabs/TabsContext.d.ts.map +1 -1
- package/dist/esm/components/Tabs/TabsContext.js +1 -0
- package/dist/esm/components/Tabs/TabsContext.js.map +1 -1
- package/dist/esm/helpers/KeyboardHandler.js +3 -2
- package/dist/esm/helpers/KeyboardHandler.js.map +1 -1
- package/dist/esm/helpers/util.d.ts +10 -0
- package/dist/esm/helpers/util.d.ts.map +1 -1
- package/dist/esm/helpers/util.js +21 -0
- package/dist/esm/helpers/util.js.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelector.d.ts +5 -0
- package/dist/js/components/DualListSelector/DualListSelector.d.ts.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelector.js +4 -3
- package/dist/js/components/DualListSelector/DualListSelector.js.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorContext.d.ts +1 -0
- package/dist/js/components/DualListSelector/DualListSelectorContext.d.ts.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorContext.js +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorContext.js.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorListWrapper.d.ts.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorListWrapper.js +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorListWrapper.js.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorTree.d.ts.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorTree.js +4 -1
- package/dist/js/components/DualListSelector/DualListSelectorTree.js.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorTreeItem.d.ts +5 -0
- package/dist/js/components/DualListSelector/DualListSelectorTreeItem.d.ts.map +1 -1
- package/dist/js/components/DualListSelector/DualListSelectorTreeItem.js +7 -3
- package/dist/js/components/DualListSelector/DualListSelectorTreeItem.js.map +1 -1
- package/dist/js/components/Tabs/OverflowTab.d.ts +26 -0
- package/dist/js/components/Tabs/OverflowTab.d.ts.map +1 -1
- package/dist/js/components/Tabs/OverflowTab.js +2 -2
- package/dist/js/components/Tabs/OverflowTab.js.map +1 -1
- package/dist/js/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/js/components/Tabs/Tab.js +4 -1
- package/dist/js/components/Tabs/Tab.js.map +1 -1
- package/dist/js/components/Tabs/Tabs.d.ts +8 -0
- package/dist/js/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/js/components/Tabs/Tabs.js +40 -8
- package/dist/js/components/Tabs/Tabs.js.map +1 -1
- package/dist/js/components/Tabs/TabsContext.d.ts +1 -0
- package/dist/js/components/Tabs/TabsContext.d.ts.map +1 -1
- package/dist/js/components/Tabs/TabsContext.js +1 -0
- package/dist/js/components/Tabs/TabsContext.js.map +1 -1
- package/dist/js/helpers/KeyboardHandler.js +3 -2
- package/dist/js/helpers/KeyboardHandler.js.map +1 -1
- package/dist/js/helpers/util.d.ts +10 -0
- package/dist/js/helpers/util.d.ts.map +1 -1
- package/dist/js/helpers/util.js +23 -1
- package/dist/js/helpers/util.js.map +1 -1
- package/dist/styles/base-no-reset.css +11 -11
- package/dist/styles/base.css +11 -11
- package/dist/umd/assets/{output-C186DUfw.css → output-CMtXQgdD.css} +19137 -19084
- package/dist/umd/react-core.min.js +2 -2
- package/helpers/package.json +1 -1
- package/layouts/package.json +1 -1
- package/next/package.json +1 -1
- package/package.json +6 -6
- package/src/components/DualListSelector/DualListSelector.tsx +18 -4
- package/src/components/DualListSelector/DualListSelectorContext.ts +2 -1
- package/src/components/DualListSelector/DualListSelectorListWrapper.tsx +8 -5
- package/src/components/DualListSelector/DualListSelectorTree.tsx +4 -0
- package/src/components/DualListSelector/DualListSelectorTreeItem.tsx +17 -2
- package/src/components/DualListSelector/__tests__/DualListSelector.test.tsx +32 -1
- package/src/components/DualListSelector/__tests__/DualListSelectorTreeItem.test.tsx +55 -0
- package/src/components/DualListSelector/examples/DualListSelectorTree.tsx +1 -1
- package/src/components/Tabs/OverflowTab.tsx +29 -0
- package/src/components/Tabs/Tab.tsx +6 -2
- package/src/components/Tabs/Tabs.tsx +70 -11
- package/src/components/Tabs/TabsContext.ts +2 -0
- package/src/components/Tabs/__tests__/Tabs.test.tsx +43 -1
- package/src/components/Tabs/__tests__/__snapshots__/Tabs.test.tsx.snap +39 -26
- package/src/components/Tabs/examples/Tabs.md +1 -1
- package/src/helpers/KeyboardHandler.tsx +2 -2
- package/src/helpers/util.ts +28 -0
package/helpers/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.3.0-prerelease.
|
|
1
|
+
{"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.3.0-prerelease.14","private":true}
|
package/layouts/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.3.0-prerelease.
|
|
1
|
+
{"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.3.0-prerelease.14","private":true}
|
package/next/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.3.0-prerelease.
|
|
1
|
+
{"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.3.0-prerelease.14","private":true}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-core",
|
|
3
|
-
"version": "6.3.0-prerelease.
|
|
3
|
+
"version": "6.3.0-prerelease.15",
|
|
4
4
|
"description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
|
|
5
5
|
"main": "dist/js/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -46,15 +46,15 @@
|
|
|
46
46
|
"subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@patternfly/react-icons": "^6.3.0-prerelease.
|
|
50
|
-
"@patternfly/react-styles": "^6.3.0-prerelease.
|
|
51
|
-
"@patternfly/react-tokens": "^6.3.0-prerelease.
|
|
49
|
+
"@patternfly/react-icons": "^6.3.0-prerelease.3",
|
|
50
|
+
"@patternfly/react-styles": "^6.3.0-prerelease.3",
|
|
51
|
+
"@patternfly/react-tokens": "^6.3.0-prerelease.3",
|
|
52
52
|
"focus-trap": "7.6.4",
|
|
53
53
|
"react-dropzone": "^14.3.5",
|
|
54
54
|
"tslib": "^2.8.1"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@patternfly/patternfly": "6.3.0-prerelease.
|
|
57
|
+
"@patternfly/patternfly": "6.3.0-prerelease.20",
|
|
58
58
|
"case-anything": "^3.1.2",
|
|
59
59
|
"css": "^3.0.0",
|
|
60
60
|
"fs-extra": "^11.3.0"
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"react": "^17 || ^18 || ^19",
|
|
64
64
|
"react-dom": "^17 || ^18 || ^19"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "729b1378613ea903bf81f164699cda93372e821c"
|
|
67
67
|
}
|
|
@@ -17,13 +17,19 @@ export interface DualListSelectorProps {
|
|
|
17
17
|
isTree?: boolean;
|
|
18
18
|
/** Content to be rendered in the dual list selector. */
|
|
19
19
|
children?: React.ReactNode;
|
|
20
|
+
/** Flag indicating whether a tree dual list selector has animations. This will always render
|
|
21
|
+
* nested dual list selector items rather than dynamically rendering them. This prop will be removed in
|
|
22
|
+
* the next breaking change release in favor of defaulting to always-rendered items.
|
|
23
|
+
*/
|
|
24
|
+
hasAnimations?: boolean;
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
class DualListSelector extends Component<DualListSelectorProps> {
|
|
23
28
|
static displayName = 'DualListSelector';
|
|
24
29
|
static defaultProps: PickOptional<DualListSelectorProps> = {
|
|
25
30
|
children: '',
|
|
26
|
-
isTree: false
|
|
31
|
+
isTree: false,
|
|
32
|
+
hasAnimations: false
|
|
27
33
|
};
|
|
28
34
|
|
|
29
35
|
constructor(props: DualListSelectorProps) {
|
|
@@ -31,13 +37,21 @@ class DualListSelector extends Component<DualListSelectorProps> {
|
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
render() {
|
|
34
|
-
const { className, children, id, isTree, ...props } = this.props;
|
|
40
|
+
const { className, children, id, isTree, hasAnimations, ...props } = this.props;
|
|
35
41
|
|
|
36
42
|
return (
|
|
37
|
-
<DualListSelectorContext.Provider value={{ isTree }}>
|
|
43
|
+
<DualListSelectorContext.Provider value={{ isTree, hasAnimations }}>
|
|
38
44
|
<GenerateId>
|
|
39
45
|
{(randomId) => (
|
|
40
|
-
<div
|
|
46
|
+
<div
|
|
47
|
+
className={css(
|
|
48
|
+
styles.dualListSelector,
|
|
49
|
+
hasAnimations && isTree && styles.modifiers.animateExpand,
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
id={id || randomId}
|
|
53
|
+
{...props}
|
|
54
|
+
>
|
|
41
55
|
{children}
|
|
42
56
|
</div>
|
|
43
57
|
)}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createContext } from 'react';
|
|
2
2
|
export const DualListSelectorContext = createContext<{
|
|
3
3
|
isTree?: boolean;
|
|
4
|
-
|
|
4
|
+
hasAnimations?: boolean;
|
|
5
|
+
}>({ isTree: false, hasAnimations: false });
|
|
5
6
|
|
|
6
7
|
export const DualListSelectorListContext = createContext<{
|
|
7
8
|
setFocusedOption?: (id: string) => void;
|
|
@@ -56,14 +56,17 @@ export const DualListSelectorListWrapperBase: React.FunctionComponent<DualListSe
|
|
|
56
56
|
}
|
|
57
57
|
event.stopImmediatePropagation();
|
|
58
58
|
const validOptions = isTree
|
|
59
|
-
? (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
? (
|
|
60
|
+
Array.from(
|
|
61
|
+
menuRef.current.querySelectorAll(
|
|
62
|
+
`.${styles.dualListSelectorItemToggle}, .${styles.dualListSelectorItemCheck} > input`
|
|
63
|
+
)
|
|
64
|
+
) as Element[]
|
|
65
|
+
).filter((item) => !item.closest(`.${styles.dualListSelectorList}[inert]`))
|
|
64
66
|
: (Array.from(menuRef.current.getElementsByTagName('LI')) as Element[]).filter(
|
|
65
67
|
(el) => !el.classList.contains('pf-m-disabled')
|
|
66
68
|
);
|
|
69
|
+
|
|
67
70
|
const activeElement = document.activeElement;
|
|
68
71
|
handleArrows(
|
|
69
72
|
event,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
1
2
|
import { css } from '@patternfly/react-styles';
|
|
2
3
|
import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector';
|
|
4
|
+
import { DualListSelectorContext } from './DualListSelectorContext';
|
|
3
5
|
import { DualListSelectorTreeItem } from './DualListSelectorTreeItem';
|
|
4
6
|
|
|
5
7
|
export interface DualListSelectorTreeItemData {
|
|
@@ -68,11 +70,13 @@ export const DualListSelectorTree: React.FunctionComponent<DualListSelectorTreeP
|
|
|
68
70
|
isDisabled = false,
|
|
69
71
|
...props
|
|
70
72
|
}: DualListSelectorTreeProps) => {
|
|
73
|
+
const { hasAnimations } = useContext(DualListSelectorContext);
|
|
71
74
|
const dataToRender = typeof data === 'function' ? data() : data;
|
|
72
75
|
const tree = dataToRender.map((item) => (
|
|
73
76
|
<DualListSelectorTreeItem
|
|
74
77
|
key={item.id}
|
|
75
78
|
text={item.text}
|
|
79
|
+
hasAnimations={hasAnimations}
|
|
76
80
|
id={item.id}
|
|
77
81
|
defaultExpanded={item.defaultExpanded !== undefined ? item.defaultExpanded : defaultAllExpanded}
|
|
78
82
|
onOptionCheck={onOptionCheck}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { memo, useContext, useEffect, useRef, useState } from 'react';
|
|
1
|
+
import { memo, useContext, useEffect, useRef, useState, cloneElement, Children, isValidElement } from 'react';
|
|
2
2
|
import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector';
|
|
3
3
|
import { css } from '@patternfly/react-styles';
|
|
4
4
|
import { DualListSelectorTreeItemData } from './DualListSelectorTree';
|
|
@@ -38,6 +38,11 @@ export interface DualListSelectorTreeItemProps extends React.HTMLProps<HTMLLIEle
|
|
|
38
38
|
isDisabled?: boolean;
|
|
39
39
|
/** Flag indicating the DualListSelector tree should utilize memoization to help render large data sets. */
|
|
40
40
|
useMemo?: boolean;
|
|
41
|
+
/** Flag indicating whether a tree dual list selector has animations. This will always render
|
|
42
|
+
* nested dual list selector items rather than dynamically rendering them. This prop will be removed in
|
|
43
|
+
* the next breaking change release in favor of defaulting to always-rendered items.
|
|
44
|
+
*/
|
|
45
|
+
hasAnimations?: boolean;
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
const DualListSelectorTreeItemBase: React.FunctionComponent<DualListSelectorTreeItemProps> = ({
|
|
@@ -53,6 +58,7 @@ const DualListSelectorTreeItemBase: React.FunctionComponent<DualListSelectorTree
|
|
|
53
58
|
badgeProps,
|
|
54
59
|
itemData,
|
|
55
60
|
isDisabled = false,
|
|
61
|
+
hasAnimations,
|
|
56
62
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
57
63
|
useMemo,
|
|
58
64
|
...props
|
|
@@ -65,6 +71,15 @@ const DualListSelectorTreeItemBase: React.FunctionComponent<DualListSelectorTree
|
|
|
65
71
|
setIsExpanded(defaultExpanded);
|
|
66
72
|
}, [defaultExpanded]);
|
|
67
73
|
|
|
74
|
+
const clonedChildren = Children.map(
|
|
75
|
+
children,
|
|
76
|
+
(child) =>
|
|
77
|
+
isValidElement(child) &&
|
|
78
|
+
cloneElement(child as React.ReactElement<any>, {
|
|
79
|
+
inert: isExpanded ? undefined : ''
|
|
80
|
+
})
|
|
81
|
+
);
|
|
82
|
+
|
|
68
83
|
return (
|
|
69
84
|
<li
|
|
70
85
|
className={css(
|
|
@@ -156,7 +171,7 @@ const DualListSelectorTreeItemBase: React.FunctionComponent<DualListSelectorTree
|
|
|
156
171
|
</span>
|
|
157
172
|
</div>
|
|
158
173
|
</div>
|
|
159
|
-
{isExpanded &&
|
|
174
|
+
{(isExpanded || hasAnimations) && clonedChildren}
|
|
160
175
|
</li>
|
|
161
176
|
);
|
|
162
177
|
};
|
|
@@ -1,6 +1,37 @@
|
|
|
1
|
-
import { render } from '@testing-library/react';
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector';
|
|
3
|
+
import { DualListSelector } from '../DualListSelector';
|
|
2
4
|
import { DualListSelectorPane } from '../DualListSelectorPane';
|
|
3
5
|
import { SearchInput } from '../../SearchInput';
|
|
6
|
+
|
|
7
|
+
// The following tests can be removed as part of https://github.com/patternfly/patternfly-react/issues/11838
|
|
8
|
+
describe('Opt-in animations', () => {
|
|
9
|
+
test(`Does not render with class ${styles.modifiers.animateExpand} by default`, () => {
|
|
10
|
+
render(<DualListSelector data-testid="test-id" />);
|
|
11
|
+
|
|
12
|
+
expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test(`Does not render with class ${styles.modifiers.animateExpand} when hasAnimations is true and isTree is false`, () => {
|
|
16
|
+
render(<DualListSelector hasAnimations data-testid="test-id" />);
|
|
17
|
+
|
|
18
|
+
expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test(`Does not render with class ${styles.modifiers.animateExpand} by default when isTree is true`, () => {
|
|
22
|
+
render(<DualListSelector isTree data-testid="test-id" />);
|
|
23
|
+
|
|
24
|
+
expect(screen.getByTestId('test-id')).not.toHaveClass(styles.modifiers.animateExpand);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test(`Renders with class ${styles.modifiers.animateExpand} when both isTree and hasAnimations are true`, () => {
|
|
28
|
+
render(<DualListSelector isTree hasAnimations data-testid="test-id" />);
|
|
29
|
+
|
|
30
|
+
expect(screen.getByTestId('test-id')).toHaveClass(styles.modifiers.animateExpand);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Following tests should be moved to a separate DualListSelectorPane test file
|
|
4
35
|
describe('DualListSelector', () => {
|
|
5
36
|
test('basic', () => {
|
|
6
37
|
const { asFragment } = render(<DualListSelectorPane id="basicTest" />);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import styles from '@patternfly/react-styles/css/components/DualListSelector/dual-list-selector';
|
|
3
|
+
import { DualListSelectorTreeItem } from '../DualListSelectorTreeItem';
|
|
4
|
+
|
|
5
|
+
// The following tests checking for children to not be/to be rendered will need to be refactored
|
|
6
|
+
// as part of https://github.com/patternfly/patternfly-react/issues/11838
|
|
7
|
+
test('Does not render children by default', () => {
|
|
8
|
+
render(
|
|
9
|
+
<DualListSelectorTreeItem id="item-id" text="Test text">
|
|
10
|
+
<div>Children content</div>
|
|
11
|
+
</DualListSelectorTreeItem>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
expect(screen.queryByText('Children content')).not.toBeInTheDocument();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('Renders children when defaultExpanded is true', () => {
|
|
18
|
+
render(
|
|
19
|
+
<DualListSelectorTreeItem defaultExpanded id="item-id" text="Test text">
|
|
20
|
+
<div>Children content</div>
|
|
21
|
+
</DualListSelectorTreeItem>
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
expect(screen.getByText('Children content')).toBeVisible();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('Renders children when hasAnimations is true', () => {
|
|
28
|
+
render(
|
|
29
|
+
<DualListSelectorTreeItem hasAnimations id="item-id" text="Test text">
|
|
30
|
+
<div>Children content</div>
|
|
31
|
+
</DualListSelectorTreeItem>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(screen.getByText('Children content')).toBeVisible();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('Renders children with inert attribute by default when hasAnimations is true', () => {
|
|
38
|
+
render(
|
|
39
|
+
<DualListSelectorTreeItem hasAnimations id="item-id" text="Test text">
|
|
40
|
+
<div>Children content</div>
|
|
41
|
+
</DualListSelectorTreeItem>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
expect(screen.getByText('Children content')).toHaveAttribute('inert', '');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('Does not render children with inert attribute when hasAnimations and defaultExpanded are true', () => {
|
|
48
|
+
render(
|
|
49
|
+
<DualListSelectorTreeItem hasAnimations defaultExpanded id="item-id" text="Test text">
|
|
50
|
+
<div>Children content</div>
|
|
51
|
+
</DualListSelectorTreeItem>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(screen.getByText('Children content')).not.toHaveAttribute('inert');
|
|
55
|
+
});
|
|
@@ -283,7 +283,7 @@ export const DualListSelectorComposableTree: React.FunctionComponent<ExampleProp
|
|
|
283
283
|
};
|
|
284
284
|
|
|
285
285
|
return (
|
|
286
|
-
<DualListSelector isTree>
|
|
286
|
+
<DualListSelector hasAnimations isTree>
|
|
287
287
|
{buildPane(false)}
|
|
288
288
|
<DualListSelectorControlsWrapper>
|
|
289
289
|
<DualListSelectorControl
|
|
@@ -8,6 +8,31 @@ import { TabsContext } from './TabsContext';
|
|
|
8
8
|
import { TabProps } from './Tab';
|
|
9
9
|
import { TabTitleText } from './TabTitleText';
|
|
10
10
|
|
|
11
|
+
export interface HorizontalOverflowPopperProps {
|
|
12
|
+
/** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */
|
|
13
|
+
direction?: 'up' | 'down';
|
|
14
|
+
/** Horizontal position of the popper */
|
|
15
|
+
position?: 'right' | 'left' | 'center' | 'start' | 'end';
|
|
16
|
+
/** Custom width of the popper. If the value is "trigger", it will set the width to the select toggle's width */
|
|
17
|
+
width?: string | 'trigger';
|
|
18
|
+
/** Minimum width of the popper. If the value is "trigger", it will set the min width to the select toggle's width */
|
|
19
|
+
minWidth?: string | 'trigger';
|
|
20
|
+
/** Maximum width of the popper. If the value is "trigger", it will set the max width to the select toggle's width */
|
|
21
|
+
maxWidth?: string | 'trigger';
|
|
22
|
+
/** Enable to flip the popper when it reaches the boundary */
|
|
23
|
+
enableFlip?: boolean;
|
|
24
|
+
/** The container to append the select to. Defaults to document.body.
|
|
25
|
+
* If your select is being cut off you can append it to an element higher up the DOM tree.
|
|
26
|
+
* Some examples:
|
|
27
|
+
* appendTo="inline"
|
|
28
|
+
* appendTo={() => document.body}
|
|
29
|
+
* appendTo={document.getElementById('target')}
|
|
30
|
+
*/
|
|
31
|
+
appendTo?: HTMLElement | (() => HTMLElement) | 'inline';
|
|
32
|
+
/** Flag to prevent the popper from overflowing its container and becoming partially obscured. */
|
|
33
|
+
preventOverflow?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
11
36
|
export interface OverflowTabProps extends React.HTMLProps<HTMLLIElement> {
|
|
12
37
|
/** Additional classes added to the overflow tab */
|
|
13
38
|
className?: string;
|
|
@@ -25,6 +50,8 @@ export interface OverflowTabProps extends React.HTMLProps<HTMLLIElement> {
|
|
|
25
50
|
shouldPreventScrollOnItemFocus?: boolean;
|
|
26
51
|
/** Time in ms to wait before firing the toggles' focus event. Defaults to 0 */
|
|
27
52
|
focusTimeoutDelay?: number;
|
|
53
|
+
/** Additional props to spread to the popper menu. */
|
|
54
|
+
popperProps?: HorizontalOverflowPopperProps;
|
|
28
55
|
}
|
|
29
56
|
|
|
30
57
|
export const OverflowTab: React.FunctionComponent<OverflowTabProps> = ({
|
|
@@ -36,6 +63,7 @@ export const OverflowTab: React.FunctionComponent<OverflowTabProps> = ({
|
|
|
36
63
|
zIndex = 9999,
|
|
37
64
|
shouldPreventScrollOnItemFocus = true,
|
|
38
65
|
focusTimeoutDelay = 0,
|
|
66
|
+
popperProps,
|
|
39
67
|
...props
|
|
40
68
|
}: OverflowTabProps) => {
|
|
41
69
|
const menuRef = useRef<HTMLDivElement>(undefined);
|
|
@@ -148,6 +176,7 @@ export const OverflowTab: React.FunctionComponent<OverflowTabProps> = ({
|
|
|
148
176
|
minWidth="revert"
|
|
149
177
|
appendTo={overflowLIRef.current}
|
|
150
178
|
zIndex={zIndex}
|
|
179
|
+
{...popperProps}
|
|
151
180
|
/>
|
|
152
181
|
</Fragment>
|
|
153
182
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useContext, forwardRef } from 'react';
|
|
1
|
+
import { useContext, forwardRef, useEffect } from 'react';
|
|
2
2
|
import styles from '@patternfly/react-styles/css/components/Tabs/tabs';
|
|
3
3
|
import { OUIAProps } from '../../helpers';
|
|
4
4
|
import { TabButton } from './TabButton';
|
|
@@ -75,7 +75,7 @@ const TabBase: React.FunctionComponent<TabProps> = ({
|
|
|
75
75
|
}),
|
|
76
76
|
{}
|
|
77
77
|
);
|
|
78
|
-
const { mountOnEnter, localActiveKey, unmountOnExit, uniqueId, handleTabClick, handleTabClose } =
|
|
78
|
+
const { mountOnEnter, localActiveKey, unmountOnExit, uniqueId, setAccentStyles, handleTabClick, handleTabClose } =
|
|
79
79
|
useContext(TabsContext);
|
|
80
80
|
let ariaControls = tabContentId ? `${tabContentId}` : `pf-tab-section-${eventKey}-${childId || uniqueId}`;
|
|
81
81
|
if ((mountOnEnter || unmountOnExit) && eventKey !== localActiveKey) {
|
|
@@ -116,6 +116,10 @@ const TabBase: React.FunctionComponent<TabProps> = ({
|
|
|
116
116
|
</TabButton>
|
|
117
117
|
);
|
|
118
118
|
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
setAccentStyles(true);
|
|
121
|
+
}, [title, actions]);
|
|
122
|
+
|
|
119
123
|
return (
|
|
120
124
|
<li
|
|
121
125
|
className={css(
|
|
@@ -5,20 +5,27 @@ import { PickOptional } from '../../helpers/typeUtils';
|
|
|
5
5
|
import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-icon';
|
|
6
6
|
import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
|
|
7
7
|
import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getUniqueId,
|
|
10
|
+
isElementInView,
|
|
11
|
+
formatBreakpointMods,
|
|
12
|
+
getLanguageDirection,
|
|
13
|
+
getInlineStartProperty
|
|
14
|
+
} from '../../helpers/util';
|
|
9
15
|
import { TabContent } from './TabContent';
|
|
10
16
|
import { TabProps } from './Tab';
|
|
11
17
|
import { TabsContextProvider } from './TabsContext';
|
|
12
|
-
import { OverflowTab } from './OverflowTab';
|
|
18
|
+
import { OverflowTab, HorizontalOverflowPopperProps } from './OverflowTab';
|
|
13
19
|
import { Button } from '../Button';
|
|
14
20
|
import { getOUIAProps, OUIAProps, getDefaultOUIAId, canUseDOM } from '../../helpers';
|
|
15
21
|
import { GenerateId } from '../../helpers/GenerateId/GenerateId';
|
|
22
|
+
import linkAccentLength from '@patternfly/react-tokens/dist/esm/c_tabs_link_accent_length';
|
|
23
|
+
import linkAccentStart from '@patternfly/react-tokens/dist/esm/c_tabs_link_accent_start';
|
|
16
24
|
|
|
17
25
|
export enum TabsComponent {
|
|
18
26
|
div = 'div',
|
|
19
27
|
nav = 'nav'
|
|
20
28
|
}
|
|
21
|
-
|
|
22
29
|
export interface HorizontalOverflowObject {
|
|
23
30
|
/** Flag which shows the count of overflowing tabs when enabled */
|
|
24
31
|
showTabCount?: boolean;
|
|
@@ -26,6 +33,8 @@ export interface HorizontalOverflowObject {
|
|
|
26
33
|
defaultTitleText?: string;
|
|
27
34
|
/** The aria label applied to the button which toggles the tab overflow menu */
|
|
28
35
|
toggleAriaLabel?: string;
|
|
36
|
+
/** Additional props to spread to the popper menu. */
|
|
37
|
+
popperProps?: HorizontalOverflowPopperProps;
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
type TabElement = React.ReactElement<TabProps, React.JSXElementConstructor<TabProps>>;
|
|
@@ -139,6 +148,9 @@ interface TabsState {
|
|
|
139
148
|
uncontrolledIsExpandedLocal: boolean;
|
|
140
149
|
ouiaStateId: string;
|
|
141
150
|
overflowingTabCount: number;
|
|
151
|
+
isInitializingAccent: boolean;
|
|
152
|
+
currentLinkAccentLength: string;
|
|
153
|
+
currentLinkAccentStart: string;
|
|
142
154
|
}
|
|
143
155
|
|
|
144
156
|
class Tabs extends Component<TabsProps, TabsState> {
|
|
@@ -158,7 +170,10 @@ class Tabs extends Component<TabsProps, TabsState> {
|
|
|
158
170
|
uncontrolledActiveKey: this.props.defaultActiveKey,
|
|
159
171
|
uncontrolledIsExpandedLocal: this.props.defaultIsExpanded,
|
|
160
172
|
ouiaStateId: getDefaultOUIAId(Tabs.displayName),
|
|
161
|
-
overflowingTabCount: 0
|
|
173
|
+
overflowingTabCount: 0,
|
|
174
|
+
isInitializingAccent: true,
|
|
175
|
+
currentLinkAccentLength: linkAccentLength.value,
|
|
176
|
+
currentLinkAccentStart: linkAccentStart.value
|
|
162
177
|
};
|
|
163
178
|
|
|
164
179
|
if (this.props.isVertical && this.props.expandable !== undefined) {
|
|
@@ -328,21 +343,49 @@ class Tabs extends Component<TabsProps, TabsState> {
|
|
|
328
343
|
}
|
|
329
344
|
};
|
|
330
345
|
|
|
346
|
+
setAccentStyles = (shouldInitializeStyle?: boolean) => {
|
|
347
|
+
const currentItem = this.tabList.current.querySelector('li.pf-m-current') as HTMLElement;
|
|
348
|
+
if (!currentItem) {
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const { isVertical } = this.props;
|
|
353
|
+
const { offsetWidth, offsetHeight, offsetTop } = currentItem;
|
|
354
|
+
const lengthValue = isVertical ? offsetHeight : offsetWidth;
|
|
355
|
+
const startValue = isVertical ? offsetTop : getInlineStartProperty(currentItem, this.tabList.current);
|
|
356
|
+
this.setState({
|
|
357
|
+
currentLinkAccentLength: `${lengthValue}px`,
|
|
358
|
+
currentLinkAccentStart: `${startValue}px`,
|
|
359
|
+
...(shouldInitializeStyle && { isInitializingAccent: true })
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
setTimeout(() => {
|
|
363
|
+
this.setState({ isInitializingAccent: false });
|
|
364
|
+
}, 0);
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
handleResize = () => {
|
|
368
|
+
this.handleScrollButtons();
|
|
369
|
+
this.setAccentStyles();
|
|
370
|
+
};
|
|
371
|
+
|
|
331
372
|
componentDidMount() {
|
|
332
373
|
if (!this.props.isVertical) {
|
|
333
374
|
if (canUseDOM) {
|
|
334
|
-
window.addEventListener('resize', this.
|
|
375
|
+
window.addEventListener('resize', this.handleResize, false);
|
|
335
376
|
}
|
|
336
377
|
this.direction = getLanguageDirection(this.tabList.current);
|
|
337
378
|
// call the handle resize function to check if scroll buttons should be shown
|
|
338
379
|
this.handleScrollButtons();
|
|
339
380
|
}
|
|
381
|
+
|
|
382
|
+
this.setAccentStyles(true);
|
|
340
383
|
}
|
|
341
384
|
|
|
342
385
|
componentWillUnmount() {
|
|
343
386
|
if (!this.props.isVertical) {
|
|
344
387
|
if (canUseDOM) {
|
|
345
|
-
window.removeEventListener('resize', this.
|
|
388
|
+
window.removeEventListener('resize', this.handleResize, false);
|
|
346
389
|
}
|
|
347
390
|
}
|
|
348
391
|
clearTimeout(this.scrollTimeout);
|
|
@@ -350,8 +393,18 @@ class Tabs extends Component<TabsProps, TabsState> {
|
|
|
350
393
|
}
|
|
351
394
|
|
|
352
395
|
componentDidUpdate(prevProps: TabsProps, prevState: TabsState) {
|
|
353
|
-
|
|
354
|
-
const {
|
|
396
|
+
this.direction = getLanguageDirection(this.tabList.current);
|
|
397
|
+
const { activeKey, mountOnEnter, isOverflowHorizontal, children, defaultActiveKey } = this.props;
|
|
398
|
+
const { shownKeys, overflowingTabCount, enableScrollButtons, uncontrolledActiveKey } = this.state;
|
|
399
|
+
const isOnCloseUpdate = !!prevProps.onClose !== !!this.props.onClose;
|
|
400
|
+
if (
|
|
401
|
+
(defaultActiveKey !== undefined && prevState.uncontrolledActiveKey !== uncontrolledActiveKey) ||
|
|
402
|
+
(defaultActiveKey === undefined && prevProps.activeKey !== activeKey) ||
|
|
403
|
+
isOnCloseUpdate
|
|
404
|
+
) {
|
|
405
|
+
this.setAccentStyles(isOnCloseUpdate);
|
|
406
|
+
}
|
|
407
|
+
|
|
355
408
|
if (prevProps.activeKey !== activeKey && mountOnEnter && shownKeys.indexOf(activeKey) < 0) {
|
|
356
409
|
this.setState({
|
|
357
410
|
shownKeys: shownKeys.concat(activeKey)
|
|
@@ -364,6 +417,7 @@ class Tabs extends Component<TabsProps, TabsState> {
|
|
|
364
417
|
Children.toArray(prevProps.children).length !== Children.toArray(children).length
|
|
365
418
|
) {
|
|
366
419
|
this.handleScrollButtons();
|
|
420
|
+
this.setAccentStyles(true);
|
|
367
421
|
}
|
|
368
422
|
|
|
369
423
|
const currentOverflowingTabCount = this.countOverflowingElements(this.tabList.current);
|
|
@@ -380,8 +434,6 @@ class Tabs extends Component<TabsProps, TabsState> {
|
|
|
380
434
|
} else if (prevState.enableScrollButtons && !enableScrollButtons) {
|
|
381
435
|
this.setState({ showScrollButtons: false });
|
|
382
436
|
}
|
|
383
|
-
|
|
384
|
-
this.direction = getLanguageDirection(this.tabList.current);
|
|
385
437
|
}
|
|
386
438
|
|
|
387
439
|
static getDerivedStateFromProps(nextProps: TabsProps, prevState: TabsState) {
|
|
@@ -450,7 +502,10 @@ class Tabs extends Component<TabsProps, TabsState> {
|
|
|
450
502
|
shownKeys,
|
|
451
503
|
uncontrolledActiveKey,
|
|
452
504
|
uncontrolledIsExpandedLocal,
|
|
453
|
-
overflowingTabCount
|
|
505
|
+
overflowingTabCount,
|
|
506
|
+
isInitializingAccent,
|
|
507
|
+
currentLinkAccentLength,
|
|
508
|
+
currentLinkAccentStart
|
|
454
509
|
} = this.state;
|
|
455
510
|
const filteredChildren = Children.toArray(children)
|
|
456
511
|
.filter((child): child is TabElement => isValidElement(child))
|
|
@@ -485,6 +540,7 @@ class Tabs extends Component<TabsProps, TabsState> {
|
|
|
485
540
|
unmountOnExit,
|
|
486
541
|
localActiveKey,
|
|
487
542
|
uniqueId,
|
|
543
|
+
setAccentStyles: this.setAccentStyles,
|
|
488
544
|
handleTabClick: (...args) => this.handleTabClick(...args),
|
|
489
545
|
handleTabClose: onClose
|
|
490
546
|
}}
|
|
@@ -493,6 +549,7 @@ class Tabs extends Component<TabsProps, TabsState> {
|
|
|
493
549
|
aria-label={ariaLabel}
|
|
494
550
|
className={css(
|
|
495
551
|
styles.tabs,
|
|
552
|
+
styles.modifiers.animateCurrent,
|
|
496
553
|
isFilled && styles.modifiers.fill,
|
|
497
554
|
isSubtab && styles.modifiers.subtab,
|
|
498
555
|
isVertical && styles.modifiers.vertical,
|
|
@@ -505,10 +562,12 @@ class Tabs extends Component<TabsProps, TabsState> {
|
|
|
505
562
|
formatBreakpointMods(inset, styles),
|
|
506
563
|
variantStyle[variant],
|
|
507
564
|
hasOverflowTab && styles.modifiers.overflow,
|
|
565
|
+
isInitializingAccent && styles.modifiers.initializingAccent,
|
|
508
566
|
className
|
|
509
567
|
)}
|
|
510
568
|
{...getOUIAProps(Tabs.displayName, ouiaId !== undefined ? ouiaId : this.state.ouiaStateId, ouiaSafe)}
|
|
511
569
|
id={id && id}
|
|
570
|
+
style={{ [linkAccentLength.name]: currentLinkAccentLength, [linkAccentStart.name]: currentLinkAccentStart }}
|
|
512
571
|
{...props}
|
|
513
572
|
>
|
|
514
573
|
{expandable && isVertical && (
|
|
@@ -6,6 +6,7 @@ export interface TabsContextProps {
|
|
|
6
6
|
unmountOnExit: boolean;
|
|
7
7
|
localActiveKey: string | number;
|
|
8
8
|
uniqueId: string;
|
|
9
|
+
setAccentStyles: (shouldInitializeStyles?: boolean) => void;
|
|
9
10
|
handleTabClick: (
|
|
10
11
|
event: React.MouseEvent<HTMLElement, MouseEvent>,
|
|
11
12
|
eventKey: number | string,
|
|
@@ -24,6 +25,7 @@ export const TabsContext = createContext<TabsContextProps>({
|
|
|
24
25
|
unmountOnExit: false,
|
|
25
26
|
localActiveKey: '',
|
|
26
27
|
uniqueId: '',
|
|
28
|
+
setAccentStyles: () => null,
|
|
27
29
|
handleTabClick: () => null,
|
|
28
30
|
handleTabClose: undefined
|
|
29
31
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { render, screen } from '@testing-library/react';
|
|
1
|
+
import { render, screen, act } from '@testing-library/react';
|
|
2
2
|
import { Tabs } from '../Tabs';
|
|
3
|
+
import styles from '@patternfly/react-styles/css/components/Tabs/tabs';
|
|
3
4
|
import { Tab } from '../Tab';
|
|
4
5
|
import { TabTitleText } from '../TabTitleText';
|
|
5
6
|
import { TabTitleIcon } from '../TabTitleIcon';
|
|
@@ -8,6 +9,47 @@ import { TabContentBody } from '../TabContentBody';
|
|
|
8
9
|
|
|
9
10
|
jest.mock('../../../helpers/GenerateId/GenerateId');
|
|
10
11
|
|
|
12
|
+
test(`Renders with classes ${styles.tabs} and ${styles.modifiers.animateCurrent} by default`, () => {
|
|
13
|
+
render(
|
|
14
|
+
<Tabs role="region">
|
|
15
|
+
<Tab title="Test title" eventKey={0}>
|
|
16
|
+
Tab Content
|
|
17
|
+
</Tab>
|
|
18
|
+
</Tabs>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
expect(screen.getByRole('region')).toHaveClass(`${styles.tabs} ${styles.modifiers.animateCurrent}`);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test(`Renders with class ${styles.modifiers.initializingAccent} when component initially mounts`, () => {
|
|
25
|
+
render(
|
|
26
|
+
<Tabs role="region">
|
|
27
|
+
<Tab title="Test title" eventKey={0}>
|
|
28
|
+
Tab Content
|
|
29
|
+
</Tab>
|
|
30
|
+
</Tabs>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
expect(screen.getByRole('region')).toHaveClass(styles.modifiers.initializingAccent);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test(`Does not render with class ${styles.modifiers.initializingAccent} when component is finished mounting`, () => {
|
|
37
|
+
jest.useFakeTimers();
|
|
38
|
+
render(
|
|
39
|
+
<Tabs role="region">
|
|
40
|
+
<Tab title="Test title" eventKey={0}>
|
|
41
|
+
Tab Content
|
|
42
|
+
</Tab>
|
|
43
|
+
</Tabs>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
act(() => {
|
|
47
|
+
jest.advanceTimersByTime(500);
|
|
48
|
+
});
|
|
49
|
+
expect(screen.getByRole('region')).not.toHaveClass(styles.modifiers.initializingAccent);
|
|
50
|
+
jest.useRealTimers();
|
|
51
|
+
});
|
|
52
|
+
|
|
11
53
|
test('should render simple tabs', () => {
|
|
12
54
|
const { asFragment } = render(
|
|
13
55
|
<Tabs id="simpleTabs">
|