@patternfly/react-core 4.223.2 → 4.224.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.
Files changed (72) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/esm/components/Form/FormGroup.d.ts +4 -2
  3. package/dist/esm/components/Form/FormGroup.d.ts.map +1 -1
  4. package/dist/esm/components/Form/FormGroup.js +4 -3
  5. package/dist/esm/components/Form/FormGroup.js.map +1 -1
  6. package/dist/esm/components/Select/Select.d.ts.map +1 -1
  7. package/dist/esm/components/Select/Select.js +25 -23
  8. package/dist/esm/components/Select/Select.js.map +1 -1
  9. package/dist/esm/components/Wizard/Wizard.d.ts +9 -0
  10. package/dist/esm/components/Wizard/Wizard.d.ts.map +1 -1
  11. package/dist/esm/components/Wizard/Wizard.js +6 -3
  12. package/dist/esm/components/Wizard/Wizard.js.map +1 -1
  13. package/dist/esm/components/Wizard/WizardBody.d.ts +6 -0
  14. package/dist/esm/components/Wizard/WizardBody.d.ts.map +1 -1
  15. package/dist/esm/components/Wizard/WizardBody.js +6 -2
  16. package/dist/esm/components/Wizard/WizardBody.js.map +1 -1
  17. package/dist/esm/components/Wizard/WizardDrawerWrapper.d.ts +11 -0
  18. package/dist/esm/components/Wizard/WizardDrawerWrapper.d.ts.map +1 -0
  19. package/dist/esm/components/Wizard/WizardDrawerWrapper.js +3 -0
  20. package/dist/esm/components/Wizard/WizardDrawerWrapper.js.map +1 -0
  21. package/dist/esm/components/Wizard/WizardToggle.d.ts +5 -1
  22. package/dist/esm/components/Wizard/WizardToggle.d.ts.map +1 -1
  23. package/dist/esm/components/Wizard/WizardToggle.js +4 -2
  24. package/dist/esm/components/Wizard/WizardToggle.js.map +1 -1
  25. package/dist/js/components/Form/FormGroup.d.ts +4 -2
  26. package/dist/js/components/Form/FormGroup.d.ts.map +1 -1
  27. package/dist/js/components/Form/FormGroup.js +4 -3
  28. package/dist/js/components/Form/FormGroup.js.map +1 -1
  29. package/dist/js/components/Select/Select.d.ts.map +1 -1
  30. package/dist/js/components/Select/Select.js +25 -23
  31. package/dist/js/components/Select/Select.js.map +1 -1
  32. package/dist/js/components/Wizard/Wizard.d.ts +9 -0
  33. package/dist/js/components/Wizard/Wizard.d.ts.map +1 -1
  34. package/dist/js/components/Wizard/Wizard.js +6 -3
  35. package/dist/js/components/Wizard/Wizard.js.map +1 -1
  36. package/dist/js/components/Wizard/WizardBody.d.ts +6 -0
  37. package/dist/js/components/Wizard/WizardBody.d.ts.map +1 -1
  38. package/dist/js/components/Wizard/WizardBody.js +6 -2
  39. package/dist/js/components/Wizard/WizardBody.js.map +1 -1
  40. package/dist/js/components/Wizard/WizardDrawerWrapper.d.ts +11 -0
  41. package/dist/js/components/Wizard/WizardDrawerWrapper.d.ts.map +1 -0
  42. package/dist/js/components/Wizard/WizardDrawerWrapper.js +7 -0
  43. package/dist/js/components/Wizard/WizardDrawerWrapper.js.map +1 -0
  44. package/dist/js/components/Wizard/WizardToggle.d.ts +5 -1
  45. package/dist/js/components/Wizard/WizardToggle.d.ts.map +1 -1
  46. package/dist/js/components/Wizard/WizardToggle.js +4 -2
  47. package/dist/js/components/Wizard/WizardToggle.js.map +1 -1
  48. package/dist/umd/react-core.js +45 -33
  49. package/dist/umd/react-core.min.js +4 -4
  50. package/package.json +6 -6
  51. package/src/components/Form/FormGroup.tsx +40 -29
  52. package/src/components/Form/examples/Form.md +12 -1271
  53. package/src/components/Form/examples/FormBasic.tsx +122 -0
  54. package/src/components/Form/examples/FormFieldGroups.tsx +324 -0
  55. package/src/components/Form/examples/FormGrid.tsx +66 -0
  56. package/src/components/Form/examples/FormGroupLabelInfo.tsx +72 -0
  57. package/src/components/Form/examples/FormHorizontal.tsx +118 -0
  58. package/src/components/Form/examples/FormHorizontalHelper.tsx +23 -0
  59. package/src/components/Form/examples/FormHorizontalStacked.tsx +11 -0
  60. package/src/components/Form/examples/FormInvalid.tsx +47 -0
  61. package/src/components/Form/examples/FormInvalidWithFormAlert.tsx +52 -0
  62. package/src/components/Form/examples/FormLimitWidth.tsx +122 -0
  63. package/src/components/Form/examples/FormSections.tsx +44 -0
  64. package/src/components/Form/examples/FormValidated.tsx +60 -0
  65. package/src/components/Select/Select.tsx +35 -33
  66. package/src/components/Wizard/Wizard.tsx +21 -1
  67. package/src/components/Wizard/WizardBody.tsx +23 -2
  68. package/src/components/Wizard/WizardDrawerWrapper.tsx +18 -0
  69. package/src/components/Wizard/WizardToggle.tsx +12 -2
  70. package/src/components/Wizard/__tests__/Wizard.test.tsx +24 -7
  71. package/src/components/Wizard/examples/Wizard.md +157 -2
  72. package/src/demos/Wizard/WizardDemo.md +1033 -2
@@ -0,0 +1,118 @@
1
+ import React from 'react';
2
+ import {
3
+ Form,
4
+ FormGroup,
5
+ TextInput,
6
+ TextArea,
7
+ FormSelect,
8
+ FormSelectOption,
9
+ Checkbox,
10
+ ActionGroup,
11
+ Button,
12
+ Radio
13
+ } from '@patternfly/react-core';
14
+
15
+ export const FormHorizontal: React.FunctionComponent = () => {
16
+ const [name, setName] = React.useState('');
17
+ const [email, setEmail] = React.useState('');
18
+ const [experience, setExperience] = React.useState('');
19
+ const [option, setOption] = React.useState('please choose');
20
+
21
+ const handleNameChange = (name: string) => {
22
+ setName(name);
23
+ };
24
+
25
+ const handleEmailChange = (email: string) => {
26
+ setEmail(email);
27
+ };
28
+
29
+ const handleExperienceChange = (experience: string) => {
30
+ setExperience(experience);
31
+ };
32
+
33
+ const handleOptionChange = (value: string, _event: React.FormEvent<HTMLSelectElement>) => {
34
+ setOption(value);
35
+ };
36
+
37
+ const options = [
38
+ { value: 'select one', label: 'Select one', disabled: false },
39
+ { value: 'mr', label: 'Mr', disabled: false },
40
+ { value: 'miss', label: 'Miss', disabled: false },
41
+ { value: 'mrs', label: 'Mrs', disabled: false },
42
+ { value: 'ms', label: 'Ms', disabled: false },
43
+ { value: 'dr', label: 'Dr', disabled: false },
44
+ { value: 'other', label: 'Other', disabled: false }
45
+ ];
46
+
47
+ return (
48
+ <Form isHorizontal>
49
+ <FormGroup
50
+ label="Full name"
51
+ isRequired
52
+ fieldId="horizontal-form-name"
53
+ helperText="Include your middle name if you have one."
54
+ >
55
+ <TextInput
56
+ value={name}
57
+ isRequired
58
+ type="text"
59
+ id="horizontal-form-name"
60
+ aria-describedby="horizontal-form-name-helper"
61
+ name="horizontal-form-name"
62
+ onChange={handleNameChange}
63
+ />
64
+ </FormGroup>
65
+ <FormGroup label="Email" isRequired fieldId="horizontal-form-email">
66
+ <TextInput
67
+ value={email}
68
+ isRequired
69
+ type="email"
70
+ id="horizontal-form-email"
71
+ name="horizontal-form-email"
72
+ onChange={handleEmailChange}
73
+ />
74
+ </FormGroup>
75
+ <FormGroup label="Your title" fieldId="horizontal-form-title">
76
+ <FormSelect
77
+ value={option}
78
+ onChange={handleOptionChange}
79
+ id="horizontal-form-title"
80
+ name="horizontal-form-title"
81
+ aria-label="Your title"
82
+ >
83
+ {options.map((option, index) => (
84
+ <FormSelectOption isDisabled={option.disabled} key={index} value={option.value} label={option.label} />
85
+ ))}
86
+ </FormSelect>
87
+ </FormGroup>
88
+ <FormGroup label="Your experience" fieldId="horizontal-form-exp">
89
+ <TextArea
90
+ value={experience}
91
+ onChange={handleExperienceChange}
92
+ id="horizontal-form-exp"
93
+ name="horizontal-form-exp"
94
+ />
95
+ </FormGroup>
96
+ <FormGroup
97
+ label="How can we contact you?"
98
+ isStack
99
+ fieldId="horizontal-form-checkbox-group"
100
+ hasNoPaddingTop
101
+ role="group"
102
+ >
103
+ <Checkbox label="Email" id="alt-form-checkbox-1" name="alt-form-checkbox-1" />
104
+ <Checkbox label="Phone" id="alt-form-checkbox-2" name="alt-form-checkbox-2" />
105
+ <Checkbox label="Mail" id="alt-form-checkbox-3" name="alt-form-checkbox-3" />
106
+ </FormGroup>
107
+ <FormGroup role="radiogroup" isStack fieldId="horizontal-form-radio-group" hasNoPaddingTop label="Time zone">
108
+ <Radio name="horizontal-inline-radio" label="Eastern" id="horizontal-inline-radio-01" />
109
+ <Radio name="horizontal-inline-radio" label="Central" id="horizontal-inline-radio-02" />
110
+ <Radio name="horizontal-inline-radio" label="Pacific" id="horizontal-inline-radio-03" />
111
+ </FormGroup>
112
+ <ActionGroup>
113
+ <Button variant="primary">Submit</Button>
114
+ <Button variant="link">Cancel</Button>
115
+ </ActionGroup>
116
+ </Form>
117
+ );
118
+ };
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { Form, FormGroup, Checkbox } from '@patternfly/react-core';
3
+
4
+ export const FormHorizontalFormHelperText: React.FunctionComponent = () => {
5
+ const [helperText] = React.useState('Select all that apply:');
6
+
7
+ return (
8
+ <Form isHorizontal>
9
+ <FormGroup
10
+ label="Label"
11
+ helperText={helperText}
12
+ isHelperTextBeforeField
13
+ hasNoPaddingTop
14
+ isStack
15
+ fieldId="horizontal-form-helper-options"
16
+ role="group"
17
+ >
18
+ <Checkbox label="Option 1" id="option-03" />
19
+ <Checkbox label="Option 2" id="option-04" />
20
+ </FormGroup>
21
+ </Form>
22
+ );
23
+ };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { Form, FormGroup, Checkbox } from '@patternfly/react-core';
3
+
4
+ export const FormHorizontalStacked: React.FunctionComponent = () => (
5
+ <Form isHorizontal>
6
+ <FormGroup role="group" label="Label" hasNoPaddingTop fieldId="horizontal-form-stacked-options" isStack>
7
+ <Checkbox label="option 1" id="option-01" />
8
+ <Checkbox label="option 2" id="option-02" />
9
+ </FormGroup>
10
+ </Form>
11
+ );
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import { Form, FormGroup, TextInput, FormHelperText } from '@patternfly/react-core';
3
+ import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
4
+
5
+ export const FormInvalid: React.FunctionComponent = () => {
6
+ type validate = 'success' | 'warning' | 'error' | 'default';
7
+
8
+ const [age, setAge] = React.useState('Five');
9
+ const [validated, setValidated] = React.useState<validate>('error');
10
+
11
+ const handleAgeChange = (age: string, _event: React.FormEvent<HTMLInputElement>) => {
12
+ setAge(age);
13
+ if (age === '') {
14
+ setValidated('default');
15
+ } else if (/^\d+$/.test(age)) {
16
+ setValidated('success');
17
+ } else {
18
+ setValidated('error');
19
+ }
20
+ };
21
+
22
+ return (
23
+ <Form>
24
+ <FormGroup
25
+ label="Age"
26
+ type="number"
27
+ helperText={
28
+ <FormHelperText icon={<ExclamationCircleIcon />} isHidden={validated !== 'default'}>
29
+ Please enter your age
30
+ </FormHelperText>
31
+ }
32
+ helperTextInvalid="Must be a number"
33
+ helperTextInvalidIcon={<ExclamationCircleIcon />}
34
+ fieldId="age-1"
35
+ validated={validated}
36
+ >
37
+ <TextInput
38
+ validated={validated}
39
+ value={age}
40
+ id="age-1"
41
+ aria-describedby="age-1-helper"
42
+ onChange={handleAgeChange}
43
+ />
44
+ </FormGroup>
45
+ </Form>
46
+ );
47
+ };
@@ -0,0 +1,52 @@
1
+ import React from 'react';
2
+ import { Alert, Form, FormAlert, FormGroup, TextInput, FormHelperText } from '@patternfly/react-core';
3
+ import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
4
+
5
+ export const FormInvalidWithAlert: React.FunctionComponent = () => {
6
+ type validate = 'success' | 'warning' | 'error' | 'default';
7
+
8
+ const [age, setAge] = React.useState('Five');
9
+ const [validated, setValidated] = React.useState<validate>('error');
10
+
11
+ const handleAgeChange = (age: string, _event: React.FormEvent<HTMLInputElement>) => {
12
+ setAge(age);
13
+ if (age === '') {
14
+ setValidated('default');
15
+ } else if (/^\d+$/.test(age)) {
16
+ setValidated('success');
17
+ } else {
18
+ setValidated('error');
19
+ }
20
+ };
21
+
22
+ return (
23
+ <Form>
24
+ {validated === 'error' && (
25
+ <FormAlert>
26
+ <Alert variant="danger" title="Fill out all required fields before continuing." aria-live="polite" isInline />
27
+ </FormAlert>
28
+ )}
29
+ <FormGroup
30
+ label="Age"
31
+ type="number"
32
+ helperText={
33
+ <FormHelperText icon={<ExclamationCircleIcon />} isHidden={validated !== 'default'}>
34
+ Please enter your age
35
+ </FormHelperText>
36
+ }
37
+ helperTextInvalid="Must be a number"
38
+ helperTextInvalidIcon={<ExclamationCircleIcon />}
39
+ fieldId="age-2"
40
+ validated={validated}
41
+ >
42
+ <TextInput
43
+ validated={validated}
44
+ value={age}
45
+ id="age-2"
46
+ aria-describedby="age-2-helper"
47
+ onChange={handleAgeChange}
48
+ />
49
+ </FormGroup>
50
+ </Form>
51
+ );
52
+ };
@@ -0,0 +1,122 @@
1
+ import React from 'react';
2
+ import { Form, FormGroup, TextInput, Checkbox, Popover, ActionGroup, Button, Radio } from '@patternfly/react-core';
3
+ import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
4
+
5
+ export const FormLimitWidth: React.FunctionComponent = () => {
6
+ const [name, setName] = React.useState('');
7
+ const [email, setEmail] = React.useState('');
8
+ const [phone, setPhone] = React.useState('');
9
+
10
+ const handleNameChange = (name: string) => {
11
+ setName(name);
12
+ };
13
+
14
+ const handleEmailChange = (email: string) => {
15
+ setEmail(email);
16
+ };
17
+
18
+ const handlePhoneChange = (phone: string) => {
19
+ setPhone(phone);
20
+ };
21
+
22
+ return (
23
+ <Form isWidthLimited>
24
+ <FormGroup
25
+ label="Full name"
26
+ labelIcon={
27
+ <Popover
28
+ headerContent={
29
+ <div>
30
+ The{' '}
31
+ <a href="https://schema.org/name" target="_blank" rel="noreferrer">
32
+ name
33
+ </a>{' '}
34
+ of a{' '}
35
+ <a href="https://schema.org/Person" target="_blank" rel="noreferrer">
36
+ Person
37
+ </a>
38
+ </div>
39
+ }
40
+ bodyContent={
41
+ <div>
42
+ Often composed of{' '}
43
+ <a href="https://schema.org/givenName" target="_blank" rel="noreferrer">
44
+ givenName
45
+ </a>{' '}
46
+ and{' '}
47
+ <a href="https://schema.org/familyName" target="_blank" rel="noreferrer">
48
+ familyName
49
+ </a>
50
+ .
51
+ </div>
52
+ }
53
+ >
54
+ <button
55
+ type="button"
56
+ aria-label="More info for name field"
57
+ onClick={e => e.preventDefault()}
58
+ aria-describedby="simple-form-name-02"
59
+ className="pf-c-form__group-label-help"
60
+ >
61
+ <HelpIcon noVerticalAlign />
62
+ </button>
63
+ </Popover>
64
+ }
65
+ isRequired
66
+ fieldId="simple-form-name-02"
67
+ helperText="Include your middle name if you have one."
68
+ >
69
+ <TextInput
70
+ isRequired
71
+ type="text"
72
+ id="simple-form-name-02"
73
+ name="simple-form-name-02"
74
+ aria-describedby="simple-form-name-02-helper"
75
+ value={name}
76
+ onChange={handleNameChange}
77
+ />
78
+ </FormGroup>
79
+ <FormGroup label="Email" isRequired fieldId="simple-form-email-02">
80
+ <TextInput
81
+ isRequired
82
+ type="email"
83
+ id="simple-form-email-02"
84
+ name="simple-form-email-02"
85
+ value={email}
86
+ onChange={handleEmailChange}
87
+ />
88
+ </FormGroup>
89
+ <FormGroup label="Phone number" isRequired fieldId="simple-form-number">
90
+ <TextInput
91
+ isRequired
92
+ type="tel"
93
+ placeholder="555-555-5555"
94
+ id="simple-form-number"
95
+ name="simple-form-number"
96
+ value={phone}
97
+ onChange={handlePhoneChange}
98
+ />
99
+ </FormGroup>
100
+ <FormGroup role="group" isInline fieldId="limit-width-form-checkbox-group" label="How can we contact you?">
101
+ <Checkbox label="Email" aria-label="Email" id="inlinecheck04" />
102
+ <Checkbox label="Phone" aria-label="Phone" id="inlinecheck05" />
103
+ <Checkbox label="Mail" aria-label="Mail" id="inlinecheck06" />
104
+ </FormGroup>
105
+ <FormGroup role="radiogroup" isInline fieldId="limit-width-form-radio-group" label="Time zone">
106
+ <Radio name="limit-width-radio" label="Eastern" id="limit-width-inline-radio-01" />
107
+ <Radio name="limit-width-radio" label="Central" id="limit-width-inline-radio-02" />
108
+ <Radio name="limit-width-radio" label="Pacific" id="limit-width-inline-radio-03" />
109
+ </FormGroup>
110
+ <FormGroup label="Additional note" fieldId="simple-form-note-02">
111
+ <TextInput isDisabled type="text" id="simple-form-note-02" name="simple-form-number" value="disabled" />
112
+ </FormGroup>
113
+ <FormGroup fieldId="checkbox02">
114
+ <Checkbox label="I'd like updates via email." id="checkbox02" name="checkbox02" aria-label="Update via email" />
115
+ </FormGroup>
116
+ <ActionGroup>
117
+ <Button variant="primary">Submit</Button>
118
+ <Button variant="link">Cancel</Button>
119
+ </ActionGroup>
120
+ </Form>
121
+ );
122
+ };
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { Form, FormGroup, FormSection, TextInput } from '@patternfly/react-core';
3
+
4
+ export const FormSections: React.FunctionComponent = () => {
5
+ const [input1, setInput1] = React.useState('');
6
+ const [input2, setInput2] = React.useState('');
7
+
8
+ const handleInputChange1 = (input1: string, _event: React.FormEvent<HTMLInputElement>) => {
9
+ setInput1(input1);
10
+ };
11
+
12
+ const handleInputChange2 = (input2: string, _event: React.FormEvent<HTMLInputElement>) => {
13
+ setInput2(input2);
14
+ };
15
+
16
+ return (
17
+ <Form>
18
+ <FormSection>
19
+ <FormGroup label="Form section 1 input" isRequired fieldId="simple-form-section-1-input">
20
+ <TextInput
21
+ isRequired
22
+ type="text"
23
+ id="simple-form-section-1-input"
24
+ name="simple-form-section-1-input"
25
+ value={input1}
26
+ onChange={handleInputChange1}
27
+ />
28
+ </FormGroup>
29
+ </FormSection>
30
+ <FormSection title="Form section 2 (optional title)" titleElement="h2">
31
+ <FormGroup label="Form section 2 input" isRequired fieldId="simple-form-section-2-input">
32
+ <TextInput
33
+ isRequired
34
+ type="text"
35
+ id="simple-form-section-2-input"
36
+ name="simple-form-section-2-input"
37
+ value={input2}
38
+ onChange={handleInputChange2}
39
+ />
40
+ </FormGroup>
41
+ </FormSection>
42
+ </Form>
43
+ );
44
+ };
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import { Form, FormGroup, TextInput } from '@patternfly/react-core';
3
+ import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
4
+
5
+ export const FormValidated: React.FunctionComponent = () => {
6
+ type validate = 'success' | 'warning' | 'error' | 'default';
7
+
8
+ const [age, setAge] = React.useState('Five');
9
+ const [invalidText, setInvalidText] = React.useState('Must be a number');
10
+ const [validated, setValidated] = React.useState<validate>('default');
11
+ const [helperText, setHelperText] = React.useState('Enter your age to continue');
12
+
13
+ const handleAgeChange = (age: string, _event: React.FormEvent<HTMLInputElement>) => {
14
+ setAge(age);
15
+ setValidated('default');
16
+ setHelperText('Validating...');
17
+ };
18
+
19
+ // useEffect is used to simulate a server call to validate the age 2000ms after the user has entered a value, preventing calling the server on every keystroke
20
+ React.useEffect(() => {
21
+ const timer = setTimeout(() => {
22
+ if (/^\d+$/.test(age)) {
23
+ if (parseInt(age) >= 21) {
24
+ setValidated('success');
25
+ setHelperText('Enjoy your stay');
26
+ } else {
27
+ setValidated('warning');
28
+ setHelperText('You must be at least 21 years old to continue');
29
+ }
30
+ } else {
31
+ setValidated('error');
32
+ setInvalidText('Must be a number');
33
+ }
34
+ }, 2000);
35
+
36
+ return () => clearTimeout(timer);
37
+ }, [age]);
38
+
39
+ return (
40
+ <Form>
41
+ <FormGroup
42
+ label="Age"
43
+ type="number"
44
+ helperText={helperText}
45
+ helperTextInvalid={invalidText}
46
+ helperTextInvalidIcon={<ExclamationCircleIcon />}
47
+ fieldId="age-3"
48
+ validated={validated}
49
+ >
50
+ <TextInput
51
+ validated={validated}
52
+ value={age}
53
+ id="age-3"
54
+ aria-describedby="age-3-helper"
55
+ onChange={handleAgeChange}
56
+ />
57
+ </FormGroup>
58
+ </Form>
59
+ );
60
+ };
@@ -297,39 +297,41 @@ export class Select extends React.Component<SelectProps & OUIAProps, SelectState
297
297
  this.setState({ viewMoreNextIndex: -1 });
298
298
  }
299
299
 
300
- const checkUpdatedChildren = (prevChildren: React.ReactElement[], currChildren: React.ReactElement[]) =>
301
- prevChildren.some((prevChild: React.ReactElement, index: number) => {
302
- const prevChildProps = prevChild.props;
303
- const currChild = currChildren[index];
304
- const { props: currChildProps } = currChild;
305
-
306
- if (prevChildProps && currChildProps) {
307
- return (
308
- prevChildProps.value !== currChildProps.value ||
309
- prevChildProps.label !== currChildProps.label ||
310
- prevChildProps.isDisabled !== currChildProps.isDisabled ||
311
- prevChildProps.isPlaceholder !== currChildProps.isPlaceholder
312
- );
313
- } else {
314
- return prevChild !== currChild;
315
- }
316
- });
317
-
318
- const hasUpdatedChildren =
319
- prevProps.children.length !== this.props.children.length ||
320
- checkUpdatedChildren(prevProps.children, this.props.children) ||
321
- (this.props.isGrouped &&
322
- prevProps.children.some(
323
- (prevChild: React.ReactElement, index: number) =>
324
- prevChild.type === SelectGroup &&
325
- prevChild.props.children &&
326
- this.props.children[index].props.children &&
327
- (prevChild.props.children.length !== this.props.children[index].props.children.length ||
328
- checkUpdatedChildren(prevChild.props.children, this.props.children[index].props.children))
329
- ));
330
-
331
- if (hasUpdatedChildren) {
332
- this.updateTypeAheadFilteredChildren(prevState.typeaheadInputValue || '', null);
300
+ if (this.props.variant === 'typeahead' || this.props.variant === 'typeaheadmulti') {
301
+ const checkUpdatedChildren = (prevChildren: React.ReactElement[], currChildren: React.ReactElement[]) =>
302
+ Array.from(prevChildren).some((prevChild: React.ReactElement, index: number) => {
303
+ const prevChildProps = prevChild.props;
304
+ const currChild = currChildren[index];
305
+ const { props: currChildProps } = currChild;
306
+
307
+ if (prevChildProps && currChildProps) {
308
+ return (
309
+ prevChildProps.value !== currChildProps.value ||
310
+ prevChildProps.label !== currChildProps.label ||
311
+ prevChildProps.isDisabled !== currChildProps.isDisabled ||
312
+ prevChildProps.isPlaceholder !== currChildProps.isPlaceholder
313
+ );
314
+ } else {
315
+ return prevChild !== currChild;
316
+ }
317
+ });
318
+
319
+ const hasUpdatedChildren =
320
+ prevProps.children.length !== this.props.children.length ||
321
+ checkUpdatedChildren(prevProps.children, this.props.children) ||
322
+ (this.props.isGrouped &&
323
+ Array.from(prevProps.children).some(
324
+ (prevChild: React.ReactElement, index: number) =>
325
+ prevChild.type === SelectGroup &&
326
+ prevChild.props.children &&
327
+ this.props.children[index].props.children &&
328
+ (prevChild.props.children.length !== this.props.children[index].props.children.length ||
329
+ checkUpdatedChildren(prevChild.props.children, this.props.children[index].props.children))
330
+ ));
331
+
332
+ if (hasUpdatedChildren) {
333
+ this.updateTypeAheadFilteredChildren(prevState.typeaheadInputValue || '', null);
334
+ }
333
335
  }
334
336
 
335
337
  // for menus with favorites,
@@ -18,6 +18,10 @@ export interface WizardStep {
18
18
  name: React.ReactNode;
19
19
  /** The component to render in the main body */
20
20
  component?: any;
21
+ /** @beta The content to render in the drawer panel (use when hasDrawer prop is set on the wizard). */
22
+ drawerPanelContent?: any;
23
+ /** @beta Custom drawer toggle button that opens the drawer. */
24
+ drawerToggleButton?: React.ReactNode;
21
25
  /** Setting to true hides the side nav and footer */
22
26
  isFinishedStep?: boolean;
23
27
  /** Enables or disables the step in the navigation. Enabled by default. */
@@ -100,6 +104,10 @@ export interface WizardProps extends React.HTMLProps<HTMLDivElement> {
100
104
  isOpen?: boolean;
101
105
  /** Flag indicating nav items with sub steps are expandable */
102
106
  isNavExpandable?: boolean;
107
+ /** @beta Flag indicating the wizard has a drawer for at least one of the wizard steps */
108
+ hasDrawer?: boolean;
109
+ /** @beta Flag indicating the wizard drawer is expanded */
110
+ isDrawerExpanded?: boolean;
103
111
  }
104
112
 
105
113
  interface WizardState {
@@ -135,10 +143,13 @@ export class Wizard extends React.Component<WizardProps, WizardState> {
135
143
  onClose: () => undefined as any,
136
144
  appendTo: null as HTMLElement,
137
145
  isOpen: undefined,
138
- isNavExpandable: false
146
+ isNavExpandable: false,
147
+ hasDrawer: false,
148
+ isDrawerExpanded: false
139
149
  };
140
150
  private titleId: string;
141
151
  private descriptionId: string;
152
+ private drawerRef: React.RefObject<any>;
142
153
 
143
154
  constructor(props: WizardProps) {
144
155
  super(props);
@@ -150,6 +161,8 @@ export class Wizard extends React.Component<WizardProps, WizardState> {
150
161
  currentStep: this.props.startAtStep && Number.isInteger(this.props.startAtStep) ? this.props.startAtStep : 1,
151
162
  isNavOpen: false
152
163
  };
164
+
165
+ this.drawerRef = React.createRef();
153
166
  }
154
167
 
155
168
  private handleKeyClicks = (event: KeyboardEvent): void => {
@@ -340,6 +353,8 @@ export class Wizard extends React.Component<WizardProps, WizardState> {
340
353
  titleId,
341
354
  descriptionId,
342
355
  isNavExpandable,
356
+ hasDrawer,
357
+ isDrawerExpanded,
343
358
  ...rest
344
359
  /* eslint-enable @typescript-eslint/no-unused-vars */
345
360
  } = this.props;
@@ -350,12 +365,14 @@ export class Wizard extends React.Component<WizardProps, WizardState> {
350
365
  const computedSteps: WizardStep[] = this.initSteps(steps);
351
366
  const firstStep = activeStep === flattenedSteps[0];
352
367
  const isValid = activeStep && activeStep.enableNext !== undefined ? activeStep.enableNext : true;
368
+
353
369
  const nav = (isWizardNavOpen: boolean) => {
354
370
  const wizNavAProps = {
355
371
  isOpen: isWizardNavOpen,
356
372
  'aria-label': navAriaLabel,
357
373
  'aria-labelledby': (title || navAriaLabelledBy) && (navAriaLabelledBy || this.titleId)
358
374
  };
375
+
359
376
  return (
360
377
  <WizardNav {...wizNavAProps}>
361
378
  {computedSteps.map((step, index) => {
@@ -466,6 +483,8 @@ export class Wizard extends React.Component<WizardProps, WizardState> {
466
483
  />
467
484
  )}
468
485
  <WizardToggle
486
+ hasDrawer={hasDrawer}
487
+ isDrawerExpanded={isDrawerExpanded}
469
488
  mainAriaLabel={mainAriaLabel}
470
489
  isInPage={isOpen === undefined}
471
490
  mainAriaLabelledBy={(title || mainAriaLabelledBy) && (mainAriaLabelledBy || this.titleId)}
@@ -509,6 +528,7 @@ export class Wizard extends React.Component<WizardProps, WizardState> {
509
528
  </Modal>
510
529
  );
511
530
  }
531
+
512
532
  return wizard;
513
533
  }
514
534
  }