@patternfly/react-core 4.234.3 → 4.235.1
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 +27 -0
- package/dist/esm/next/components/Wizard/Wizard.d.ts +40 -0
- package/dist/esm/next/components/Wizard/Wizard.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/Wizard.js +86 -0
- package/dist/esm/next/components/Wizard/Wizard.js.map +1 -0
- package/dist/esm/next/components/Wizard/WizardBody.d.ts +20 -0
- package/dist/esm/next/components/Wizard/WizardBody.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/WizardBody.js +7 -0
- package/dist/esm/next/components/Wizard/WizardBody.js.map +1 -0
- package/dist/esm/next/components/Wizard/WizardContext.d.ts +49 -0
- package/dist/esm/next/components/Wizard/WizardContext.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/WizardContext.js +34 -0
- package/dist/esm/next/components/Wizard/WizardContext.js.map +1 -0
- package/dist/esm/next/components/Wizard/WizardFooter.d.ts +28 -0
- package/dist/esm/next/components/Wizard/WizardFooter.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/WizardFooter.js +11 -0
- package/dist/esm/next/components/Wizard/WizardFooter.js.map +1 -0
- package/dist/esm/next/components/Wizard/WizardHeader.d.ts +21 -0
- package/dist/esm/next/components/Wizard/WizardHeader.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/WizardHeader.js +13 -0
- package/dist/esm/next/components/Wizard/WizardHeader.js.map +1 -0
- package/dist/esm/next/components/Wizard/WizardNav.d.ts +15 -0
- package/dist/esm/next/components/Wizard/WizardNav.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/WizardNav.js +13 -0
- package/dist/esm/next/components/Wizard/WizardNav.js.map +1 -0
- package/dist/esm/next/components/Wizard/WizardNavItem.d.ts +25 -0
- package/dist/esm/next/components/Wizard/WizardNavItem.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/WizardNavItem.js +33 -0
- package/dist/esm/next/components/Wizard/WizardNavItem.js.map +1 -0
- package/dist/esm/next/components/Wizard/WizardStep.d.ts +20 -0
- package/dist/esm/next/components/Wizard/WizardStep.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/WizardStep.js +5 -0
- package/dist/esm/next/components/Wizard/WizardStep.js.map +1 -0
- package/dist/esm/next/components/Wizard/WizardToggle.d.ts +26 -0
- package/dist/esm/next/components/Wizard/WizardToggle.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/WizardToggle.js +81 -0
- package/dist/esm/next/components/Wizard/WizardToggle.js.map +1 -0
- package/dist/esm/next/components/Wizard/hooks/index.d.ts +2 -0
- package/dist/esm/next/components/Wizard/hooks/index.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/hooks/index.js +2 -0
- package/dist/esm/next/components/Wizard/hooks/index.js.map +1 -0
- package/dist/esm/next/components/Wizard/hooks/useWizardFooter.d.ts +8 -0
- package/dist/esm/next/components/Wizard/hooks/useWizardFooter.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/hooks/useWizardFooter.js +20 -0
- package/dist/esm/next/components/Wizard/hooks/useWizardFooter.js.map +1 -0
- package/dist/esm/next/components/Wizard/index.d.ts +12 -0
- package/dist/esm/next/components/Wizard/index.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/index.js +12 -0
- package/dist/esm/next/components/Wizard/index.js.map +1 -0
- package/dist/esm/next/components/Wizard/types.d.ts +69 -0
- package/dist/esm/next/components/Wizard/types.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/types.js +20 -0
- package/dist/esm/next/components/Wizard/types.js.map +1 -0
- package/dist/esm/next/components/Wizard/utils.d.ts +15 -0
- package/dist/esm/next/components/Wizard/utils.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/utils.js +35 -0
- package/dist/esm/next/components/Wizard/utils.js.map +1 -0
- package/dist/esm/next/components/index.d.ts +1 -1
- package/dist/esm/next/components/index.d.ts.map +1 -1
- package/dist/esm/next/components/index.js +1 -1
- package/dist/esm/next/components/index.js.map +1 -1
- package/dist/js/next/components/Wizard/Wizard.d.ts +40 -0
- package/dist/js/next/components/Wizard/Wizard.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/Wizard.js +90 -0
- package/dist/js/next/components/Wizard/Wizard.js.map +1 -0
- package/dist/js/next/components/Wizard/WizardBody.d.ts +20 -0
- package/dist/js/next/components/Wizard/WizardBody.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/WizardBody.js +12 -0
- package/dist/js/next/components/Wizard/WizardBody.js.map +1 -0
- package/dist/js/next/components/Wizard/WizardContext.d.ts +49 -0
- package/dist/js/next/components/Wizard/WizardContext.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/WizardContext.js +40 -0
- package/dist/js/next/components/Wizard/WizardContext.js.map +1 -0
- package/dist/js/next/components/Wizard/WizardFooter.d.ts +28 -0
- package/dist/js/next/components/Wizard/WizardFooter.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/WizardFooter.js +16 -0
- package/dist/js/next/components/Wizard/WizardFooter.js.map +1 -0
- package/dist/js/next/components/Wizard/WizardHeader.d.ts +21 -0
- package/dist/js/next/components/Wizard/WizardHeader.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/WizardHeader.js +18 -0
- package/dist/js/next/components/Wizard/WizardHeader.js.map +1 -0
- package/dist/js/next/components/Wizard/WizardNav.d.ts +15 -0
- package/dist/js/next/components/Wizard/WizardNav.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/WizardNav.js +18 -0
- package/dist/js/next/components/Wizard/WizardNav.js.map +1 -0
- package/dist/js/next/components/Wizard/WizardNavItem.d.ts +25 -0
- package/dist/js/next/components/Wizard/WizardNavItem.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/WizardNavItem.js +37 -0
- package/dist/js/next/components/Wizard/WizardNavItem.js.map +1 -0
- package/dist/js/next/components/Wizard/WizardStep.d.ts +20 -0
- package/dist/js/next/components/Wizard/WizardStep.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/WizardStep.js +10 -0
- package/dist/js/next/components/Wizard/WizardStep.js.map +1 -0
- package/dist/js/next/components/Wizard/WizardToggle.d.ts +26 -0
- package/dist/js/next/components/Wizard/WizardToggle.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/WizardToggle.js +86 -0
- package/dist/js/next/components/Wizard/WizardToggle.js.map +1 -0
- package/dist/js/next/components/Wizard/hooks/index.d.ts +2 -0
- package/dist/js/next/components/Wizard/hooks/index.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/hooks/index.js +6 -0
- package/dist/js/next/components/Wizard/hooks/index.js.map +1 -0
- package/dist/js/next/components/Wizard/hooks/useWizardFooter.d.ts +8 -0
- package/dist/js/next/components/Wizard/hooks/useWizardFooter.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/hooks/useWizardFooter.js +25 -0
- package/dist/js/next/components/Wizard/hooks/useWizardFooter.js.map +1 -0
- package/dist/js/next/components/Wizard/index.d.ts +12 -0
- package/dist/js/next/components/Wizard/index.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/index.js +17 -0
- package/dist/js/next/components/Wizard/index.js.map +1 -0
- package/dist/js/next/components/Wizard/types.d.ts +69 -0
- package/dist/js/next/components/Wizard/types.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/types.js +29 -0
- package/dist/js/next/components/Wizard/types.js.map +1 -0
- package/dist/js/next/components/Wizard/utils.d.ts +15 -0
- package/dist/js/next/components/Wizard/utils.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/utils.js +41 -0
- package/dist/js/next/components/Wizard/utils.js.map +1 -0
- package/dist/js/next/components/index.d.ts +1 -1
- package/dist/js/next/components/index.d.ts.map +1 -1
- package/dist/js/next/components/index.js +1 -1
- package/dist/js/next/components/index.js.map +1 -1
- package/dist/umd/react-core.css +230 -230
- package/dist/umd/react-core.min.css +734 -734
- package/package.json +5 -5
- package/src/components/Card/examples/Card.md +67 -38
- package/src/components/Wizard/examples/Wizard.md +21 -4
- package/src/demos/CardDemos.md +4 -0
- package/src/next/components/Wizard/Wizard.tsx +184 -0
- package/src/next/components/Wizard/WizardBody.tsx +34 -0
- package/src/next/components/Wizard/WizardContext.tsx +104 -0
- package/src/next/components/Wizard/WizardFooter.tsx +63 -0
- package/src/next/components/Wizard/WizardHeader.tsx +53 -0
- package/src/next/components/Wizard/WizardNav.tsx +41 -0
- package/src/next/components/Wizard/WizardNavItem.tsx +103 -0
- package/src/next/components/Wizard/WizardStep.tsx +23 -0
- package/src/next/components/Wizard/WizardToggle.tsx +209 -0
- package/src/next/components/Wizard/__tests__/Wizard.test.tsx +298 -0
- package/src/next/components/Wizard/examples/Wizard.md +125 -0
- package/src/next/components/Wizard/examples/WizardBasic.tsx +22 -0
- package/src/next/components/Wizard/examples/WizardCustomNav.tsx +46 -0
- package/src/next/components/Wizard/examples/WizardKitchenSink.tsx +170 -0
- package/src/next/components/Wizard/hooks/index.ts +1 -0
- package/src/next/components/Wizard/hooks/useWizardFooter.tsx +22 -0
- package/src/next/components/Wizard/index.ts +11 -0
- package/src/next/components/Wizard/types.tsx +101 -0
- package/src/next/components/Wizard/utils.ts +47 -0
- package/src/next/components/index.ts +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import styles from '@patternfly/react-styles/css/components/Wizard/wizard';
|
|
3
|
+
import { css } from '@patternfly/react-styles';
|
|
4
|
+
import { Button } from '../../../components/Button';
|
|
5
|
+
import { Title } from '../../../components/Title';
|
|
6
|
+
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
|
|
7
|
+
|
|
8
|
+
export interface WizardHeaderProps {
|
|
9
|
+
/** Callback function called when the X (Close) button is clicked */
|
|
10
|
+
onClose?: () => void;
|
|
11
|
+
/** Title of the wizard */
|
|
12
|
+
title: string;
|
|
13
|
+
/** Description of the wizard */
|
|
14
|
+
description?: React.ReactNode;
|
|
15
|
+
/** Component type of the description */
|
|
16
|
+
descriptionComponent?: 'div' | 'p';
|
|
17
|
+
/** Flag indicating whether the close button should be in the header */
|
|
18
|
+
hideClose?: boolean;
|
|
19
|
+
/** Aria-label applied to the X (Close) button */
|
|
20
|
+
closeButtonAriaLabel?: string;
|
|
21
|
+
/** id for the title */
|
|
22
|
+
titleId?: string;
|
|
23
|
+
/** id for the description */
|
|
24
|
+
descriptionId?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const WizardHeader: React.FunctionComponent<WizardHeaderProps> = ({
|
|
28
|
+
onClose = () => undefined,
|
|
29
|
+
title,
|
|
30
|
+
description,
|
|
31
|
+
hideClose,
|
|
32
|
+
closeButtonAriaLabel,
|
|
33
|
+
titleId,
|
|
34
|
+
descriptionComponent: Component = 'p',
|
|
35
|
+
descriptionId
|
|
36
|
+
}: WizardHeaderProps) => (
|
|
37
|
+
<div className={css(styles.wizardHeader)}>
|
|
38
|
+
{!hideClose && (
|
|
39
|
+
<Button variant="plain" className={css(styles.wizardClose)} aria-label={closeButtonAriaLabel} onClick={onClose}>
|
|
40
|
+
<TimesIcon aria-hidden="true" />
|
|
41
|
+
</Button>
|
|
42
|
+
)}
|
|
43
|
+
<Title headingLevel="h2" size="3xl" className={css(styles.wizardTitle)} aria-label={title} id={titleId}>
|
|
44
|
+
{title || <> </>}
|
|
45
|
+
</Title>
|
|
46
|
+
{description && (
|
|
47
|
+
<Component className={css(styles.wizardDescription)} id={descriptionId}>
|
|
48
|
+
{description}
|
|
49
|
+
</Component>
|
|
50
|
+
)}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
WizardHeader.displayName = 'WizardHeader';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import styles from '@patternfly/react-styles/css/components/Wizard/wizard';
|
|
3
|
+
import { css } from '@patternfly/react-styles';
|
|
4
|
+
|
|
5
|
+
export interface WizardNavProps {
|
|
6
|
+
/** children should be WizardNavItem components */
|
|
7
|
+
children?: any;
|
|
8
|
+
/** Aria-label applied to the nav element */
|
|
9
|
+
'aria-label'?: string;
|
|
10
|
+
/** Sets the aria-labelledby attribute on the nav element */
|
|
11
|
+
'aria-labelledby'?: string;
|
|
12
|
+
/** Whether the nav is expanded */
|
|
13
|
+
isOpen?: boolean;
|
|
14
|
+
/** True to return the inner list without the wrapping nav element */
|
|
15
|
+
returnList?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const WizardNav: React.FunctionComponent<WizardNavProps> = ({
|
|
19
|
+
children,
|
|
20
|
+
'aria-label': ariaLabel,
|
|
21
|
+
'aria-labelledby': ariaLabelledBy,
|
|
22
|
+
isOpen = false,
|
|
23
|
+
returnList = false
|
|
24
|
+
}: WizardNavProps) => {
|
|
25
|
+
const innerList = <ol className={css(styles.wizardNavList)}>{children}</ol>;
|
|
26
|
+
|
|
27
|
+
if (returnList) {
|
|
28
|
+
return innerList;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<nav
|
|
33
|
+
className={css(styles.wizardNav, isOpen && styles.modifiers.expanded)}
|
|
34
|
+
aria-label={ariaLabel}
|
|
35
|
+
aria-labelledby={ariaLabelledBy}
|
|
36
|
+
>
|
|
37
|
+
<ol className={css(styles.wizardNavList)}>{children}</ol>
|
|
38
|
+
</nav>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
WizardNav.displayName = 'WizardNav';
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { css } from '@patternfly/react-styles';
|
|
3
|
+
import styles from '@patternfly/react-styles/css/components/Wizard/wizard';
|
|
4
|
+
import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
|
|
5
|
+
|
|
6
|
+
export interface WizardNavItemProps {
|
|
7
|
+
/** Can nest a WizardNav component for substeps */
|
|
8
|
+
children?: React.ReactNode;
|
|
9
|
+
/** The content to display in the nav item */
|
|
10
|
+
content?: React.ReactNode;
|
|
11
|
+
/** Whether the nav item is the currently active item */
|
|
12
|
+
isCurrent?: boolean;
|
|
13
|
+
/** Whether the nav item is disabled */
|
|
14
|
+
isDisabled?: boolean;
|
|
15
|
+
/** The step passed into the onNavItemClick callback */
|
|
16
|
+
step: number;
|
|
17
|
+
/** Callback for when the nav item is clicked */
|
|
18
|
+
onNavItemClick?: (step: number) => any;
|
|
19
|
+
/** Component used to render WizardNavItem */
|
|
20
|
+
navItemComponent?: 'button' | 'a';
|
|
21
|
+
/** An optional url to use for when using an anchor component */
|
|
22
|
+
href?: string;
|
|
23
|
+
/** Flag indicating that this NavItem has child steps and is expandable */
|
|
24
|
+
isExpandable?: boolean;
|
|
25
|
+
/** The id for the nav item */
|
|
26
|
+
id?: string | number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const WizardNavItem: React.FunctionComponent<WizardNavItemProps> = ({
|
|
30
|
+
children = null,
|
|
31
|
+
content = '',
|
|
32
|
+
isCurrent = false,
|
|
33
|
+
isDisabled = false,
|
|
34
|
+
step,
|
|
35
|
+
onNavItemClick = () => undefined,
|
|
36
|
+
navItemComponent = 'button',
|
|
37
|
+
href = null,
|
|
38
|
+
isExpandable = false,
|
|
39
|
+
id,
|
|
40
|
+
...rest
|
|
41
|
+
}: WizardNavItemProps) => {
|
|
42
|
+
const NavItemComponent = navItemComponent;
|
|
43
|
+
|
|
44
|
+
const [isExpanded, setIsExpanded] = React.useState(false);
|
|
45
|
+
|
|
46
|
+
React.useEffect(() => {
|
|
47
|
+
setIsExpanded(isCurrent);
|
|
48
|
+
}, [isCurrent]);
|
|
49
|
+
|
|
50
|
+
if (navItemComponent === 'a' && !href && process.env.NODE_ENV !== 'production') {
|
|
51
|
+
// eslint-disable-next-line no-console
|
|
52
|
+
console.error('WizardNavItem: When using an anchor, please provide an href');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const btnProps = {
|
|
56
|
+
disabled: isDisabled
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const linkProps = {
|
|
60
|
+
tabIndex: isDisabled ? -1 : undefined,
|
|
61
|
+
href
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<li
|
|
66
|
+
className={css(
|
|
67
|
+
styles.wizardNavItem,
|
|
68
|
+
isExpandable && styles.modifiers.expandable,
|
|
69
|
+
isExpandable && isExpanded && styles.modifiers.expanded
|
|
70
|
+
)}
|
|
71
|
+
>
|
|
72
|
+
<NavItemComponent
|
|
73
|
+
{...rest}
|
|
74
|
+
{...(navItemComponent === 'a' ? { ...linkProps } : { ...btnProps })}
|
|
75
|
+
{...(id && { id: id.toString() })}
|
|
76
|
+
onClick={() => (isExpandable ? setIsExpanded(!isExpanded || isCurrent) : onNavItemClick(step))}
|
|
77
|
+
className={css(
|
|
78
|
+
styles.wizardNavLink,
|
|
79
|
+
isCurrent && styles.modifiers.current,
|
|
80
|
+
isDisabled && styles.modifiers.disabled
|
|
81
|
+
)}
|
|
82
|
+
aria-disabled={isDisabled ? true : null}
|
|
83
|
+
aria-current={isCurrent && !children ? 'step' : false}
|
|
84
|
+
{...(isExpandable && { 'aria-expanded': isExpanded })}
|
|
85
|
+
>
|
|
86
|
+
{isExpandable ? (
|
|
87
|
+
<>
|
|
88
|
+
<span className={css(styles.wizardNavLinkText)}>{content}</span>
|
|
89
|
+
<span className={css(styles.wizardNavLinkToggle)}>
|
|
90
|
+
<span className={css(styles.wizardNavLinkToggleIcon)}>
|
|
91
|
+
<AngleRightIcon />
|
|
92
|
+
</span>
|
|
93
|
+
</span>
|
|
94
|
+
</>
|
|
95
|
+
) : (
|
|
96
|
+
content
|
|
97
|
+
)}
|
|
98
|
+
</NavItemComponent>
|
|
99
|
+
{children}
|
|
100
|
+
</li>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
WizardNavItem.displayName = 'WizardNavItem';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { WizardControlStep } from './types';
|
|
4
|
+
import { WizardBody, WizardBodyProps } from './WizardBody';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Used as a passthrough of step properties for Wizard and all supporting child components.
|
|
8
|
+
* Also acts as a wrapper for content, with an optional inclusion of WizardBody.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface WizardStepProps extends Omit<WizardControlStep, 'parentId' | 'subStepIds' | 'visited'> {
|
|
12
|
+
/** Optional for when the step is used as a parent to sub-steps */
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
/** Props for WizardBody that wraps content by default. Can be set to null for exclusion of WizardBody. */
|
|
15
|
+
body?: WizardBodyProps | null;
|
|
16
|
+
/** Optional list of sub-steps */
|
|
17
|
+
steps?: React.ReactElement<WizardStepProps>[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const WizardStep = ({ body, children }: WizardStepProps) =>
|
|
21
|
+
body === undefined ? <WizardBody {...body}>{children}</WizardBody> : <>{children}</>;
|
|
22
|
+
|
|
23
|
+
WizardStep.displayName = 'WizardStep';
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { css } from '@patternfly/react-styles';
|
|
4
|
+
import styles from '@patternfly/react-styles/css/components/Wizard/wizard';
|
|
5
|
+
import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
|
|
6
|
+
import CaretDownIcon from '@patternfly/react-icons/dist/esm/icons/caret-down-icon';
|
|
7
|
+
|
|
8
|
+
import { KeyTypes } from '../../../helpers/constants';
|
|
9
|
+
import { WizardNav, WizardNavItem } from '../Wizard';
|
|
10
|
+
import {
|
|
11
|
+
WizardControlStep,
|
|
12
|
+
CustomWizardNavFunction,
|
|
13
|
+
DefaultWizardNavProps,
|
|
14
|
+
isWizardBasicStep,
|
|
15
|
+
isWizardParentStep,
|
|
16
|
+
isWizardSubStep,
|
|
17
|
+
isCustomWizardNav
|
|
18
|
+
} from './types';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Used to toggle between step content, including the body and footer. This is also where the nav and its expandability is controlled.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export interface WizardToggleProps {
|
|
25
|
+
/** List of steps and/or sub-steps */
|
|
26
|
+
steps: WizardControlStep[];
|
|
27
|
+
/** The currently active WizardStep */
|
|
28
|
+
activeStep: WizardControlStep;
|
|
29
|
+
/** The WizardFooter */
|
|
30
|
+
footer: React.ReactElement;
|
|
31
|
+
/** Custom WizardNav or callback used to create a default WizardNav */
|
|
32
|
+
nav: DefaultWizardNavProps | CustomWizardNavFunction;
|
|
33
|
+
/** Navigate using the step index */
|
|
34
|
+
goToStepByIndex: (index: number) => void;
|
|
35
|
+
/** The button's aria-label */
|
|
36
|
+
'aria-label'?: string;
|
|
37
|
+
/** Flag to unmount inactive steps instead of hiding. Defaults to true */
|
|
38
|
+
unmountInactiveSteps?: boolean;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const WizardToggle = ({
|
|
42
|
+
steps,
|
|
43
|
+
activeStep,
|
|
44
|
+
footer,
|
|
45
|
+
nav,
|
|
46
|
+
goToStepByIndex,
|
|
47
|
+
unmountInactiveSteps = true,
|
|
48
|
+
'aria-label': ariaLabel = 'Wizard toggle'
|
|
49
|
+
}: WizardToggleProps) => {
|
|
50
|
+
const [isNavOpen, setIsNavOpen] = React.useState(false);
|
|
51
|
+
const isActiveSubStep = isWizardSubStep(activeStep);
|
|
52
|
+
|
|
53
|
+
const handleKeyClicks = React.useCallback(
|
|
54
|
+
(event: KeyboardEvent): void => {
|
|
55
|
+
if (isNavOpen && event.key === KeyTypes.Escape) {
|
|
56
|
+
setIsNavOpen(!isNavOpen);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
[isNavOpen]
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Open/close collapsable nav on keydown event
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
const target = typeof document !== 'undefined' ? document.body : null;
|
|
65
|
+
target?.addEventListener('keydown', handleKeyClicks, false);
|
|
66
|
+
|
|
67
|
+
return () => {
|
|
68
|
+
target?.removeEventListener('keydown', handleKeyClicks, false);
|
|
69
|
+
};
|
|
70
|
+
}, [handleKeyClicks]);
|
|
71
|
+
|
|
72
|
+
// Only render the active step when unmountInactiveSteps is true
|
|
73
|
+
const bodyContent = unmountInactiveSteps
|
|
74
|
+
? activeStep?.component
|
|
75
|
+
: steps.map(step => {
|
|
76
|
+
if (activeStep?.name === step.name) {
|
|
77
|
+
return step.component;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<div key={step.id} style={{ display: 'none' }}>
|
|
82
|
+
{step.component}
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const wizardNav = isCustomWizardNav(nav)
|
|
88
|
+
? nav(isNavOpen, steps, activeStep, goToStepByIndex)
|
|
89
|
+
: React.useMemo(() => {
|
|
90
|
+
const props = {
|
|
91
|
+
isOpen: isNavOpen,
|
|
92
|
+
'aria-label': nav?.ariaLabel || 'Wizard nav',
|
|
93
|
+
...(nav?.ariaLabelledBy && { 'aria-labelledby': nav?.ariaLabelledBy })
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<WizardNav {...props}>
|
|
98
|
+
{steps.map((step, index) => {
|
|
99
|
+
const stepIndex = index + 1;
|
|
100
|
+
const stepNavItem = step.navItem && <React.Fragment key={step.id}>{step.navItem}</React.Fragment>;
|
|
101
|
+
|
|
102
|
+
if (isWizardParentStep(step)) {
|
|
103
|
+
let firstSubStepIndex;
|
|
104
|
+
let hasActiveChild = false;
|
|
105
|
+
|
|
106
|
+
const subNavItems = step.subStepIds?.map((subStepId, index) => {
|
|
107
|
+
const subStep = steps.find(step => step.id === subStepId);
|
|
108
|
+
const subStepIndex = steps.indexOf(subStep) + 1;
|
|
109
|
+
|
|
110
|
+
if (index === 0) {
|
|
111
|
+
firstSubStepIndex = subStepIndex;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (activeStep?.id === subStep.id) {
|
|
115
|
+
hasActiveChild = true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return subStep.navItem ? (
|
|
119
|
+
<React.Fragment key={subStep.id}>{subStep.navItem}</React.Fragment>
|
|
120
|
+
) : (
|
|
121
|
+
<WizardNavItem
|
|
122
|
+
key={subStep.id}
|
|
123
|
+
id={subStep.id}
|
|
124
|
+
content={subStep.name}
|
|
125
|
+
isCurrent={activeStep?.id === subStep.id}
|
|
126
|
+
isDisabled={subStep.isDisabled || (nav?.forceStepVisit && !subStep.visited)}
|
|
127
|
+
step={subStepIndex}
|
|
128
|
+
onNavItemClick={goToStepByIndex}
|
|
129
|
+
/>
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const hasEnabledChildren = React.Children.toArray(subNavItems).some(
|
|
134
|
+
child => React.isValidElement(child) && !child.props.isDisabled
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
stepNavItem || (
|
|
139
|
+
<WizardNavItem
|
|
140
|
+
key={step.id}
|
|
141
|
+
id={step.id}
|
|
142
|
+
content={step.name}
|
|
143
|
+
isExpandable={nav?.isExpandable}
|
|
144
|
+
isCurrent={hasActiveChild}
|
|
145
|
+
isDisabled={!hasEnabledChildren}
|
|
146
|
+
step={firstSubStepIndex}
|
|
147
|
+
onNavItemClick={goToStepByIndex}
|
|
148
|
+
>
|
|
149
|
+
<WizardNav {...props} returnList>
|
|
150
|
+
{subNavItems}
|
|
151
|
+
</WizardNav>
|
|
152
|
+
</WizardNavItem>
|
|
153
|
+
)
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (isWizardBasicStep(step)) {
|
|
158
|
+
return (
|
|
159
|
+
stepNavItem || (
|
|
160
|
+
<WizardNavItem
|
|
161
|
+
key={step.id}
|
|
162
|
+
id={step.id}
|
|
163
|
+
content={step.name}
|
|
164
|
+
isCurrent={activeStep?.id === step.id}
|
|
165
|
+
isDisabled={step.isDisabled || (nav?.forceStepVisit && !step.visited)}
|
|
166
|
+
step={stepIndex}
|
|
167
|
+
onNavItemClick={goToStepByIndex}
|
|
168
|
+
/>
|
|
169
|
+
)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
})}
|
|
173
|
+
</WizardNav>
|
|
174
|
+
);
|
|
175
|
+
}, [activeStep?.id, goToStepByIndex, isNavOpen, nav, steps]);
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<>
|
|
179
|
+
<button
|
|
180
|
+
onClick={() => setIsNavOpen(prevIsOpen => !prevIsOpen)}
|
|
181
|
+
className={css(styles.wizardToggle, isNavOpen && 'pf-m-expanded')}
|
|
182
|
+
aria-label={ariaLabel}
|
|
183
|
+
aria-expanded={isNavOpen}
|
|
184
|
+
>
|
|
185
|
+
<span className={css(styles.wizardToggleList)}>
|
|
186
|
+
<span className={css(styles.wizardToggleListItem)}>
|
|
187
|
+
{activeStep?.name}
|
|
188
|
+
{isActiveSubStep && <AngleRightIcon className={css(styles.wizardToggleSeparator)} aria-hidden="true" />}
|
|
189
|
+
</span>
|
|
190
|
+
{isActiveSubStep && <span className={css(styles.wizardToggleListItem)}>{activeStep?.name}</span>}
|
|
191
|
+
</span>
|
|
192
|
+
|
|
193
|
+
<span className={css(styles.wizardToggleIcon)}>
|
|
194
|
+
<CaretDownIcon aria-hidden="true" />
|
|
195
|
+
</span>
|
|
196
|
+
</button>
|
|
197
|
+
<div className={css(styles.wizardOuterWrap)}>
|
|
198
|
+
<div className={css(styles.wizardInnerWrap)}>
|
|
199
|
+
{wizardNav}
|
|
200
|
+
{bodyContent}
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
{footer}
|
|
204
|
+
</div>
|
|
205
|
+
</>
|
|
206
|
+
);
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
WizardToggle.displayName = 'WizardToggle';
|