@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.
- package/CHANGELOG.md +30 -0
- package/dist/esm/components/Form/FormGroup.d.ts +4 -2
- package/dist/esm/components/Form/FormGroup.d.ts.map +1 -1
- package/dist/esm/components/Form/FormGroup.js +4 -3
- package/dist/esm/components/Form/FormGroup.js.map +1 -1
- package/dist/esm/components/Select/Select.d.ts.map +1 -1
- package/dist/esm/components/Select/Select.js +25 -23
- package/dist/esm/components/Select/Select.js.map +1 -1
- package/dist/esm/components/Wizard/Wizard.d.ts +9 -0
- package/dist/esm/components/Wizard/Wizard.d.ts.map +1 -1
- package/dist/esm/components/Wizard/Wizard.js +6 -3
- package/dist/esm/components/Wizard/Wizard.js.map +1 -1
- package/dist/esm/components/Wizard/WizardBody.d.ts +6 -0
- package/dist/esm/components/Wizard/WizardBody.d.ts.map +1 -1
- package/dist/esm/components/Wizard/WizardBody.js +6 -2
- package/dist/esm/components/Wizard/WizardBody.js.map +1 -1
- package/dist/esm/components/Wizard/WizardDrawerWrapper.d.ts +11 -0
- package/dist/esm/components/Wizard/WizardDrawerWrapper.d.ts.map +1 -0
- package/dist/esm/components/Wizard/WizardDrawerWrapper.js +3 -0
- package/dist/esm/components/Wizard/WizardDrawerWrapper.js.map +1 -0
- package/dist/esm/components/Wizard/WizardToggle.d.ts +5 -1
- package/dist/esm/components/Wizard/WizardToggle.d.ts.map +1 -1
- package/dist/esm/components/Wizard/WizardToggle.js +4 -2
- package/dist/esm/components/Wizard/WizardToggle.js.map +1 -1
- package/dist/js/components/Form/FormGroup.d.ts +4 -2
- package/dist/js/components/Form/FormGroup.d.ts.map +1 -1
- package/dist/js/components/Form/FormGroup.js +4 -3
- package/dist/js/components/Form/FormGroup.js.map +1 -1
- package/dist/js/components/Select/Select.d.ts.map +1 -1
- package/dist/js/components/Select/Select.js +25 -23
- package/dist/js/components/Select/Select.js.map +1 -1
- package/dist/js/components/Wizard/Wizard.d.ts +9 -0
- package/dist/js/components/Wizard/Wizard.d.ts.map +1 -1
- package/dist/js/components/Wizard/Wizard.js +6 -3
- package/dist/js/components/Wizard/Wizard.js.map +1 -1
- package/dist/js/components/Wizard/WizardBody.d.ts +6 -0
- package/dist/js/components/Wizard/WizardBody.d.ts.map +1 -1
- package/dist/js/components/Wizard/WizardBody.js +6 -2
- package/dist/js/components/Wizard/WizardBody.js.map +1 -1
- package/dist/js/components/Wizard/WizardDrawerWrapper.d.ts +11 -0
- package/dist/js/components/Wizard/WizardDrawerWrapper.d.ts.map +1 -0
- package/dist/js/components/Wizard/WizardDrawerWrapper.js +7 -0
- package/dist/js/components/Wizard/WizardDrawerWrapper.js.map +1 -0
- package/dist/js/components/Wizard/WizardToggle.d.ts +5 -1
- package/dist/js/components/Wizard/WizardToggle.d.ts.map +1 -1
- package/dist/js/components/Wizard/WizardToggle.js +4 -2
- package/dist/js/components/Wizard/WizardToggle.js.map +1 -1
- package/dist/umd/react-core.js +45 -33
- package/dist/umd/react-core.min.js +4 -4
- package/package.json +6 -6
- package/src/components/Form/FormGroup.tsx +40 -29
- package/src/components/Form/examples/Form.md +12 -1271
- package/src/components/Form/examples/FormBasic.tsx +122 -0
- package/src/components/Form/examples/FormFieldGroups.tsx +324 -0
- package/src/components/Form/examples/FormGrid.tsx +66 -0
- package/src/components/Form/examples/FormGroupLabelInfo.tsx +72 -0
- package/src/components/Form/examples/FormHorizontal.tsx +118 -0
- package/src/components/Form/examples/FormHorizontalHelper.tsx +23 -0
- package/src/components/Form/examples/FormHorizontalStacked.tsx +11 -0
- package/src/components/Form/examples/FormInvalid.tsx +47 -0
- package/src/components/Form/examples/FormInvalidWithFormAlert.tsx +52 -0
- package/src/components/Form/examples/FormLimitWidth.tsx +122 -0
- package/src/components/Form/examples/FormSections.tsx +44 -0
- package/src/components/Form/examples/FormValidated.tsx +60 -0
- package/src/components/Select/Select.tsx +35 -33
- package/src/components/Wizard/Wizard.tsx +21 -1
- package/src/components/Wizard/WizardBody.tsx +23 -2
- package/src/components/Wizard/WizardDrawerWrapper.tsx +18 -0
- package/src/components/Wizard/WizardToggle.tsx +12 -2
- package/src/components/Wizard/__tests__/Wizard.test.tsx +24 -7
- package/src/components/Wizard/examples/Wizard.md +157 -2
- 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
|
-
|
|
301
|
-
prevChildren
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
(
|
|
324
|
-
prevChild.
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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
|
}
|