@patternfly/react-core 4.249.0 → 4.250.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/esm/next/components/Select/Select.d.ts +28 -0
- package/dist/esm/next/components/Select/Select.d.ts.map +1 -0
- package/dist/esm/next/components/Select/Select.js +62 -0
- package/dist/esm/next/components/Select/Select.js.map +1 -0
- package/dist/esm/next/components/Select/SelectGroup.d.ts +12 -0
- package/dist/esm/next/components/Select/SelectGroup.d.ts.map +1 -0
- package/dist/esm/next/components/Select/SelectGroup.js +10 -0
- package/dist/esm/next/components/Select/SelectGroup.js.map +1 -0
- package/dist/esm/next/components/Select/SelectList.d.ts +10 -0
- package/dist/esm/next/components/Select/SelectList.d.ts.map +1 -0
- package/dist/esm/next/components/Select/SelectList.js +10 -0
- package/dist/esm/next/components/Select/SelectList.js.map +1 -0
- package/dist/esm/next/components/Select/SelectOption.d.ts +20 -0
- package/dist/esm/next/components/Select/SelectOption.d.ts.map +1 -0
- package/dist/esm/next/components/Select/SelectOption.js +10 -0
- package/dist/esm/next/components/Select/SelectOption.js.map +1 -0
- package/dist/esm/next/components/Select/index.d.ts +5 -0
- package/dist/esm/next/components/Select/index.d.ts.map +1 -0
- package/dist/esm/next/components/Select/index.js +5 -0
- package/dist/esm/next/components/Select/index.js.map +1 -0
- package/dist/esm/next/components/Wizard/Wizard.d.ts +9 -7
- package/dist/esm/next/components/Wizard/Wizard.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/Wizard.js +62 -48
- package/dist/esm/next/components/Wizard/Wizard.js.map +1 -1
- package/dist/esm/next/components/Wizard/WizardBody.d.ts +2 -2
- package/dist/esm/next/components/Wizard/WizardBody.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/WizardBody.js +1 -1
- package/dist/esm/next/components/Wizard/WizardBody.js.map +1 -1
- package/dist/esm/next/components/Wizard/WizardContext.d.ts +21 -20
- package/dist/esm/next/components/Wizard/WizardContext.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/WizardContext.js +63 -32
- package/dist/esm/next/components/Wizard/WizardContext.js.map +1 -1
- package/dist/esm/next/components/Wizard/WizardFooter.d.ts +20 -6
- package/dist/esm/next/components/Wizard/WizardFooter.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/WizardFooter.js +13 -4
- package/dist/esm/next/components/Wizard/WizardFooter.js.map +1 -1
- package/dist/esm/next/components/Wizard/WizardHeader.d.ts +1 -1
- package/dist/esm/next/components/Wizard/WizardHeader.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/WizardHeader.js +2 -2
- package/dist/esm/next/components/Wizard/WizardHeader.js.map +1 -1
- package/dist/esm/next/components/Wizard/WizardNav.d.ts +5 -5
- package/dist/esm/next/components/Wizard/WizardNav.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/WizardNav.js +3 -4
- package/dist/esm/next/components/Wizard/WizardNav.js.map +1 -1
- package/dist/esm/next/components/Wizard/WizardNavInternal.d.ts +14 -0
- package/dist/esm/next/components/Wizard/WizardNavInternal.d.ts.map +1 -0
- package/dist/esm/next/components/Wizard/WizardNavInternal.js +49 -0
- package/dist/esm/next/components/Wizard/WizardNavInternal.js.map +1 -0
- package/dist/esm/next/components/Wizard/WizardNavItem.d.ts +12 -8
- package/dist/esm/next/components/Wizard/WizardNavItem.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/WizardNavItem.js +23 -12
- package/dist/esm/next/components/Wizard/WizardNavItem.js.map +1 -1
- package/dist/esm/next/components/Wizard/WizardStep.d.ts +22 -6
- package/dist/esm/next/components/Wizard/WizardStep.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/WizardStep.js +20 -1
- package/dist/esm/next/components/Wizard/WizardStep.js.map +1 -1
- package/dist/esm/next/components/Wizard/WizardToggle.d.ts +9 -15
- package/dist/esm/next/components/Wizard/WizardToggle.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/WizardToggle.js +15 -50
- package/dist/esm/next/components/Wizard/WizardToggle.js.map +1 -1
- package/dist/esm/next/components/Wizard/hooks/useWizardFooter.d.ts +2 -2
- package/dist/esm/next/components/Wizard/hooks/useWizardFooter.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/hooks/useWizardFooter.js +3 -3
- package/dist/esm/next/components/Wizard/hooks/useWizardFooter.js.map +1 -1
- package/dist/esm/next/components/Wizard/types.d.ts +37 -46
- package/dist/esm/next/components/Wizard/types.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/types.js +10 -2
- package/dist/esm/next/components/Wizard/types.js.map +1 -1
- package/dist/esm/next/components/Wizard/utils.d.ts +4 -5
- package/dist/esm/next/components/Wizard/utils.d.ts.map +1 -1
- package/dist/esm/next/components/Wizard/utils.js +20 -13
- package/dist/esm/next/components/Wizard/utils.js.map +1 -1
- package/dist/esm/next/components/index.d.ts +2 -1
- package/dist/esm/next/components/index.d.ts.map +1 -1
- package/dist/esm/next/components/index.js +2 -1
- package/dist/esm/next/components/index.js.map +1 -1
- package/dist/js/next/components/Select/Select.d.ts +28 -0
- package/dist/js/next/components/Select/Select.d.ts.map +1 -0
- package/dist/js/next/components/Select/Select.js +65 -0
- package/dist/js/next/components/Select/Select.js.map +1 -0
- package/dist/js/next/components/Select/SelectGroup.d.ts +12 -0
- package/dist/js/next/components/Select/SelectGroup.d.ts.map +1 -0
- package/dist/js/next/components/Select/SelectGroup.js +14 -0
- package/dist/js/next/components/Select/SelectGroup.js.map +1 -0
- package/dist/js/next/components/Select/SelectList.d.ts +10 -0
- package/dist/js/next/components/Select/SelectList.d.ts.map +1 -0
- package/dist/js/next/components/Select/SelectList.js +14 -0
- package/dist/js/next/components/Select/SelectList.js.map +1 -0
- package/dist/js/next/components/Select/SelectOption.d.ts +20 -0
- package/dist/js/next/components/Select/SelectOption.d.ts.map +1 -0
- package/dist/js/next/components/Select/SelectOption.js +14 -0
- package/dist/js/next/components/Select/SelectOption.js.map +1 -0
- package/dist/js/next/components/Select/index.d.ts +5 -0
- package/dist/js/next/components/Select/index.d.ts.map +1 -0
- package/dist/js/next/components/Select/index.js +8 -0
- package/dist/js/next/components/Select/index.js.map +1 -0
- package/dist/js/next/components/Wizard/Wizard.d.ts +9 -7
- package/dist/js/next/components/Wizard/Wizard.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/Wizard.js +59 -45
- package/dist/js/next/components/Wizard/Wizard.js.map +1 -1
- package/dist/js/next/components/Wizard/WizardBody.d.ts +2 -2
- package/dist/js/next/components/Wizard/WizardBody.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/WizardBody.js +1 -1
- package/dist/js/next/components/Wizard/WizardBody.js.map +1 -1
- package/dist/js/next/components/Wizard/WizardContext.d.ts +21 -20
- package/dist/js/next/components/Wizard/WizardContext.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/WizardContext.js +61 -30
- package/dist/js/next/components/Wizard/WizardContext.js.map +1 -1
- package/dist/js/next/components/Wizard/WizardFooter.d.ts +20 -6
- package/dist/js/next/components/Wizard/WizardFooter.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/WizardFooter.js +15 -6
- package/dist/js/next/components/Wizard/WizardFooter.js.map +1 -1
- package/dist/js/next/components/Wizard/WizardHeader.d.ts +1 -1
- package/dist/js/next/components/Wizard/WizardHeader.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/WizardHeader.js +2 -2
- package/dist/js/next/components/Wizard/WizardHeader.js.map +1 -1
- package/dist/js/next/components/Wizard/WizardNav.d.ts +5 -5
- package/dist/js/next/components/Wizard/WizardNav.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/WizardNav.js +3 -4
- package/dist/js/next/components/Wizard/WizardNav.js.map +1 -1
- package/dist/js/next/components/Wizard/WizardNavInternal.d.ts +14 -0
- package/dist/js/next/components/Wizard/WizardNavInternal.d.ts.map +1 -0
- package/dist/js/next/components/Wizard/WizardNavInternal.js +54 -0
- package/dist/js/next/components/Wizard/WizardNavInternal.js.map +1 -0
- package/dist/js/next/components/Wizard/WizardNavItem.d.ts +12 -8
- package/dist/js/next/components/Wizard/WizardNavItem.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/WizardNavItem.js +23 -12
- package/dist/js/next/components/Wizard/WizardNavItem.js.map +1 -1
- package/dist/js/next/components/Wizard/WizardStep.d.ts +22 -6
- package/dist/js/next/components/Wizard/WizardStep.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/WizardStep.js +20 -1
- package/dist/js/next/components/Wizard/WizardStep.js.map +1 -1
- package/dist/js/next/components/Wizard/WizardToggle.d.ts +9 -15
- package/dist/js/next/components/Wizard/WizardToggle.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/WizardToggle.js +15 -51
- package/dist/js/next/components/Wizard/WizardToggle.js.map +1 -1
- package/dist/js/next/components/Wizard/hooks/useWizardFooter.d.ts +2 -2
- package/dist/js/next/components/Wizard/hooks/useWizardFooter.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/hooks/useWizardFooter.js +3 -3
- package/dist/js/next/components/Wizard/hooks/useWizardFooter.js.map +1 -1
- package/dist/js/next/components/Wizard/types.d.ts +37 -46
- package/dist/js/next/components/Wizard/types.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/types.js +12 -3
- package/dist/js/next/components/Wizard/types.js.map +1 -1
- package/dist/js/next/components/Wizard/utils.d.ts +4 -5
- package/dist/js/next/components/Wizard/utils.d.ts.map +1 -1
- package/dist/js/next/components/Wizard/utils.js +24 -15
- package/dist/js/next/components/Wizard/utils.js.map +1 -1
- package/dist/js/next/components/index.d.ts +2 -1
- package/dist/js/next/components/index.d.ts.map +1 -1
- package/dist/js/next/components/index.js +2 -1
- package/dist/js/next/components/index.js.map +1 -1
- package/dist/umd/react-core.min.css +940 -940
- package/package.json +2 -2
- package/src/next/components/Select/Select.tsx +129 -0
- package/src/next/components/Select/SelectGroup.tsx +24 -0
- package/src/next/components/Select/SelectList.tsx +21 -0
- package/src/next/components/Select/SelectOption.tsx +31 -0
- package/src/next/components/Select/examples/Select.md +37 -0
- package/src/next/components/Select/examples/SelectBasic.tsx +54 -0
- package/src/next/components/Select/examples/SelectCheckbox.tsx +67 -0
- package/src/next/components/Select/examples/SelectGrouped.tsx +63 -0
- package/src/next/components/Select/examples/SelectMultiTypeahead.tsx +195 -0
- package/src/next/components/Select/examples/SelectTypeahead.tsx +191 -0
- package/src/next/components/Select/index.ts +4 -0
- package/src/next/components/Wizard/Wizard.tsx +107 -64
- package/src/next/components/Wizard/WizardBody.tsx +4 -4
- package/src/next/components/Wizard/WizardContext.tsx +117 -65
- package/src/next/components/Wizard/WizardFooter.tsx +39 -17
- package/src/next/components/Wizard/WizardHeader.tsx +6 -3
- package/src/next/components/Wizard/WizardNav.tsx +9 -10
- package/src/next/components/Wizard/WizardNavInternal.tsx +137 -0
- package/src/next/components/Wizard/WizardNavItem.tsx +47 -20
- package/src/next/components/Wizard/WizardStep.tsx +52 -7
- package/src/next/components/Wizard/WizardToggle.tsx +24 -142
- package/src/next/components/Wizard/__tests__/Wizard.test.tsx +10 -13
- package/src/next/components/Wizard/__tests__/WizardBody.test.tsx +3 -3
- package/src/next/components/Wizard/__tests__/WizardFooter.test.tsx +11 -14
- package/src/next/components/Wizard/__tests__/WizardStep.test.tsx +100 -0
- package/src/next/components/Wizard/__tests__/WizardToggle.test.tsx +4 -4
- package/src/next/components/Wizard/examples/Wizard.md +40 -15
- package/src/next/components/Wizard/examples/WizardBasic.tsx +2 -2
- package/src/next/components/Wizard/examples/WizardCustomNav.tsx +4 -4
- package/src/next/components/Wizard/examples/WizardKitchenSink.tsx +126 -60
- package/src/next/components/Wizard/hooks/__tests__/useWizardFooter.test.tsx +23 -34
- package/src/next/components/Wizard/hooks/useWizardFooter.tsx +5 -5
- package/src/next/components/Wizard/types.tsx +59 -53
- package/src/next/components/Wizard/utils.ts +25 -16
- package/src/next/components/index.ts +2 -1
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
|
|
2
3
|
import { render, screen } from '@testing-library/react';
|
|
4
|
+
|
|
3
5
|
import { WizardStep } from '../WizardStep';
|
|
6
|
+
import * as useWizardFooter from '../hooks/useWizardFooter';
|
|
7
|
+
import * as WizardContext from '../WizardContext';
|
|
8
|
+
import { WizardStepProps } from '..';
|
|
9
|
+
|
|
10
|
+
const testStep: WizardStepProps = {
|
|
11
|
+
id: 'test-step',
|
|
12
|
+
name: 'Test step',
|
|
13
|
+
footer: <>Step footer</>
|
|
14
|
+
};
|
|
15
|
+
const wizardContext: WizardContext.WizardContextProps = {
|
|
16
|
+
steps: [testStep],
|
|
17
|
+
currentStep: testStep,
|
|
18
|
+
currentStepIndex: 1,
|
|
19
|
+
footer: <>Wizard footer</>,
|
|
20
|
+
onNext: jest.fn(),
|
|
21
|
+
onBack: jest.fn(),
|
|
22
|
+
onClose: jest.fn(),
|
|
23
|
+
goToStepById: jest.fn(),
|
|
24
|
+
goToStepByName: jest.fn(),
|
|
25
|
+
goToStepByIndex: jest.fn(),
|
|
26
|
+
setFooter: jest.fn(),
|
|
27
|
+
getStep: jest.fn(),
|
|
28
|
+
setStep: jest.fn(),
|
|
29
|
+
toggleStep: jest.fn()
|
|
30
|
+
};
|
|
31
|
+
const useWizardContextSpy = jest.spyOn(WizardContext, 'useWizardContext');
|
|
32
|
+
const useWizardFooterSpy = jest.spyOn(useWizardFooter, 'useWizardFooter');
|
|
4
33
|
|
|
5
34
|
test('renders without children', () => {
|
|
6
35
|
const { container } = render(<WizardStep id="test-step" name="Test step" />);
|
|
@@ -31,3 +60,74 @@ test('uses body props for WizardBody when passed', () => {
|
|
|
31
60
|
|
|
32
61
|
expect(screen.getByLabelText('Some label')).toBeVisible();
|
|
33
62
|
});
|
|
63
|
+
|
|
64
|
+
test('calls useWizardFooter', () => {
|
|
65
|
+
useWizardContextSpy.mockReturnValueOnce(wizardContext);
|
|
66
|
+
|
|
67
|
+
render(<WizardStep {...testStep}>content</WizardStep>);
|
|
68
|
+
expect(useWizardFooterSpy).toHaveBeenCalledWith(testStep.footer, 'test-step');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('updates "isDisabled" in context when the value changes', () => {
|
|
72
|
+
const setStep = jest.fn();
|
|
73
|
+
useWizardContextSpy.mockReturnValueOnce({ ...wizardContext, setStep });
|
|
74
|
+
|
|
75
|
+
render(<WizardStep {...testStep} isDisabled />);
|
|
76
|
+
|
|
77
|
+
expect(setStep).toHaveBeenCalledWith({ id: testStep.id, isDisabled: true, isVisited: true });
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('updates "navItem" in context when the value changes', () => {
|
|
81
|
+
const setStep = jest.fn();
|
|
82
|
+
const testNavItem = <>Some nav item</>;
|
|
83
|
+
useWizardContextSpy.mockReturnValueOnce({ ...wizardContext, setStep });
|
|
84
|
+
|
|
85
|
+
render(<WizardStep {...testStep} navItem={testNavItem} />);
|
|
86
|
+
|
|
87
|
+
expect(setStep).toHaveBeenCalledWith({ id: testStep.id, navItem: testNavItem, isVisited: true });
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('updates "status" in context when the value changes', () => {
|
|
91
|
+
const setStep = jest.fn();
|
|
92
|
+
useWizardContextSpy.mockReturnValueOnce({ ...wizardContext, setStep });
|
|
93
|
+
|
|
94
|
+
render(<WizardStep {...testStep} status="error" />);
|
|
95
|
+
|
|
96
|
+
expect(setStep).toHaveBeenCalledWith({ id: testStep.id, status: 'error', isVisited: true });
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('calls "toggleStep" when isHidden value changes and the previous value was not undefined', () => {
|
|
100
|
+
const toggleStep = jest.fn();
|
|
101
|
+
useWizardContextSpy.mockReturnValueOnce({ ...wizardContext, toggleStep });
|
|
102
|
+
|
|
103
|
+
render(<WizardStep {...testStep} isHidden />);
|
|
104
|
+
|
|
105
|
+
expect(toggleStep).toHaveBeenCalledWith(testStep.id, true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('does not call "toggleStep" when isHidden value changes and was previously undefined', () => {
|
|
109
|
+
const toggleStep = jest.fn();
|
|
110
|
+
useWizardContextSpy.mockReturnValueOnce({
|
|
111
|
+
...wizardContext,
|
|
112
|
+
toggleStep
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
render(<WizardStep {...testStep} isHidden={undefined} />);
|
|
116
|
+
|
|
117
|
+
expect(toggleStep).not.toHaveBeenCalled();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('does not update "isVisited" value in context when the step was previously visited', () => {
|
|
121
|
+
const setStep = jest.fn();
|
|
122
|
+
const visitedTestStep = { ...testStep, isVisited: true };
|
|
123
|
+
useWizardContextSpy.mockReturnValueOnce({
|
|
124
|
+
...wizardContext,
|
|
125
|
+
currentStep: visitedTestStep,
|
|
126
|
+
steps: [visitedTestStep],
|
|
127
|
+
setStep
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
render(<WizardStep {...visitedTestStep} />);
|
|
131
|
+
|
|
132
|
+
expect(setStep).not.toHaveBeenCalled();
|
|
133
|
+
});
|
|
@@ -13,13 +13,13 @@ const steps = [
|
|
|
13
13
|
|
|
14
14
|
const defaultProps: WizardToggleProps = {
|
|
15
15
|
steps,
|
|
16
|
-
|
|
16
|
+
currentStep: steps[0],
|
|
17
17
|
footer: <div>Some footer</div>,
|
|
18
18
|
nav: <div>Some nav</div>,
|
|
19
19
|
'aria-label': 'Some label'
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
test('renders provided footer, nav, and
|
|
22
|
+
test('renders provided footer, nav, and current step content', () => {
|
|
23
23
|
render(<WizardToggle {...defaultProps} />);
|
|
24
24
|
|
|
25
25
|
expect(screen.getByText('Some footer')).toBeVisible();
|
|
@@ -58,8 +58,8 @@ test('renders only the active step content by default', async () => {
|
|
|
58
58
|
expect(screen.queryByText('Second step content')).toBeNull;
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
test('renders all step content when
|
|
62
|
-
render(<WizardToggle {...defaultProps}
|
|
61
|
+
test('renders all step content when hasUnmountedSteps is false', async () => {
|
|
62
|
+
render(<WizardToggle {...defaultProps} hasUnmountedSteps={false} />);
|
|
63
63
|
|
|
64
64
|
expect(screen.getByText('First step content')).toBeInTheDocument();
|
|
65
65
|
expect(screen.getByText('Second step content')).toBeInTheDocument();
|
|
@@ -16,8 +16,7 @@ propComponents:
|
|
|
16
16
|
'WizardBasicStep',
|
|
17
17
|
'WizardParentStep',
|
|
18
18
|
'WizardSubStep',
|
|
19
|
-
'
|
|
20
|
-
'DefaultWizardFooterProps',
|
|
19
|
+
'WizardNavStepData',
|
|
21
20
|
]
|
|
22
21
|
beta: true
|
|
23
22
|
---
|
|
@@ -28,7 +27,9 @@ TextInput,
|
|
|
28
27
|
Drawer,
|
|
29
28
|
DrawerContent,
|
|
30
29
|
Button,
|
|
30
|
+
Title,
|
|
31
31
|
Flex,
|
|
32
|
+
Checkbox,
|
|
32
33
|
DrawerPanelContent,
|
|
33
34
|
DrawerColorVariant,
|
|
34
35
|
DrawerHead,
|
|
@@ -38,6 +39,7 @@ DrawerCloseButton
|
|
|
38
39
|
import {
|
|
39
40
|
Wizard,
|
|
40
41
|
WizardFooter,
|
|
42
|
+
WizardFooterWrapper,
|
|
41
43
|
WizardToggle,
|
|
42
44
|
WizardStep,
|
|
43
45
|
WizardBody,
|
|
@@ -66,7 +68,7 @@ The `Wizard`'s `nav` property can be used to build your own navigation.
|
|
|
66
68
|
export type CustomWizardNavFunction = (
|
|
67
69
|
isExpanded: boolean,
|
|
68
70
|
steps: WizardControlStep[],
|
|
69
|
-
|
|
71
|
+
currentStep: WizardControlStep,
|
|
70
72
|
goToStepByIndex: (index: number) => void
|
|
71
73
|
) => React.ReactElement<WizardNavProps>;
|
|
72
74
|
|
|
@@ -79,9 +81,18 @@ type WizardControlStep = WizardBasicStep | WizardParentStep | WizardSubStep;
|
|
|
79
81
|
|
|
80
82
|
### Kitchen sink
|
|
81
83
|
|
|
82
|
-
Includes
|
|
84
|
+
Includes the following:
|
|
83
85
|
|
|
84
|
-
|
|
86
|
+
- Header
|
|
87
|
+
- Custom footer
|
|
88
|
+
- Sub-steps
|
|
89
|
+
- Step content with a drawer
|
|
90
|
+
- Custom navigation item
|
|
91
|
+
- Disabled navigation items until visited
|
|
92
|
+
- Action to toggle visibility of a step
|
|
93
|
+
- Action to toggle navigation item error status
|
|
94
|
+
|
|
95
|
+
Custom operations when navigating between steps can be achieved by utilizing `onNext`, `onBack`, or `onNavByIndex` properties whose callback functions return the 'id' and 'name' of the currently focused step (currentStep), and the previously focused step (previousStep).
|
|
85
96
|
|
|
86
97
|
```noLive
|
|
87
98
|
/** Callback for the Wizard's 'onNext', 'onBack', and 'onNavByIndex' properties */
|
|
@@ -91,33 +102,47 @@ type WizardNavStepFunction = (currentStep: WizardNavStepData, previousStep: Wiza
|
|
|
91
102
|
type WizardNavStepData = Pick<WizardControlStep, 'id' | 'name'>;
|
|
92
103
|
```
|
|
93
104
|
|
|
105
|
+
#
|
|
106
|
+
|
|
107
|
+
The `WizardStep`'s `navItem` property can be used to build your own nav item for that step.
|
|
108
|
+
|
|
109
|
+
```noLive
|
|
110
|
+
/** Callback for the Wizard's 'navItem' property. Returns element which replaces the WizardStep's default navItem. */
|
|
111
|
+
export type CustomWizardNavItemFunction = (
|
|
112
|
+
step: WizardControlStep,
|
|
113
|
+
currentStep: WizardControlStep,
|
|
114
|
+
steps: WizardControlStep[],
|
|
115
|
+
goToStepByIndex: (index: number) => void
|
|
116
|
+
) => React.ReactElement<WizardNavItemProps>;
|
|
117
|
+
```
|
|
118
|
+
|
|
94
119
|
```ts file="./WizardKitchenSink.tsx"
|
|
95
120
|
```
|
|
96
121
|
|
|
97
122
|
## Hooks
|
|
98
123
|
|
|
99
|
-
###
|
|
124
|
+
### useWizardContext
|
|
100
125
|
|
|
101
|
-
Used to
|
|
126
|
+
Used to access any property of [WizardContext](#wizardcontextprops):
|
|
102
127
|
|
|
103
128
|
```noLive
|
|
104
|
-
import {
|
|
129
|
+
import { useWizardContext } from '@patternfly/react-core/next';
|
|
105
130
|
|
|
106
131
|
const StepContent = () => {
|
|
107
|
-
|
|
108
|
-
return <>
|
|
132
|
+
const { currentStep } = useWizardContext();
|
|
133
|
+
return <>This is the current step: {currentStep}</>;
|
|
109
134
|
}
|
|
110
135
|
```
|
|
111
136
|
|
|
112
|
-
###
|
|
137
|
+
### useWizardFooter
|
|
113
138
|
|
|
114
|
-
Used to
|
|
139
|
+
Used to set a unique footer for the wizard on any given step. See step 3 of [Kitchen sink](#kitchen-sink) for a live example.
|
|
115
140
|
|
|
116
141
|
```noLive
|
|
117
|
-
import {
|
|
142
|
+
import { useWizardFooter } from '@patternfly/react-core/next';
|
|
118
143
|
|
|
119
144
|
const StepContent = () => {
|
|
120
|
-
|
|
121
|
-
return <>
|
|
145
|
+
useWizardFooter(<>Some footer</>);
|
|
146
|
+
return <>Step content</>;
|
|
122
147
|
}
|
|
123
148
|
```
|
|
@@ -13,9 +13,9 @@ export const WizardBasic: React.FunctionComponent = () => (
|
|
|
13
13
|
<p>Step 3 content</p>
|
|
14
14
|
</WizardStep>
|
|
15
15
|
<WizardStep name="Fourth step" id="basic-fourth-step">
|
|
16
|
-
<p>Step 4 content</p>
|
|
16
|
+
<p>Step 4 content</p>
|
|
17
17
|
</WizardStep>
|
|
18
|
-
<WizardStep name="Review" id="basic-review-step" nextButtonText
|
|
18
|
+
<WizardStep name="Review" id="basic-review-step" footer={{ nextButtonText: 'Finish' }}>
|
|
19
19
|
<p>Review step content</p>
|
|
20
20
|
</WizardStep>
|
|
21
21
|
</Wizard>
|
|
@@ -12,7 +12,7 @@ export const WizardCustomNav: React.FunctionComponent = () => {
|
|
|
12
12
|
const nav: CustomWizardNavFunction = (
|
|
13
13
|
isExpanded: boolean,
|
|
14
14
|
steps: WizardControlStep[],
|
|
15
|
-
|
|
15
|
+
currentStep: WizardControlStep,
|
|
16
16
|
goToStepByIndex: (index: number) => void
|
|
17
17
|
) => (
|
|
18
18
|
<WizardNav isExpanded={isExpanded}>
|
|
@@ -21,9 +21,9 @@ export const WizardCustomNav: React.FunctionComponent = () => {
|
|
|
21
21
|
key={step.id}
|
|
22
22
|
id={step.id}
|
|
23
23
|
content={step.name}
|
|
24
|
-
isCurrent={
|
|
24
|
+
isCurrent={currentStep.id === step.id}
|
|
25
25
|
isDisabled={step.isDisabled}
|
|
26
|
-
|
|
26
|
+
stepIndex={index + 1}
|
|
27
27
|
onNavItemClick={goToStepByIndex}
|
|
28
28
|
/>
|
|
29
29
|
))}
|
|
@@ -38,7 +38,7 @@ export const WizardCustomNav: React.FunctionComponent = () => {
|
|
|
38
38
|
<WizardStep name="Second step" id="cnav-second-step">
|
|
39
39
|
<p>Step 2 content</p>
|
|
40
40
|
</WizardStep>
|
|
41
|
-
<WizardStep name="Review" id="cnav-review-step" nextButtonText
|
|
41
|
+
<WizardStep name="Review" id="cnav-review-step" footer={{ nextButtonText: 'Wrap it up' }}>
|
|
42
42
|
<p>Review step content</p>
|
|
43
43
|
</WizardStep>
|
|
44
44
|
</Wizard>
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
DrawerColorVariant,
|
|
12
12
|
DrawerHead,
|
|
13
13
|
DrawerActions,
|
|
14
|
-
DrawerCloseButton
|
|
14
|
+
DrawerCloseButton,
|
|
15
|
+
Checkbox
|
|
15
16
|
} from '@patternfly/react-core';
|
|
16
17
|
import {
|
|
17
18
|
Wizard,
|
|
@@ -19,32 +20,55 @@ import {
|
|
|
19
20
|
WizardBody,
|
|
20
21
|
WizardFooter,
|
|
21
22
|
WizardStepProps,
|
|
22
|
-
WizardControlStep,
|
|
23
|
-
useWizardFooter,
|
|
24
23
|
useWizardContext,
|
|
25
24
|
WizardNavStepFunction,
|
|
26
25
|
WizardNavStepData,
|
|
27
26
|
WizardNavItem,
|
|
28
|
-
WizardHeader
|
|
27
|
+
WizardHeader,
|
|
28
|
+
WizardFooterWrapper,
|
|
29
|
+
WizardNavItemType
|
|
29
30
|
} from '@patternfly/react-core/next';
|
|
30
31
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
const StepId = {
|
|
33
|
+
StepOne: 'sink-step-1',
|
|
34
|
+
StepTwo: 'sink-step-2',
|
|
35
|
+
StepTwoSubOne: 'sink-step-2-1',
|
|
36
|
+
StepTwoSubTwo: 'sink-step-2-2',
|
|
37
|
+
StepThree: 'sink-step-3',
|
|
38
|
+
StepFour: 'sink-step-4',
|
|
39
|
+
ReviewStep: 'sink-review-step'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
interface SomeContextProps {
|
|
43
|
+
isToggleStepChecked: boolean;
|
|
44
|
+
errorMessage: string | undefined;
|
|
45
|
+
setIsToggleStepChecked(isHidden: boolean): void;
|
|
46
|
+
setErrorMessage(error: string | undefined): void;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const SomeContext = React.createContext({} as SomeContextProps);
|
|
50
|
+
|
|
51
|
+
const SomeContextProvider = ({ children }) => {
|
|
52
|
+
const [isToggleStepChecked, setIsToggleStepChecked] = React.useState(false);
|
|
53
|
+
const [errorMessage, setErrorMessage] = React.useState<string>();
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<SomeContext.Provider value={{ isToggleStepChecked, errorMessage, setIsToggleStepChecked, setErrorMessage }}>
|
|
57
|
+
{children}
|
|
58
|
+
</SomeContext.Provider>
|
|
59
|
+
);
|
|
34
60
|
};
|
|
35
61
|
|
|
36
|
-
const
|
|
37
|
-
const {
|
|
38
|
-
const step = (steps.find(step => step.id === 'third-step') || {}) as WizardControlStep;
|
|
62
|
+
const CustomWizardFooter = () => {
|
|
63
|
+
const { currentStep, currentStepIndex, onNext, onBack, onClose } = useWizardContext();
|
|
39
64
|
|
|
40
65
|
return (
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
onNavItemClick={goToStepByIndex}
|
|
66
|
+
<WizardFooter
|
|
67
|
+
currentStep={currentStep}
|
|
68
|
+
onNext={onNext}
|
|
69
|
+
onBack={onBack}
|
|
70
|
+
onClose={onClose}
|
|
71
|
+
isBackDisabled={currentStepIndex === 1}
|
|
48
72
|
/>
|
|
49
73
|
);
|
|
50
74
|
};
|
|
@@ -84,7 +108,7 @@ const StepContentWithDrawer = () => {
|
|
|
84
108
|
);
|
|
85
109
|
};
|
|
86
110
|
|
|
87
|
-
const StepWithCustomFooter = () => {
|
|
111
|
+
const StepWithCustomFooter = (props: WizardStepProps) => {
|
|
88
112
|
const { onNext: goToNextStep, onBack, onClose } = useWizardContext();
|
|
89
113
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
90
114
|
|
|
@@ -98,7 +122,7 @@ const StepWithCustomFooter = () => {
|
|
|
98
122
|
|
|
99
123
|
const footer = React.useMemo(
|
|
100
124
|
() => (
|
|
101
|
-
|
|
125
|
+
<WizardFooterWrapper>
|
|
102
126
|
<Button variant="primary" onClick={() => onNext(goToNextStep)} isLoading={isLoading} isDisabled={isLoading}>
|
|
103
127
|
Async Next
|
|
104
128
|
</Button>
|
|
@@ -108,55 +132,97 @@ const StepWithCustomFooter = () => {
|
|
|
108
132
|
<Button variant="link" onClick={onClose}>
|
|
109
133
|
Cancel
|
|
110
134
|
</Button>
|
|
111
|
-
|
|
135
|
+
</WizardFooterWrapper>
|
|
112
136
|
),
|
|
113
|
-
[isLoading, onBack, onClose
|
|
137
|
+
[goToNextStep, isLoading, onBack, onClose]
|
|
114
138
|
);
|
|
115
|
-
useWizardFooter(footer);
|
|
116
139
|
|
|
117
|
-
return
|
|
140
|
+
return (
|
|
141
|
+
<WizardStep {...props} footer={footer}>
|
|
142
|
+
Step 3 content w/ custom async footer
|
|
143
|
+
</WizardStep>
|
|
144
|
+
);
|
|
118
145
|
};
|
|
119
146
|
|
|
120
|
-
const
|
|
147
|
+
const StepWithContextActions = (props: WizardStepProps) => {
|
|
148
|
+
const { isToggleStepChecked, errorMessage, setIsToggleStepChecked, setErrorMessage } = React.useContext(SomeContext);
|
|
121
149
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
150
|
+
const navItem: WizardNavItemType = React.useCallback(
|
|
151
|
+
(step, currentStep, steps, goToStepByIndex) => (
|
|
152
|
+
<WizardNavItem
|
|
153
|
+
id={step.id}
|
|
154
|
+
content={step.name}
|
|
155
|
+
isCurrent={currentStep.id === step.id}
|
|
156
|
+
stepIndex={steps.indexOf(step) + 1}
|
|
157
|
+
isDisabled={step.isDisabled || !step.isVisited}
|
|
158
|
+
isVisited={step.isVisited}
|
|
159
|
+
onNavItemClick={goToStepByIndex}
|
|
160
|
+
status={errorMessage ? 'error' : 'default'}
|
|
161
|
+
/>
|
|
162
|
+
),
|
|
163
|
+
[errorMessage]
|
|
164
|
+
);
|
|
127
165
|
|
|
128
166
|
return (
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
<WizardStep id="sink-sub-step-one" key="substep-one" name="Substep 1">
|
|
144
|
-
Substep 1 content
|
|
145
|
-
</WizardStep>,
|
|
146
|
-
<WizardStep id="sink-sub-step-two" key="substep-two" name="Substep 2">
|
|
147
|
-
Substep 2 content
|
|
148
|
-
</WizardStep>
|
|
149
|
-
]}
|
|
167
|
+
<WizardStep {...props} navItem={navItem}>
|
|
168
|
+
<Checkbox
|
|
169
|
+
label="Give this step an error status"
|
|
170
|
+
isChecked={!!errorMessage}
|
|
171
|
+
onChange={checked => setErrorMessage(checked ? 'Some error message' : undefined)}
|
|
172
|
+
id="toggle-error-checkbox"
|
|
173
|
+
name="Toggle Error Checkbox"
|
|
174
|
+
/>
|
|
175
|
+
<Checkbox
|
|
176
|
+
label="Toggle visibility of the next step"
|
|
177
|
+
isChecked={isToggleStepChecked}
|
|
178
|
+
onChange={checked => setIsToggleStepChecked(checked)}
|
|
179
|
+
id="toggle-hide-step-checkbox"
|
|
180
|
+
name="Toggle Hide Step Checkbox"
|
|
150
181
|
/>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
182
|
+
</WizardStep>
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const StepToHide = (props: WizardStepProps) => {
|
|
187
|
+
const { isToggleStepChecked } = React.useContext(SomeContext);
|
|
188
|
+
return <WizardStep {...props} isHidden={isToggleStepChecked} />;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const WizardKitchenSink: React.FunctionComponent = () => {
|
|
192
|
+
const onNext: WizardNavStepFunction = (_currentStep: WizardNavStepData, _previousStep: WizardNavStepData) => {};
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<SomeContextProvider>
|
|
196
|
+
<Wizard
|
|
197
|
+
height={400}
|
|
198
|
+
header={<WizardHeader title="You're a wizard, Harry" closeButtonAriaLabel="Close header" />}
|
|
199
|
+
footer={<CustomWizardFooter />}
|
|
200
|
+
isStepVisitRequired
|
|
201
|
+
onNext={onNext}
|
|
202
|
+
hasUnmountedSteps={false}
|
|
203
|
+
>
|
|
204
|
+
<WizardStep id={StepId.StepOne} name="Step 1" body={null} status="error">
|
|
205
|
+
<StepContentWithDrawer />
|
|
206
|
+
</WizardStep>
|
|
207
|
+
<WizardStep
|
|
208
|
+
id={StepId.StepTwo}
|
|
209
|
+
name="Step 2"
|
|
210
|
+
steps={[
|
|
211
|
+
<StepWithContextActions id={StepId.StepTwoSubOne} key={StepId.StepTwoSubOne} name="Substep 1" />,
|
|
212
|
+
<StepToHide id={StepId.StepTwoSubTwo} key={StepId.StepTwoSubTwo} name="Substep 2">
|
|
213
|
+
Substep 2 content
|
|
214
|
+
</StepToHide>
|
|
215
|
+
]}
|
|
216
|
+
/>
|
|
217
|
+
<StepWithCustomFooter
|
|
218
|
+
id={StepId.StepThree}
|
|
219
|
+
name="Step 3"
|
|
220
|
+
navItem={{ content: <span style={{ color: 'var(--pf-global--default-color--200)' }}>Custom item</span> }}
|
|
221
|
+
/>
|
|
222
|
+
<WizardStep id={StepId.ReviewStep} name="Review" footer={{ nextButtonText: 'Submit' }}>
|
|
223
|
+
Review step content
|
|
224
|
+
</WizardStep>
|
|
225
|
+
</Wizard>
|
|
226
|
+
</SomeContextProvider>
|
|
161
227
|
);
|
|
162
228
|
};
|
|
@@ -5,47 +5,36 @@ import { renderHook } from '@testing-library/react-hooks';
|
|
|
5
5
|
import { useWizardFooter } from '../useWizardFooter';
|
|
6
6
|
import * as WizardContext from '../../WizardContext';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const setFooter = jest.fn();
|
|
8
|
+
const customFooter = <>My custom footer</>;
|
|
9
|
+
const useWizardContextSpy = jest.spyOn(WizardContext, 'useWizardContext');
|
|
10
|
+
const setFooter = jest.fn();
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
test('sets the footer when one is provided without a stepId', () => {
|
|
13
|
+
useWizardContextSpy.mockReturnValueOnce({ setFooter } as any);
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
it(`sets the footer when the provided stepId matches the activeStep's id`, () => {
|
|
21
|
-
useWizardContextSpy.mockReturnValueOnce({ setFooter, activeStep: { id: 'active-step-id' } } as any);
|
|
22
|
-
|
|
23
|
-
renderHook(() => useWizardFooter(customFooter, 'active-step-id'));
|
|
24
|
-
expect(setFooter).toHaveBeenCalledWith(customFooter);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it(`does not set the footer when the provided stepId does not match the activeStep's id`, () => {
|
|
28
|
-
useWizardContextSpy.mockReturnValueOnce({ setFooter, activeStep: { id: 'active-step-id' } } as any);
|
|
15
|
+
renderHook(() => useWizardFooter(customFooter));
|
|
16
|
+
expect(setFooter).toHaveBeenCalledWith(customFooter);
|
|
17
|
+
});
|
|
29
18
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
});
|
|
19
|
+
test(`sets the footer when the provided stepId matches the currentStep's id`, () => {
|
|
20
|
+
useWizardContextSpy.mockReturnValueOnce({ setFooter, currentStep: { id: 'curr-step-id' } } as any);
|
|
33
21
|
|
|
34
|
-
|
|
35
|
-
|
|
22
|
+
renderHook(() => useWizardFooter(customFooter, 'curr-step-id'));
|
|
23
|
+
expect(setFooter).toHaveBeenCalledWith(customFooter);
|
|
24
|
+
});
|
|
36
25
|
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
test(`does not set the footer when the provided stepId does not match the currentStep's id`, () => {
|
|
27
|
+
useWizardContextSpy.mockReturnValueOnce({ setFooter, currentStep: { id: 'curr-step-id' } } as any);
|
|
39
28
|
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
renderHook(() => useWizardFooter(customFooter, 'some-other-step-id'));
|
|
30
|
+
expect(setFooter).not.toHaveBeenCalled();
|
|
31
|
+
});
|
|
42
32
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
useWizardContextSpy.mockReturnValueOnce({ setFooter } as any);
|
|
33
|
+
test('sets the footer to null on unmount', () => {
|
|
34
|
+
useWizardContextSpy.mockReturnValueOnce({ setFooter } as any);
|
|
46
35
|
|
|
47
|
-
|
|
36
|
+
const { unmount } = renderHook(() => useWizardFooter(customFooter));
|
|
37
|
+
unmount();
|
|
48
38
|
|
|
49
|
-
|
|
50
|
-
});
|
|
39
|
+
expect(setFooter).toHaveBeenCalledWith(null);
|
|
51
40
|
});
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import { DefaultWizardFooterProps } from '../types';
|
|
4
3
|
import { useWizardContext } from '../WizardContext';
|
|
4
|
+
import { WizardFooterProps } from '../WizardFooter';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Set a unique footer for the wizard. stepId is only required if inactive steps are hidden instead of unmounted.
|
|
8
8
|
* @param footer
|
|
9
9
|
* @param stepId
|
|
10
10
|
*/
|
|
11
|
-
export const useWizardFooter = (footer:
|
|
12
|
-
const {
|
|
11
|
+
export const useWizardFooter = (footer: React.ReactElement | Partial<WizardFooterProps>, stepId?: string | number) => {
|
|
12
|
+
const { currentStep, setFooter } = useWizardContext();
|
|
13
13
|
|
|
14
14
|
React.useEffect(() => {
|
|
15
|
-
if (!stepId ||
|
|
15
|
+
if (footer && (!stepId || currentStep?.id === stepId)) {
|
|
16
16
|
setFooter(footer);
|
|
17
17
|
|
|
18
18
|
// Reset the footer on unmount.
|
|
@@ -20,5 +20,5 @@ export const useWizardFooter = (footer: DefaultWizardFooterProps | React.ReactEl
|
|
|
20
20
|
setFooter(null);
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
-
}, [
|
|
23
|
+
}, [currentStep, footer, setFooter, stepId]);
|
|
24
24
|
};
|