forked from patternfly/patternfly-react
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(patternfly-4/react-core/): added Select Component (patternfly#590)
* feat(patternfly-4/react-core/): added Select Componentt affects: @patternfly/react-core ISSUES CLOSED: patternfly#461 * feat(patternfly-4/react-core): added Select component for PF4 affects: @patternfly/react-core ISSUES CLOSED: patternfly#461 * feat(/patternfly-4/react-core): add Select Component affects: @patternfly/react-core ISSUES CLOSED: patternfly#461 * feat(patternfly-4/react-core): added the Patternfly 4 Select component affects: @patternfly/react-core ISSUES CLOSED: patternfly#461 * feat(patternfly-4/react-core): added the Patternfly 4 Select component affects: @patternfly/react-core ISSUES CLOSED: patternfly#461 * feat(patternfly-4/react-core): added the Patternfly 4 Select component affects: @patternfly/react-core ISSUES CLOSED: patternfly#461
- Loading branch information
Showing
16 changed files
with
835 additions
and
0 deletions.
There are no files selected for viewing
16 changes: 16 additions & 0 deletions
16
packages/patternfly-4/react-core/src/components/Select/Select.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { HTMLProps, FormEvent } from 'react'; | ||
import { Omit } from '../../typeUtils'; | ||
|
||
export interface SelectProps extends Omit<HTMLProps<HTMLInputElement>, 'onChange' | 'onBlur' | 'onFocus' | 'disabled'> { | ||
children: any; | ||
value?: any; | ||
isValid?: boolean; | ||
isDisabled?: boolean; | ||
onBlur(event: React.FormEvent<HTMLSelectElement>): void; | ||
onFocus(event: React.FormEvent<HTMLSelectElement>): void; | ||
onChange(event: React.FormEvent<HTMLSelectElement>): void; | ||
} | ||
|
||
declare const Select: React.SFC<SelectProps>; | ||
|
||
export default Select; |
14 changes: 14 additions & 0 deletions
14
packages/patternfly-4/react-core/src/components/Select/Select.docs.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Select, SelectOption, SelectOptionGroup } from '@patternfly/react-core'; | ||
import SelectInput from './examples/SelectInput'; | ||
import SelectInputDisabled from './examples/SelectInputDisabled'; | ||
import SelectInputGrouped from './examples/SelectInputGrouped'; | ||
|
||
export default { | ||
title: 'Select', | ||
components: { | ||
Select, | ||
SelectOption, | ||
SelectOptionGroup | ||
}, | ||
examples: [SelectInput, SelectInputGrouped, SelectInputDisabled] | ||
}; |
68 changes: 68 additions & 0 deletions
68
packages/patternfly-4/react-core/src/components/Select/Select.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import React from 'react'; | ||
import styles from '@patternfly/patternfly-next/components/FormControls/styles.css'; | ||
import { css } from '@patternfly/react-styles'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const propTypes = { | ||
/** content rendered inside the Select */ | ||
children: PropTypes.node.isRequired, | ||
/** additional classes added to the Select control */ | ||
className: PropTypes.string, | ||
/** value of selected option */ | ||
value: PropTypes.any, | ||
/** Flag indicating selection is valid */ | ||
isValid: PropTypes.bool, | ||
/** Flag indicating the Select is disabled */ | ||
isDisabled: PropTypes.bool, | ||
/** Optional callback for updating when selection loses focus */ | ||
onBlur: PropTypes.func, | ||
/** Optional callback for updating when selection gets focus */ | ||
onFocus: PropTypes.func, | ||
/** Optional callback for updating when selection changes */ | ||
onChange: PropTypes.func, | ||
/** Custom flag to show that the Select requires an associated id or aria-label. */ | ||
'aria-label': props => { | ||
if (!props.id && !props['aria-label']) { | ||
return new Error('Select requires either an id or aria-label to be specified'); | ||
} | ||
return null; | ||
} | ||
}; | ||
|
||
const defaultProps = { | ||
className: '', | ||
value: '', | ||
isValid: true, | ||
isDisabled: false, | ||
onBlur: () => undefined, | ||
onFocus: () => undefined, | ||
onChange: () => undefined, | ||
'aria-label': null | ||
}; | ||
|
||
class Select extends React.Component { | ||
handleChange = event => { | ||
this.props.onChange(event.currentTarget.value, event); | ||
}; | ||
|
||
render() { | ||
const { children, className, value, isValid, isDisabled, ...props } = this.props; | ||
return ( | ||
<select | ||
{...props} | ||
className={css(styles.formControl, className, !isValid && styles.modifiers.invalid)} | ||
aria-invalid={!isValid} | ||
onChange={this.handleChange} | ||
disabled={isDisabled} | ||
value={value} | ||
> | ||
{children} | ||
</select> | ||
); | ||
} | ||
} | ||
|
||
Select.propTypes = propTypes; | ||
Select.defaultProps = defaultProps; | ||
|
||
export default Select; |
152 changes: 152 additions & 0 deletions
152
packages/patternfly-4/react-core/src/components/Select/Select.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import React from 'react'; | ||
import { shallow } from 'enzyme'; | ||
import Select from './Select'; | ||
import SelectOption from './SelectOption'; | ||
import SelectOptionGroup from './SelectOptionGroup'; | ||
|
||
const props = { | ||
options: [ | ||
{ value: 'please choose', label: 'Please Choose', disabled: true }, | ||
{ value: 'mr', label: 'Mr', disabled: false }, | ||
{ value: 'miss', label: 'Miss', disabled: false }, | ||
{ value: 'mrs', label: 'Mrs', disabled: false }, | ||
{ value: 'ms', label: 'Ms', disabled: false }, | ||
{ value: 'dr', label: 'Dr', disabled: false }, | ||
{ value: 'other', label: 'Other', disabled: true } | ||
], | ||
value: 'mrs' | ||
}; | ||
|
||
const groupedProps = { | ||
groups: [ | ||
{ | ||
groupLabel: 'Group1', | ||
disabled: false, | ||
options: [ | ||
{ value: '1', label: 'The First Option', disabled: false }, | ||
{ value: '2', label: 'Second option is selected by default', disabled: false } | ||
] | ||
}, | ||
{ | ||
groupLabel: 'Group2', | ||
disabled: false, | ||
options: [ | ||
{ value: '3', label: 'The Third Option', disabled: false }, | ||
{ value: '4', label: 'The Fourth option', disabled: false } | ||
] | ||
}, | ||
{ | ||
groupLabel: 'Group3', | ||
disabled: true, | ||
options: [ | ||
{ value: '5', label: 'The Fifth Option', disabled: false }, | ||
{ value: '6', label: 'The Sixth option', disabled: false } | ||
] | ||
} | ||
], | ||
value: '2' | ||
}; | ||
|
||
test('Simple Select input', () => { | ||
const view = shallow( | ||
<Select value={props.value} aria-label="simple Select"> | ||
{props.options.map((option, index) => ( | ||
<SelectOption isDisabled={option.disabled} key={index} value={option.value} label={option.label} /> | ||
))} | ||
</Select> | ||
); | ||
expect(view).toMatchSnapshot(); | ||
}); | ||
|
||
test('Grouped Select input', () => { | ||
const view = shallow( | ||
<Select value={groupedProps.value} aria-label=" grouped Select"> | ||
{groupedProps.groups.map((group, index) => ( | ||
<SelectOptionGroup isDisabled={group.disabled} key={index} label={group.groupLabel}> | ||
{group.options.map((option, i) => ( | ||
<SelectOption isDisabled={option.disabled} key={i} value={option.value} label={option.label} /> | ||
))} | ||
</SelectOptionGroup> | ||
))} | ||
</Select> | ||
); | ||
expect(view).toMatchSnapshot(); | ||
}); | ||
|
||
test('Disabled Select input ', () => { | ||
const view = shallow( | ||
<Select isDisabled aria-label="disabled Select"> | ||
<SelectOption key={1} value={props.options[1].value} label={props.options[1].label} /> | ||
</Select> | ||
); | ||
expect(view).toMatchSnapshot(); | ||
}); | ||
|
||
test('Select input with aria-label does not generate console error', () => { | ||
const myMock = jest.fn(); | ||
global.console = { error: myMock }; | ||
const view = shallow( | ||
<Select aria-label="Select with aria-label"> | ||
<SelectOption key={1} value={props.options[1].value} label={props.options[1].label} /> | ||
</Select> | ||
); | ||
expect(view).toMatchSnapshot(); | ||
expect(myMock).not.toBeCalled(); | ||
}); | ||
|
||
test('Select input with id does not generate console error', () => { | ||
const myMock = jest.fn(); | ||
global.console = { error: myMock }; | ||
const view = shallow( | ||
<Select id="id"> | ||
<SelectOption key={1} value={props.options[1].value} label={props.options[1].label} /> | ||
</Select> | ||
); | ||
expect(view).toMatchSnapshot(); | ||
expect(myMock).not.toBeCalled(); | ||
}); | ||
|
||
test('Select input with no aria-label or id generates console error', () => { | ||
const myMock = jest.fn(); | ||
global.console = { error: myMock }; | ||
const view = shallow( | ||
<Select> | ||
<SelectOption key={1} value={props.options[1].value} label={props.options[1].label} /> | ||
</Select> | ||
); | ||
expect(view).toMatchSnapshot(); | ||
expect(myMock).toBeCalled(); | ||
}); | ||
|
||
test('invalid Select input', () => { | ||
const view = shallow( | ||
<Select isValid={false} aria-label="invalid Select"> | ||
<SelectOption key={1} value={props.options[1].value} label={props.options[1].label} /> | ||
</Select> | ||
); | ||
expect(view).toMatchSnapshot(); | ||
}); | ||
|
||
test('required Select input', () => { | ||
const view = shallow( | ||
<Select required aria-label="required Select"> | ||
<SelectOption key={1} value={props.options[1].value} label={props.options[1].label} /> | ||
</Select> | ||
); | ||
expect(view).toMatchSnapshot(); | ||
}); | ||
|
||
test('Select passes value and event to onChange handler', () => { | ||
const myMock = jest.fn(); | ||
const newValue = 1; | ||
const event = { | ||
currentTarget: { value: newValue } | ||
}; | ||
const view = shallow( | ||
<Select onChange={myMock} aria-label="onchange Select"> | ||
<SelectOption key={1} value={props.options[1].value} label={props.options[1].label} /> | ||
</Select> | ||
); | ||
view.find('select').simulate('change', event); | ||
expect(myMock).toBeCalledWith(newValue, event); | ||
}); |
13 changes: 13 additions & 0 deletions
13
packages/patternfly-4/react-core/src/components/Select/SelectOption.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { HTMLProps, FormEvent } from 'react'; | ||
import { Omit } from '../../typeUtils'; | ||
|
||
export interface SelectOptionProps extends Omit<HTMLProps<HTMLOptionElement>, 'disabled'> { | ||
value?: any; | ||
label: string; | ||
isValid?: boolean; | ||
isDisabled?: boolean; | ||
} | ||
|
||
declare const SelectOption: React.SFC<SelectOptionProps>; | ||
|
||
export default SelectOption; |
30 changes: 30 additions & 0 deletions
30
packages/patternfly-4/react-core/src/components/Select/SelectOption.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const propTypes = { | ||
/** additional classes added to the Select Option */ | ||
className: PropTypes.string, | ||
/** the value for the option */ | ||
value: PropTypes.any, | ||
/** the label for the option */ | ||
label: PropTypes.string.isRequired, | ||
/** flag indicating if the option is disabled */ | ||
isDisabled: PropTypes.bool | ||
}; | ||
|
||
const defaultProps = { | ||
className: '', | ||
value: '', | ||
isDisabled: false | ||
}; | ||
|
||
const SelectOption = ({ className, value, label, isDisabled, ...props }) => ( | ||
<option {...props} className={className} value={value} disabled={isDisabled}> | ||
{label} | ||
</option> | ||
); | ||
|
||
SelectOption.propTypes = propTypes; | ||
SelectOption.defaultProps = defaultProps; | ||
|
||
export default SelectOption; |
12 changes: 12 additions & 0 deletions
12
packages/patternfly-4/react-core/src/components/Select/SelectOptionGroup.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { HTMLProps, FormEvent } from 'react'; | ||
import { Omit } from '../../typeUtils'; | ||
|
||
export interface SelectOptionGroupProps extends Omit<HTMLProps<HTMLOptGroupElement>, 'disabled'> { | ||
children: any; | ||
label: string; | ||
isDisabled?: boolean; | ||
} | ||
|
||
declare const SelectOptionGroup: React.SFC<SelectOptionGroupProps>; | ||
|
||
export default SelectOptionGroup; |
30 changes: 30 additions & 0 deletions
30
packages/patternfly-4/react-core/src/components/Select/SelectOptionGroup.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const propTypes = { | ||
/** content rendered inside the Select Option Group */ | ||
children: PropTypes.node, | ||
/** additional classes added to the Select Option */ | ||
className: PropTypes.string, | ||
/** the label for the option */ | ||
label: PropTypes.string.isRequired, | ||
/** flag indicating if the Option Group is disabled */ | ||
isDisabled: PropTypes.bool | ||
}; | ||
|
||
const defaultProps = { | ||
children: null, | ||
className: '', | ||
isDisabled: false | ||
}; | ||
|
||
const SelectOptionGroup = ({ children, className, label, isDisabled, ...props }) => ( | ||
<optgroup {...props} disabled={!!isDisabled} className={className} label={label}> | ||
{children} | ||
</optgroup> | ||
); | ||
|
||
SelectOptionGroup.propTypes = propTypes; | ||
SelectOptionGroup.defaultProps = defaultProps; | ||
|
||
export default SelectOptionGroup; |
Oops, something went wrong.