@patternfly/react-core 4.234.4 → 4.235.2
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 +991 -991
- package/dist/umd/react-core.js +509 -413
- package/dist/umd/react-core.min.css +70 -70
- package/dist/umd/react-core.min.js +5 -5
- package/package.json +10 -10
- package/src/components/Wizard/examples/Wizard.md +21 -4
- 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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.235.2",
|
|
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",
|
|
@@ -50,9 +50,9 @@
|
|
|
50
50
|
"generate": "node scripts/copyStyles.js"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@patternfly/react-icons": "^4.
|
|
54
|
-
"@patternfly/react-styles": "^4.
|
|
55
|
-
"@patternfly/react-tokens": "^4.
|
|
53
|
+
"@patternfly/react-icons": "^4.86.2",
|
|
54
|
+
"@patternfly/react-styles": "^4.85.2",
|
|
55
|
+
"@patternfly/react-tokens": "^4.87.2",
|
|
56
56
|
"focus-trap": "6.9.2",
|
|
57
57
|
"react-dropzone": "9.0.0",
|
|
58
58
|
"tippy.js": "5.1.2",
|
|
@@ -60,21 +60,21 @@
|
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@patternfly/patternfly": "4.210.2",
|
|
63
|
-
"@rollup/plugin-commonjs": "^
|
|
64
|
-
"@rollup/plugin-node-resolve": "^13.
|
|
65
|
-
"@rollup/plugin-replace": "^
|
|
63
|
+
"@rollup/plugin-commonjs": "^21.0.0",
|
|
64
|
+
"@rollup/plugin-node-resolve": "^13.0.0",
|
|
65
|
+
"@rollup/plugin-replace": "^3.0.0",
|
|
66
66
|
"css": "^2.2.3",
|
|
67
67
|
"fs-extra": "^6.0.1",
|
|
68
68
|
"glob": "^7.1.2",
|
|
69
69
|
"rimraf": "^3.0.2",
|
|
70
|
-
"rollup": "^2.
|
|
70
|
+
"rollup": "^2.58.0",
|
|
71
71
|
"rollup-plugin-scss": "^3.0.0",
|
|
72
|
-
"rollup-plugin-terser": "^7.0.
|
|
72
|
+
"rollup-plugin-terser": "^7.0.0",
|
|
73
73
|
"typescript": "^4.7.4"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"react": "^16.8.0 || ^17.0.0",
|
|
77
77
|
"react-dom": "^16.8.0 || ^17.0.0"
|
|
78
78
|
},
|
|
79
|
-
"gitHead": "
|
|
79
|
+
"gitHead": "481223940736dfb78100455556d8aa23738cec66"
|
|
80
80
|
}
|
|
@@ -13,6 +13,8 @@ import SlackHashIcon from '@patternfly/react-icons/dist/esm/icons/slack-hash-ico
|
|
|
13
13
|
import FinishedStep from './FinishedStep';
|
|
14
14
|
import SampleForm from './SampleForm';
|
|
15
15
|
|
|
16
|
+
If you seek a wizard solution that allows for more composition, see the [React next](/components/wizard/react-next) tab.
|
|
17
|
+
|
|
16
18
|
## Examples
|
|
17
19
|
|
|
18
20
|
### Basic
|
|
@@ -54,7 +56,7 @@ class SimpleWizard extends React.Component {
|
|
|
54
56
|
render() {
|
|
55
57
|
const steps = [
|
|
56
58
|
{ name: 'First step', component: <p>Step 1 content</p> },
|
|
57
|
-
{ name: 'Second step', component: <p>Step 2 content</p>, isDisabled: true},
|
|
59
|
+
{ name: 'Second step', component: <p>Step 2 content</p>, isDisabled: true },
|
|
58
60
|
{ name: 'Third step', component: <p>Step 3 content</p> },
|
|
59
61
|
{ name: 'Fourth step', component: <p>Step 4 content</p>, isDisabled: true },
|
|
60
62
|
{ name: 'Review', component: <p>Review step content</p>, nextButtonText: 'Finish' }
|
|
@@ -145,9 +147,24 @@ class IncrementallyEnabledStepsWizard extends React.Component {
|
|
|
145
147
|
|
|
146
148
|
const steps = [
|
|
147
149
|
{ id: 'incrementally-enabled-1', name: 'First step', component: <p>Step 1 content</p> },
|
|
148
|
-
{
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
{
|
|
151
|
+
id: 'incrementally-enabled-2',
|
|
152
|
+
name: 'Second step',
|
|
153
|
+
component: <p>Step 2 content</p>,
|
|
154
|
+
canJumpTo: stepIdReached >= 2
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: 'incrementally-enabled-3',
|
|
158
|
+
name: 'Third step',
|
|
159
|
+
component: <p>Step 3 content</p>,
|
|
160
|
+
canJumpTo: stepIdReached >= 3
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
id: 'incrementally-enabled-4',
|
|
164
|
+
name: 'Fourth step',
|
|
165
|
+
component: <p>Step 4 content</p>,
|
|
166
|
+
canJumpTo: stepIdReached >= 4
|
|
167
|
+
},
|
|
151
168
|
{
|
|
152
169
|
id: 'incrementally-enabled-5',
|
|
153
170
|
name: 'Review',
|
|
@@ -0,0 +1,184 @@
|
|
|
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
|
+
|
|
6
|
+
import {
|
|
7
|
+
DefaultWizardFooterProps,
|
|
8
|
+
DefaultWizardNavProps,
|
|
9
|
+
isCustomWizardFooter,
|
|
10
|
+
isWizardParentStep,
|
|
11
|
+
WizardNavStepFunction,
|
|
12
|
+
CustomWizardNavFunction
|
|
13
|
+
} from './types';
|
|
14
|
+
import { buildSteps, normalizeNavStep } from './utils';
|
|
15
|
+
import { useWizardContext, WizardContextProvider } from './WizardContext';
|
|
16
|
+
import { WizardStepProps } from './WizardStep';
|
|
17
|
+
import { WizardFooter } from './WizardFooter';
|
|
18
|
+
import { WizardToggle } from './WizardToggle';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Wrapper for all steps and hosts state, including navigation helpers, within context.
|
|
22
|
+
* The WizardContext provided by default gives any child of wizard access to those resources.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export interface WizardProps extends React.HTMLProps<HTMLDivElement> {
|
|
26
|
+
/** Step components */
|
|
27
|
+
children: React.ReactElement<WizardStepProps> | React.ReactElement<WizardStepProps>[];
|
|
28
|
+
/** Wizard header */
|
|
29
|
+
header?: React.ReactNode;
|
|
30
|
+
/** Wizard footer */
|
|
31
|
+
footer?: DefaultWizardFooterProps | React.ReactElement;
|
|
32
|
+
/** Default wizard nav props or a custom WizardNav (with callback) */
|
|
33
|
+
nav?: DefaultWizardNavProps | CustomWizardNavFunction;
|
|
34
|
+
/** The initial index the wizard is to start on (1 or higher). Defaults to 1. */
|
|
35
|
+
startIndex?: number;
|
|
36
|
+
/** Additional classes spread to the wizard */
|
|
37
|
+
className?: string;
|
|
38
|
+
/** Custom width of the wizard */
|
|
39
|
+
width?: number | string;
|
|
40
|
+
/** Custom height of the wizard */
|
|
41
|
+
height?: number | string;
|
|
42
|
+
/** Callback function when a step in the nav is clicked */
|
|
43
|
+
onNavByIndex?: WizardNavStepFunction;
|
|
44
|
+
/** Callback function after next button is clicked */
|
|
45
|
+
onNext?: WizardNavStepFunction;
|
|
46
|
+
/** Callback function after back button is clicked */
|
|
47
|
+
onBack?: WizardNavStepFunction;
|
|
48
|
+
/** Callback function to save at the end of the wizard, if not specified uses onClose */
|
|
49
|
+
onSave?: () => void;
|
|
50
|
+
/** Callback function to close the wizard */
|
|
51
|
+
onClose?: () => void;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const Wizard = (props: WizardProps) => {
|
|
55
|
+
const { startIndex = 1, children, footer, onNavByIndex, onNext, onBack, onSave, onClose, ...internalProps } = props;
|
|
56
|
+
const [currentStepIndex, setCurrentStepIndex] = React.useState(startIndex);
|
|
57
|
+
const steps = buildSteps(children);
|
|
58
|
+
|
|
59
|
+
const goToStepByIndex = (index: number) => {
|
|
60
|
+
const lastStepIndex = steps.length;
|
|
61
|
+
|
|
62
|
+
if (index < 1) {
|
|
63
|
+
index = 1;
|
|
64
|
+
} else if (index > lastStepIndex) {
|
|
65
|
+
index = lastStepIndex;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const currStep = steps[index - 1];
|
|
69
|
+
const prevStep = steps[currentStepIndex - 1];
|
|
70
|
+
setCurrentStepIndex(index);
|
|
71
|
+
|
|
72
|
+
return onNavByIndex?.(normalizeNavStep(currStep), normalizeNavStep(prevStep));
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const goToNextStep = () => {
|
|
76
|
+
// Save when on the last step, otherwise close
|
|
77
|
+
if (currentStepIndex >= steps.length) {
|
|
78
|
+
if (onSave) {
|
|
79
|
+
return onSave();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return onClose?.();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let currStep = steps[currentStepIndex];
|
|
86
|
+
let newStepIndex = currentStepIndex + 1;
|
|
87
|
+
const prevStep = steps[currentStepIndex - 1];
|
|
88
|
+
|
|
89
|
+
// Skip parent step and focus on the first sub-step if they exist
|
|
90
|
+
if (isWizardParentStep(currStep)) {
|
|
91
|
+
newStepIndex += 1;
|
|
92
|
+
currStep = steps[currentStepIndex + 1];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
setCurrentStepIndex(newStepIndex);
|
|
96
|
+
return onNext?.(normalizeNavStep(currStep), normalizeNavStep(prevStep));
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const goToPrevStep = () => {
|
|
100
|
+
if (steps.length < currentStepIndex) {
|
|
101
|
+
// Previous step was removed, just update the currentStep state
|
|
102
|
+
setCurrentStepIndex(steps.length);
|
|
103
|
+
} else {
|
|
104
|
+
let currStep = steps[currentStepIndex - 2];
|
|
105
|
+
let newStepIndex = currentStepIndex - 1;
|
|
106
|
+
const prevStep = steps[currentStepIndex - 1];
|
|
107
|
+
|
|
108
|
+
// // Skip parent step and focus on the step prior
|
|
109
|
+
if (isWizardParentStep(currStep)) {
|
|
110
|
+
newStepIndex -= 1;
|
|
111
|
+
currStep = steps[currentStepIndex - 3];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
setCurrentStepIndex(newStepIndex);
|
|
115
|
+
return onBack?.(normalizeNavStep(currStep), normalizeNavStep(prevStep));
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const goToStepById = (id: number | string) => {
|
|
120
|
+
const stepIndex = steps.findIndex(step => step.id === id) + 1;
|
|
121
|
+
stepIndex > 0 && setCurrentStepIndex(stepIndex);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const goToStepByName = (name: string) => {
|
|
125
|
+
const stepIndex = steps.findIndex(step => step.name === name) + 1;
|
|
126
|
+
stepIndex > 0 && setCurrentStepIndex(stepIndex);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<WizardContextProvider
|
|
131
|
+
steps={steps}
|
|
132
|
+
currentStepIndex={currentStepIndex}
|
|
133
|
+
footer={isCustomWizardFooter(footer) && footer}
|
|
134
|
+
onNext={goToNextStep}
|
|
135
|
+
onBack={goToPrevStep}
|
|
136
|
+
onClose={onClose}
|
|
137
|
+
goToStepById={goToStepById}
|
|
138
|
+
goToStepByName={goToStepByName}
|
|
139
|
+
goToStepByIndex={goToStepByIndex}
|
|
140
|
+
>
|
|
141
|
+
<WizardInternal {...internalProps} footer={footer}>
|
|
142
|
+
{children}
|
|
143
|
+
</WizardInternal>
|
|
144
|
+
</WizardContextProvider>
|
|
145
|
+
);
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// eslint-disable-next-line patternfly-react/no-anonymous-functions
|
|
149
|
+
const WizardInternal = ({ height, width, className, header, footer, nav, ...divProps }: WizardProps) => {
|
|
150
|
+
const { activeStep, steps, footer: customFooter, onNext, onBack, onClose, goToStepByIndex } = useWizardContext();
|
|
151
|
+
|
|
152
|
+
const wizardFooter = customFooter || (
|
|
153
|
+
<WizardFooter
|
|
154
|
+
activeStep={activeStep}
|
|
155
|
+
onNext={onNext}
|
|
156
|
+
onBack={onBack}
|
|
157
|
+
onClose={onClose}
|
|
158
|
+
disableBackButton={activeStep?.id === steps[0]?.id}
|
|
159
|
+
{...footer}
|
|
160
|
+
/>
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<div
|
|
165
|
+
className={css(styles.wizard, className)}
|
|
166
|
+
style={{
|
|
167
|
+
...(height ? { height } : {}),
|
|
168
|
+
...(width ? { width } : {})
|
|
169
|
+
}}
|
|
170
|
+
{...divProps}
|
|
171
|
+
>
|
|
172
|
+
{header}
|
|
173
|
+
<WizardToggle
|
|
174
|
+
steps={steps}
|
|
175
|
+
activeStep={activeStep}
|
|
176
|
+
footer={wizardFooter}
|
|
177
|
+
nav={nav}
|
|
178
|
+
goToStepByIndex={goToStepByIndex}
|
|
179
|
+
/>
|
|
180
|
+
</div>
|
|
181
|
+
);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
Wizard.displayName = 'Wizard';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import styles from '@patternfly/react-styles/css/components/Wizard/wizard';
|
|
4
|
+
import { css } from '@patternfly/react-styles';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Used as a wrapper for WizardStep content, where the wrapping element is customizable.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export interface WizardBodyProps {
|
|
11
|
+
children?: React.ReactNode | React.ReactNode[];
|
|
12
|
+
/** Set to true to remove the default body padding */
|
|
13
|
+
hasNoBodyPadding?: boolean;
|
|
14
|
+
/** An aria-label to use for the wrapper element */
|
|
15
|
+
'aria-label'?: string;
|
|
16
|
+
/** Sets the aria-labelledby attribute for the wrapper element */
|
|
17
|
+
'aria-labelledby'?: string;
|
|
18
|
+
/** Component used as the wrapping content container */
|
|
19
|
+
wrapperElement?: React.ElementType;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const WizardBody = ({
|
|
23
|
+
children,
|
|
24
|
+
hasNoBodyPadding = false,
|
|
25
|
+
'aria-label': ariaLabel,
|
|
26
|
+
'aria-labelledby': ariaLabelledBy,
|
|
27
|
+
wrapperElement: Wrapper = 'div'
|
|
28
|
+
}: WizardBodyProps) => (
|
|
29
|
+
<Wrapper aria-label={ariaLabel} aria-labelledby={ariaLabelledBy} className={css(styles.wizardMain)}>
|
|
30
|
+
<div className={css(styles.wizardMainBody, hasNoBodyPadding && styles.modifiers.noPadding)}>{children}</div>
|
|
31
|
+
</Wrapper>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
WizardBody.displayName = 'WizardBody';
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { WizardControlStep } from './types';
|
|
3
|
+
import { getActiveStep } from './utils';
|
|
4
|
+
|
|
5
|
+
export interface WizardContextProps {
|
|
6
|
+
/** List of steps */
|
|
7
|
+
steps: WizardControlStep[];
|
|
8
|
+
/** Active step */
|
|
9
|
+
activeStep: WizardControlStep;
|
|
10
|
+
/** Footer element */
|
|
11
|
+
footer: React.ReactElement;
|
|
12
|
+
/** Navigate to the next step */
|
|
13
|
+
onNext: () => void;
|
|
14
|
+
/** Navigate to the previous step */
|
|
15
|
+
onBack: () => void;
|
|
16
|
+
/** Close the wizard */
|
|
17
|
+
onClose: () => void;
|
|
18
|
+
/** Navigate to step by ID */
|
|
19
|
+
goToStepById: (id: number | string) => void;
|
|
20
|
+
/** Navigate to step by name */
|
|
21
|
+
goToStepByName: (name: string) => void;
|
|
22
|
+
/** Navigate to step by index */
|
|
23
|
+
goToStepByIndex: (index: number) => void;
|
|
24
|
+
/** Update the footer with any react element */
|
|
25
|
+
setFooter: (footer: React.ReactElement) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const WizardContext = React.createContext({} as WizardContextProps);
|
|
29
|
+
|
|
30
|
+
interface WizardContextRenderProps {
|
|
31
|
+
steps: WizardControlStep[];
|
|
32
|
+
activeStep: WizardControlStep;
|
|
33
|
+
footer: React.ReactElement;
|
|
34
|
+
onNext(): void;
|
|
35
|
+
onBack(): void;
|
|
36
|
+
onClose(): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface WizardContextProviderProps {
|
|
40
|
+
steps: WizardControlStep[];
|
|
41
|
+
currentStepIndex: number;
|
|
42
|
+
footer: React.ReactElement;
|
|
43
|
+
children: React.ReactElement | ((props: WizardContextRenderProps) => React.ReactElement);
|
|
44
|
+
onNext(): void;
|
|
45
|
+
onBack(): void;
|
|
46
|
+
onClose(): void;
|
|
47
|
+
goToStepById(id: number | string): void;
|
|
48
|
+
goToStepByName(name: string): void;
|
|
49
|
+
goToStepByIndex(index: number): void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// eslint-disable-next-line patternfly-react/no-anonymous-functions
|
|
53
|
+
export const WizardContextProvider: React.FunctionComponent<WizardContextProviderProps> = ({
|
|
54
|
+
steps: initialSteps,
|
|
55
|
+
footer: initialFooter,
|
|
56
|
+
currentStepIndex,
|
|
57
|
+
children,
|
|
58
|
+
onNext,
|
|
59
|
+
onBack,
|
|
60
|
+
onClose,
|
|
61
|
+
goToStepById,
|
|
62
|
+
goToStepByName,
|
|
63
|
+
goToStepByIndex
|
|
64
|
+
}) => {
|
|
65
|
+
const [steps, setSteps] = React.useState(initialSteps);
|
|
66
|
+
const [footer, setFooter] = React.useState(initialFooter);
|
|
67
|
+
const activeStep = getActiveStep(steps, currentStepIndex);
|
|
68
|
+
|
|
69
|
+
// When the active step changes and the newly active step isn't visited, set the visited flag to true.
|
|
70
|
+
React.useEffect(() => {
|
|
71
|
+
if (activeStep && !activeStep?.visited) {
|
|
72
|
+
setSteps(prevSteps =>
|
|
73
|
+
prevSteps.map(step => {
|
|
74
|
+
if (step.id === activeStep.id) {
|
|
75
|
+
return { ...step, visited: true };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return step;
|
|
79
|
+
})
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}, [activeStep]);
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<WizardContext.Provider
|
|
86
|
+
value={{
|
|
87
|
+
steps,
|
|
88
|
+
activeStep,
|
|
89
|
+
footer,
|
|
90
|
+
onNext,
|
|
91
|
+
onBack,
|
|
92
|
+
onClose,
|
|
93
|
+
goToStepById,
|
|
94
|
+
goToStepByName,
|
|
95
|
+
goToStepByIndex,
|
|
96
|
+
setFooter
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
{typeof children === 'function' ? children({ activeStep, steps, footer, onNext, onBack, onClose }) : children}
|
|
100
|
+
</WizardContext.Provider>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const useWizardContext = () => React.useContext(WizardContext);
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
|
|
6
|
+
import { Button, ButtonVariant } from '../../../components/Button';
|
|
7
|
+
import { WizardControlStep, WizardNavStepFunction } from './types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Hosts the standard structure of a footer with ties to the active step so that text for buttons can vary from step to step.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export interface WizardFooterProps {
|
|
14
|
+
/** The currently active WizardStep */
|
|
15
|
+
activeStep: WizardControlStep;
|
|
16
|
+
/** Next button callback */
|
|
17
|
+
onNext: () => WizardNavStepFunction | void;
|
|
18
|
+
/** Back button callback */
|
|
19
|
+
onBack: () => WizardNavStepFunction | void;
|
|
20
|
+
/** Cancel link callback */
|
|
21
|
+
onClose: () => void;
|
|
22
|
+
/** Custom text for the Next button. The activeStep's nextButtonText takes precedence. */
|
|
23
|
+
nextButtonText?: React.ReactNode;
|
|
24
|
+
/** Custom text for the Back button */
|
|
25
|
+
backButtonText?: React.ReactNode;
|
|
26
|
+
/** Custom text for the Cancel link */
|
|
27
|
+
cancelButtonText?: React.ReactNode;
|
|
28
|
+
/** Optional flag to disable the first step's back button */
|
|
29
|
+
disableBackButton?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const WizardFooter = ({
|
|
33
|
+
onNext,
|
|
34
|
+
onBack,
|
|
35
|
+
onClose,
|
|
36
|
+
activeStep,
|
|
37
|
+
disableBackButton,
|
|
38
|
+
nextButtonText = 'Next',
|
|
39
|
+
backButtonText = 'Back',
|
|
40
|
+
cancelButtonText = 'Cancel'
|
|
41
|
+
}: WizardFooterProps) => (
|
|
42
|
+
<footer className={css(styles.wizardFooter)}>
|
|
43
|
+
<Button variant={ButtonVariant.primary} type="submit" onClick={onNext} isDisabled={activeStep?.disableNext}>
|
|
44
|
+
{activeStep?.nextButtonText || nextButtonText}
|
|
45
|
+
</Button>
|
|
46
|
+
|
|
47
|
+
{!activeStep?.hideBackButton && (
|
|
48
|
+
<Button variant={ButtonVariant.secondary} onClick={onBack} isDisabled={disableBackButton}>
|
|
49
|
+
{backButtonText}
|
|
50
|
+
</Button>
|
|
51
|
+
)}
|
|
52
|
+
|
|
53
|
+
{!activeStep?.hideCancelButton && (
|
|
54
|
+
<div className={styles.wizardFooterCancel}>
|
|
55
|
+
<Button variant={ButtonVariant.link} onClick={onClose}>
|
|
56
|
+
{cancelButtonText}
|
|
57
|
+
</Button>
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
</footer>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
WizardFooter.displayName = 'WizardFooter';
|
|
@@ -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';
|